1use crate::jobs::JobBuffer;
24use crate::utils::defaults::DEFAULT_TEXT_ITEM;
25use crate::utils::types::RUMString;
26use axum::extract::State;
27use phf::OrderedMap;
28pub use phf_macros::phf_ordered_map as rumtk_create_const_ordered_map;
29use rumtk_core::types::{RUMDeserialize, RUMDeserializer, RUMSerialize, RUMSerializer, RUMID};
30use rumtk_core::types::{RUMHashMap, RUMOrderedMap};
31use std::sync::{Arc, RwLock};
32
33pub type TextMap = RUMOrderedMap<RUMString, RUMString>;
34pub type NestedTextMap = RUMOrderedMap<RUMString, TextMap>;
35pub type NestedNestedTextMap = RUMOrderedMap<RUMString, NestedTextMap>;
36pub type RootNestedNestedTextMap = RUMOrderedMap<RUMString, NestedNestedTextMap>;
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: RootNestedNestedTextMap,
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) -> NestedTextMap {
102 match self.strings.get(&self.lang) {
103 Some(l) => match l.get(item) {
104 Some(i) => i.clone(),
105 None => NestedTextMap::default(),
106 },
107 None => NestedTextMap::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 struct AppState {
131 pub config: AppConf,
132 pub clipboard: TextMap,
133 pub jobs: RUMHashMap<RUMID, Option<JobBuffer>>,
134}
135
136pub type SharedAppState = Arc<RwLock<AppState>>;
137pub type RouterAppState = State<Arc<RwLock<AppState>>>;
138
139#[macro_export]
140macro_rules! rumtk_web_load_conf {
141 ( $args:expr ) => {{
142 rumtk_web_load_conf!($args, "./app.json")
143 }};
144 ( $args:expr, $path:expr ) => {{
145 use rumtk_core::rumtk_deserialize;
146 use rumtk_core::strings::RUMStringConversions;
147 use rumtk_core::types::RUMHashMap;
148 use std::fs;
149 use std::sync::{Arc, RwLock};
150
151 use $crate::rumtk_web_save_conf;
152 use $crate::utils::{AppConf, AppState, TextMap};
153
154 let json = match fs::read_to_string($path) {
155 Ok(json) => json,
156 Err(err) => rumtk_web_save_conf!($path),
157 };
158
159 let mut conf: AppConf = match rumtk_deserialize!(json) {
160 Ok(conf) => conf,
161 Err(err) => panic!(
162 "The App config file in {} does not meet the expected structure. \
163 See the documentation for more information. Error: {}\n{}",
164 $path, err, json
165 ),
166 };
167 conf.update_site_info(
168 $args.title.clone(),
169 $args.description.clone(),
170 $args.company.clone(),
171 $args.copyright.clone(),
172 );
173 Arc::new(RwLock::new(AppState {
174 config: conf,
175 clipboard: TextMap::default(),
176 jobs: RUMHashMap::default(),
177 }))
178 }};
179}
180
181#[macro_export]
182macro_rules! rumtk_web_save_conf {
183 ( $path:expr ) => {{
184 use rumtk_core::rumtk_serialize;
185 use rumtk_core::strings::RUMStringConversions;
186 use std::fs;
187 use $crate::utils::AppConf;
188
189 let json = rumtk_serialize!(AppConf::default(), true)?;
190 fs::write($path, &json);
191 json
192 }};
193}
194
195#[macro_export]
196macro_rules! rumtk_web_get_string {
197 ( $conf:expr, $item:expr ) => {{
198 let owned_state = $conf.read().expect("Lock failure");
199 owned_state.config.get_text($item)
200 }};
201}
202
203#[macro_export]
204macro_rules! rumtk_web_get_conf {
205 ( $conf:expr, $item:expr ) => {{
206 let owned_state = $conf.read().expect("Lock failure");
207 owned_state.config.get_conf($item)
208 }};
209}
210
211pub const DEFAULT_TEXT: fn() -> RUMString = || RUMString::default();
215pub const DEFAULT_TEXTMAP: fn() -> TextMap = || TextMap::default();
216pub const DEFAULT_NESTEDTEXTMAP: fn() -> NestedTextMap = || NestedTextMap::default();
217pub const DEFAULT_NESTEDNESTEDTEXTMAP: fn() -> NestedNestedTextMap =
218 || NestedNestedTextMap::default();