Skip to main content

rumtk_web/components/app/
app_nav.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) 2026  Luis M. Santos, M.D. <lsantos@medicalmasses.com>
5 *     Copyright (C) 2026  MedicalMasses L.L.C. <contact@medicalmasses.com>
6 *
7 *     This program is free software: you can redistribute it and/or modify
8 *     it under the terms of the GNU General Public License as published by
9 *     the Free Software Foundation, either version 3 of the License, or
10 *     (at your option) any later version.
11 *
12 *     This program is distributed in the hope that it will be useful,
13 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *     GNU General Public License for more details.
16 *
17 *     You should have received a copy of the GNU General Public License
18 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 */
20
21/*
22 * rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
23 * This toolkit aims to be reliable, simple, performant, and standards compliant.
24 * Copyright (C) 2025  Luis M. Santos, M.D. <lsantos@medicalmasses.com>
25 * Copyright (C) 2025  Ethan Dixon
26 * Copyright (C) 2025  MedicalMasses L.L.C. <contact@medicalmasses.com>
27 *
28 * This program is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, either version 3 of the License, or
31 * (at your option) any later version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
40 */
41use crate::components::app::logo::{logo, Logo};
42use crate::components::app::navlink::{navlink, NavLink};
43use crate::components::html::{header, Header};
44use crate::components::title::{title, Title};
45use crate::defaults::{PARAMS_TARGET, PARAMS_TITLE};
46use crate::utils::defaults::{DEFAULT_TEXT_ITEM, PARAMS_CSS_CLASS, PARAMS_SOURCE_URL};
47use crate::utils::types::{RUMString, SharedAppState, URLParams, URLPath};
48use crate::{rumtk_web_get_config, rumtk_web_get_text_item, rumtk_web_params_map, ComponentResult, PageConf, RUMWebData, RUMWebTemplate, RUMWebTemplateSafe};
49use rumtk_core::base::RUMResult;
50
51#[derive(RUMWebTemplate, Debug, Clone)]
52#[template(
53    source = "
54        {% if !disable_logo %}
55        <div class='header-{{ css_class }}-navlogo'>
56            <a class='undecorated no-select logo-{{css_class}}-container' href='./'>
57                {{logo|safe}}
58                {{company|safe}}
59            </a>
60        </div>
61        {% endif %}
62        {% if !disable_links %}
63        <div class='header-{{ css_class }}-navactions gap-10'>
64            {% for item in nav_links %}
65                {{item|safe}}
66            {% endfor %}
67        </div>
68        {% else %}
69        {{title|safe}}
70        {% endif %}
71        <div class='header-{{ css_class }}-misc gap-10'>
72        </div>
73    ",
74    ext = "html"
75)]
76pub struct Nav {
77    company: Title,
78    logo: Logo,
79    title: Title,
80    nav_links: Vec<NavLink>,
81    disable_links: bool,
82    disable_logo: bool,
83    css_class: RUMString,
84}
85
86impl RUMWebTemplateSafe for Nav {}
87
88fn get_nav_links(itms: &Vec<(RUMString, PageConf)>, app_state: SharedAppState) -> RUMResult<Vec<NavLink>> {
89    let mut nav_links = Vec::<NavLink>::with_capacity(itms.len());
90    for (k, itm) in itms {
91        nav_links.push(
92            navlink(
93                &[],
94                &RUMWebData::from([
95                    (PARAMS_TITLE.to_string(), k.to_string()),
96                    (PARAMS_TARGET.to_string(), itm.url.to_string()),
97                ]),
98                app_state.clone(),
99            )?,
100        );
101    }
102
103    Ok(nav_links)
104}
105
106#[derive(RUMWebTemplate, Debug, Clone)]
107#[template(
108    source = "
109        {{app_nav}}
110    ",
111    ext = "html"
112)]
113pub struct AppNav {
114    app_nav: Header<Nav>,
115}
116
117impl RUMWebTemplateSafe for AppNav {}
118
119pub fn app_nav<'a>(_path_components: URLPath<'a, 'a>, params: URLParams<'a>, state: SharedAppState) -> ComponentResult<AppNav> {
120    let css_class = rumtk_web_get_text_item!(params, PARAMS_CSS_CLASS, DEFAULT_TEXT_ITEM).to_string();
121
122    let company_params = rumtk_web_params_map!([(
123        PARAMS_TITLE,
124        rumtk_web_get_config!(state).company.as_str()
125    )]);
126    let company = title(
127        _path_components,
128        company_params.get_inner(),
129        state.clone()
130    )?;
131
132    let title_params = rumtk_web_params_map!([(
133                PARAMS_TITLE,
134                rumtk_web_get_config!(state).title.as_str()
135            )]);
136    let title = title(
137            _path_components,
138            title_params.get_inner(),
139            state.clone()
140        )?;
141
142    let links = match &rumtk_web_get_config!(state).router.pages {
143        Some(pages) => {
144            let mut links = Vec::<(RUMString, PageConf)>::with_capacity(pages.len());
145            for (k, v) in pages.iter() {
146                links.push((k.clone(), v.clone()));
147            }
148            links
149        },
150        None => vec![],
151    };
152    let disable_links = rumtk_web_get_config!(state).header_conf.disable_navlinks;
153    let nav_links = get_nav_links(&links, state.clone())?;
154
155    let disable_logo =
156        rumtk_web_get_config!(state).header_conf.disable_logo;
157    let logo_params = rumtk_web_params_map!(
158        [
159            (
160                PARAMS_SOURCE_URL,
161                rumtk_web_get_config!(state).header_conf.logo_source.clone().unwrap_or_default().as_str()
162            ),
163        ]
164    );
165    let logo = logo(_path_components, logo_params.get_inner(), state.clone())?;
166
167    let contents = Nav {
168        company,
169        logo,
170        title,
171        nav_links,
172        disable_logo,
173        disable_links,
174        css_class
175    };
176
177    let app_nav = header(
178        contents,
179        params,
180        state
181    )?;
182
183    Ok(AppNav {
184        app_nav
185    })
186}