rumtk_web/pages/mod.rs
1/*
2 * rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
3 * This toolkit aims to be reliable, simple, performant, and standards compliant.
4 * Copyright (C) 2025 Luis M. Santos, M.D.
5 * Copyright (C) 2025 Nick Stephenson
6 * Copyright (C) 2025 Ethan Dixon
7 * Copyright (C) 2025 MedicalMasses L.L.C.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23pub mod index;
24
25use crate::utils::PageFunction;
26use rumtk_core::cache::{new_cache, LazyRUMCache, LazyRUMCacheValue};
27use rumtk_core::strings::RUMString;
28use rumtk_core::{rumtk_cache_get, rumtk_cache_push};
29use std::ops::Deref;
30
31pub type PageCache = LazyRUMCache<RUMString, PageFunction>;
32pub type PageItem<'a> = (&'a str, PageFunction);
33pub type UserPages<'a> = Vec<PageItem<'a>>;
34pub type PageCacheItem = LazyRUMCacheValue<PageFunction>;
35
36static mut PAGE_CACHE: PageCache = new_cache();
37static mut DEFAULT_PAGE: PageFunction = index::index;
38pub const DEFAULT_PAGE_NAME: &str = "index";
39
40pub fn register_page(name: &str, component_fxn: PageFunction) -> PageCacheItem {
41 let key = RUMString::from(name);
42 let r = rumtk_cache_push!(&raw mut PAGE_CACHE, &key, &component_fxn);
43
44 if key == DEFAULT_PAGE_NAME {
45 unsafe {
46 DEFAULT_PAGE = component_fxn;
47 }
48 }
49 println!(
50 " ➡ Registered page {} => page function [{:?}]",
51 name, &component_fxn
52 );
53 r
54}
55
56pub fn get_page(name: &str) -> PageCacheItem {
57 rumtk_cache_get!(
58 &raw mut PAGE_CACHE,
59 &RUMString::from(name),
60 get_default_page()
61 )
62}
63
64pub fn get_default_page() -> &'static PageFunction {
65 unsafe { &DEFAULT_PAGE }
66}
67
68pub fn init_pages(user_components: &UserPages) {
69 println!("🗎 Registering user pages! 🗎");
70 /* Init any user prescribed components */
71 for (name, value) in user_components {
72 let _ = register_page(name, *value);
73 }
74 println!(
75 " ➡ Default page => page function [{:?}]",
76 &get_default_page()
77 );
78 println!("🗎 ~~~~~~~~~~~~~~~~~~~~~~ 🗎");
79}
80
81#[macro_export]
82macro_rules! rumtk_web_register_page {
83 ( $key:expr, $fxn:expr ) => {{
84 use $crate::pages::register_page;
85 register_page($key, $fxn)
86 }};
87}
88
89///
90/// Helper function for retrieving pages registered in the global cache using a string key!
91///
92/// ## Example
93///
94/// ### With Named Page
95///
96/// ```
97/// use rumtk_core::strings::rumtk_format;
98/// use rumtk_web::utils::{SharedAppState, RenderedPageComponents};
99/// use rumtk_web::{rumtk_web_render_component, rumtk_web_register_page, rumtk_web_get_page};
100///
101/// pub fn index(app_state: SharedAppState) -> RenderedPageComponents {
102/// let title_welcome = rumtk_web_render_component!("title", [("type", "welcome")], app_state.clone());
103///
104/// vec![
105/// title_welcome,
106/// ]
107/// }
108///
109/// let r = rumtk_format!("{:?}", &rumtk_web_register_page!("index", index));
110/// let p = rumtk_format!("{:?}", &rumtk_web_get_page!("index"));
111///
112/// assert_eq!(&r, &p, "{}", rumtk_format!("The registered page does not match the retrieved page!\nGot: {:?}\nExpected: {:?}", &r, &p));
113///
114/// ```
115///
116/// ### With Default Page
117///
118/// ```
119/// use rumtk_core::strings::rumtk_format;
120/// use rumtk_web::utils::{SharedAppState, RenderedPageComponents};
121/// use rumtk_web::{rumtk_web_render_component, rumtk_web_register_page, rumtk_web_get_page, rumtk_web_get_default_page};
122///
123/// pub fn index(app_state: SharedAppState) -> RenderedPageComponents {
124/// let title_welcome = rumtk_web_render_component!("title", [("type", "welcome")], app_state.clone());
125///
126/// vec![
127/// title_welcome,
128/// ]
129/// }
130///
131/// let default = rumtk_format!("{:?}", rumtk_web_get_default_page!());
132/// let r = rumtk_format!("{:?}", &rumtk_web_register_page!("index", index));
133/// let p = rumtk_format!("{:?}", &rumtk_web_get_page!(""));
134///
135/// assert_ne!(&default, &p, "{}", rumtk_format!("The default page matches the retrieved page!\nGot: {:?}\nExpected: {:?}", &r, &p));
136/// assert_eq!(&r, &p, "{}", rumtk_format!("The registered page does not match the retrieved page!\nGot: {:?}\nExpected: {:?}", &r, &p));
137///
138/// ```
139///
140#[macro_export]
141macro_rules! rumtk_web_get_page {
142 ( $key:expr ) => {{
143 use $crate::pages::get_page;
144 get_page($key)
145 }};
146}
147
148///
149/// Returns the default page function that can be used for rendering that page
150///
151#[macro_export]
152macro_rules! rumtk_web_get_default_page {
153 ( ) => {{
154 use $crate::pages::get_default_page;
155 get_default_page()
156 }};
157}
158
159///
160/// Registers a set of pages provided by the user.
161///
162/// ## Example
163///
164///```
165/// use std::ops::Deref;
166/// use rumtk_core::strings::rumtk_format;
167/// use rumtk_web::utils::{SharedAppState, RenderedPageComponents};
168/// use rumtk_web::{rumtk_web_render_component, rumtk_web_init_pages, rumtk_web_get_page};
169///
170/// fn my_page(app_state: SharedAppState) -> RenderedPageComponents {
171/// let title_welcome = rumtk_web_render_component!("title", [("type", "welcome")], app_state.clone());
172///
173/// vec![
174/// title_welcome,
175/// ]
176/// }
177///
178/// let my_page_name = "my_page";
179///
180/// rumtk_web_init_pages!(&vec![(my_page_name, my_page)]);
181///```
182///
183///
184#[macro_export]
185macro_rules! rumtk_web_init_pages {
186 ( $pages:expr ) => {{
187 use $crate::pages::init_pages;
188 init_pages($pages)
189 }};
190}
191
192#[macro_export]
193macro_rules! rumtk_web_collect_page {
194 ( $page:expr, $app_state:expr ) => {{
195 use $crate::rumtk_web_get_page;
196
197 let page = rumtk_web_get_page!(&$page);
198
199 page($app_state.clone())
200 }};
201}