1use crate::utils::defaults::DEFAULT_TEXT_ITEM;
24use crate::utils::types::RUMString;
25use axum::extract::State;
26use phf::OrderedMap;
27pub use phf_macros::phf_ordered_map as rumtk_create_const_ordered_map;
28use rumtk_core::types::{RUMDeserialize, RUMDeserializer, RUMSerialize, RUMSerializer};
29use std::collections::HashMap;
30use std::sync::{Arc, RwLock};
31
32pub type TextMap = HashMap<RUMString, RUMString>;
33pub type NestedTextMap = HashMap<RUMString, TextMap>;
34pub type NestedNestedTextMap = HashMap<RUMString, NestedTextMap>;
35pub type RootNestedNestedTextMap = HashMap<RUMString, NestedNestedTextMap>;
36pub type RootRootNestedNestedTextMap = HashMap<RUMString, RootNestedNestedTextMap>;
37
38pub type ConstTextMap = OrderedMap<&'static str, &'static str>;
39pub type ConstNestedTextMap = OrderedMap<&'static str, &'static ConstTextMap>;
40pub type ConstNestedNestedTextMap = OrderedMap<&'static str, &'static ConstNestedTextMap>;
41
42#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
43pub struct HeaderConf {
44 pub logo_size: RUMString,
45 pub disable_navlinks: bool,
46 pub disable_logo: bool,
47}
48
49#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
50pub struct FooterConf {
51 pub socials_list: RUMString,
52 pub disable_contact_button: bool,
53}
54
55#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
63pub struct AppConf {
64 pub title: RUMString,
65 pub description: RUMString,
66 pub company: RUMString,
67 pub copyright: RUMString,
68 pub lang: RUMString,
69 pub theme: RUMString,
70 pub custom_css: bool,
71 pub header_conf: HeaderConf,
72 pub footer_conf: FooterConf,
73
74 strings: RootRootNestedNestedTextMap,
75 config: NestedNestedTextMap,
76 }
78
79impl AppConf {
80 pub fn update_site_info(
81 &mut self,
82 title: RUMString,
83 description: RUMString,
84 company: RUMString,
85 copyright: RUMString,
86 ) {
87 if !title.is_empty() {
88 self.title = title;
89 }
90 if !company.is_empty() {
91 self.company = company;
92 }
93 if !description.is_empty() {
94 self.description = description;
95 }
96 if !copyright.is_empty() {
97 self.copyright = copyright;
98 }
99 }
100
101 pub fn get_text(&self, item: &str) -> NestedNestedTextMap {
102 match self.strings.get(&self.lang) {
103 Some(l) => match l.get(item) {
104 Some(i) => i.clone(),
105 None => NestedNestedTextMap::default(),
106 },
107 None => NestedNestedTextMap::default(),
108 }
109 }
110
111 pub fn get_conf(&self, section: &str) -> TextMap {
112 match self.config.get(section) {
113 Some(l) => match l.get(&self.lang) {
114 Some(i) => i.clone(),
115 None => match l.get(DEFAULT_TEXT_ITEM) {
116 Some(i) => i.clone(),
117 None => TextMap::default(),
118 },
119 },
120 None => TextMap::default(),
121 }
122 }
123}
124
125pub type SharedAppConf = Arc<RwLock<AppConf>>;
126pub type RouterAppConf = State<Arc<RwLock<AppConf>>>;
127
128#[macro_export]
129macro_rules! rumtk_web_load_conf {
130 ( $args:expr ) => {{
131 rumtk_web_load_conf!($args, "./app.json")
132 }};
133 ( $args:expr, $path:expr ) => {{
134 use rumtk_core::strings::RUMStringConversions;
135 use rumtk_core::{rumtk_deserialize, rumtk_serialize};
136 use std::fs;
137 use std::sync::{Arc, RwLock};
138 use $crate::utils::AppConf;
139
140 let json = match fs::read_to_string($path) {
141 Ok(json) => json,
142 Err(err) => {
143 let json = rumtk_serialize!(AppConf::default(), true)?;
144 fs::write($path, &json);
145 json
146 }
147 };
148
149 let mut conf: AppConf = match rumtk_deserialize!(json) {
150 Ok(conf) => conf,
151 Err(err) => panic!(
152 "The App config file in {} does not meet the expected structure. \
153 See the documentation for more information. Error: {}\n{}",
154 $path, err, json
155 ),
156 };
157 conf.update_site_info(
158 $args.title.clone(),
159 $args.description.clone(),
160 $args.company.clone(),
161 $args.copyright.clone(),
162 );
163 Arc::new(RwLock::new(conf))
164 }};
165}
166
167#[macro_export]
168macro_rules! rumtk_web_get_string {
169 ( $conf:expr, $item:expr ) => {{
170 let owned_state = $conf.read().expect("Lock failure");
171 owned_state.get_text($item)
172 }};
173}
174
175#[macro_export]
176macro_rules! rumtk_web_get_conf {
177 ( $conf:expr, $item:expr ) => {{
178 let owned_state = $conf.read().expect("Lock failure");
179 owned_state.get_conf($item)
180 }};
181}
182
183pub const DEFAULT_TEXT: fn() -> RUMString = || RUMString::default();
187pub const DEFAULT_TEXTMAP: fn() -> TextMap = || TextMap::default();
188pub const DEFAULT_NESTEDTEXTMAP: fn() -> NestedTextMap = || NestedTextMap::default();
189pub const DEFAULT_NESTEDNESTEDTEXTMAP: fn() -> NestedNestedTextMap =
190 || NestedNestedTextMap::default();