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