Ver código fonte

chore: add grid filter test

appflowy 2 anos atrás
pai
commit
60675afd1d

+ 1 - 1
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -11,7 +11,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
         .event(GridEvent::GetGridData, get_grid_data_handler)
         .event(GridEvent::GetGridBlocks, get_grid_blocks_handler)
         .event(GridEvent::GetGridSetting, get_grid_setting_handler)
-        .event(GridEvent::UpdateGridSetting, get_grid_setting_handler)
+        .event(GridEvent::UpdateGridSetting, update_grid_setting_handler)
         // Field
         .event(GridEvent::GetFields, get_fields_handler)
         .event(GridEvent::UpdateField, update_field_handler)

+ 4 - 0
frontend/rust-lib/flowy-grid/tests/grid/script.rs

@@ -261,6 +261,10 @@ impl GridEditorTest {
             .unwrap()
             .row_revs
     }
+
+    pub(crate) async fn get_grid_setting(&self) -> GridSettingRevision {
+        self.editor.get_grid_setting().await.unwrap()
+    }
 }
 
 pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {

+ 28 - 0
frontend/rust-lib/flowy-grid/tests/grid/setting_test.rs

@@ -1 +1,29 @@
+use crate::grid::script::EditorScript::*;
+use crate::grid::script::*;
+use flowy_grid_data_model::entities::{
+    CreateGridFilterParams, CreateGridFilterPayload, GridLayoutType, GridSettingChangesetParams,
+};
+use flowy_grid_data_model::revision::GridSettingRevision;
 
+#[tokio::test]
+async fn grid_setting_create_filter_test() {
+    let test = GridEditorTest::new().await;
+
+    let layout_type = GridLayoutType::Table;
+    let field_rev = test.field_revs.last().unwrap();
+    let create_params: CreateGridFilterParams = CreateGridFilterPayload {
+        field_id: field_rev.id.clone(),
+        field_type: field_rev.field_type.clone(),
+    }
+    .try_into()
+    .unwrap();
+    let params = GridSettingChangesetParams::from_insert_filter(&test.grid_id, layout_type, create_params);
+
+    let scripts = vec![UpdateGridSetting { params }];
+    GridEditorTest::new().await.run_scripts(scripts).await;
+
+    // let mut expected_grid_setting = test.get_grid_setting().await;
+}
+
+#[tokio::test]
+async fn grid_setting_sort_test() {}

+ 154 - 0
shared-lib/flowy-grid-data-model/src/entities/grid_filter.rs

@@ -0,0 +1,154 @@
+use crate::parser::NotEmptyStr;
+use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
+use flowy_error_code::ErrorCode;
+
+use crate::entities::FieldType;
+use crate::revision::{
+    FilterInfoRevision, GridFilterRevision, NumberFilterConditionRevision, TextFilterConditionRevision,
+};
+use std::convert::TryInto;
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridFilter {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2)]
+    pub field_id: String,
+
+    #[pb(index = 3)]
+    pub info: FilterInfo,
+}
+
+impl std::convert::From<GridFilterRevision> for GridFilter {
+    fn from(rev: GridFilterRevision) -> Self {
+        GridFilter {
+            id: rev.id,
+            field_id: rev.field_id,
+            info: rev.info.into(),
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct FilterInfo {
+    #[pb(index = 1, one_of)]
+    pub condition: Option<String>,
+
+    #[pb(index = 2, one_of)]
+    pub content: Option<String>,
+}
+
+impl std::convert::From<FilterInfoRevision> for FilterInfo {
+    fn from(rev: FilterInfoRevision) -> Self {
+        FilterInfo {
+            condition: rev.condition,
+            content: rev.content,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct RepeatedGridFilter {
+    #[pb(index = 1)]
+    pub items: Vec<GridFilter>,
+}
+
+impl std::convert::From<Vec<GridFilterRevision>> for RepeatedGridFilter {
+    fn from(revs: Vec<GridFilterRevision>) -> Self {
+        RepeatedGridFilter {
+            items: revs.into_iter().map(|rev| rev.into()).collect(),
+        }
+    }
+}
+
+impl std::convert::From<Vec<GridFilter>> for RepeatedGridFilter {
+    fn from(items: Vec<GridFilter>) -> Self {
+        Self { items }
+    }
+}
+
+#[derive(ProtoBuf, Debug, Default, Clone)]
+pub struct CreateGridFilterPayload {
+    #[pb(index = 1)]
+    pub field_id: String,
+
+    #[pb(index = 2)]
+    pub field_type: FieldType,
+}
+
+pub struct CreateGridFilterParams {
+    pub field_id: String,
+    pub field_type: FieldType,
+}
+
+impl TryInto<CreateGridFilterParams> for CreateGridFilterPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateGridFilterParams, Self::Error> {
+        let field_id = NotEmptyStr::parse(self.field_id)
+            .map_err(|_| ErrorCode::FieldIdIsEmpty)?
+            .0;
+
+        Ok(CreateGridFilterParams {
+            field_id,
+            field_type: self.field_type,
+        })
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
+#[repr(u8)]
+pub enum TextFilterCondition {
+    Is = 0,
+    IsNot = 1,
+    Contains = 2,
+    DoesNotContain = 3,
+    StartsWith = 4,
+    EndsWith = 5,
+    TextIsEmpty = 6,
+    TextIsNotEmpty = 7,
+}
+
+impl std::convert::From<TextFilterConditionRevision> for TextFilterCondition {
+    fn from(rev: TextFilterConditionRevision) -> Self {
+        match rev {
+            TextFilterConditionRevision::Is => TextFilterCondition::Is,
+            TextFilterConditionRevision::IsNot => TextFilterCondition::IsNot,
+            TextFilterConditionRevision::Contains => TextFilterCondition::Contains,
+            TextFilterConditionRevision::DoesNotContain => TextFilterCondition::DoesNotContain,
+            TextFilterConditionRevision::StartsWith => TextFilterCondition::StartsWith,
+            TextFilterConditionRevision::EndsWith => TextFilterCondition::EndsWith,
+            TextFilterConditionRevision::IsEmpty => TextFilterCondition::TextIsEmpty,
+            TextFilterConditionRevision::IsNotEmpty => TextFilterCondition::TextIsNotEmpty,
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
+#[repr(u8)]
+pub enum NumberFilterCondition {
+    Equal = 0,
+    NotEqual = 1,
+    GreaterThan = 2,
+    LessThan = 3,
+    GreaterThanOrEqualTo = 4,
+    LessThanOrEqualTo = 5,
+    NumberIsEmpty = 6,
+    NumberIsNotEmpty = 7,
+}
+
+impl std::convert::From<NumberFilterConditionRevision> for NumberFilterCondition {
+    fn from(rev: NumberFilterConditionRevision) -> Self {
+        match rev {
+            NumberFilterConditionRevision::Equal => NumberFilterCondition::Equal,
+            NumberFilterConditionRevision::NotEqual => NumberFilterCondition::NotEqual,
+            NumberFilterConditionRevision::GreaterThan => NumberFilterCondition::GreaterThan,
+            NumberFilterConditionRevision::LessThan => NumberFilterCondition::LessThan,
+            NumberFilterConditionRevision::GreaterThanOrEqualTo => NumberFilterCondition::GreaterThan,
+            NumberFilterConditionRevision::LessThanOrEqualTo => NumberFilterCondition::LessThanOrEqualTo,
+            NumberFilterConditionRevision::IsEmpty => NumberFilterCondition::NumberIsEmpty,
+            NumberFilterConditionRevision::IsNotEmpty => NumberFilterCondition::NumberIsNotEmpty,
+        }
+    }
+}

+ 80 - 0
shared-lib/flowy-grid-data-model/src/entities/grid_group.rs

@@ -0,0 +1,80 @@
+use crate::parser::NotEmptyStr;
+use flowy_derive::ProtoBuf;
+use flowy_error_code::ErrorCode;
+
+use crate::revision::GridGroupRevision;
+use std::convert::TryInto;
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridGroup {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2, one_of)]
+    pub group_field_id: Option<String>,
+
+    #[pb(index = 3, one_of)]
+    pub sub_group_field_id: Option<String>,
+}
+
+impl std::convert::From<GridGroupRevision> for GridGroup {
+    fn from(rev: GridGroupRevision) -> Self {
+        GridGroup {
+            id: rev.id,
+            group_field_id: rev.field_id,
+            sub_group_field_id: rev.sub_field_id,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct RepeatedGridGroup {
+    #[pb(index = 1)]
+    pub items: Vec<GridGroup>,
+}
+
+impl std::convert::From<Vec<GridGroup>> for RepeatedGridGroup {
+    fn from(items: Vec<GridGroup>) -> Self {
+        Self { items }
+    }
+}
+
+impl std::convert::From<Vec<GridGroupRevision>> for RepeatedGridGroup {
+    fn from(revs: Vec<GridGroupRevision>) -> Self {
+        RepeatedGridGroup {
+            items: revs.into_iter().map(|rev| rev.into()).collect(),
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct CreateGridGroupPayload {
+    #[pb(index = 1, one_of)]
+    pub field_id: Option<String>,
+
+    #[pb(index = 2, one_of)]
+    pub sub_field_id: Option<String>,
+}
+
+pub struct CreateGridGroupParams {
+    pub field_id: Option<String>,
+    pub sub_field_id: Option<String>,
+}
+
+impl TryInto<CreateGridGroupParams> for CreateGridGroupPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateGridGroupParams, Self::Error> {
+        let field_id = match self.field_id {
+            None => None,
+            Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+        };
+
+        let sub_field_id = match self.sub_field_id {
+            None => None,
+            Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+        };
+
+        Ok(CreateGridGroupParams { field_id, sub_field_id })
+    }
+}

+ 124 - 36
shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs

@@ -1,4 +1,9 @@
-use crate::parser::{NotEmptyStr, ViewFilterParser, ViewGroupParser, ViewSortParser};
+use crate::entities::{
+    CreateGridFilterParams, CreateGridFilterPayload, CreateGridGroupParams, CreateGridGroupPayload,
+    CreateGridSortParams, CreateGridSortPayload, RepeatedGridFilter, RepeatedGridGroup, RepeatedGridSort,
+};
+use crate::parser::NotEmptyStr;
+use crate::revision::{GridLayoutRevision, GridSettingRevision};
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error_code::ErrorCode;
 use std::collections::HashMap;
@@ -7,13 +12,41 @@ use std::convert::TryInto;
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
 pub struct GridSetting {
     #[pb(index = 1)]
-    pub filter: HashMap<String, GridFilter>,
+    pub filters_by_layout_ty: HashMap<String, RepeatedGridFilter>,
 
     #[pb(index = 2)]
-    pub group: HashMap<String, GridGroup>,
+    pub groups_by_layout_ty: HashMap<String, RepeatedGridGroup>,
 
     #[pb(index = 3)]
-    pub sort: HashMap<String, GridSort>,
+    pub sorts_by_layout_ty: HashMap<String, RepeatedGridSort>,
+}
+
+impl std::convert::From<GridSettingRevision> for GridSetting {
+    fn from(rev: GridSettingRevision) -> Self {
+        let filters_by_layout_ty: HashMap<String, RepeatedGridFilter> = rev
+            .filter
+            .into_iter()
+            .map(|(layout_rev, filter_revs)| (layout_rev.to_string(), filter_revs.into()))
+            .collect();
+
+        let groups_by_layout_ty: HashMap<String, RepeatedGridGroup> = rev
+            .group
+            .into_iter()
+            .map(|(layout_rev, group_revs)| (layout_rev.to_string(), group_revs.into()))
+            .collect();
+
+        let sorts_by_layout_ty: HashMap<String, RepeatedGridSort> = rev
+            .sort
+            .into_iter()
+            .map(|(layout_rev, sort_revs)| (layout_rev.to_string(), sort_revs.into()))
+            .collect();
+
+        GridSetting {
+            filters_by_layout_ty,
+            groups_by_layout_ty,
+            sorts_by_layout_ty,
+        }
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
@@ -29,25 +62,22 @@ impl std::default::Default for GridLayoutType {
     }
 }
 
-#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
-pub struct GridFilter {
-    #[pb(index = 1, one_of)]
-    pub field_id: Option<String>,
-}
-
-#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
-pub struct GridGroup {
-    #[pb(index = 1, one_of)]
-    pub group_field_id: Option<String>,
-
-    #[pb(index = 2, one_of)]
-    pub sub_group_field_id: Option<String>,
+impl std::convert::From<GridLayoutRevision> for GridLayoutType {
+    fn from(rev: GridLayoutRevision) -> Self {
+        match rev {
+            GridLayoutRevision::Table => GridLayoutType::Table,
+            GridLayoutRevision::Board => GridLayoutType::Board,
+        }
+    }
 }
 
-#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
-pub struct GridSort {
-    #[pb(index = 1, one_of)]
-    pub field_id: Option<String>,
+impl std::convert::From<GridLayoutType> for GridLayoutRevision {
+    fn from(layout: GridLayoutType) -> Self {
+        match layout {
+            GridLayoutType::Table => GridLayoutRevision::Table,
+            GridLayoutType::Board => GridLayoutRevision::Board,
+        }
+    }
 }
 
 #[derive(Default, ProtoBuf)]
@@ -59,21 +89,61 @@ pub struct GridSettingChangesetPayload {
     pub layout_type: GridLayoutType,
 
     #[pb(index = 3, one_of)]
-    pub filter: Option<GridFilter>,
+    pub insert_filter: Option<CreateGridFilterPayload>,
 
     #[pb(index = 4, one_of)]
-    pub group: Option<GridGroup>,
+    pub delete_filter: Option<String>,
 
     #[pb(index = 5, one_of)]
-    pub sort: Option<GridSort>,
+    pub insert_group: Option<CreateGridGroupPayload>,
+
+    #[pb(index = 6, one_of)]
+    pub delete_group: Option<String>,
+
+    #[pb(index = 7, one_of)]
+    pub insert_sort: Option<CreateGridSortPayload>,
+
+    #[pb(index = 8, one_of)]
+    pub delete_sort: Option<String>,
 }
 
 pub struct GridSettingChangesetParams {
     pub grid_id: String,
     pub layout_type: GridLayoutType,
-    pub filter: Option<GridFilter>,
-    pub group: Option<GridGroup>,
-    pub sort: Option<GridSort>,
+    pub insert_filter: Option<CreateGridFilterParams>,
+    pub delete_filter: Option<String>,
+    pub insert_group: Option<CreateGridGroupParams>,
+    pub delete_group: Option<String>,
+    pub insert_sort: Option<CreateGridSortParams>,
+    pub delete_sort: Option<String>,
+}
+
+impl GridSettingChangesetParams {
+    pub fn from_insert_filter(grid_id: &str, layout_type: GridLayoutType, params: CreateGridFilterParams) -> Self {
+        Self {
+            grid_id: grid_id.to_owned(),
+            layout_type,
+            insert_filter: Some(params),
+            delete_filter: None,
+            insert_group: None,
+            delete_group: None,
+            insert_sort: None,
+            delete_sort: None,
+        }
+    }
+
+    pub fn from_delete_filter(grid_id: &str, layout_type: GridLayoutType, filter_id: &str) -> Self {
+        Self {
+            grid_id: grid_id.to_owned(),
+            layout_type,
+            insert_filter: None,
+            delete_filter: Some(filter_id.to_string()),
+            insert_group: None,
+            delete_group: None,
+            insert_sort: None,
+            delete_sort: None,
+        }
+    }
 }
 
 impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayload {
@@ -84,27 +154,45 @@ impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayload {
             .map_err(|_| ErrorCode::FieldIdIsEmpty)?
             .0;
 
-        let filter = match self.filter {
+        let insert_filter = match self.insert_filter {
+            None => None,
+            Some(payload) => Some(payload.try_into()?),
+        };
+
+        let delete_filter = match self.delete_filter {
+            None => None,
+            Some(filter_id) => Some(NotEmptyStr::parse(filter_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+        };
+
+        let insert_group = match self.insert_group {
+            Some(payload) => Some(payload.try_into()?),
+            None => None,
+        };
+
+        let delete_group = match self.delete_group {
             None => None,
-            Some(filter) => Some(ViewFilterParser::parse(filter)?),
+            Some(filter_id) => Some(NotEmptyStr::parse(filter_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
         };
 
-        let group = match self.group {
+        let insert_sort = match self.insert_sort {
             None => None,
-            Some(group) => Some(ViewGroupParser::parse(group)?),
+            Some(payload) => Some(payload.try_into()?),
         };
 
-        let sort = match self.sort {
+        let delete_sort = match self.delete_sort {
             None => None,
-            Some(sort) => Some(ViewSortParser::parse(sort)?),
+            Some(filter_id) => Some(NotEmptyStr::parse(filter_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
         };
 
         Ok(GridSettingChangesetParams {
             grid_id: view_id,
             layout_type: self.layout_type,
-            filter,
-            group,
-            sort,
+            insert_filter,
+            delete_filter,
+            insert_group,
+            delete_group,
+            insert_sort,
+            delete_sort,
         })
     }
 }

+ 67 - 0
shared-lib/flowy-grid-data-model/src/entities/grid_sort.rs

@@ -0,0 +1,67 @@
+use crate::parser::NotEmptyStr;
+use flowy_derive::ProtoBuf;
+use flowy_error_code::ErrorCode;
+
+use crate::revision::GridSortRevision;
+use std::convert::TryInto;
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridSort {
+    #[pb(index = 1)]
+    pub id: String,
+
+    #[pb(index = 2, one_of)]
+    pub field_id: Option<String>,
+}
+
+impl std::convert::From<GridSortRevision> for GridSort {
+    fn from(rev: GridSortRevision) -> Self {
+        GridSort {
+            id: rev.id,
+            field_id: rev.field_id,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct RepeatedGridSort {
+    #[pb(index = 1)]
+    pub items: Vec<GridSort>,
+}
+
+impl std::convert::From<Vec<GridSortRevision>> for RepeatedGridSort {
+    fn from(revs: Vec<GridSortRevision>) -> Self {
+        RepeatedGridSort {
+            items: revs.into_iter().map(|rev| rev.into()).collect(),
+        }
+    }
+}
+
+impl std::convert::From<Vec<GridSort>> for RepeatedGridSort {
+    fn from(items: Vec<GridSort>) -> Self {
+        Self { items }
+    }
+}
+
+#[derive(ProtoBuf, Debug, Default, Clone)]
+pub struct CreateGridSortPayload {
+    #[pb(index = 1, one_of)]
+    pub field_id: Option<String>,
+}
+
+pub struct CreateGridSortParams {
+    pub field_id: Option<String>,
+}
+
+impl TryInto<CreateGridSortParams> for CreateGridSortPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateGridSortParams, Self::Error> {
+        let field_id = match self.field_id {
+            None => None,
+            Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+        };
+
+        Ok(CreateGridSortParams { field_id })
+    }
+}

+ 6 - 0
shared-lib/flowy-grid-data-model/src/entities/mod.rs

@@ -1,7 +1,13 @@
 mod field;
 mod grid;
+mod grid_filter;
+mod grid_group;
 mod grid_setting;
+mod grid_sort;
 
 pub use field::*;
 pub use grid::*;
+pub use grid_filter::*;
+pub use grid_group::*;
 pub use grid_setting::*;
+pub use grid_sort::*;

+ 0 - 58
shared-lib/flowy-grid-data-model/src/parser/grid_info_parser.rs

@@ -1,58 +0,0 @@
-use crate::entities::{GridFilter, GridGroup, GridSort};
-use crate::parser::NotEmptyStr;
-use flowy_error_code::ErrorCode;
-
-pub struct ViewFilterParser(pub GridFilter);
-
-impl ViewFilterParser {
-    pub fn parse(value: GridFilter) -> Result<GridFilter, ErrorCode> {
-        let field_id = match value.field_id {
-            None => None,
-            Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
-        };
-
-        Ok(GridFilter { field_id })
-    }
-}
-
-pub struct ViewGroupParser(pub GridGroup);
-
-impl ViewGroupParser {
-    pub fn parse(value: GridGroup) -> Result<GridGroup, ErrorCode> {
-        let group_field_id = match value.group_field_id {
-            None => None,
-            Some(group_field_id) => Some(
-                NotEmptyStr::parse(group_field_id)
-                    .map_err(|_| ErrorCode::FieldIdIsEmpty)?
-                    .0,
-            ),
-        };
-
-        let sub_group_field_id = match value.sub_group_field_id {
-            None => None,
-            Some(sub_group_field_id) => Some(
-                NotEmptyStr::parse(sub_group_field_id)
-                    .map_err(|_| ErrorCode::FieldIdIsEmpty)?
-                    .0,
-            ),
-        };
-
-        Ok(GridGroup {
-            group_field_id,
-            sub_group_field_id,
-        })
-    }
-}
-
-pub struct ViewSortParser(pub GridSort);
-
-impl ViewSortParser {
-    pub fn parse(value: GridSort) -> Result<GridSort, ErrorCode> {
-        let field_id = match value.field_id {
-            None => None,
-            Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
-        };
-
-        Ok(GridSort { field_id })
-    }
-}

+ 0 - 3
shared-lib/flowy-grid-data-model/src/parser/mod.rs

@@ -1,5 +1,2 @@
-mod grid_info_parser;
 mod str_parser;
-
-pub use grid_info_parser::*;
 pub use str_parser::*;

+ 0 - 2
shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs

@@ -31,8 +31,6 @@ pub struct GridRevision {
     pub grid_id: String,
     pub fields: Vec<FieldRevision>,
     pub blocks: Vec<GridBlockRevision>,
-
-    #[serde(skip)]
     pub setting: GridSettingRevision,
 }
 

+ 74 - 59
shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs

@@ -1,19 +1,31 @@
-use crate::entities::{GridFilter, GridGroup, GridLayoutType, GridSetting, GridSort};
 use indexmap::IndexMap;
+use nanoid::nanoid;
 use serde::{Deserialize, Serialize};
 use serde_repr::*;
-use std::collections::HashMap;
+use std::str::FromStr;
+
+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)
+}
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
 pub struct GridSettingRevision {
     #[serde(with = "indexmap::serde_seq")]
-    pub filter: IndexMap<GridLayoutRevision, GridFilterRevision>,
+    pub filter: IndexMap<GridLayoutRevision, Vec<GridFilterRevision>>,
 
-    #[serde(with = "indexmap::serde_seq")]
-    pub group: IndexMap<GridLayoutRevision, GridGroupRevision>,
+    #[serde(skip, with = "indexmap::serde_seq")]
+    pub group: IndexMap<GridLayoutRevision, Vec<GridGroupRevision>>,
 
-    #[serde(with = "indexmap::serde_seq")]
-    pub sort: IndexMap<GridLayoutRevision, GridSortRevision>,
+    #[serde(skip, with = "indexmap::serde_seq")]
+    pub sort: IndexMap<GridLayoutRevision, Vec<GridSortRevision>>,
 }
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
@@ -36,81 +48,84 @@ impl std::default::Default for GridLayoutRevision {
     }
 }
 
-impl std::convert::From<GridLayoutRevision> for GridLayoutType {
-    fn from(rev: GridLayoutRevision) -> Self {
-        match rev {
-            GridLayoutRevision::Table => GridLayoutType::Table,
-            GridLayoutRevision::Board => GridLayoutType::Board,
-        }
-    }
-}
-
-impl std::convert::From<GridLayoutType> for GridLayoutRevision {
-    fn from(layout: GridLayoutType) -> Self {
-        match layout {
-            GridLayoutType::Table => GridLayoutRevision::Table,
-            GridLayoutType::Board => GridLayoutRevision::Board,
-        }
-    }
-}
-
 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
 pub struct GridFilterRevision {
-    pub field_id: Option<String>,
+    pub id: String,
+    pub field_id: String,
+    pub info: FilterInfoRevision,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
 pub struct GridGroupRevision {
-    pub group_field_id: Option<String>,
-    pub sub_group_field_id: Option<String>,
+    pub id: String,
+    pub field_id: Option<String>,
+    pub sub_field_id: Option<String>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
 pub struct GridSortRevision {
+    pub id: String,
     pub field_id: Option<String>,
 }
 
-impl std::convert::From<GridFilterRevision> for GridFilter {
-    fn from(rev: GridFilterRevision) -> Self {
-        GridFilter { field_id: rev.field_id }
-    }
+#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
+pub struct FilterInfoRevision {
+    pub condition: Option<String>,
+    pub content: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
+#[repr(u8)]
+pub enum TextFilterConditionRevision {
+    Is = 0,
+    IsNot = 1,
+    Contains = 2,
+    DoesNotContain = 3,
+    StartsWith = 4,
+    EndsWith = 5,
+    IsEmpty = 6,
+    IsNotEmpty = 7,
 }
 
-impl std::convert::From<GridGroupRevision> for GridGroup {
-    fn from(rev: GridGroupRevision) -> Self {
-        GridGroup {
-            group_field_id: rev.group_field_id,
-            sub_group_field_id: rev.sub_group_field_id,
-        }
+impl ToString for TextFilterConditionRevision {
+    fn to_string(&self) -> String {
+        (self.clone() as u8).to_string()
     }
 }
 
-impl std::convert::From<GridSortRevision> for GridSort {
-    fn from(rev: GridSortRevision) -> Self {
-        GridSort { field_id: rev.field_id }
+impl FromStr for TextFilterConditionRevision {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let rev = serde_json::from_str(s)?;
+        Ok(rev)
     }
 }
 
-impl std::convert::From<GridSettingRevision> for GridSetting {
-    fn from(rev: GridSettingRevision) -> Self {
-        let filter: HashMap<String, GridFilter> = rev
-            .filter
-            .into_iter()
-            .map(|(layout_rev, filter_rev)| (layout_rev.to_string(), filter_rev.into()))
-            .collect();
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
+#[repr(u8)]
+pub enum NumberFilterConditionRevision {
+    Equal = 0,
+    NotEqual = 1,
+    GreaterThan = 2,
+    LessThan = 3,
+    GreaterThanOrEqualTo = 4,
+    LessThanOrEqualTo = 5,
+    IsEmpty = 6,
+    IsNotEmpty = 7,
+}
 
-        let group: HashMap<String, GridGroup> = rev
-            .group
-            .into_iter()
-            .map(|(layout_rev, group_rev)| (layout_rev.to_string(), group_rev.into()))
-            .collect();
+impl ToString for NumberFilterConditionRevision {
+    fn to_string(&self) -> String {
+        (self.clone() as u8).to_string()
+    }
+}
 
-        let sort: HashMap<String, GridSort> = rev
-            .sort
-            .into_iter()
-            .map(|(layout_rev, sort_rev)| (layout_rev.to_string(), sort_rev.into()))
-            .collect();
+impl FromStr for NumberFilterConditionRevision {
+    type Err = serde_json::Error;
 
-        GridSetting { filter, group, sort }
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let rev = serde_json::from_str(s)?;
+        Ok(rev)
     }
 }

+ 42 - 24
shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs

@@ -5,8 +5,9 @@ use bytes::Bytes;
 use flowy_grid_data_model::entities::{FieldChangesetParams, FieldOrder};
 use flowy_grid_data_model::entities::{FieldType, GridSettingChangesetParams};
 use flowy_grid_data_model::revision::{
-    gen_block_id, gen_grid_id, FieldRevision, GridBlockRevision, GridBlockRevisionChangeset, GridFilterRevision,
-    GridGroupRevision, GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision,
+    gen_block_id, gen_grid_filter_id, gen_grid_group_id, gen_grid_id, gen_grid_sort_id, FieldRevision,
+    GridBlockRevision, GridBlockRevisionChangeset, GridFilterRevision, GridGroupRevision, GridLayoutRevision,
+    GridRevision, GridSettingRevision, GridSortRevision,
 };
 use lib_infra::util::move_vec_element;
 use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
@@ -341,34 +342,51 @@ impl GridRevisionPad {
             let mut is_changed = None;
             let layout_rev: GridLayoutRevision = changeset.layout_type.into();
 
-            if let Some(filter) = changeset.filter {
-                grid_rev.setting.filter.insert(
-                    layout_rev.clone(),
-                    GridFilterRevision {
-                        field_id: filter.field_id,
-                    },
-                );
+            if let Some(params) = changeset.insert_filter {
+                let rev = GridFilterRevision {
+                    id: gen_grid_filter_id(),
+                    field_id: params.field_id,
+                    info: Default::default(),
+                };
+                grid_rev
+                    .setting
+                    .filter
+                    .entry(layout_rev.clone())
+                    .or_insert_with(std::vec::Vec::new)
+                    .push(rev);
+
                 is_changed = Some(())
             }
 
-            if let Some(group) = changeset.group {
-                grid_rev.setting.group.insert(
-                    layout_rev.clone(),
-                    GridGroupRevision {
-                        group_field_id: group.group_field_id,
-                        sub_group_field_id: group.sub_group_field_id,
-                    },
-                );
+            if let Some(params) = changeset.insert_group {
+                let rev = GridGroupRevision {
+                    id: gen_grid_group_id(),
+                    field_id: params.field_id,
+                    sub_field_id: params.sub_field_id,
+                };
+
+                grid_rev
+                    .setting
+                    .group
+                    .entry(layout_rev.clone())
+                    .or_insert_with(std::vec::Vec::new)
+                    .push(rev);
+
                 is_changed = Some(())
             }
 
-            if let Some(sort) = changeset.sort {
-                grid_rev.setting.sort.insert(
-                    layout_rev,
-                    GridSortRevision {
-                        field_id: sort.field_id,
-                    },
-                );
+            if let Some(sort) = changeset.insert_sort {
+                let rev = GridSortRevision {
+                    id: gen_grid_sort_id(),
+                    field_id: sort.field_id,
+                };
+
+                grid_rev
+                    .setting
+                    .sort
+                    .entry(layout_rev)
+                    .or_insert_with(std::vec::Vec::new)
+                    .push(rev);
                 is_changed = Some(())
             }