actix_admin/
view_model.rs

1use async_trait::async_trait;
2use regex::Regex;
3use sea_orm::DatabaseConnection;
4use serde_derive::{Serialize, Deserialize};
5use std::collections::HashMap;
6use crate::{ActixAdminModel, SortOrder, model::ActixAdminModelFilterType};
7use actix_session::Session;
8use std::convert::From;
9use crate::ActixAdminError;
10pub struct ActixAdminViewModelParams {
11    pub page: Option<u64>,
12    pub entities_per_page: Option<u64>,
13    pub viewmodel_filter: Vec<ActixAdminViewModelFilter>,
14    pub search: String,
15    pub sort_by: String,
16    pub sort_order: SortOrder,
17    pub tenant_ref: Option<i32>
18}
19
20#[async_trait(?Send)]
21pub trait ActixAdminViewModelTrait {
22    async fn list(
23        db: &DatabaseConnection,
24        params: &ActixAdminViewModelParams
25    ) -> Result<(Option<u64>, Vec<ActixAdminModel>), ActixAdminError>;
26    
27    // TODO: Replace return value with proper Result Type containing Ok or Err
28    async fn create_entity(db: &DatabaseConnection, model: ActixAdminModel, tenant_ref: Option<i32>) -> Result<ActixAdminModel, ActixAdminError>;
29    async fn delete_entity(db: &DatabaseConnection, id: i32, tenant_ref: Option<i32>) -> Result<bool, ActixAdminError>;
30    async fn get_entity(db: &DatabaseConnection, id: i32, tenant_ref: Option<i32>) -> Result<ActixAdminModel, ActixAdminError>;
31    async fn edit_entity(db: &DatabaseConnection, id: i32, model: ActixAdminModel, tenant_ref: Option<i32>) -> Result<ActixAdminModel, ActixAdminError>;
32    async fn get_select_lists(db: &DatabaseConnection, tenant_ref: Option<i32>) -> Result<HashMap<String, Vec<(String, String)>>, ActixAdminError>;
33    async fn get_viewmodel_filter(db: &DatabaseConnection) -> HashMap<String, ActixAdminViewModelFilter>;
34    async fn validate_entity(model: &mut ActixAdminModel, db: &DatabaseConnection);
35
36    fn get_entity_name() -> String;
37}
38
39#[derive(Clone)]
40pub struct ActixAdminViewModel {
41    pub entity_name: String,
42    pub primary_key: String,
43    pub fields: &'static[ActixAdminViewModelField],
44    pub show_search: bool,
45    pub user_can_access: Option<fn(&Session) -> bool>,
46    pub default_show_aside: bool,
47    pub inline_edit: bool
48}
49
50#[derive(Clone, Debug, Serialize)]
51pub struct ActixAdminViewModelSerializable {
52    pub entity_name: String,
53    pub primary_key: String,
54    pub fields: &'static [ActixAdminViewModelField],
55    pub show_search: bool,
56    pub default_show_aside: bool,
57    pub inline_edit: bool
58}
59
60#[derive(Clone, Debug, Serialize)]
61pub struct ActixAdminViewModelFilter {
62    pub name: String,
63    pub value: Option<String>,
64    pub foreign_key: Option<String>,
65    pub values: Option<Vec<(String, String)>>,
66    pub filter_type: Option<ActixAdminModelFilterType>
67}
68
69// TODO: better alternative to serialize only specific fields for ActixAdminViewModel
70impl From<ActixAdminViewModel> for ActixAdminViewModelSerializable {
71    fn from(entity: ActixAdminViewModel) -> Self {
72        ActixAdminViewModelSerializable {
73            entity_name: entity.entity_name,
74            primary_key: entity.primary_key,
75            fields: entity.fields,
76            show_search: entity.show_search,
77            default_show_aside: entity.default_show_aside,
78            inline_edit: entity.inline_edit
79        }
80    }
81}
82
83#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
84pub enum ActixAdminViewModelFieldType {
85    Number,
86    Text,
87    TextArea,
88    Checkbox,
89    Date,
90    Time,
91    DateTime,
92    SelectList,
93    FileUpload
94}
95
96#[derive(Clone, Debug, Serialize, Deserialize)]
97pub struct ActixAdminViewModelField {
98    pub field_name: String,
99    pub html_input_type: String,
100    pub select_list: String,
101    pub dateformat: Option<String>,
102    pub is_option: bool,
103    pub field_type: ActixAdminViewModelFieldType,
104    pub list_sort_position: usize,
105    pub list_hide_column: bool,
106    #[serde(skip_serializing, skip_deserializing)]
107    pub list_regex_mask: Option<Regex>,
108    pub foreign_key: String,
109    pub is_tenant_ref: bool,
110    pub ceil: Option<u8>,
111    pub floor: Option<u8>,
112    pub shorten: Option<u16>,
113    pub use_tom_select_callback: bool
114}
115
116impl ActixAdminViewModelFieldType {
117    pub fn get_field_type(type_path: &str, select_list: String, is_textarea: bool, is_file_upload: bool) -> ActixAdminViewModelFieldType {
118        if !select_list.is_empty() {
119            return ActixAdminViewModelFieldType::SelectList;
120        }
121        if is_textarea {
122            return ActixAdminViewModelFieldType::TextArea;
123        }
124        if is_file_upload {
125            return ActixAdminViewModelFieldType::FileUpload;
126        }
127
128        match type_path {
129            "i32" => ActixAdminViewModelFieldType::Number,
130            "i64" => ActixAdminViewModelFieldType::Number,
131            "usize" => ActixAdminViewModelFieldType::Number,
132            "String"  => ActixAdminViewModelFieldType::Text,
133            "bool"  => ActixAdminViewModelFieldType::Checkbox,
134            "DateTimeWithTimeZone" => ActixAdminViewModelFieldType::DateTime,
135            "DateTime" => ActixAdminViewModelFieldType::DateTime,
136            "Date" => ActixAdminViewModelFieldType::Date,
137            _      => ActixAdminViewModelFieldType::Text
138        }
139    }
140}