Browse Source

chore: update test

appflowy 2 years ago
parent
commit
a08590bcba

+ 1 - 0
frontend/rust-lib/flowy-grid/tests/grid/cell_test.rs

@@ -1,3 +1,4 @@
+use crate::grid::field_util::make_date_cell_string;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
 use crate::grid::script::*;
 use flowy_grid::services::field::{MultiSelectTypeOption, SelectOptionCellContentChangeset, SingleSelectTypeOption};
 use flowy_grid::services::field::{MultiSelectTypeOption, SelectOptionCellContentChangeset, SingleSelectTypeOption};

+ 1 - 0
frontend/rust-lib/flowy-grid/tests/grid/field_test.rs

@@ -1,3 +1,4 @@
+use crate::grid::field_util::*;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
 use crate::grid::script::*;
 use flowy_grid::services::field::{SelectOption, SingleSelectTypeOption};
 use flowy_grid::services::field::{SelectOption, SingleSelectTypeOption};

+ 84 - 0
frontend/rust-lib/flowy-grid/tests/grid/field_util.rs

@@ -0,0 +1,84 @@
+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_sync::client_grid::GridBuilder;
+
+pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
+    let field_rev = FieldBuilder::new(RichTextTypeOptionBuilder::default())
+        .name("Name")
+        .visibility(true)
+        .build();
+
+    let cloned_field_rev = field_rev.clone();
+
+    let type_option_data = field_rev
+        .get_type_option_entry::<RichTextTypeOption>(&field_rev.field_type)
+        .unwrap()
+        .protobuf_bytes()
+        .to_vec();
+
+    let field = Field {
+        id: field_rev.id,
+        name: field_rev.name,
+        desc: field_rev.desc,
+        field_type: field_rev.field_type,
+        frozen: field_rev.frozen,
+        visibility: field_rev.visibility,
+        width: field_rev.width,
+        is_primary: false,
+    };
+
+    let params = InsertFieldParams {
+        grid_id: grid_id.to_owned(),
+        field,
+        type_option_data,
+        start_field_id: None,
+    };
+    (params, cloned_field_rev)
+}
+
+pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
+    let single_select = SingleSelectTypeOptionBuilder::default()
+        .option(SelectOption::new("Done"))
+        .option(SelectOption::new("Progress"));
+
+    let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build();
+    let cloned_field_rev = field_rev.clone();
+    let type_option_data = field_rev
+        .get_type_option_entry::<SingleSelectTypeOption>(&field_rev.field_type)
+        .unwrap()
+        .protobuf_bytes()
+        .to_vec();
+
+    let field = Field {
+        id: field_rev.id,
+        name: field_rev.name,
+        desc: field_rev.desc,
+        field_type: field_rev.field_type,
+        frozen: field_rev.frozen,
+        visibility: field_rev.visibility,
+        width: field_rev.width,
+        is_primary: false,
+    };
+
+    let params = InsertFieldParams {
+        grid_id: grid_id.to_owned(),
+        field,
+        type_option_data,
+        start_field_id: None,
+    };
+    (params, cloned_field_rev)
+}
+
+//  The grid will contains all existing field types and there are three empty rows in this grid.
+
+pub fn make_date_cell_string(s: &str) -> String {
+    serde_json::to_string(&DateCellContentChangeset {
+        date: Some(s.to_string()),
+        time: None,
+    })
+    .unwrap()
+}

+ 46 - 0
frontend/rust-lib/flowy-grid/tests/grid/filter_test.rs

