Browse Source

refactor: rename structs

appflowy 2 years ago
parent
commit
d3cd60e527
27 changed files with 212 additions and 97 deletions
  1. 1 1
      frontend/app_flowy/lib/startup/plugin/plugin.dart
  2. 1 1
      frontend/app_flowy/lib/workspace/application/app/app_bloc.dart
  3. 1 1
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart
  4. 24 18
      frontend/rust-lib/flowy-folder/src/entities/view.rs
  5. 3 3
      frontend/rust-lib/flowy-folder/src/manager.rs
  6. 4 4
      frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs
  7. 34 15
      frontend/rust-lib/flowy-folder/src/services/view/controller.rs
  8. 4 4
      frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs
  9. 6 6
      frontend/rust-lib/flowy-folder/tests/workspace/script.rs
  10. 12 3
      frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs
  11. 1 1
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  12. 0 2
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs
  13. 7 2
      frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs
  14. 1 0
      frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs
  15. 13 5
      frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs
  16. 1 1
      frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs
  17. 1 0
      frontend/rust-lib/flowy-grid/tests/grid/group_test/mod.rs
  18. 54 0
      frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs
  19. 1 0
      frontend/rust-lib/flowy-grid/tests/grid/mod.rs
  20. 1 1
      frontend/rust-lib/flowy-net/src/local_server/server.rs
  21. 7 7
      frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs
  22. 1 1
      frontend/rust-lib/flowy-sdk/src/lib.rs
  23. 22 7
      frontend/rust-lib/flowy-test/src/helper.rs
  24. 5 3
      shared-lib/flowy-folder-data-model/src/revision/view_rev.rs
  25. 2 2
      shared-lib/flowy-folder-data-model/src/user_default.rs
  26. 5 5
      shared-lib/flowy-sync/src/client_folder/folder_pad.rs
  27. 0 4
      shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs

+ 1 - 1
frontend/app_flowy/lib/startup/plugin/plugin.dart

@@ -56,7 +56,7 @@ abstract class PluginBuilder {
 
   ViewDataTypePB get dataType => ViewDataTypePB.TextBlock;
 
-  SubViewDataTypePB? get subDataType => null;
+  SubViewDataTypePB get subDataType;
 }
 
 abstract class PluginConfig {

+ 1 - 1
frontend/app_flowy/lib/workspace/application/app/app_bloc.dart

@@ -140,7 +140,7 @@ class AppEvent with _$AppEvent {
     String name,
     String desc,
     ViewDataTypePB dataType,
-    SubViewDataTypePB? subDataType,
+    SubViewDataTypePB subDataType,
     PluginType pluginType,
   ) = CreateView;
   const factory AppEvent.delete() = Delete;

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart

@@ -114,7 +114,7 @@ class MenuAppHeader extends StatelessWidget {
                 LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
                 "",
                 pluginBuilder.dataType,
-                pluginBuilder.subDataType,
+                pluginBuilder.subDataType!,
                 pluginBuilder.pluginType,
               ));
         },

+ 24 - 18
frontend/rust-lib/flowy-folder/src/entities/view.rs

