Pārlūkot izejas kodu

chore: delete/create filter

appflowy 2 gadi atpakaļ
vecāks
revīzija
ead305ddda

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

@@ -27,7 +27,7 @@ pub(crate) async fn get_grid_setting_handler(
     let grid_id: GridId = data.into_inner();
     let editor = manager.open_grid(grid_id).await?;
     let grid_setting = editor.get_grid_setting().await?;
-    data_result(grid_setting.into())
+    data_result(grid_setting)
 }
 
 #[tracing::instrument(level = "trace", skip(data, manager), err)]

+ 13 - 4
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -438,10 +438,19 @@ impl GridRevisionEditor {
         })
     }
 
-    pub async fn get_grid_setting(&self) -> FlowyResult<GridSettingRevision> {
-        let pad_read_guard = self.grid_pad.read().await;
-        let grid_setting_rev = pad_read_guard.get_grid_setting_rev();
-        Ok(grid_setting_rev)
+    pub async fn get_grid_setting(&self) -> FlowyResult<GridSetting> {
+        let read_guard = self.grid_pad.read().await;
+        let grid_setting_rev = read_guard.get_grid_setting_rev();
+        Ok(grid_setting_rev.into())
+    }
+
+    pub async fn get_grid_filter(&self, layout_type: &GridLayoutType) -> FlowyResult<Vec<GridFilter>> {
+        let layout_type: GridLayoutRevision = layout_type.clone().into();
+        let read_guard = self.grid_pad.read().await;
+        match read_guard.get_grid_setting_rev().filter.get(&layout_type) {
+            Some(filter_revs) => Ok(filter_revs.iter().map(GridFilter::from).collect::<Vec<GridFilter>>()),
+            None => Ok(vec![]),
+        }
     }
 
     pub async fn update_grid_setting(&self, params: GridSettingChangesetParams) -> FlowyResult<()> {

+ 1 - 0
frontend/rust-lib/flowy-grid/src/services/mod.rs

@@ -6,3 +6,4 @@ pub mod field;
 pub mod grid_editor;
 pub mod persistence;
 pub mod row;
+pub mod setting;

+ 3 - 0
frontend/rust-lib/flowy-grid/src/services/setting/mod.rs

@@ -0,0 +1,3 @@
+mod setting_builder;
+
+pub use setting_builder::*;

+ 35 - 0
frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs

@@ -0,0 +1,35 @@
+use flowy_grid_data_model::entities::{CreateGridFilterParams, GridLayoutType, GridSettingChangesetParams};
+
+pub struct GridSettingChangesetBuilder {
+    params: GridSettingChangesetParams,
+}
+
+impl GridSettingChangesetBuilder {
+    pub fn new(grid_id: &str, layout_type: &GridLayoutType) -> Self {
+        let params = GridSettingChangesetParams {
+            grid_id: grid_id.to_string(),
+            layout_type: layout_type.clone(),
+            insert_filter: None,
+            delete_filter: None,
+            insert_group: None,
+            delete_group: None,
+            insert_sort: None,
+            delete_sort: None,
+        };
+        Self { params }
+    }
+
+    pub fn insert_filter(mut self, params: CreateGridFilterParams) -> Self {
+        self.params.insert_filter = Some(params);
+        self
+    }
+
+    pub fn delete_filter(mut self, filter_id: &str) -> Self {
+        self.params.delete_filter = Some(filter_id.to_string());
+        self
+    }
+
+    pub fn build(self) -> GridSettingChangesetParams {
+        self.params
+    }
+}

+ 43 - 3
frontend/rust-lib/flowy-grid/tests/grid/script.rs

@@ -2,6 +2,7 @@ use bytes::Bytes;
 use flowy_grid::services::field::*;
 use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor};
 use flowy_grid::services::row::CreateRowRevisionPayload;
+use flowy_grid::services::setting::GridSettingChangesetBuilder;
 use flowy_grid_data_model::entities::*;
 use flowy_grid_data_model::revision::*;
 use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
@@ -66,8 +67,17 @@ pub enum EditorScript {
     UpdateGridSetting {
         params: GridSettingChangesetParams,
     },
+    InsertGridTableFilter {
+        payload: CreateGridFilterPayload,
+    },
+    AssertTableFilterCount {
+        count: i32,
+    },
+    DeleteGridTableFilter {
+        filter_id: String,
+    },
     AssertGridSetting {
-        expected_setting: GridSettingRevision,
+        expected_setting: GridSetting,
     },
     AssertGridRevisionPad,
 }
@@ -239,6 +249,26 @@ impl GridEditorTest {
             EditorScript::UpdateGridSetting { params } => {
                 let _ = self.editor.update_grid_setting(params).await.unwrap();
             }
+            EditorScript::InsertGridTableFilter { payload } => {
+                let params: CreateGridFilterParams = payload.try_into().unwrap();
+                let layout_type = GridLayoutType::Table;
+                let params = GridSettingChangesetBuilder::new(&self.grid_id, &layout_type)
+                    .insert_filter(params)
+                    .build();
+                let _ = self.editor.update_grid_setting(params).await.unwrap();
+            }
+            EditorScript::AssertTableFilterCount { count } => {
+                let layout_type = GridLayoutType::Table;
+                let filters = self.editor.get_grid_filter(&layout_type).await.unwrap();
+                assert_eq!(count as usize, filters.len());
+            }
+            EditorScript::DeleteGridTableFilter { filter_id } => {
+                let layout_type = GridLayoutType::Table;
+                let params = GridSettingChangesetBuilder::new(&self.grid_id, &layout_type)
+                    .delete_filter(&filter_id)
+                    .build();
+                let _ = self.editor.update_grid_setting(params).await.unwrap();
+            }
             EditorScript::AssertGridSetting { expected_setting } => {
                 let setting = self.editor.get_grid_setting().await.unwrap();
                 assert_eq!(expected_setting, setting);
@@ -262,8 +292,18 @@ impl GridEditorTest {
             .row_revs
     }
 
-    pub(crate) async fn get_grid_setting(&self) -> GridSettingRevision {
-        self.editor.get_grid_setting().await.unwrap()
+    pub async fn grid_filters(&self) -> Vec<GridFilter> {
+        let layout_type = GridLayoutType::Table;
+        self.editor.get_grid_filter(&layout_type).await.unwrap()
+    }
+
+    pub fn text_field(&self) -> &FieldRevision {
+        self.field_revs
+            .iter()
+            .filter(|field_rev| field_rev.field_type == FieldType::RichText)
+            .collect::<Vec<_>>()
+            .pop()
+            .unwrap()
     }
 }
 

+ 58 - 15
frontend/rust-lib/flowy-grid/tests/grid/setting_test.rs

@@ -1,29 +1,72 @@
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
+
 use flowy_grid_data_model::entities::{
-    CreateGridFilterParams, CreateGridFilterPayload, GridLayoutType, GridSettingChangesetParams,
+    CreateGridFilterParams, CreateGridFilterPayload, GridLayoutType, GridSettingChangesetParams, TextFilterCondition,
 };
-use flowy_grid_data_model::revision::GridSettingRevision;
 
 #[tokio::test]
-async fn grid_setting_create_filter_test() {
+async fn grid_setting_create_text_filter_test() {
     let test = GridEditorTest::new().await;
+    let field_rev = test.text_field();
+    let condition = TextFilterCondition::TextIsEmpty as i32;
 
-    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 }];
+    let scripts = vec![
+        InsertGridTableFilter {
+            payload: CreateGridFilterPayload {
+                field_id: field_rev.id.clone(),
+                field_type: field_rev.field_type.clone(),
+                condition,
+                content: Some("abc".to_owned()),
+            },
+        },
+        AssertTableFilterCount { count: 1 },
+    ];
     GridEditorTest::new().await.run_scripts(scripts).await;
+}
 
-    // let mut expected_grid_setting = test.get_grid_setting().await;
+#[tokio::test]
+#[should_panic]
+async fn grid_setting_create_text_filter_panic_test() {
+    let test = GridEditorTest::new().await;
+    let field_rev = test.text_field();
+    let scripts = vec![InsertGridTableFilter {
+        payload: CreateGridFilterPayload {
+            field_id: field_rev.id.clone(),
+            field_type: field_rev.field_type.clone(),
+            condition: 20, // Invalid condition type
+            content: Some("abc".to_owned()),
+        },
+    }];
+    GridEditorTest::new().await.run_scripts(scripts).await;
 }
 
+#[tokio::test]
+async fn grid_setting_delete_text_filter_test() {
+    let mut test = GridEditorTest::new().await;
+    let field_rev = test.text_field();
+    let condition = TextFilterCondition::TextIsEmpty as i32;
+
+    let scripts = vec![
+        InsertGridTableFilter {
+            payload: CreateGridFilterPayload {
+                field_id: field_rev.id.clone(),
+                field_type: field_rev.field_type.clone(),
+                condition,
+                content: Some("abc".to_owned()),
+            },
+        },
+        AssertTableFilterCount { count: 1 },
+    ];
+
+    test.run_scripts(scripts).await;
+    let filter = test.grid_filters().await.pop().unwrap();
+
+    test.run_scripts(vec![
+        DeleteGridTableFilter { filter_id: filter.id },
+        AssertTableFilterCount { count: 0 },
+    ])
+    .await;
+}
 #[tokio::test]
 async fn grid_setting_sort_test() {}

+ 1 - 0
frontend/scripts/flowy-tool/src/proto/template/proto_file/struct_template.rs

@@ -11,6 +11,7 @@ static RUST_TYPE_MAP: phf::Map<&'static str, &'static str> = phf_map! {
     "i32" => "int32",
     "u64" => "uint64",
     "u32" => "uint32",
+    "u8" => "uint8",
     "Vec" => "repeated",
     "f64" => "double",
     "HashMap" => "map",

+ 208 - 62
shared-lib/flowy-grid-data-model/src/entities/grid_filter.rs

@@ -3,49 +3,13 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error_code::ErrorCode;
 
 use crate::entities::FieldType;
-use crate::revision::{
-    FilterInfoRevision, GridFilterRevision, NumberFilterConditionRevision, TextFilterConditionRevision,
-};
+use crate::revision::GridFilterRevision;
 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)]
@@ -54,10 +18,16 @@ pub struct RepeatedGridFilter {
     pub items: Vec<GridFilter>,
 }
 
-impl std::convert::From<Vec<GridFilterRevision>> for RepeatedGridFilter {
-    fn from(revs: Vec<GridFilterRevision>) -> Self {
+impl std::convert::From<&GridFilterRevision> for GridFilter {
+    fn from(rev: &GridFilterRevision) -> Self {
+        Self { id: rev.id.clone() }
+    }
+}
+
+impl std::convert::From<&Vec<GridFilterRevision>> for RepeatedGridFilter {
+    fn from(revs: &Vec<GridFilterRevision>) -> Self {
         RepeatedGridFilter {
-            items: revs.into_iter().map(|rev| rev.into()).collect(),
+            items: revs.iter().map(|rev| rev.into()).collect(),
         }
     }
 }
@@ -75,11 +45,19 @@ pub struct CreateGridFilterPayload {
 
     #[pb(index = 2)]
     pub field_type: FieldType,
+
+    #[pb(index = 3)]
+    pub condition: i32,
+
+    #[pb(index = 4, one_of)]
+    pub content: Option<String>,
 }
 
 pub struct CreateGridFilterParams {
     pub field_id: String,
     pub field_type: FieldType,
+    pub condition: u8,
+    pub content: Option<String>,
 }
 
 impl TryInto<CreateGridFilterParams> for CreateGridFilterPayload {
@@ -89,14 +67,40 @@ impl TryInto<CreateGridFilterParams> for CreateGridFilterPayload {
         let field_id = NotEmptyStr::parse(self.field_id)
             .map_err(|_| ErrorCode::FieldIdIsEmpty)?
             .0;
+        let condition = self.condition as u8;
+        match self.field_type {
+            FieldType::RichText | FieldType::Checkbox | FieldType::URL => {
+                let _ = TextFilterCondition::try_from(condition)?;
+            }
+            FieldType::Number => {
+                let _ = NumberFilterCondition::try_from(condition)?;
+            }
+            FieldType::DateTime => {
+                let _ = DateFilterCondition::try_from(condition)?;
+            }
+            FieldType::SingleSelect | FieldType::MultiSelect => {
+                let _ = SelectOptionCondition::try_from(condition)?;
+            }
+        }
 
         Ok(CreateGridFilterParams {
             field_id,
             field_type: self.field_type,
+            condition,
+            content: self.content,
         })
     }
 }
 
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridTextFilter {
+    #[pb(index = 1)]
+    pub condition: TextFilterCondition,
+
+    #[pb(index = 2, one_of)]
+    pub content: Option<String>,
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
 #[repr(u8)]
 pub enum TextFilterCondition {
@@ -110,21 +114,47 @@ pub enum TextFilterCondition {
     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,
+impl std::default::Default for TextFilterCondition {
+    fn default() -> Self {
+        TextFilterCondition::Is
+    }
+}
+impl std::convert::TryFrom<u8> for TextFilterCondition {
+    type Error = ErrorCode;
+
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(TextFilterCondition::Is),
+            1 => Ok(TextFilterCondition::IsNot),
+            2 => Ok(TextFilterCondition::Contains),
+            3 => Ok(TextFilterCondition::DoesNotContain),
+            4 => Ok(TextFilterCondition::StartsWith),
+            5 => Ok(TextFilterCondition::EndsWith),
+            6 => Ok(TextFilterCondition::TextIsEmpty),
+            7 => Ok(TextFilterCondition::TextIsNotEmpty),
+            _ => Err(ErrorCode::InvalidData),
         }
     }
 }
 
+impl std::convert::From<GridFilterRevision> for GridTextFilter {
+    fn from(rev: GridFilterRevision) -> Self {
+        GridTextFilter {
+            condition: TextFilterCondition::try_from(rev.condition).unwrap_or(TextFilterCondition::Is),
+            content: rev.content,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridNumberFilter {
+    #[pb(index = 1)]
+    pub condition: NumberFilterCondition,
+
+    #[pb(index = 2, one_of)]
+    pub content: Option<String>,
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
 #[repr(u8)]
 pub enum NumberFilterCondition {
@@ -137,18 +167,134 @@ pub enum NumberFilterCondition {
     NumberIsEmpty = 6,
     NumberIsNotEmpty = 7,
 }
+impl std::default::Default for NumberFilterCondition {
+    fn default() -> Self {
+        NumberFilterCondition::Equal
+    }
+}
+
+impl std::convert::TryFrom<u8> for NumberFilterCondition {
+    type Error = ErrorCode;
 
-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,
+    fn try_from(n: u8) -> Result<Self, Self::Error> {
+        match n {
+            0 => Ok(NumberFilterCondition::Equal),
+            1 => Ok(NumberFilterCondition::NotEqual),
+            2 => Ok(NumberFilterCondition::GreaterThan),
+            3 => Ok(NumberFilterCondition::LessThan),
+            4 => Ok(NumberFilterCondition::GreaterThanOrEqualTo),
+            5 => Ok(NumberFilterCondition::LessThanOrEqualTo),
+            6 => Ok(NumberFilterCondition::NumberIsEmpty),
+            7 => Ok(NumberFilterCondition::NumberIsNotEmpty),
+            _ => Err(ErrorCode::InvalidData),
+        }
+    }
+}
+
+impl std::convert::From<GridFilterRevision> for GridNumberFilter {
+    fn from(rev: GridFilterRevision) -> Self {
+        GridNumberFilter {
+            condition: NumberFilterCondition::try_from(rev.condition).unwrap_or(NumberFilterCondition::Equal),
+            content: rev.content,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridSelectOptionFilter {
+    #[pb(index = 1)]
+    pub condition: SelectOptionCondition,
+
+    #[pb(index = 2, one_of)]
+    pub content: Option<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
+#[repr(u8)]
+pub enum SelectOptionCondition {
+    OptionIs = 0,
+    OptionIsNot = 1,
+    OptionIsEmpty = 2,
+    OptionIsNotEmpty = 3,
+}
+
+impl std::default::Default for SelectOptionCondition {
+    fn default() -> Self {
+        SelectOptionCondition::OptionIs
+    }
+}
+
+impl std::convert::TryFrom<u8> for SelectOptionCondition {
+    type Error = ErrorCode;
+
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(SelectOptionCondition::OptionIs),
+            1 => Ok(SelectOptionCondition::OptionIsNot),
+            2 => Ok(SelectOptionCondition::OptionIsEmpty),
+            3 => Ok(SelectOptionCondition::OptionIsNotEmpty),
+            _ => Err(ErrorCode::InvalidData),
+        }
+    }
+}
+
+impl std::convert::From<GridFilterRevision> for GridSelectOptionFilter {
+    fn from(rev: GridFilterRevision) -> Self {
+        GridSelectOptionFilter {
+            condition: SelectOptionCondition::try_from(rev.condition).unwrap_or(SelectOptionCondition::OptionIs),
+            content: rev.content,
+        }
+    }
+}
+
+#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
+pub struct GridDateFilter {
+    #[pb(index = 1)]
+    pub condition: DateFilterCondition,
+
+    #[pb(index = 2, one_of)]
+    pub content: Option<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
+#[repr(u8)]
+pub enum DateFilterCondition {
+    DateIs = 0,
+    DateBefore = 1,
+    DateAfter = 2,
+    DateOnOrBefore = 3,
+    DateOnOrAfter = 4,
+    DateWithIn = 5,
+    DateIsEmpty = 6,
+}
+
+impl std::default::Default for DateFilterCondition {
+    fn default() -> Self {
+        DateFilterCondition::DateIs
+    }
+}
+
+impl std::convert::TryFrom<u8> for DateFilterCondition {
+    type Error = ErrorCode;
+
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(DateFilterCondition::DateIs),
+            1 => Ok(DateFilterCondition::DateBefore),
+            2 => Ok(DateFilterCondition::DateAfter),
+            3 => Ok(DateFilterCondition::DateOnOrBefore),
+            4 => Ok(DateFilterCondition::DateOnOrAfter),
+            5 => Ok(DateFilterCondition::DateWithIn),
+            6 => Ok(DateFilterCondition::DateIsEmpty),
+            _ => Err(ErrorCode::InvalidData),
+        }
+    }
+}
+impl std::convert::From<GridFilterRevision> for GridDateFilter {
+    fn from(rev: GridFilterRevision) -> Self {
+        GridDateFilter {
+            condition: DateFilterCondition::try_from(rev.condition).unwrap_or(DateFilterCondition::DateIs),
+            content: rev.content,
         }
     }
 }

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

@@ -17,12 +17,12 @@ pub struct GridGroup {
     pub sub_group_field_id: Option<String>,
 }
 
-impl std::convert::From<GridGroupRevision> for GridGroup {
-    fn from(rev: GridGroupRevision) -> Self {
+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,
+            id: rev.id.clone(),
+            group_field_id: rev.field_id.clone(),
+            sub_group_field_id: rev.sub_field_id.clone(),
         }
     }
 }
@@ -39,10 +39,10 @@ impl std::convert::From<Vec<GridGroup>> for RepeatedGridGroup {
     }
 }
 
-impl std::convert::From<Vec<GridGroupRevision>> for RepeatedGridGroup {
-    fn from(revs: Vec<GridGroupRevision>) -> Self {
+impl std::convert::From<&Vec<GridGroupRevision>> for RepeatedGridGroup {
+    fn from(revs: &Vec<GridGroupRevision>) -> Self {
         RepeatedGridGroup {
-            items: revs.into_iter().map(|rev| rev.into()).collect(),
+            items: revs.iter().map(|rev| rev.into()).collect(),
         }
     }
 }

+ 5 - 33
shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs

@@ -21,23 +21,23 @@ pub struct GridSetting {
     pub sorts_by_layout_ty: HashMap<String, RepeatedGridSort>,
 }
 
-impl std::convert::From<GridSettingRevision> for GridSetting {
-    fn from(rev: GridSettingRevision) -> Self {
+impl std::convert::From<&GridSettingRevision> for GridSetting {
+    fn from(rev: &GridSettingRevision) -> Self {
         let filters_by_layout_ty: HashMap<String, RepeatedGridFilter> = rev
             .filter
-            .into_iter()
+            .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()
+            .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()
+            .iter()
             .map(|(layout_rev, sort_revs)| (layout_rev.to_string(), sort_revs.into()))
             .collect();
 
@@ -118,34 +118,6 @@ pub struct GridSettingChangesetParams {
     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 {
     type Error = ErrorCode;
 

+ 8 - 7
shared-lib/flowy-grid-data-model/src/entities/grid_sort.rs

@@ -14,11 +14,12 @@ pub struct GridSort {
     pub field_id: Option<String>,
 }
 
-impl std::convert::From<GridSortRevision> for GridSort {
-    fn from(rev: GridSortRevision) -> Self {
+impl std::convert::From<&GridSortRevision> for GridSort {
+    fn from(rev: &GridSortRevision) -> Self {
         GridSort {
-            id: rev.id,
-            field_id: rev.field_id,
+            id: rev.id.clone(),
+
+            field_id: rev.field_id.clone(),
         }
     }
 }
@@ -29,10 +30,10 @@ pub struct RepeatedGridSort {
     pub items: Vec<GridSort>,
 }
 
-impl std::convert::From<Vec<GridSortRevision>> for RepeatedGridSort {
-    fn from(revs: Vec<GridSortRevision>) -> Self {
+impl std::convert::From<&Vec<GridSortRevision>> for RepeatedGridSort {
+    fn from(revs: &Vec<GridSortRevision>) -> Self {
         RepeatedGridSort {
-            items: revs.into_iter().map(|rev| rev.into()).collect(),
+            items: revs.iter().map(|rev| rev.into()).collect(),
         }
     }
 }

+ 94 - 0
shared-lib/flowy-grid-data-model/src/revision/grid_filter_rev.rs

@@ -0,0 +1,94 @@
+use crate::entities::NumberFilterCondition;
+use indexmap::IndexMap;
+use nanoid::nanoid;
+use serde::{Deserialize, Serialize};
+use serde_repr::*;
+use std::str::FromStr;
+
+#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
+pub struct GridFilterRevision {
+    pub id: String,
+    pub field_id: String,
+    pub condition: u8,
+    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 ToString for TextFilterConditionRevision {
+    fn to_string(&self) -> String {
+        (self.clone() as u8).to_string()
+    }
+}
+
+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)
+    }
+}
+
+#[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,
+}
+
+impl ToString for NumberFilterConditionRevision {
+    fn to_string(&self) -> String {
+        (self.clone() as u8).to_string()
+    }
+}
+
+impl FromStr for NumberFilterConditionRevision {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let rev = serde_json::from_str(s)?;
+        Ok(rev)
+    }
+}
+
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
+#[repr(u8)]
+pub enum SelectOptionConditionRevision {
+    OptionIs = 0,
+    OptionIsNot = 1,
+    OptionIsEmpty = 2,
+    OptionIsNotEmpty = 3,
+}
+
+impl ToString for SelectOptionConditionRevision {
+    fn to_string(&self) -> String {
+        (self.clone() as u8).to_string()
+    }
+}
+
+impl FromStr for SelectOptionConditionRevision {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let rev = serde_json::from_str(s)?;
+        Ok(rev)
+    }
+}

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

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

+ 2 - 64
shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs

@@ -2,7 +2,6 @@ use indexmap::IndexMap;
 use nanoid::nanoid;
 use serde::{Deserialize, Serialize};
 use serde_repr::*;
-use std::str::FromStr;
 
 pub fn gen_grid_filter_id() -> String {
     nanoid!(6)
@@ -52,7 +51,8 @@ impl std::default::Default for GridLayoutRevision {
 pub struct GridFilterRevision {
     pub id: String,
     pub field_id: String,
-    pub info: FilterInfoRevision,
+    pub condition: u8,
+    pub content: Option<String>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
@@ -67,65 +67,3 @@ pub struct GridSortRevision {
     pub id: String,
     pub field_id: Option<String>,
 }
-
-#[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 ToString for TextFilterConditionRevision {
-    fn to_string(&self) -> String {
-        (self.clone() as u8).to_string()
-    }
-}
-
-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)
-    }
-}
-
-#[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,
-}
-
-impl ToString for NumberFilterConditionRevision {
-    fn to_string(&self) -> String {
-        (self.clone() as u8).to_string()
-    }
-}
-
-impl FromStr for NumberFilterConditionRevision {
-    type Err = serde_json::Error;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        let rev = serde_json::from_str(s)?;
-        Ok(rev)
-    }
-}

+ 5 - 3
shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs

@@ -330,8 +330,8 @@ impl GridRevisionPad {
         })
     }
 
-    pub fn get_grid_setting_rev(&self) -> GridSettingRevision {
-        self.grid_rev.setting.clone()
+    pub fn get_grid_setting_rev(&self) -> &GridSettingRevision {
+        &self.grid_rev.setting
     }
 
     pub fn update_grid_setting_rev(
@@ -346,8 +346,10 @@ impl GridRevisionPad {
                 let rev = GridFilterRevision {
                     id: gen_grid_filter_id(),
                     field_id: params.field_id,
-                    info: Default::default(),
+                    condition: params.condition,
+                    content: params.content,
                 };
+
                 grid_rev
                     .setting
                     .filter