@@ -0,0 +1,46 @@
+use crate::grid::script::EditorScript::*;
+use crate::grid::script::*;
+
+use flowy_grid_data_model::entities::{
+    CreateGridFilterParams, CreateGridFilterPayload, GridLayoutType, GridSettingChangesetParams, TextFilterCondition,
+};
+
+#[tokio::test]
+async fn grid_setting_create_text_filter_test() {
+    let test = GridEditorTest::new().await;
+    let field_rev = test.text_field();
+    let payload = CreateGridFilterPayload::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
+    let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
+    GridEditorTest::new().await.run_scripts(scripts).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();
+
+    // 100 is not a valid condition, so this test should be panic.
+    let payload = CreateGridFilterPayload::new(field_rev, 100, Some("abc".to_owned()));
+    let scripts = vec![InsertGridTableFilter { payload }];
+    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 payload = CreateGridFilterPayload::new(field_rev, 100, Some("abc".to_owned()));
+    let scripts = vec![InsertGridTableFilter { payload }, 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() {}

+ 3 - 1
frontend/rust-lib/flowy-grid/tests/grid/mod.rs

@@ -1,6 +1,8 @@
 mod block_test;
 mod block_test;
 mod cell_test;
 mod cell_test;
 mod field_test;
 mod field_test;
+mod field_util;
+mod filter_test;
 mod row_test;
 mod row_test;
+mod row_util;
 mod script;
 mod script;
-mod setting_test;

+ 17 - 14
frontend/rust-lib/flowy-grid/tests/grid/row_test.rs

@@ -1,23 +1,26 @@
+use crate::grid::field_util::*;
+use crate::grid::row_util::GridRowTestBuilder;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::EditorScript::*;
 use crate::grid::script::*;
 use crate::grid::script::*;
 use chrono::NaiveDateTime;
 use chrono::NaiveDateTime;
 use flowy_grid::services::field::{
 use flowy_grid::services::field::{
     DateCellData, MultiSelectTypeOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
     DateCellData, MultiSelectTypeOption, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
 };
 };
-use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowRevisionBuilder};
+use flowy_grid::services::row::{
+    decode_cell_data_from_type_option_cell_data, CreateRowRevisionBuilder, CreateRowRevisionPayload,
+};
 use flowy_grid_data_model::entities::FieldType;
 use flowy_grid_data_model::entities::FieldType;
-use flowy_grid_data_model::revision::RowMetaChangeset;
+use flowy_grid_data_model::revision::{FieldRevision, RowMetaChangeset};
 
 
 #[tokio::test]
 #[tokio::test]
 async fn grid_create_row_count_test() {
 async fn grid_create_row_count_test() {
     let test = GridEditorTest::new().await;
     let test = GridEditorTest::new().await;
-    let create_row_context = CreateRowRevisionBuilder::new(&test.field_revs).build();
     let scripts = vec![
     let scripts = vec![
         AssertRowCount(3),
         AssertRowCount(3),
         CreateEmptyRow,
         CreateEmptyRow,
         CreateEmptyRow,
         CreateEmptyRow,
         CreateRow {
         CreateRow {
-            context: create_row_context,
+            payload: GridRowTestBuilder::new(&test).build(),
         },
         },
         AssertRowCount(6),
         AssertRowCount(6),
     ];
     ];
@@ -27,15 +30,15 @@ async fn grid_create_row_count_test() {
 #[tokio::test]
 #[tokio::test]
 async fn grid_update_row() {
 async fn grid_update_row() {
     let mut test = GridEditorTest::new().await;
     let mut test = GridEditorTest::new().await;
-    let context = CreateRowRevisionBuilder::new(&test.field_revs).build();
+    let payload = GridRowTestBuilder::new(&test).build();
     let changeset = RowMetaChangeset {
     let changeset = RowMetaChangeset {
-        row_id: context.row_id.clone(),
+        row_id: payload.row_id.clone(),
         height: None,
         height: None,
         visibility: None,
         visibility: None,
         cell_by_field_id: Default::default(),
         cell_by_field_id: Default::default(),
     };
     };
 
 
-    let scripts = vec![AssertRowCount(3), CreateRow { context }, UpdateRow { changeset }];
+    let scripts = vec![AssertRowCount(3), CreateRow { payload }, UpdateRow { changeset }];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
 
 
     let expected_row = (&*test.row_revs.last().cloned().unwrap()).clone();
     let expected_row = (&*test.row_revs.last().cloned().unwrap()).clone();
@@ -46,13 +49,13 @@ async fn grid_update_row() {
 #[tokio::test]
 #[tokio::test]
 async fn grid_delete_row() {
 async fn grid_delete_row() {
     let mut test = GridEditorTest::new().await;
     let mut test = GridEditorTest::new().await;
-    let context_1 = CreateRowRevisionBuilder::new(&test.field_revs).build();
-    let context_2 = CreateRowRevisionBuilder::new(&test.field_revs).build();
-    let row_ids = vec![context_1.row_id.clone(), context_2.row_id.clone()];
+    let payload1 = GridRowTestBuilder::new(&test).build();
+    let payload2 = GridRowTestBuilder::new(&test).build();
+    let row_ids = vec![payload1.row_id.clone(), payload2.row_id.clone()];
     let scripts = vec![
     let scripts = vec![
         AssertRowCount(3),
         AssertRowCount(3),
-        CreateRow { context: context_1 },
-        CreateRow { context: context_2 },
+        CreateRow { payload: payload1 },
+        CreateRow { payload: payload2 },
         AssertBlockCount(1),
         AssertBlockCount(1),
         AssertBlock {
         AssertBlock {
             block_index: 0,
             block_index: 0,
@@ -110,7 +113,7 @@ async fn grid_row_add_cells_test() {
         }
         }
     }
     }
     let context = builder.build();
     let context = builder.build();
-    let scripts = vec![CreateRow { context }, AssertGridRevisionPad];
+    let scripts = vec![CreateRow { payload: context }, AssertGridRevisionPad];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
 }
 }
 
 
@@ -142,6 +145,6 @@ async fn grid_row_add_date_cell_test() {
             .date,
             .date,
         "2022/03/16",
         "2022/03/16",
     );
     );
-    let scripts = vec![CreateRow { context }];
+    let scripts = vec![CreateRow { payload: context }];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
 }
 }

+ 32 - 0
frontend/rust-lib/flowy-grid/tests/grid/row_util.rs

@@ -0,0 +1,32 @@
+use crate::grid::script::GridEditorTest;
+use flowy_grid::services::row::{CreateRowRevisionBuilder, CreateRowRevisionPayload};
+use flowy_grid_data_model::entities::FieldType;
+use flowy_grid_data_model::revision::FieldRevision;
+use strum::EnumCount;
+
+pub struct GridRowTestBuilder<'a> {
+    test: &'a GridEditorTest,
+    inner_builder: CreateRowRevisionBuilder<'a>,
+}
+
+impl<'a> GridRowTestBuilder<'a> {
+    pub fn new(test: &'a GridEditorTest) -> Self {
+        assert_eq!(test.field_revs.len(), FieldType::COUNT);
+
+        let inner_builder = CreateRowRevisionBuilder::new(&test.field_revs);
+        Self { test, inner_builder }
+    }
+
+    pub fn update_text_cell(&mut self) -> Self {
+        let text_field = self
+            .test
+            .field_revs
+            .iter()
+            .find(|field_rev| field_rev.field_type == FieldType::RichText);
+        // self.inner_builder
+    }
+
+    pub fn build(self) -> CreateRowRevisionPayload {
+        self.inner_builder.build()
+    }
+}

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

@@ -48,7 +48,7 @@ pub enum EditorScript {
     },
     },
     CreateEmptyRow,
     CreateEmptyRow,
     CreateRow {
     CreateRow {
-        context: CreateRowRevisionPayload,
+        payload: CreateRowRevisionPayload,
     },
     },
     UpdateRow {
     UpdateRow {
         changeset: RowMetaChangeset,
         changeset: RowMetaChangeset,
@@ -98,7 +98,7 @@ impl GridEditorTest {
     pub async fn new() -> Self {
     pub async fn new() -> Self {
         let sdk = FlowySDKTest::default();
         let sdk = FlowySDKTest::default();
         let _ = sdk.init_user().await;
         let _ = sdk.init_user().await;
-        let build_context = make_test_grid();
+        let build_context = make_all_field_test_grid();
         let view_data: Bytes = build_context.into();
         let view_data: Bytes = build_context.into();
         let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await;
         let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await;
         let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
         let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
@@ -199,7 +199,7 @@ impl GridEditorTest {
                 self.row_revs = self.get_row_revs().await;
                 self.row_revs = self.get_row_revs().await;
                 self.grid_block_revs = self.editor.get_block_metas().await.unwrap();
                 self.grid_block_revs = self.editor.get_block_metas().await.unwrap();
             }
             }
-            EditorScript::CreateRow { context } => {
+            EditorScript::CreateRow { payload: context } => {
                 let row_orders = self.editor.insert_rows(vec![context]).await.unwrap();
                 let row_orders = self.editor.insert_rows(vec![context]).await.unwrap();
                 for row_order in row_orders {
                 for row_order in row_orders {
                     self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
                     self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
@@ -307,74 +307,7 @@ impl GridEditorTest {
     }
     }
 }
 }
 
 
-pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
-    let field_rev = FieldBuilder::new(RichTextTypeOptionBuilder::default())
-        .name("Name")
-        .visibility(true)
-        .build();
-
-    let cloned_field_rev = field_rev.clone();
-
-    let type_option_data = field_rev
-        .get_type_option_entry::<RichTextTypeOption>(&field_rev.field_type)
-        .unwrap()
-        .protobuf_bytes()
-        .to_vec();
-
-    let field = Field {
-        id: field_rev.id,
-        name: field_rev.name,
-        desc: field_rev.desc,
-        field_type: field_rev.field_type,
-        frozen: field_rev.frozen,
-        visibility: field_rev.visibility,
-        width: field_rev.width,
-        is_primary: false,
-    };
-
-    let params = InsertFieldParams {
-        grid_id: grid_id.to_owned(),
-        field,
-        type_option_data,
-        start_field_id: None,
-    };
-    (params, cloned_field_rev)
-}
-
-pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
-    let single_select = SingleSelectTypeOptionBuilder::default()
-        .option(SelectOption::new("Done"))
-        .option(SelectOption::new("Progress"));
-
-    let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build();
-    let cloned_field_rev = field_rev.clone();
-    let type_option_data = field_rev
-        .get_type_option_entry::<SingleSelectTypeOption>(&field_rev.field_type)
-        .unwrap()
-        .protobuf_bytes()
-        .to_vec();
-
-    let field = Field {
-        id: field_rev.id,
-        name: field_rev.name,
-        desc: field_rev.desc,
-        field_type: field_rev.field_type,
-        frozen: field_rev.frozen,
-        visibility: field_rev.visibility,
-        width: field_rev.width,
-        is_primary: false,
-    };
-
-    let params = InsertFieldParams {
-        grid_id: grid_id.to_owned(),
-        field,
-        type_option_data,
-        start_field_id: None,
-    };
-    (params, cloned_field_rev)
-}
-
-fn make_test_grid() -> BuildGridContext {
+fn make_all_field_test_grid() -> BuildGridContext {
     let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
     let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
         .name("Name")
         .name("Name")
         .visibility(true)
         .visibility(true)
@@ -429,11 +362,3 @@ fn make_test_grid() -> BuildGridContext {
         .add_empty_row()
         .add_empty_row()
         .build()
         .build()
 }
 }
-
-pub fn make_date_cell_string(s: &str) -> String {
-    serde_json::to_string(&DateCellContentChangeset {
-        date: Some(s.to_string()),
-        time: None,
-    })
-    .unwrap()
-}

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

@@ -1,72 +0,0 @@
-use crate::grid::script::EditorScript::*;
-use crate::grid::script::*;
-
-use flowy_grid_data_model::entities::{
-    CreateGridFilterParams, CreateGridFilterPayload, GridLayoutType, GridSettingChangesetParams, TextFilterCondition,
-};
-
-#[tokio::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 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;
-}
-
-#[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() {}

+ 29 - 1
shared-lib/flowy-grid-data-model/src/entities/grid_filter.rs

@@ -3,7 +3,7 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error_code::ErrorCode;
 use flowy_error_code::ErrorCode;
 
 
 use crate::entities::FieldType;
 use crate::entities::FieldType;
-use crate::revision::GridFilterRevision;
+use crate::revision::{FieldRevision, GridFilterRevision};
 use std::convert::TryInto;
 use std::convert::TryInto;
 
 
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
@@ -53,6 +53,18 @@ pub struct CreateGridFilterPayload {
     pub content: Option<String>,
     pub content: Option<String>,
 }
 }
 
 
+impl CreateGridFilterPayload {
+    #[allow(dead_code)]
+    pub fn new<T: Into<i32>>(field_rev: &FieldRevision, condition: T, content: Option<String>) -> Self {
+        Self {
+            field_id: field_rev.id.clone(),
+            field_type: field_rev.field_type.clone(),
+            condition: condition.into(),
+            content,
+        }
+    }
+}
+
 pub struct CreateGridFilterParams {
 pub struct CreateGridFilterParams {
     pub field_id: String,
     pub field_id: String,
     pub field_type: FieldType,
     pub field_type: FieldType,
@@ -113,6 +125,11 @@ pub enum TextFilterCondition {
     TextIsEmpty = 6,
     TextIsEmpty = 6,
     TextIsNotEmpty = 7,
     TextIsNotEmpty = 7,
 }
 }
+impl std::convert::Into<i32> for TextFilterCondition {
+    fn into(self) -> i32 {
+        self as i32
+    }
+}
 
 
 impl std::default::Default for TextFilterCondition {
 impl std::default::Default for TextFilterCondition {
     fn default() -> Self {
     fn default() -> Self {
@@ -173,6 +190,11 @@ impl std::default::Default for NumberFilterCondition {
     }
     }
 }
 }
 
 
+impl std::convert::Into<i32> for NumberFilterCondition {
+    fn into(self) -> i32 {
+        self as i32
+    }
+}
 impl std::convert::TryFrom<u8> for NumberFilterCondition {
 impl std::convert::TryFrom<u8> for NumberFilterCondition {
     type Error = ErrorCode;
     type Error = ErrorCode;
 
 
@@ -218,6 +240,12 @@ pub enum SelectOptionCondition {
     OptionIsNotEmpty = 3,
     OptionIsNotEmpty = 3,
 }
 }
 
 
+impl std::convert::Into<i32> for SelectOptionCondition {
+    fn into(self) -> i32 {
+        self as i32
+    }
+}
+
 impl std::default::Default for SelectOptionCondition {
 impl std::default::Default for SelectOptionCondition {
     fn default() -> Self {
     fn default() -> Self {
         SelectOptionCondition::OptionIs
         SelectOptionCondition::OptionIs

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

@@ -359,7 +359,12 @@ impl GridRevisionPad {
 
 
                 is_changed = Some(())
                 is_changed = Some(())
             }
             }
-
+            if let Some(delete_filter_id) = changeset.delete_filter {
+                match grid_rev.setting.filter.get_mut(&layout_rev) {
+                    Some(filters) => filters.retain(|filter| filter.id != delete_filter_id),
+                    None => {}
+                }
+            }
             if let Some(params) = changeset.insert_group {
             if let Some(params) = changeset.insert_group {
                 let rev = GridGroupRevision {
                 let rev = GridGroupRevision {
                     id: gen_grid_group_id(),
                     id: gen_grid_group_id(),
@@ -376,7 +381,12 @@ impl GridRevisionPad {
 
 
                 is_changed = Some(())
                 is_changed = Some(())
             }
             }
-
+            if let Some(delete_group_id) = changeset.delete_group {
+                match grid_rev.setting.group.get_mut(&layout_rev) {
+                    Some(groups) => groups.retain(|group| group.id != delete_group_id),
+                    None => {}
+                }
+            }
             if let Some(sort) = changeset.insert_sort {
             if let Some(sort) = changeset.insert_sort {
                 let rev = GridSortRevision {
                 let rev = GridSortRevision {
                     id: gen_grid_sort_id(),
                     id: gen_grid_sort_id(),
@@ -386,12 +396,18 @@ impl GridRevisionPad {
                 grid_rev
                 grid_rev
                     .setting
                     .setting
                     .sort
                     .sort
-                    .entry(layout_rev)
+                    .entry(layout_rev.clone())
                     .or_insert_with(std::vec::Vec::new)
                     .or_insert_with(std::vec::Vec::new)
                     .push(rev);
                     .push(rev);
                 is_changed = Some(())
                 is_changed = Some(())
             }
             }
 
 
+            if let Some(delete_sort_id) = changeset.delete_sort {
+                match grid_rev.setting.sort.get_mut(&layout_rev) {
+                    Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id),
+                    None => {}
+                }
+            }
             Ok(is_changed)
             Ok(is_changed)
         })
         })
     }
     }