@@ -16,7 +16,7 @@ pub struct ViewPB {
     pub id: String,
 
     #[pb(index = 2)]
-    pub belong_to_id: String,
+    pub app_id: String,
 
     #[pb(index = 3)]
     pub name: String,
@@ -38,7 +38,7 @@ impl std::convert::From<ViewRevision> for ViewPB {
     fn from(rev: ViewRevision) -> Self {
         ViewPB {
             id: rev.id,
-            belong_to_id: rev.belong_to_id,
+            app_id: rev.app_id,
             name: rev.name,
             data_type: rev.data_type.into(),
             modified_time: rev.modified_time,
@@ -50,16 +50,10 @@ impl std::convert::From<ViewRevision> for ViewPB {
 
 #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
 pub enum ViewDataTypePB {
-    TextBlock = 0,
+    Document = 0,
     Database = 1,
 }
 
-#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
-pub enum SubViewDataTypePB {
-    Grid = 0,
-    Board = 1,
-}
-
 impl std::default::Default for ViewDataTypePB {
     fn default() -> Self {
         ViewDataTypeRevision::default().into()
@@ -69,7 +63,7 @@ impl std::default::Default for ViewDataTypePB {
 impl std::convert::From<ViewDataTypeRevision> for ViewDataTypePB {
     fn from(rev: ViewDataTypeRevision) -> Self {
         match rev {
-            ViewDataTypeRevision::TextBlock => ViewDataTypePB::TextBlock,
+            ViewDataTypeRevision::Document => ViewDataTypePB::Document,
             ViewDataTypeRevision::Database => ViewDataTypePB::Database,
         }
     }
@@ -78,12 +72,24 @@ impl std::convert::From<ViewDataTypeRevision> for ViewDataTypePB {
 impl std::convert::From<ViewDataTypePB> for ViewDataTypeRevision {
     fn from(ty: ViewDataTypePB) -> Self {
         match ty {
-            ViewDataTypePB::TextBlock => ViewDataTypeRevision::TextBlock,
+            ViewDataTypePB::Document => ViewDataTypeRevision::Document,
             ViewDataTypePB::Database => ViewDataTypeRevision::Database,
         }
     }
 }
 
+#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
+pub enum ViewLayoutTypePB {
+    Grid = 0,
+    Board = 1,
+}
+
+impl std::default::Default for ViewLayoutTypePB {
+    fn default() -> Self {
+        ViewLayoutTypePB::Grid
+    }
+}
+
 #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)]
 pub struct RepeatedViewPB {
     #[pb(index = 1)]
@@ -121,14 +127,14 @@ pub struct CreateViewPayloadPB {
     #[pb(index = 5)]
     pub data_type: ViewDataTypePB,
 
-    #[pb(index = 6, one_of)]
-    pub sub_data_type: Option<SubViewDataTypePB>,
+    #[pb(index = 6)]
+    pub layout: ViewLayoutTypePB,
 
     #[pb(index = 7)]
     pub plugin_type: i32,
 
     #[pb(index = 8)]
-    pub data: Vec<u8>,
+    pub view_content_data: Vec<u8>,
 }
 
 #[derive(Debug, Clone)]
@@ -138,9 +144,9 @@ pub struct CreateViewParams {
     pub desc: String,
     pub thumbnail: String,
     pub data_type: ViewDataTypePB,
-    pub sub_data_type: Option<SubViewDataTypePB>,
+    pub layout: ViewLayoutTypePB,
     pub view_id: String,
-    pub data: Vec<u8>,
+    pub view_content_data: Vec<u8>,
     pub plugin_type: i32,
 }
 
@@ -161,10 +167,10 @@ impl TryInto<CreateViewParams> for CreateViewPayloadPB {
             name,
             desc: self.desc,
             data_type: self.data_type,
-            sub_data_type: self.sub_data_type,
+            layout: self.layout,
             thumbnail,
             view_id,
-            data: self.data,
+            view_content_data: self.view_content_data,
             plugin_type: self.plugin_type,
         })
     }

+ 3 - 3
frontend/rust-lib/flowy-folder/src/manager.rs

@@ -1,5 +1,5 @@
 use crate::entities::view::ViewDataTypePB;
-use crate::entities::SubViewDataTypePB;
+use crate::entities::ViewLayoutTypePB;
 use crate::services::folder_editor::FolderRevisionCompactor;
 use crate::{
     dart_notification::{send_dart_notification, FolderNotification},
@@ -222,7 +222,7 @@ impl DefaultFolderBuilder {
                 };
                 let _ = view_controller.set_latest_view(&view.id);
                 let _ = view_controller
-                    .create_view(&view.id, ViewDataTypePB::TextBlock, Bytes::from(view_data))
+                    .create_view(&view.id, ViewDataTypePB::Document, Bytes::from(view_data))
                     .await?;
             }
         }
@@ -261,7 +261,7 @@ pub trait ViewDataProcessor {
         &self,
         user_id: &str,
         view_id: &str,
-        sub_data_type: Option<SubViewDataTypePB>,
+        sub_data_type: ViewLayoutTypePB,
     ) -> FutureResult<Bytes, FlowyError>;
 
     fn create_view_from_delta_data(

+ 4 - 4
frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs

@@ -87,13 +87,13 @@ pub(crate) struct ViewTable {
 impl ViewTable {
     pub fn new(view_rev: ViewRevision) -> Self {
         let data_type = match view_rev.data_type {
-            ViewDataTypeRevision::TextBlock => SqlViewDataType::Block,
+            ViewDataTypeRevision::Document => SqlViewDataType::Block,
             ViewDataTypeRevision::Database => SqlViewDataType::Grid,
         };
 
         ViewTable {
             id: view_rev.id,
-            belong_to_id: view_rev.belong_to_id,
+            belong_to_id: view_rev.app_id,
             name: view_rev.name,
             desc: view_rev.desc,
             modified_time: view_rev.modified_time,
@@ -110,13 +110,13 @@ impl ViewTable {
 impl std::convert::From<ViewTable> for ViewRevision {
     fn from(table: ViewTable) -> Self {
         let data_type = match table.view_type {
-            SqlViewDataType::Block => ViewDataTypeRevision::TextBlock,
+            SqlViewDataType::Block => ViewDataTypeRevision::Document,
             SqlViewDataType::Grid => ViewDataTypeRevision::Database,
         };
 
         ViewRevision {
             id: table.id,
-            belong_to_id: table.belong_to_id,
+            app_id: table.belong_to_id,
             name: table.name,
             desc: table.desc,
             data_type,

+ 34 - 15
frontend/rust-lib/flowy-folder/src/services/view/controller.rs

@@ -1,5 +1,5 @@
 pub use crate::entities::view::ViewDataTypePB;
-use crate::entities::ViewInfoPB;
+use crate::entities::{ViewInfoPB, ViewLayoutTypePB};
 use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
 use crate::{
     dart_notification::{send_dart_notification, FolderNotification},
@@ -19,6 +19,7 @@ use flowy_database::kv::KV;
 use flowy_folder_data_model::revision::{gen_view_id, ViewRevision};
 use flowy_sync::entities::text_block::TextBlockIdPB;
 use futures::{FutureExt, StreamExt};
+use lib_infra::util::timestamp;
 use std::{collections::HashSet, sync::Arc};
 
 const LATEST_VIEW_ID: &str = "latest_view_id";
@@ -60,14 +61,14 @@ impl ViewController {
     ) -> Result<ViewRevision, FlowyError> {
         let processor = self.get_data_processor(params.data_type.clone())?;
         let user_id = self.user.user_id()?;
-        if params.data.is_empty() {
+        if params.view_content_data.is_empty() {
             let view_data = processor
-                .create_default_view(&user_id, &params.view_id, params.sub_data_type.clone())
+                .create_default_view(&user_id, &params.view_id, params.layout.clone())
                 .await?;
-            params.data = view_data.to_vec();
+            params.view_content_data = view_data.to_vec();
         } else {
             let delta_data = processor
-                .create_view_from_delta_data(&user_id, &params.view_id, params.data.clone())
+                .create_view_from_delta_data(&user_id, &params.view_id, params.view_content_data.clone())
                 .await?;
             let _ = self
                 .create_view(&params.view_id, params.data_type.clone(), delta_data)
@@ -99,7 +100,7 @@ impl ViewController {
         let trash_controller = self.trash_controller.clone();
         self.persistence
             .begin_transaction(|transaction| {
-                let belong_to_id = view_rev.belong_to_id.clone();
+                let belong_to_id = view_rev.app_id.clone();
                 let _ = transaction.create_view(view_rev)?;
                 let _ = notify_views_changed(&belong_to_id, trash_controller, &transaction)?;
                 Ok(())
@@ -139,7 +140,7 @@ impl ViewController {
 
                 let view_info = ViewInfoPB {
                     id: view_rev.id,
-                    belong_to_id: view_rev.belong_to_id,
+                    belong_to_id: view_rev.app_id,
                     name: view_rev.name,
                     desc: view_rev.desc,
                     data_type: view_rev.data_type.into(),
@@ -197,7 +198,7 @@ impl ViewController {
             .begin_transaction(|transaction| {
                 let _ = transaction.move_view(view_id, from, to)?;
                 let view = transaction.read_view(view_id)?;
-                let _ = notify_views_changed(&view.belong_to_id, self.trash_controller.clone(), &transaction)?;
+                let _ = notify_views_changed(&view.app_id, self.trash_controller.clone(), &transaction)?;
                 Ok(())
             })
             .await?;
@@ -214,13 +215,13 @@ impl ViewController {
         let processor = self.get_data_processor(view_rev.data_type.clone())?;
         let delta_bytes = processor.get_delta_data(view_id).await?;
         let duplicate_params = CreateViewParams {
-            belong_to_id: view_rev.belong_to_id.clone(),
+            belong_to_id: view_rev.app_id.clone(),
             name: format!("{} (copy)", &view_rev.name),
             desc: view_rev.desc,
             thumbnail: view_rev.thumbnail,
             data_type: view_rev.data_type.into(),
-            sub_data_type: None,
-            data: delta_bytes.to_vec(),
+            layout: ViewLayoutTypePB::Board,
+            view_content_data: delta_bytes.to_vec(),
             view_id: gen_view_id(),
             plugin_type: view_rev.plugin_type,
         };
@@ -252,7 +253,7 @@ impl ViewController {
                 send_dart_notification(&view_id, FolderNotification::ViewUpdated)
                     .payload(view)
                     .send();
-                let _ = notify_views_changed(&view_rev.belong_to_id, self.trash_controller.clone(), &transaction)?;
+                let _ = notify_views_changed(&view_rev.app_id, self.trash_controller.clone(), &transaction)?;
                 Ok(view_rev)
             })
             .await?;
@@ -395,7 +396,7 @@ async fn handle_trash_event(
                 .begin_transaction(|transaction| {
                     let view_revs = read_local_views_with_transaction(identifiers, &transaction)?;
                     for view_rev in view_revs {
-                        let _ = notify_views_changed(&view_rev.belong_to_id, trash_can.clone(), &transaction)?;
+                        let _ = notify_views_changed(&view_rev.app_id, trash_can.clone(), &transaction)?;
                         notify_dart(view_rev.into(), FolderNotification::ViewDeleted);
                     }
                     Ok(())
@@ -408,7 +409,7 @@ async fn handle_trash_event(
                 .begin_transaction(|transaction| {
                     let view_revs = read_local_views_with_transaction(identifiers, &transaction)?;
                     for view_rev in view_revs {
-                        let _ = notify_views_changed(&view_rev.belong_to_id, trash_can.clone(), &transaction)?;
+                        let _ = notify_views_changed(&view_rev.app_id, trash_can.clone(), &transaction)?;
                         notify_dart(view_rev.into(), FolderNotification::ViewRestored);
                     }
                     Ok(())
@@ -425,7 +426,7 @@ async fn handle_trash_event(
                         for identifier in identifiers.items {
                             let view = transaction.read_view(&identifier.id)?;
                             let _ = transaction.delete_view(&view.id)?;
-                            notify_ids.insert(view.belong_to_id.clone());
+                            notify_ids.insert(view.app_id.clone());
                             views.push(view);
                         }
                         for notify_id in notify_ids {
@@ -453,6 +454,24 @@ async fn handle_trash_event(
     }
 }
 
+fn make_view_rev_from(params: CreateViewParams) -> ViewRevision {
+    let time = timestamp();
+    ViewRevision {
+        id: params.view_id,
+        app_id: params.belong_to_id,
+        name: params.name,
+        desc: params.desc,
+        data_type: params.data_type.into(),
+        version: 0,
+        belongings: vec![],
+        modified_time: time,
+        create_time: time,
+        ext_data: "".to_string(),
+        thumbnail: params.thumbnail,
+        plugin_type: params.plugin_type,
+    }
+}
+
 fn get_data_processor(
     data_processors: ViewDataProcessorMap,
     data_type: &ViewDataTypePB,

+ 4 - 4
frontend/rust-lib/flowy-folder/tests/workspace/folder_test.rs

@@ -134,7 +134,7 @@ async fn app_create_with_view() {
         CreateView {
             name: "View A".to_owned(),
             desc: "View A description".to_owned(),
-            data_type: ViewDataTypePB::TextBlock,
+            data_type: ViewDataTypePB::Document,
         },
         CreateView {
             name: "Grid".to_owned(),
@@ -198,7 +198,7 @@ async fn view_delete_all() {
         CreateView {
             name: "View A".to_owned(),
             desc: "View A description".to_owned(),
-            data_type: ViewDataTypePB::TextBlock,
+            data_type: ViewDataTypePB::Document,
         },
         CreateView {
             name: "Grid".to_owned(),
@@ -231,7 +231,7 @@ async fn view_delete_all_permanent() {
         CreateView {
             name: "View A".to_owned(),
             desc: "View A description".to_owned(),
-            data_type: ViewDataTypePB::TextBlock,
+            data_type: ViewDataTypePB::Document,
         },
         ReadApp(app.id.clone()),
     ])
@@ -330,7 +330,7 @@ async fn folder_sync_revision_with_new_view() {
         CreateView {
             name: view_name.clone(),
             desc: view_desc.clone(),
-            data_type: ViewDataTypePB::TextBlock,
+            data_type: ViewDataTypePB::Document,
         },
         AssertCurrentRevId(3),
         AssertNextSyncRevId(Some(3)),

+ 6 - 6
frontend/rust-lib/flowy-folder/tests/workspace/script.rs

@@ -5,7 +5,7 @@ use flowy_folder::entities::{
     trash::{RepeatedTrashPB, TrashIdPB, TrashType},
     view::{CreateViewPayloadPB, UpdateViewPayloadPB},
     workspace::{CreateWorkspacePayloadPB, RepeatedWorkspacePB},
-    SubViewDataTypePB,
+    ViewLayoutTypePB,
 };
 use flowy_folder::entities::{
     app::{AppPB, RepeatedAppPB},
@@ -99,7 +99,7 @@ impl FolderTest {
             &app.id,
             "Folder View",
             "Folder test view",
-            ViewDataTypePB::TextBlock,
+            ViewDataTypePB::Document,
         )
         .await;
         app.belongings = RepeatedViewPB {
@@ -355,8 +355,8 @@ pub async fn create_view(
     data_type: ViewDataTypePB,
 ) -> ViewPB {
     let sub_data_type = match data_type {
-        ViewDataTypePB::TextBlock => None,
-        ViewDataTypePB::Database => Some(SubViewDataTypePB::Grid),
+        ViewDataTypePB::Document => None,
+        ViewDataTypePB::Database => Some(ViewLayoutTypePB::Grid),
     };
 
     let request = CreateViewPayloadPB {
@@ -365,9 +365,9 @@ pub async fn create_view(
         desc: desc.to_string(),
         thumbnail: None,
         data_type,
-        sub_data_type,
+        layout: sub_data_type,
         plugin_type: 0,
-        data: vec![],
+        view_content_data: vec![],
     };
     let view = FolderEventBuilder::new(sdk.clone())
         .event(CreateView)

+ 12 - 3
frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs

@@ -19,9 +19,18 @@ pub struct GroupRowsChangesetPB {
 
 impl std::fmt::Display for GroupRowsChangesetPB {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        let _ = f.write_fmt(format_args!("Group:{}", self.group_id))?;
-        let _ = f.write_fmt(format_args!("Insert:{:?}", self.inserted_rows))?;
-        f.write_fmt(format_args!("Delete:{:?}", self.deleted_rows))
+        for inserted_row in &self.inserted_rows {
+            let _ = f.write_fmt(format_args!(
+                "Insert: {} row at {:?}",
+                inserted_row.row.id, inserted_row.index
+            ))?;
+        }
+
+        for deleted_row in &self.deleted_rows {
+            let _ = f.write_fmt(format_args!("Delete: {} row", deleted_row))?;
+        }
+
+        Ok(())
     }
 }
 

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

@@ -225,7 +225,7 @@ async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType)
     Ok(type_option_data)
 }
 
-#[tracing::instrument(level = "debug", skip(data, manager), err)]
+// #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn get_row_handler(
     data: Data<RowIdPB>,
     manager: AppData<Arc<GridManager>>,

+ 0 - 2
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs

@@ -65,10 +65,8 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSel
         let select_option_changeset = changeset.try_into_inner()?;
         let new_cell_data: String;
         if let Some(insert_option_id) = select_option_changeset.insert_option_id {
-            tracing::trace!("Insert single select option: {}", &insert_option_id);
             new_cell_data = insert_option_id;
         } else {
-            tracing::trace!("Delete single select option");
             new_cell_data = "".to_string()
         }
 

+ 7 - 2
frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs

@@ -117,7 +117,12 @@ impl GridViewRevisionEditor {
         }
     }
 
-    pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, upper_row_id: &str) {
+    pub(crate) async fn did_move_row(
+        &self,
+        row_rev: &RowRevision,
+        row_changeset: &mut RowChangeset,
+        upper_row_id: &str,
+    ) {
         if let Some(changesets) = self
             .group_service
             .write()
@@ -128,7 +133,7 @@ impl GridViewRevisionEditor {
             .await
         {
             for changeset in changesets {
-                tracing::trace!("Group changeset: {}", changeset);
+                tracing::trace!("Group: {} changeset: {}", changeset.group_id, changeset);
                 self.notify_did_update_group(changeset).await;
             }
         }

+ 1 - 0
frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs

@@ -277,6 +277,7 @@ where
         if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
             let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev);
             let cell_data = cell_bytes.parser::<P>()?;
+            tracing::trace!("Move row:{} to row:{}", row_rev.id, to_row_id);
             Ok(self.move_row_if_match(field_rev, row_rev, row_changeset, &cell_data, to_row_id))
         } else {
             Ok(vec![])

+ 13 - 5
frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs

@@ -248,11 +248,15 @@ fn move_row(
     to_row_id: &str,
 ) {
     cell_data.select_options.iter().for_each(|option| {
-        if option.id == group.id && group.contains_row(&row_rev.id) {
-            group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
-            group.remove_row(&row_rev.id);
+        // Remove the row in which group contains the row
+        if option.id == group.id {
+            if group.contains_row(&row_rev.id) {
+                group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
+                group.remove_row(&row_rev.id);
+            }
         }
 
+        // Find the inserted group
         if let Some(index) = group.index_of_row(to_row_id) {
             let row_pb = RowPB::from(row_rev);
             let inserted_row = InsertedRowPB {
@@ -262,8 +266,12 @@ fn move_row(
             group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row]));
             group.insert_row(index, row_pb);
 
-            let cell_rev = insert_select_option_cell(group.id.clone(), field_rev);
-            row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev);
+            // If the inserted row comes from other group, it needs to update the corresponding cell content.
+            if option.id != group.id {
+                // Update the corresponding row's cell content.
+                let cell_rev = insert_select_option_cell(group.id.clone(), field_rev);
+                row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev);
+            }
         }
     });
 }

+ 1 - 1
frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs

@@ -36,7 +36,7 @@ pub struct GridFilterTest {
 
 impl GridFilterTest {
     pub async fn new() -> Self {
-     let editor_test =  GridEditorTest::new().await;
+        let editor_test =  GridEditorTest::new().await;
         Self {
             inner: editor_test
         }

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

@@ -0,0 +1 @@
+mod script;

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

@@ -0,0 +1,54 @@
+use crate::grid::grid_editor::GridEditorTest;
+use flowy_grid::entities::MoveRowParams;
+
+pub enum GroupScript {
+    MoveCard { from_row_id: String, to_row_id: String },
+    AssertGroupCount(usize),
+}
+
+pub struct GridGroupTest {
+    inner: GridEditorTest,
+}
+
+impl GridGroupTest {
+    pub async fn new() -> Self {
+        let editor_test = GridEditorTest::new().await;
+        Self { inner: editor_test }
+    }
+
+    pub async fn run_scripts(&mut self, scripts: Vec<GroupScript>) {
+        for script in scripts {
+            self.run_script(script).await;
+        }
+    }
+
+    pub async fn run_script(&mut self, script: GroupScript) {
+        match script {
+            GroupScript::MoveCard { from_row_id, to_row_id } => {
+                let params = MoveRowParams {
+                    view_id: self.inner.grid_id.clone(),
+                    from_row_id,
+                    to_row_id,
+                };
+                let _ = self.editor.move_row(params).await.unwrap();
+            }
+            GroupScript::AssertGroupCount(count) => {
+                //
+            }
+        }
+    }
+}
+
+impl std::ops::Deref for GridGroupTest {
+    type Target = GridEditorTest;
+
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+impl std::ops::DerefMut for GridGroupTest {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.inner
+    }
+}

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

@@ -3,3 +3,4 @@ mod cell_test;
 mod field_test;
 mod filter_test;
 mod grid_editor;
+mod group_test;

+ 1 - 1
frontend/rust-lib/flowy-net/src/local_server/server.rs

@@ -305,7 +305,7 @@ impl FolderCouldServiceV1 for LocalServer {
         let time = timestamp();
         let view = ViewRevision {
             id: params.view_id,
-            belong_to_id: params.belong_to_id,
+            app_id: params.belong_to_id,
             name: params.name,
             desc: params.desc,
             data_type: params.data_type.into(),

+ 7 - 7
frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs

@@ -1,6 +1,6 @@
 use bytes::Bytes;
 use flowy_database::ConnectionPool;
-use flowy_folder::entities::{SubViewDataTypePB, ViewDataTypePB};
+use flowy_folder::entities::{ViewDataTypePB, ViewLayoutTypePB};
 use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap};
 use flowy_folder::{
     errors::{internal_error, FlowyError},
@@ -184,7 +184,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
         &self,
         user_id: &str,
         view_id: &str,
-        _sub_data_type: Option<SubViewDataTypePB>,
+        sub_data_type: ViewLayoutTypePB,
     ) -> FutureResult<Bytes, FlowyError> {
         let user_id = user_id.to_string();
         let view_id = view_id.to_string();
@@ -209,7 +209,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
     }
 
     fn data_type(&self) -> ViewDataTypePB {
-        ViewDataTypePB::TextBlock
+        ViewDataTypePB::Document
     }
 }
 
@@ -261,11 +261,11 @@ impl ViewDataProcessor for GridViewDataProcessor {
         &self,
         user_id: &str,
         view_id: &str,
-        sub_data_type: Option<SubViewDataTypePB>,
+        sub_data_type: ViewLayoutTypePB,
     ) -> FutureResult<Bytes, FlowyError> {
-        let build_context = match sub_data_type.unwrap() {
-            SubViewDataTypePB::Grid => make_default_grid(),
-            SubViewDataTypePB::Board => make_default_board(),
+        let build_context = match sub_data_type {
+            ViewLayoutTypePB::Grid => make_default_grid(),
+            ViewLayoutTypePB::Board => make_default_board(),
         };
         let user_id = user_id.to_string();
         let view_id = view_id.to_string();

+ 1 - 1
frontend/rust-lib/flowy-sdk/src/lib.rs

@@ -74,7 +74,7 @@ fn crate_log_filter(level: String) -> String {
     filters.push(format!("lib_ot={}", level));
     filters.push(format!("lib_ws={}", level));
     filters.push(format!("lib_infra={}", level));
-    filters.push(format!("flowy_sync={}", level));
+    // filters.push(format!("flowy_sync={}", level));
     // filters.push(format!("flowy_revision={}", level));
     // filters.push(format!("lib_dispatch={}", level));
 

+ 22 - 7
frontend/rust-lib/flowy-test/src/helper.rs

@@ -25,11 +25,16 @@ pub struct ViewTest {
 
 impl ViewTest {
     #[allow(dead_code)]
-    pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataTypePB, data: Vec<u8>) -> Self {
+    pub async fn new(
+        sdk: &FlowySDKTest,
+        data_type: ViewDataTypePB,
+        sub_data_type: ViewLayoutTypePB,
+        data: Vec<u8>,
+    ) -> Self {
         let workspace = create_workspace(sdk, "Workspace", "").await;
         open_workspace(sdk, &workspace.id).await;
         let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
-        let view = create_view(sdk, &app.id, data_type, data).await;
+        let view = create_view(sdk, &app.id, data_type, sub_data_type, data).await;
         Self {
             sdk: sdk.clone(),
             workspace,
@@ -39,11 +44,15 @@ impl ViewTest {
     }
 
     pub async fn new_grid_view(sdk: &FlowySDKTest, data: Vec<u8>) -> Self {
-        Self::new(sdk, ViewDataTypePB::Database, data).await
+        Self::new(sdk, ViewDataTypePB::Database, ViewLayoutTypePB::Grid, data).await
+    }
+
+    pub async fn new_board_view(sdk: &FlowySDKTest, data: Vec<u8>) -> Self {
+        Self::new(sdk, ViewDataTypePB::Database, ViewLayoutTypePB::Board, data).await
     }
 
     pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self {
-        Self::new(sdk, ViewDataTypePB::TextBlock, vec![]).await
+        Self::new(sdk, ViewDataTypePB::Document, ViewLayoutTypePB::Grid, vec![]).await
     }
 }
 
@@ -90,16 +99,22 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s
     app
 }
 
-async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataTypePB, data: Vec<u8>) -> ViewPB {
+async fn create_view(
+    sdk: &FlowySDKTest,
+    app_id: &str,
+    data_type: ViewDataTypePB,
+    sub_data_type: ViewLayoutTypePB,
+    data: Vec<u8>,
+) -> ViewPB {
     let request = CreateViewPayloadPB {
         belong_to_id: app_id.to_string(),
         name: "View A".to_string(),
         desc: "".to_string(),
         thumbnail: Some("http://1.png".to_string()),
         data_type,
-        sub_data_type: None,
+        layout: sub_data_type,
         plugin_type: 0,
-        data,
+        view_content_data: data,
     };
 
     let view = FolderEventBuilder::new(sdk.clone())

+ 5 - 3
shared-lib/flowy-folder-data-model/src/revision/view_rev.rs

@@ -9,7 +9,9 @@ pub fn gen_view_id() -> String {
 pub struct ViewRevision {
     pub id: String,
 
-    pub belong_to_id: String,
+    // Maybe app_id or vi
+    #[serde(rename = "belong_to_id")]
+    pub app_id: String,
 
     pub name: String,
 
@@ -52,12 +54,12 @@ impl std::convert::From<ViewRevision> for TrashRevision {
 #[derive(Eq, PartialEq, Debug, Clone, Serialize_repr, Deserialize_repr)]
 #[repr(u8)]
 pub enum ViewDataTypeRevision {
-    TextBlock = 0,
+    Document = 0,
     Database = 1,
 }
 
 impl std::default::Default for ViewDataTypeRevision {
     fn default() -> Self {
-        ViewDataTypeRevision::TextBlock
+        ViewDataTypeRevision::Document
     }
 }

+ 2 - 2
shared-lib/flowy-folder-data-model/src/user_default.rs

@@ -46,10 +46,10 @@ fn create_default_view(app_id: String, time: chrono::DateTime<Utc>) -> ViewRevis
 
     ViewRevision {
         id: view_id,
-        belong_to_id: app_id,
+        app_id: app_id,
         name,
         desc: "".to_string(),
-        data_type: ViewDataTypeRevision::TextBlock,
+        data_type: ViewDataTypeRevision::Document,
         version: 0,
         belongings: vec![],
         modified_time: time.timestamp(),

+ 5 - 5
shared-lib/flowy-sync/src/client_folder/folder_pad.rs

@@ -202,7 +202,7 @@ impl FolderPad {
 
     #[tracing::instrument(level = "trace", skip(self), fields(view_name=%view_rev.name), err)]
     pub fn create_view(&mut self, view_rev: ViewRevision) -> CollaborateResult<Option<FolderChangeset>> {
-        let app_id = view_rev.belong_to_id.clone();
+        let app_id = view_rev.app_id.clone();
         self.with_app(&app_id, move |app| {
             if app.belongings.contains(&view_rev) {
                 tracing::warn!("[RootFolder]: Duplicate view");
@@ -243,7 +243,7 @@ impl FolderPad {
         modified_time: i64,
     ) -> CollaborateResult<Option<FolderChangeset>> {
         let view = self.read_view(view_id)?;
-        self.with_view(&view.belong_to_id, view_id, |view| {
+        self.with_view(&view.app_id, view_id, |view| {
             if let Some(name) = name {
                 view.name = name;
             }
@@ -260,7 +260,7 @@ impl FolderPad {
     #[tracing::instrument(level = "trace", skip(self), err)]
     pub fn delete_view(&mut self, view_id: &str) -> CollaborateResult<Option<FolderChangeset>> {
         let view = self.read_view(view_id)?;
-        self.with_app(&view.belong_to_id, |app| {
+        self.with_app(&view.app_id, |app| {
             app.belongings.retain(|view| view.id != view_id);
             Ok(Some(()))
         })
@@ -269,7 +269,7 @@ impl FolderPad {
     #[tracing::instrument(level = "trace", skip(self), err)]
     pub fn move_view(&mut self, view_id: &str, from: usize, to: usize) -> CollaborateResult<Option<FolderChangeset>> {
         let view = self.read_view(view_id)?;
-        self.with_app(&view.belong_to_id, |app| {
+        self.with_app(&view.app_id, |app| {
             match move_vec_element(&mut app.belongings, |view| view.id == view_id, from, to).map_err(internal_error)? {
                 true => Ok(Some(())),
                 false => Ok(None),
@@ -807,7 +807,7 @@ mod tests {
     fn test_view_folder() -> (FolderPad, FolderDelta, ViewRevision) {
         let (mut folder, mut initial_delta, app) = test_app_folder();
         let mut view_rev = ViewRevision::default();
-        view_rev.belong_to_id = app.id.clone();
+        view_rev.app_id = app.id.clone();
         view_rev.name = "🎃 my first view".to_owned();
 
         initial_delta = initial_delta

+ 0 - 4
shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs

@@ -204,10 +204,6 @@ impl GridBlockRevisionPad {
                     None => Ok(None),
                     Some(delta) => {
                         tracing::trace!("[GridBlockRevision] Composing delta {}", delta.json_str());
-                        // tracing::debug!(
-                        //     "[GridBlockMeta] current delta: {}",
-                        //     self.delta.to_str().unwrap_or_else(|_| "".to_string())
-                        // );
                         self.delta = self.delta.compose(&delta)?;
                         Ok(Some(GridBlockRevisionChangeset {
                             delta,