admin_gp/administrator/
actix_gp.rs

1//! Helper methods for the admin panel.
2
3use actix_web::web::BytesMut;
4use green_barrel::models::{
5    db_query_api::{commons::QCommons, paladins::QPaladins},
6    helpers::Meta,
7};
8use mongodb::bson::{doc, document::Document, oid::ObjectId};
9use serde::{de::DeserializeOwned, ser::Serialize};
10use serde_json::{json, Value};
11use std::error::Error;
12
13/// The output data for the admin panel.
14pub enum OutputDataAdmin<T> {
15    Instance(Option<T>),
16    EarlyResult(String),
17}
18
19/// Helper methods for the admin panel.
20pub trait Administrator: QCommons + QPaladins {
21    /// Json-line for admin panel.
22    /// ( converts a field type map to a list, in the order of the Model fields )
23    // *********************************************************************************************
24    ///
25    /// # Example:
26    ///
27    /// ```
28    /// let model_name = ModelName{...};
29    /// println!("{}", model_name.instance_to_json_for_admin()?);
30    /// ```
31    ///
32    fn instance_to_json_for_admin(&self) -> Result<String, Box<dyn Error>>
33    where
34        Self: Serialize + DeserializeOwned + Sized,
35    {
36        // Get cached Model data.
37        let (model_cache, _client_cache) = Self::get_cache_data_for_query()?;
38        // Get Model metadata.
39        let meta: Meta = model_cache.meta;
40        //
41        let model_json = self.self_to_json_val()?;
42        let mut field_type_list = Vec::<Value>::new();
43        let hash = self.hash();
44        // Get a list of fields type in the order of the model fields.
45        for field_name in meta.fields_name.iter() {
46            let mut field_type = model_json.get(field_name).unwrap().clone();
47            if field_name == "created_at" || field_name == "updated_at" {
48                *field_type.get_mut("input_type").unwrap() = json!("datetime");
49                *field_type.get_mut("is_hide").unwrap() = json!(false);
50            }
51            if field_name.contains("password") && !hash.is_empty() {
52                *field_type.get_mut("input_type").unwrap() = json!("hidden");
53                *field_type.get_mut("is_hide").unwrap() = json!(true);
54                *field_type.get_mut("value").unwrap() = json!("");
55            }
56            field_type_list.push(field_type);
57        }
58        //
59        Ok(serde_json::to_string(&field_type_list)?)
60    }
61
62    /// Get the model instance for actix-mango-panel.
63    // *********************************************************************************************
64    fn actix_instance_for_admin(
65        doc_hash: Option<&str>,
66        bytes: Option<&BytesMut>,
67        filter: Option<&Document>,
68        dyn_data: Option<Value>,
69    ) -> Result<OutputDataAdmin<Self>, Box<dyn Error>>
70    where
71        Self: Serialize + DeserializeOwned + Sized,
72    {
73        //
74        if let Some(doc_hash) = doc_hash {
75            // For - Get document
76            if doc_hash.is_empty() {
77                return Ok(OutputDataAdmin::EarlyResult(
78                    Self::model_to_json_for_admin()?
79                ));
80            }
81            let object_id = ObjectId::with_string(doc_hash);
82            if object_id.is_err() {
83                Err(format!(
84                    "Model: `{}` > \
85                        Method: `instance_for_admin` => \
86                        Invalid document hash.",
87                    Self::key()?
88                ))?
89            }
90            let object_id = object_id.unwrap();
91            let filter = doc! {"_id": object_id};
92            Ok(OutputDataAdmin::Instance(Self::find_one_to_instance(
93                filter, None,
94            )?))
95        } else if let Some(bytes) = bytes {
96            // For - Save document
97            Ok(OutputDataAdmin::Instance(Some(serde_json::from_slice::<
98                Self,
99            >(bytes)?)))
100        } else if let Some(filter) = filter {
101            // For - Delete document
102            Ok(OutputDataAdmin::Instance(Self::find_one_to_instance(
103                filter.clone(),
104                None,
105            )?))
106        } else if let Some(dyn_data) = dyn_data {
107            // Update dynamic field type data
108            Self::update_dyn_field(dyn_data)?;
109            Ok(OutputDataAdmin::EarlyResult(String::new()))
110        } else {
111            Err(format!(
112                "Model: `{}` > \
113                    Method: `instance_for_admin` => \
114                    No match on function arguments.",
115                Self::key()?
116            ))?
117        }
118    }
119
120    /// Get result for actix-mango-panel.
121    // *********************************************************************************************
122    fn actix_result_for_admin(
123        &mut self,
124        doc_hash: Option<&str>,
125        bytes: Option<&BytesMut>,
126        filter: Option<&Document>,
127    ) -> Result<String, Box<dyn Error>>
128    where
129        Self: Serialize + DeserializeOwned + Sized,
130    {
131        //
132        if doc_hash.is_some() {
133            // Get document
134            return self.instance_to_json_for_admin();
135        } else if bytes.is_some() {
136            // Save document
137            let output_data = self.save(None, None)?;
138            return output_data.json_for_admin();
139        } else if filter.is_some() {
140            // Delete document
141            let output_data = self.delete(None)?;
142            if !output_data.is_valid() {
143                return Ok(output_data.err_msg());
144            }
145        } else {
146            Err(format!(
147                "Model: `{}` > \
148                    Method: `result_for_admin` => \
149                    No match on function arguments.",
150                Self::key()?
151            ))?
152        }
153        //
154        Ok(String::new())
155    }
156}