Skip to main content

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}
76
77#[macro_export]
78macro_rules! rumtk_web_register_page {
79    ( $key:expr, $fxn:expr ) => {{
80        use $crate::pages::register_page;
81        register_page($key, $fxn)
82    }};
83}
84
85///
86/// Helper function for retrieving pages registered in the global cache using a string key!
87///
88/// ## Example
89///
90/// ### With Named Page
91///
92/// ```
93/// use rumtk_core::strings::rumtk_format;
94/// use rumtk_web::utils::{SharedAppState, RenderedPageComponents};
95/// use rumtk_web::{rumtk_web_render_component, rumtk_web_register_page, rumtk_web_get_page};
96///
97/// pub fn index(app_state: SharedAppState) -> RenderedPageComponents {
98///     let title_welcome = rumtk_web_render_component!("title", [("type", "welcome")], app_state.clone());
99///
100///     vec![
101///         title_welcome,
102///     ]
103/// }
104///
105/// let r = rumtk_format!("{:?}", &rumtk_web_register_page!("index", index));
106/// let p = rumtk_format!("{:?}", &rumtk_web_get_page!("index"));
107///
108///  assert_eq!(&r, &p, "{}", rumtk_format!("The registered page does not match the retrieved page!\nGot: {:?}\nExpected: {:?}", &r, &p));
109///
110/// ```
111///
112/// ### With Default Page
113///
114/// ```
115/// use rumtk_core::strings::rumtk_format;
116/// use rumtk_web::utils::{SharedAppState, RenderedPageComponents};
117/// use rumtk_web::{rumtk_web_render_component, rumtk_web_register_page, rumtk_web_get_page, rumtk_web_get_default_page};
118///
119/// pub fn index(app_state: SharedAppState) -> RenderedPageComponents {
120///     let title_welcome = rumtk_web_render_component!("title", [("type", "welcome")], app_state.clone());
121///
122///     vec![
123///         title_welcome,
124///     ]
125/// }
126///
127/// let default = rumtk_format!("{:?}", rumtk_web_get_default_page!());
128/// let r = rumtk_format!("{:?}", &rumtk_web_register_page!("index", index));
129/// let p = rumtk_format!("{:?}", &rumtk_web_get_page!(""));
130///
131///  assert_ne!(&default, &p, "{}", rumtk_format!("The default page matches the retrieved page!\nGot: {:?}\nExpected: {:?}", &r, &p));
132///  assert_eq!(&r, &p, "{}", rumtk_format!("The registered page does not match the retrieved page!\nGot: {:?}\nExpected: {:?}", &r, &p));
133///
134/// ```
135///
136#[macro_export]
137macro_rules! rumtk_web_get_page {
138    ( $key:expr ) => {{
139        use $crate::pages::get_page;
140        get_page($key)
141    }};
142}
143
144///
145/// Returns the default page function that can be used for rendering that page
146///
147#[macro_export]
148macro_rules! rumtk_web_get_default_page {
149    ( ) => {{
150        use $crate::pages::get_default_page;
151        get_default_page()
152    }};
153}
154
155///
156/// Registers a set of pages provided by the user.
157///
158/// ## Example
159///
160///```
161/// use std::ops::Deref;
162/// use rumtk_core::strings::rumtk_format;
163/// use rumtk_web::utils::{SharedAppState, RenderedPageComponents};
164/// use rumtk_web::{rumtk_web_render_component, rumtk_web_init_pages, rumtk_web_get_page};
165///
166/// fn my_page(app_state: SharedAppState) -> RenderedPageComponents {
167///     let title_welcome = rumtk_web_render_component!("title", [("type", "welcome")], app_state.clone());
168///
169///     vec![
170///         title_welcome,
171///     ]
172/// }
173///
174/// let my_page_name = "my_page";
175///
176/// rumtk_web_init_pages!(&vec![(my_page_name, my_page)]);
177///```
178///
179///
180#[macro_export]
181macro_rules! rumtk_web_init_pages {
182    ( $pages:expr ) => {{
183        use $crate::pages::init_pages;
184        init_pages($pages)
185    }};
186}
187
188#[macro_export]
189macro_rules! rumtk_web_collect_page {
190    ( $page:expr, $app_state:expr ) => {{
191        use $crate::rumtk_web_get_page;
192
193        let page = rumtk_web_get_page!(&$page);
194
195        page($app_state.clone())
196    }};
197}