1use crate::jobs::{Job, JobID};
22use crate::utils::defaults::DEFAULT_TEXT_ITEM;
23use crate::utils::types::RUMString;
24use askama::PrimitiveType;
25use axum::extract::State;
26use phf::OrderedMap;
27pub use phf_macros::phf_ordered_map as rumtk_create_const_ordered_map;
28use rumtk_core::net::tcp::SafeLock;
29use rumtk_core::pipelines::pipeline_types::RUMCommandLine;
30use rumtk_core::strings::RUMStringConversions;
31use rumtk_core::types::{RUMDeserialize, RUMSerialize, RUMID};
32use rumtk_core::types::{RUMHashMap, RUMOrderedMap};
33use rumtk_core::{rumtk_generate_id, rumtk_new_lock};
34
35pub type TextMap = RUMOrderedMap<RUMString, RUMString>;
36pub type NestedTextMap = RUMOrderedMap<RUMString, TextMap>;
37pub type NestedNestedTextMap = RUMOrderedMap<RUMString, NestedTextMap>;
38pub type RootNestedNestedTextMap = RUMOrderedMap<RUMString, NestedNestedTextMap>;
39
40pub type ConstTextMap = OrderedMap<&'static str, &'static str>;
41pub type ConstNestedTextMap = OrderedMap<&'static str, &'static ConstTextMap>;
42pub type ConstNestedNestedTextMap = OrderedMap<&'static str, &'static ConstNestedTextMap>;
43
44pub type PipelineGroup = RUMHashMap<RUMString, RUMCommandLine>;
45
46#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
47pub struct HeaderConf {
48 pub logo_source: Option<RUMString>,
49 pub logo_size: RUMString,
50 pub disable_navlinks: bool,
51 pub disable_logo: bool,
52}
53
54#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
55pub struct FooterConf {
56 pub socials_list: RUMString,
57 pub disable_contact_button: bool,
58}
59
60#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
61pub struct PipelineConf {
62 pub settings: Option<TextMap>,
63 pub data_templates: Option<NestedTextMap>,
64 pub targets: Option<TextMap>,
65 pub categories: Option<RUMHashMap<RUMString, PipelineGroup>>
66}
67
68impl PipelineConf {
69 pub fn get_settings(&self) -> Option<&TextMap> {
70 self.settings.as_ref()
71 }
72
73 pub fn get_pipeline_category(&self, pipeline_category: &str) -> Option<&PipelineGroup> {
74 match self.categories {
75 Some(ref categories) => {
76 match categories.get(pipeline_category) {
77 Some(pipelines) => Some(pipelines),
78 None => None
79 }
80 }
81 None => None,
82 }
83 }
84 pub fn get_available_pipeline_names(&self) -> Vec<&RUMString> {
85 match self.targets.as_ref() {
86 Some(group) => {
87 let mut keys = group.keys().collect::<Vec<&RUMString>>();
88 keys.sort_unstable();
89 keys
90 },
91 None => vec![]
92 }
93 }
94 pub fn get_pipeline(&self, pipeline_category: &str, pipeline_name: &str) -> RUMCommandLine {
95 match self.get_pipeline_category(pipeline_category) {
96 Some(group) => match group.get(pipeline_name) {
97 Some(pipeline) => pipeline.to_owned(),
98 None => RUMCommandLine::new()
99 },
100 None => RUMCommandLine::new()
101 }
102 }
103
104 pub fn get_target(&self, profile: &str) -> RUMString {
105 match self.targets.as_ref() {
106 Some(targets) => match targets.get(profile) {
107 Some(pipeline) => pipeline.to_owned(),
108 None => RUMString::default()
109 },
110 None => RUMString::default()
111 }
112 }
113
114 pub fn get_template(&self, name: &str) -> Option<&TextMap> {
115 match self.data_templates.as_ref() {
116 Some(templates) => templates.get(name),
117 None => None
118 }
119 }
120
121 pub fn get_available_data_templates(&self) -> Vec<&RUMString> {
122 match self.data_templates.as_ref() {
123 Some(group) => {
124 let mut keys = group.keys().collect::<Vec<&RUMString>>();
125 keys.sort_unstable();
126 keys
127 },
128 None => vec![]
129 }
130 }
131}
132
133#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone, Default)]
141pub struct AppConf {
142 pub title: RUMString,
143 pub description: RUMString,
144 pub company: RUMString,
145 pub copyright: RUMString,
146 pub lang: RUMString,
147 pub theme: RUMString,
148 pub custom_css: bool,
149 pub header_conf: HeaderConf,
150 pub footer_conf: FooterConf,
151
152 strings: RootNestedNestedTextMap,
153 config: NestedNestedTextMap,
154 pipelines: PipelineConf,
155 }
157
158impl AppConf {
159 pub fn update_site_info(
160 &mut self,
161 title: RUMString,
162 description: RUMString,
163 company: RUMString,
164 copyright: RUMString,
165 ) {
166 if !title.is_empty() {
167 self.title = title;
168 }
169 if !company.is_empty() {
170 self.company = company;
171 }
172 if !description.is_empty() {
173 self.description = description;
174 }
175 if !copyright.is_empty() {
176 self.copyright = copyright;
177 }
178 }
179
180 pub fn get_pipelines(&self) -> &PipelineConf {
181 &self.pipelines
182 }
183
184 pub fn get_text(&self, item: &str) -> NestedTextMap {
185 match self.strings.get(&self.lang) {
186 Some(l) => match l.get(item) {
187 Some(i) => i.clone(),
188 None => NestedTextMap::default(),
189 },
190 None => NestedTextMap::default(),
191 }
192 }
193
194 pub fn get_section(&self, section: &str) -> TextMap {
195 match self.config.get(&self.lang) {
196 Some(l) => match l.get(section) {
197 Some(i) => i.clone(),
198 None => self.get_default_item(section),
199 },
200 None => self.get_default_item(section),
201 }
202 }
203
204 pub fn get_default_item(&self, section: &str) -> TextMap {
205 match self.config.get(DEFAULT_TEXT_ITEM) {
206 Some(l) => match l.get(section) {
207 Some(i) => i.clone(),
208 None => TextMap::default(),
209 },
210 None => TextMap::default(),
211 }
212 }
213}
214
215pub type ClipboardID = RUMString;
216#[derive(Default, Debug, Clone)]
222pub struct AppState {
223 config: AppConf,
224 clipboard: NestedTextMap,
225 jobs: RUMHashMap<RUMID, Job>,
226}
227
228pub type SharedAppState = SafeLock<AppState>;
229
230impl AppState {
231 pub fn new() -> AppState {
232 AppState {
233 config: AppConf::default(),
234 clipboard: NestedTextMap::default(),
235 jobs: RUMHashMap::default(),
236 }
237 }
238
239 pub fn new_safe() -> SharedAppState {
240 rumtk_new_lock!(AppState::new())
241 }
242
243 pub fn from_safe(conf: AppConf) -> SharedAppState {
244 rumtk_new_lock!(AppState::from(conf))
245 }
246
247 pub fn get_config(&self) -> &AppConf {
248 &self.config
249 }
250
251 pub fn get_config_mut(&mut self) -> &mut AppConf {
252 &mut self.config
253 }
254
255 pub fn has_clipboard(&self, id: &ClipboardID) -> bool {
256 self.clipboard.contains_key(id)
257 }
258
259 pub fn has_job(&self, id: &JobID) -> bool {
260 self.jobs.contains_key(id)
261 }
262
263 pub fn push_job_result(&mut self, id: &JobID, job: Job) {
264 self.jobs.insert(id.clone(), job);
265 }
266
267 pub fn push_to_clipboard(&mut self, data: TextMap) -> ClipboardID {
268 let clipboard_id = rumtk_generate_id!().to_rumstring();
269 self.clipboard.insert(clipboard_id.clone(), data);
270 clipboard_id
271 }
272
273 pub fn request_clipboard_slice(&mut self) -> ClipboardID {
274 let clipboard_id = rumtk_generate_id!().to_rumstring();
275 self.clipboard
276 .insert(clipboard_id.clone(), TextMap::default());
277 clipboard_id
278 }
279
280 pub fn pop_job(&mut self, id: &RUMID) -> Option<Job> {
281 self.jobs.remove(id)
282 }
283
284 pub fn pop_clipboard(&mut self, id: &ClipboardID) -> Option<TextMap> {
285 self.clipboard.shift_remove(id)
286 }
287}
288
289impl From<AppConf> for AppState {
290 fn from(config: AppConf) -> Self {
291 AppState {
292 config,
293 clipboard: NestedTextMap::default(),
294 jobs: RUMHashMap::default(),
295 }
296 }
297}
298
299pub type RouterAppState = State<SharedAppState>;
300
301#[macro_export]
344macro_rules! rumtk_web_load_conf {
345 ( $args:expr ) => {{
346 use $crate::defaults::{DEFAULT_APP_CONFIG};
347 rumtk_web_load_conf!($args, DEFAULT_APP_CONFIG)
348 }};
349 ( $args:expr, $path:expr ) => {{
350 use rumtk_core::rumtk_deserialize;
351 use rumtk_core::strings::RUMStringConversions;
352 use rumtk_core::types::RUMHashMap;
353 use $crate::AppConf;
354 use std::fs;
355
356 use $crate::rumtk_web_save_conf;
357 use $crate::utils::{AppState, TextMap};
358
359 let json = match fs::read_to_string($path) {
360 Ok(json) => json,
361 Err(err) => rumtk_web_save_conf!($path),
362 };
363
364 let mut conf: AppConf = match rumtk_deserialize!(json) {
365 Ok(conf) => conf,
366 Err(err) => panic!(
367 "The App config file in {} does not meet the expected structure. \
368 See the documentation for more information. Error: {}\n{}",
369 $path, err, json
370 ),
371 };
372 conf.update_site_info(
373 $args.title.clone(),
374 $args.description.clone(),
375 $args.company.clone(),
376 $args.copyright.clone(),
377 );
378 AppState::from_safe(conf)
379 }};
380}
381
382#[macro_export]
414macro_rules! rumtk_web_save_conf {
415 ( ) => {{
416 $crate::utils::defaults::DEFAULT_APP_CONFIG;
417 rumtk_web_save_conf!(DEFAULT_APP_CONFIG)
418 }};
419 ( $path:expr ) => {{
420 use rumtk_core::rumtk_serialize;
421 use rumtk_core::strings::RUMStringConversions;
422 use std::fs;
423 use $crate::utils::AppConf;
424
425 let json = rumtk_serialize!(AppConf::default(), true).unwrap_or_default();
426 fs::write($path, &json);
427 json
428 }};
429}
430
431#[macro_export]
436macro_rules! rumtk_web_get_config_string {
437 ( $conf:expr, $item:expr ) => {{
438 use $crate::rumtk_web_get_config;
439 use $crate::AppConf;
440 rumtk_web_get_config!($conf).get_text($item)
441 }};
442}
443
444#[macro_export]
450macro_rules! rumtk_web_get_config_section {
451 ( $conf:expr, $item:expr ) => {{
452 use $crate::rumtk_web_get_config;
453 use $crate::AppConf;
454 rumtk_web_get_config!($conf).get_section($item)
455 }};
456}
457
458#[macro_export]
476macro_rules! rumtk_web_get_pipelines {
477 ( $conf:expr ) => {{
478 use $crate::rumtk_web_get_config;
479 use $crate::AppConf;
480 rumtk_web_get_config!($conf).get_pipelines()
481 }};
482}
483
484#[macro_export]
502macro_rules! rumtk_web_get_config {
503 ( $state:expr ) => {{
504 use rumtk_core::{rumtk_lock_read};
505 rumtk_lock_read!($state.clone()).get_config()
506 }};
507}
508
509#[macro_export]
531macro_rules! rumtk_web_set_config {
532 ( $state:expr ) => {{
533 use rumtk_core::rumtk_lock_write;
534 rumtk_lock_write!($state.clone()).get_config_mut()
535 }};
536}
537
538#[macro_export]
557macro_rules! rumtk_web_modify_state {
558 ( $state:expr ) => {{
559 use rumtk_core::rumtk_lock_write;
560 rumtk_lock_write!($state.clone())
561 }};
562}
563
564pub const DEFAULT_TEXT: fn() -> RUMString = || RUMString::default();
568pub const DEFAULT_TEXTMAP: fn() -> TextMap = || TextMap::default();
569pub const DEFAULT_NESTEDTEXTMAP: fn() -> NestedTextMap = || NestedTextMap::default();
570pub const DEFAULT_NESTEDNESTEDTEXTMAP: fn() -> NestedNestedTextMap =
571 || NestedNestedTextMap::default();