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        "  ➡ 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}