use crate::revision::{FieldRevision, FieldTypeRevision}; use indexmap::IndexMap; use nanoid::nanoid; use serde::{Deserialize, Serialize}; use serde_repr::*; use std::collections::HashMap; use std::fmt::Debug; use std::sync::Arc; pub fn gen_grid_filter_id() -> String { nanoid!(6) } pub fn gen_grid_group_id() -> String { nanoid!(6) } pub fn gen_grid_sort_id() -> String { nanoid!(6) } pub type FilterConfiguration = Configuration; pub type FilterConfigurationsByFieldId = HashMap>>; // pub type GroupConfiguration = Configuration; pub type GroupConfigurationsByFieldId = HashMap>>; // pub type SortConfiguration = Configuration; pub type SortConfigurationsByFieldId = HashMap>>; #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] pub struct SettingRevision { pub layout: LayoutRevision, pub filters: FilterConfiguration, #[serde(default)] pub groups: GroupConfiguration, #[serde(skip)] pub sorts: SortConfiguration, } #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum LayoutRevision { Table = 0, Board = 1, } impl ToString for LayoutRevision { fn to_string(&self) -> String { let layout_rev = self.clone() as u8; layout_rev.to_string() } } impl std::default::Default for LayoutRevision { fn default() -> Self { LayoutRevision::Table } } impl SettingRevision { pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { self.groups.get_all_objects(field_revs) } pub fn get_groups( &self, field_id: &str, field_type_rev: &FieldTypeRevision, ) -> Option>> { self.groups.get_objects(field_id, field_type_rev) } pub fn get_mut_groups( &mut self, field_id: &str, field_type: &FieldTypeRevision, ) -> Option<&mut Vec>> { self.groups.get_mut_objects(field_id, field_type) } pub fn insert_group( &mut self, field_id: &str, field_type: &FieldTypeRevision, group_rev: GroupConfigurationRevision, ) { // only one group can be set self.groups.remove_all(); self.groups.insert_object(field_id, field_type, group_rev); } pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { self.filters.get_all_objects(field_revs) } pub fn get_filters( &self, field_id: &str, field_type_rev: &FieldTypeRevision, ) -> Option>> { self.filters.get_objects(field_id, field_type_rev) } pub fn get_mut_filters( &mut self, field_id: &str, field_type: &FieldTypeRevision, ) -> Option<&mut Vec>> { self.filters.get_mut_objects(field_id, field_type) } pub fn insert_filter( &mut self, field_id: &str, field_type: &FieldTypeRevision, filter_rev: FilterConfigurationRevision, ) { self.filters.insert_object(field_id, field_type, filter_rev); } pub fn get_all_sort(&self) -> Option { None } } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct SortConfigurationRevision { pub id: String, pub field_id: Option, } #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[serde(transparent)] pub struct Configuration where T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, { /// Key: field_id /// Value: this value contains key/value. /// Key: FieldType, /// Value: the corresponding objects. #[serde(with = "indexmap::serde_seq")] inner: IndexMap>, } impl Configuration where T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, { pub fn get_mut_objects(&mut self, field_id: &str, field_type: &FieldTypeRevision) -> Option<&mut Vec>> { let value = self .inner .get_mut(field_id) .and_then(|object_rev_map| object_rev_map.get_mut(field_type)); if value.is_none() { tracing::warn!("Can't find the {:?} with", std::any::type_name::()); } value } pub fn get_objects(&self, field_id: &str, field_type_rev: &FieldTypeRevision) -> Option>> { self.inner .get(field_id) .and_then(|object_rev_map| object_rev_map.get(field_type_rev)) .cloned() } pub fn get_all_objects(&self, field_revs: &[Arc]) -> Option>>> { // Get the objects according to the FieldType, so we need iterate the field_revs. let objects_by_field_id = field_revs .iter() .flat_map(|field_rev| { let field_type = &field_rev.ty; let field_id = &field_rev.id; let object_rev_map = self.inner.get(field_id)?; let objects: Vec> = object_rev_map.get(field_type)?.clone(); Some((field_rev.id.clone(), objects)) }) .collect::>>>(); Some(objects_by_field_id) } pub fn insert_object(&mut self, field_id: &str, field_type: &FieldTypeRevision, object: T) { let object_rev_map = self .inner .entry(field_id.to_string()) .or_insert_with(ObjectIndexMap::::new); object_rev_map .entry(field_type.to_owned()) .or_insert_with(Vec::new) .push(Arc::new(object)) } pub fn remove_all(&mut self) { self.inner.clear() } } #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[serde(transparent)] pub struct ObjectIndexMap where T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, { #[serde(with = "indexmap::serde_seq")] pub object_by_field_type: IndexMap>>, } impl ObjectIndexMap where T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, { pub fn new() -> Self { ObjectIndexMap::default() } } impl std::ops::Deref for ObjectIndexMap where T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, { type Target = IndexMap>>; fn deref(&self) -> &Self::Target { &self.object_by_field_type } } impl std::ops::DerefMut for ObjectIndexMap where T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.object_by_field_type } } pub trait GroupConfigurationSerde { fn from_configuration(s: &str) -> Result; } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GroupConfigurationRevision { pub id: String, pub field_id: String, pub field_type_rev: FieldTypeRevision, pub content: String, } impl GroupConfigurationRevision { pub fn new(field_id: String, field_type: FieldTypeRevision, content: T) -> Result where T: serde::Serialize, { let content = serde_json::to_string(&content)?; Ok(Self { id: gen_grid_group_id(), field_id, field_type_rev: field_type, content, }) } } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] pub struct FilterConfigurationRevision { pub id: String, pub field_id: String, pub condition: u8, pub content: Option, }