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}