Bläddra i källkod

chore: group the row after updated the row

appflowy 2 år sedan
förälder
incheckning
9922645e59

+ 45 - 0
frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs

@@ -0,0 +1,45 @@
+use crate::services::block_manager::GridBlockManager;
+use crate::services::grid_view_manager::{GridViewRowDelegate, GridViewRowOperation};
+use flowy_error::FlowyResult;
+use flowy_grid_data_model::revision::RowRevision;
+use lib_infra::future::{wrap_future, AFFuture};
+use std::sync::Arc;
+
+impl GridViewRowDelegate for Arc<GridBlockManager> {
+    fn gv_index_of_row(&self, row_id: &str) -> AFFuture<Option<usize>> {
+        let block_manager = self.clone();
+        let row_id = row_id.to_owned();
+        wrap_future(async move { block_manager.index_of_row(&row_id).await })
+    }
+
+    fn gv_get_row_rev(&self, row_id: &str) -> AFFuture<Option<Arc<RowRevision>>> {
+        let block_manager = self.clone();
+        let row_id = row_id.to_owned();
+        wrap_future(async move {
+            match block_manager.get_row_rev(&row_id).await {
+                Ok(row_rev) => row_rev,
+                Err(_) => None,
+            }
+        })
+    }
+
+    fn gv_row_revs(&self) -> AFFuture<Vec<Arc<RowRevision>>> {
+        let block_manager = self.clone();
+
+        wrap_future(async move {
+            let blocks = block_manager.get_block_snapshots(None).await.unwrap();
+            blocks
+                .into_iter()
+                .map(|block| block.row_revs)
+                .flatten()
+                .collect::<Vec<Arc<RowRevision>>>()
+        })
+    }
+}
+
+impl GridViewRowOperation for Arc<GridBlockManager> {
+    fn gv_move_row(&self, row_rev: Arc<RowRevision>, from: usize, to: usize) -> AFFuture<FlowyResult<()>> {
+        let block_manager = self.clone();
+        wrap_future(async move { block_manager.move_row(row_rev, from, to).await })
+    }
+}

+ 5 - 3
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -3,6 +3,7 @@ use crate::entities::GridCellIdParams;
 use crate::entities::*;
 use crate::manager::{GridTaskSchedulerRwLock, GridUser};
 use crate::services::block_manager::GridBlockManager;
+use crate::services::block_manager_trait_impl::*;
 use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data, CellBytes};
 use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
 use crate::services::filter::GridFilterService;
@@ -11,7 +12,6 @@ use crate::services::persistence::block_index::BlockIndexCache;
 use crate::services::row::{
     make_grid_blocks, make_row_from_row_rev, make_rows_from_row_revs, GridBlockSnapshot, RowRevisionBuilder,
 };
-
 use bytes::Bytes;
 use flowy_error::{ErrorCode, FlowyError, FlowyResult};
 use flowy_grid_data_model::revision::*;
@@ -68,9 +68,11 @@ impl GridRevisionEditor {
         // View manager
         let view_manager = Arc::new(
             GridViewManager::new(
+                grid_id.to_owned(),
                 user.clone(),
-                grid_pad.clone(),
-                block_manager.clone(),
+                Arc::new(grid_pad.clone()),
+                Arc::new(block_manager.clone()),
+                Arc::new(block_manager.clone()),
                 Arc::new(task_scheduler.clone()),
             )
             .await?,

+ 32 - 0
frontend/rust-lib/flowy-grid/src/services/grid_editor_trait_impl.rs

@@ -0,0 +1,32 @@
+use crate::services::grid_view_manager::GridViewFieldDelegate;
+use flowy_grid_data_model::revision::FieldRevision;
+use flowy_sync::client_grid::GridRevisionPad;
+use lib_infra::future::{wrap_future, AFFuture};
+use std::sync::Arc;
+use tokio::sync::RwLock;
+
+impl GridViewFieldDelegate for Arc<RwLock<GridRevisionPad>> {
+    fn get_field_revs(&self) -> AFFuture<Vec<Arc<FieldRevision>>> {
+        let pad = self.clone();
+        wrap_future(async move {
+            match pad.read().await.get_field_revs(None) {
+                Ok(field_revs) => field_revs,
+                Err(e) => {
+                    tracing::error!("[GridViewRevisionDelegate] get field revisions failed: {}", e);
+                    vec![]
+                }
+            }
+        })
+    }
+
+    fn get_field_rev(&self, field_id: &str) -> AFFuture<Option<Arc<FieldRevision>>> {
+        let pad = self.clone();
+        let field_id = field_id.to_owned();
+        wrap_future(async move {
+            pad.read()
+                .await
+                .get_field_rev(&field_id)
+                .map(|(_, field_rev)| field_rev.clone())
+        })
+    }
+}

+ 51 - 45
frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs

@@ -1,59 +1,44 @@
-use flowy_error::{FlowyError, FlowyResult};
-
+use crate::dart_notification::{send_dart_notification, GridNotification};
 use crate::entities::{
     CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, GroupPB, GroupRowsChangesetPB, InsertedRowPB,
     RowPB,
 };
 use crate::services::grid_editor_task::GridServiceTaskScheduler;
+use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
 use crate::services::group::{default_group_configuration, Group, GroupConfigurationDelegate, GroupService};
+use crate::services::setting::make_grid_setting;
+use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowRevision};
 use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder};
 use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
-use flowy_sync::entities::revision::Revision;
-
-use crate::dart_notification::{send_dart_notification, GridNotification};
-use crate::services::setting::make_grid_setting;
 use flowy_sync::entities::grid::GridSettingChangesetParams;
+use flowy_sync::entities::revision::Revision;
 use lib_infra::future::{wrap_future, AFFuture, FutureResult};
 use std::sync::Arc;
 use tokio::sync::RwLock;
 
-pub trait GridViewRevisionDelegate: Send + Sync + 'static {
-    fn get_field_revs(&self) -> AFFuture<Vec<Arc<FieldRevision>>>;
-    fn get_field_rev(&self, field_id: &str) -> AFFuture<Option<Arc<FieldRevision>>>;
-}
-
-pub trait GridViewRevisionRowDataSource: Send + Sync + 'static {
-    fn row_revs(&self) -> AFFuture<Vec<Arc<RowRevision>>>;
-}
-
 #[allow(dead_code)]
 pub struct GridViewRevisionEditor {
     user_id: String,
     view_id: String,
     pad: Arc<RwLock<GridViewRevisionPad>>,
     rev_manager: Arc<RevisionManager>,
-    delegate: Arc<dyn GridViewRevisionDelegate>,
-    data_source: Arc<dyn GridViewRevisionRowDataSource>,
+    field_delegate: Arc<dyn GridViewFieldDelegate>,
+    row_delegate: Arc<dyn GridViewRowDelegate>,
     group_service: Arc<RwLock<GroupService>>,
-    groups: Arc<RwLock<Vec<Group>>>,
     scheduler: Arc<dyn GridServiceTaskScheduler>,
 }
 
 impl GridViewRevisionEditor {
-    pub(crate) async fn new<Delegate, DataSource>(
+    pub(crate) async fn new(
         user_id: &str,
         token: &str,
         view_id: String,
-        delegate: Delegate,
-        data_source: DataSource,
+        field_delegate: Arc<dyn GridViewFieldDelegate>,
+        row_delegate: Arc<dyn GridViewRowDelegate>,
         scheduler: Arc<dyn GridServiceTaskScheduler>,
         mut rev_manager: RevisionManager,
-    ) -> FlowyResult<Self>
-    where
-        Delegate: GridViewRevisionDelegate,
-        DataSource: GridViewRevisionRowDataSource,
-    {
+    ) -> FlowyResult<Self> {
         let cloud = Arc::new(GridViewRevisionCloudService {
             token: token.to_owned(),
         });
@@ -62,16 +47,14 @@ impl GridViewRevisionEditor {
         let rev_manager = Arc::new(rev_manager);
         let group_service = GroupService::new(Box::new(pad.clone())).await;
         let user_id = user_id.to_owned();
-        let groups = Arc::new(RwLock::new(vec![]));
         Ok(Self {
             pad,
             user_id,
             view_id,
             rev_manager,
             scheduler,
-            groups,
-            delegate: Arc::new(delegate),
-            data_source: Arc::new(data_source),
+            field_delegate,
+            row_delegate,
             group_service: Arc::new(RwLock::new(group_service)),
         })
     }
@@ -87,7 +70,9 @@ impl GridViewRevisionEditor {
                     self.group_service
                         .read()
                         .await
-                        .update_row(row_rev, group_id, |field_id| self.delegate.get_field_rev(&field_id))
+                        .fill_row(row_rev, group_id, |field_id| {
+                            self.field_delegate.get_field_rev(&field_id)
+                        })
                         .await;
                 }
             },
@@ -120,34 +105,55 @@ impl GridViewRevisionEditor {
         }
     }
 
+    pub(crate) async fn did_update_row(&self, row_rev: Arc<RowRevision>) {
+        match self.group_id_of_row(&row_rev.id).await {
+            None => {}
+            Some(group_id) => {
+                // self.get_mut_group(&group_id, |group| Ok(()));
+            }
+        }
+    }
+
     async fn group_id_of_row(&self, row_id: &str) -> Option<String> {
-        let read_guard = self.groups.read().await;
+        let read_guard = &self.group_service.read().await.groups;
         for group in read_guard.iter() {
             if group.rows.iter().any(|row| row.id == row_id) {
                 return Some(group.id.clone());
             }
         }
-
         None
     }
 
-    pub(crate) async fn load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
-        let field_revs = self.delegate.get_field_revs().await;
-        let row_revs = self.data_source.row_revs().await;
+    // async fn get_mut_group<F>(&self, group_id: &str, f: F) -> FlowyResult<()>
+    // where
+    //     F: Fn(&mut Group) -> FlowyResult<()>,
+    // {
+    //     for group in self.groups.write().await.iter_mut() {
+    //         if group.id == group_id {
+    //             let _ = f(group)?;
+    //         }
+    //     }
+    //     Ok(())
+    // }
 
-        //
-        let mut write_guard = self.group_service.write().await;
-        match write_guard.load_groups(&field_revs, row_revs).await {
+    pub(crate) async fn load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
+        let field_revs = self.field_delegate.get_field_revs().await;
+        let row_revs = self.row_delegate.gv_row_revs().await;
+
+        match self
+            .group_service
+            .write()
+            .await
+            .load_groups(&field_revs, row_revs)
+            .await
+        {
             None => Ok(vec![]),
-            Some(groups) => {
-                *self.groups.write().await = groups.clone();
-                Ok(groups.into_iter().map(GroupPB::from).collect())
-            }
+            Some(groups) => Ok(groups.into_iter().map(GroupPB::from).collect()),
         }
     }
 
     pub(crate) async fn get_setting(&self) -> GridSettingPB {
-        let field_revs = self.delegate.get_field_revs().await;
+        let field_revs = self.field_delegate.get_field_revs().await;
         let grid_setting = make_grid_setting(self.pad.read().await.get_setting_rev(), &field_revs);
         grid_setting
     }
@@ -158,7 +164,7 @@ impl GridViewRevisionEditor {
     }
 
     pub(crate) async fn get_filters(&self) -> Vec<GridFilterConfiguration> {
-        let field_revs = self.delegate.get_field_revs().await;
+        let field_revs = self.field_delegate.get_field_revs().await;
         match self.pad.read().await.get_setting_rev().get_all_filters(&field_revs) {
             None => vec![],
             Some(filters) => filters

+ 51 - 68
frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs

@@ -4,9 +4,7 @@ use crate::entities::{
 use crate::manager::GridUser;
 use crate::services::block_manager::GridBlockManager;
 use crate::services::grid_editor_task::GridServiceTaskScheduler;
-use crate::services::grid_view_editor::{
-    GridViewRevisionDelegate, GridViewRevisionEditor, GridViewRevisionRowDataSource,
-};
+use crate::services::grid_view_editor::GridViewRevisionEditor;
 use bytes::Bytes;
 use dashmap::DashMap;
 use flowy_error::FlowyResult;
@@ -23,26 +21,48 @@ use tokio::sync::RwLock;
 
 type ViewId = String;
 
+pub trait GridViewFieldDelegate: Send + Sync + 'static {
+    fn get_field_revs(&self) -> AFFuture<Vec<Arc<FieldRevision>>>;
+    fn get_field_rev(&self, field_id: &str) -> AFFuture<Option<Arc<FieldRevision>>>;
+}
+
+pub trait GridViewRowDelegate: Send + Sync + 'static {
+    fn gv_index_of_row(&self, row_id: &str) -> AFFuture<Option<usize>>;
+    fn gv_get_row_rev(&self, row_id: &str) -> AFFuture<Option<Arc<RowRevision>>>;
+    fn gv_row_revs(&self) -> AFFuture<Vec<Arc<RowRevision>>>;
+}
+
+pub trait GridViewRowOperation: Send + Sync + 'static {
+    // Will be removed in the future.
+    fn gv_move_row(&self, row_rev: Arc<RowRevision>, from: usize, to: usize) -> AFFuture<FlowyResult<()>>;
+}
+
 pub(crate) struct GridViewManager {
+    grid_id: String,
     user: Arc<dyn GridUser>,
-    grid_pad: Arc<RwLock<GridRevisionPad>>,
-    block_manager: Arc<GridBlockManager>,
+    field_delegate: Arc<dyn GridViewFieldDelegate>,
+    row_delegate: Arc<dyn GridViewRowDelegate>,
+    row_operation: Arc<dyn GridViewRowOperation>,
     view_editors: DashMap<ViewId, Arc<GridViewRevisionEditor>>,
     scheduler: Arc<dyn GridServiceTaskScheduler>,
 }
 
 impl GridViewManager {
     pub(crate) async fn new(
+        grid_id: String,
         user: Arc<dyn GridUser>,
-        grid_pad: Arc<RwLock<GridRevisionPad>>,
-        block_manager: Arc<GridBlockManager>,
+        field_delegate: Arc<dyn GridViewFieldDelegate>,
+        row_delegate: Arc<dyn GridViewRowDelegate>,
+        row_operation: Arc<dyn GridViewRowOperation>,
         scheduler: Arc<dyn GridServiceTaskScheduler>,
     ) -> FlowyResult<Self> {
         Ok(Self {
+            grid_id,
             user,
-            grid_pad,
             scheduler,
-            block_manager,
+            field_delegate,
+            row_delegate,
+            row_operation,
             view_editors: DashMap::default(),
         })
     }
@@ -54,7 +74,7 @@ impl GridViewManager {
     }
 
     pub(crate) async fn did_update_row(&self, row_id: &str) {
-        let row = self.block_manager.get_row_rev(row_id).await;
+        let row = self.row_delegate.gv_get_row_rev(row_id).await;
     }
 
     pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) {
@@ -103,19 +123,19 @@ impl GridViewManager {
 
         let from_index = from_index as usize;
 
-        match self.block_manager.get_row_rev(&row_id).await? {
+        match self.row_delegate.gv_get_row_rev(&row_id).await {
             None => tracing::warn!("Move row failed, can not find the row:{}", row_id),
             Some(row_rev) => match layout {
                 GridLayout::Table => {
                     tracing::trace!("Move row from {} to {}", from_index, to_index);
                     let to_index = to_index as usize;
-                    let _ = self.block_manager.move_row(row_rev, from_index, to_index).await?;
+                    let _ = self.row_operation.gv_move_row(row_rev, from_index, to_index).await?;
                 }
                 GridLayout::Board => {
                     if let Some(upper_row_id) = upper_row_id {
-                        if let Some(to_index) = self.block_manager.index_of_row(&upper_row_id).await {
+                        if let Some(to_index) = self.row_delegate.gv_index_of_row(&upper_row_id).await {
                             tracing::trace!("Move row from {} to {}", from_index, to_index);
-                            let _ = self.block_manager.move_row(row_rev, from_index, to_index).await?;
+                            let _ = self.row_operation.gv_move_row(row_rev, from_index, to_index).await?;
                         }
                     }
                 }
@@ -132,8 +152,8 @@ impl GridViewManager {
                     make_view_editor(
                         &self.user,
                         view_id,
-                        self.grid_pad.clone(),
-                        self.block_manager.clone(),
+                        self.field_delegate.clone(),
+                        self.row_delegate.clone(),
                         self.scheduler.clone(),
                     )
                     .await?,
@@ -146,29 +166,33 @@ impl GridViewManager {
     }
 
     async fn get_default_view_editor(&self) -> FlowyResult<Arc<GridViewRevisionEditor>> {
-        let grid_id = self.grid_pad.read().await.grid_id();
-        self.get_view_editor(&grid_id).await
+        self.get_view_editor(&self.grid_id).await
     }
 }
 
-async fn make_view_editor<Delegate, DataSource>(
+async fn make_view_editor(
     user: &Arc<dyn GridUser>,
     view_id: &str,
-    delegate: Delegate,
-    data_source: DataSource,
+    field_delegate: Arc<dyn GridViewFieldDelegate>,
+    row_delegate: Arc<dyn GridViewRowDelegate>,
     scheduler: Arc<dyn GridServiceTaskScheduler>,
-) -> FlowyResult<GridViewRevisionEditor>
-where
-    Delegate: GridViewRevisionDelegate,
-    DataSource: GridViewRevisionRowDataSource,
-{
+) -> FlowyResult<GridViewRevisionEditor> {
     tracing::trace!("Open view:{} editor", view_id);
 
     let rev_manager = make_grid_view_rev_manager(user, view_id).await?;
     let user_id = user.user_id()?;
     let token = user.token()?;
     let view_id = view_id.to_owned();
-    GridViewRevisionEditor::new(&user_id, &token, view_id, delegate, data_source, scheduler, rev_manager).await
+    GridViewRevisionEditor::new(
+        &user_id,
+        &token,
+        view_id,
+        field_delegate,
+        row_delegate,
+        scheduler,
+        rev_manager,
+    )
+    .await
 }
 
 pub async fn make_grid_view_rev_manager(user: &Arc<dyn GridUser>, view_id: &str) -> FlowyResult<RevisionManager> {
@@ -197,44 +221,3 @@ impl RevisionCompactor for GridViewRevisionCompactor {
         Ok(delta.json_bytes())
     }
 }
-
-impl GridViewRevisionRowDataSource for Arc<GridBlockManager> {
-    fn row_revs(&self) -> AFFuture<Vec<Arc<RowRevision>>> {
-        let block_manager = self.clone();
-
-        wrap_future(async move {
-            let blocks = block_manager.get_block_snapshots(None).await.unwrap();
-            blocks
-                .into_iter()
-                .map(|block| block.row_revs)
-                .flatten()
-                .collect::<Vec<Arc<RowRevision>>>()
-        })
-    }
-}
-
-impl GridViewRevisionDelegate for Arc<RwLock<GridRevisionPad>> {
-    fn get_field_revs(&self) -> AFFuture<Vec<Arc<FieldRevision>>> {
-        let pad = self.clone();
-        wrap_future(async move {
-            match pad.read().await.get_field_revs(None) {
-                Ok(field_revs) => field_revs,
-                Err(e) => {
-                    tracing::error!("[GridViewRevisionDelegate] get field revisions failed: {}", e);
-                    vec![]
-                }
-            }
-        })
-    }
-
-    fn get_field_rev(&self, field_id: &str) -> AFFuture<Option<Arc<FieldRevision>>> {
-        let pad = self.clone();
-        let field_id = field_id.to_owned();
-        wrap_future(async move {
-            pad.read()
-                .await
-                .get_field_rev(&field_id)
-                .map(|(_, field_rev)| field_rev.clone())
-        })
-    }
-}

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

@@ -30,7 +30,7 @@ impl GroupActionHandler for CheckboxGroupController {
         self.handle_rows(row_revs, field_rev)
     }
 
-    fn update_card(&self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) {
+    fn fill_row(&self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) {
         todo!()
     }
 }

+ 2 - 1
frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs

@@ -27,10 +27,11 @@ pub trait Groupable {
 }
 
 pub trait GroupActionHandler: Send + Sync {
+    // The field that is used for grouping the rows
     fn field_id(&self) -> &str;
     fn build_groups(&self) -> Vec<Group>;
     fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>;
-    fn update_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
+    fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
 }
 
 pub trait GroupActionHandler2: Send + Sync {

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

@@ -38,7 +38,7 @@ impl GroupActionHandler for SingleSelectGroupController {
         self.handle_rows(row_revs, field_rev)
     }
 
-    fn update_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
+    fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
         let group: Option<&Group> = self.groups_map.get(group_id);
         match group {
             None => {}
@@ -102,7 +102,7 @@ impl GroupActionHandler for MultiSelectGroupController {
         self.handle_rows(row_revs, field_rev)
     }
 
-    fn update_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
+    fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
         let group: Option<&Group> = self.groups_map.get(group_id);
         match group {
             None => tracing::warn!("Can not find the group: {}", group_id),

+ 20 - 26
frontend/rust-lib/flowy-grid/src/services/group/group_service.rs

@@ -18,15 +18,17 @@ pub trait GroupConfigurationDelegate: Send + Sync + 'static {
 }
 
 pub(crate) struct GroupService {
+    pub groups: Vec<Group>,
     delegate: Box<dyn GroupConfigurationDelegate>,
-    action_handler: Option<Arc<RwLock<dyn GroupActionHandler>>>,
+    group_action: Option<Arc<RwLock<dyn GroupActionHandler>>>,
 }
 
 impl GroupService {
     pub(crate) async fn new(delegate: Box<dyn GroupConfigurationDelegate>) -> Self {
         Self {
+            groups: vec![],
             delegate,
-            action_handler: None,
+            group_action: None,
         }
     }
 
@@ -35,47 +37,39 @@ impl GroupService {
         field_revs: &[Arc<FieldRevision>],
         row_revs: Vec<Arc<RowRevision>>,
     ) -> Option<Vec<Group>> {
-        let field_rev = find_group_field(field_revs).unwrap();
+        let field_rev = find_group_field(field_revs)?;
         let field_type: FieldType = field_rev.field_type_rev.into();
         let configuration = self.delegate.get_group_configuration(field_rev.clone()).await;
-
         match self
             .build_groups(&field_type, &field_rev, row_revs, configuration)
             .await
         {
-            Ok(groups) => Some(groups),
+            Ok(groups) => {
+                self.groups = groups.clone();
+                Some(groups)
+            }
             Err(_) => None,
         }
     }
 
-    pub(crate) async fn update_row<F, O>(&self, row_rev: &mut RowRevision, group_id: &str, f: F)
+    pub(crate) async fn fill_row<F, O>(&self, row_rev: &mut RowRevision, group_id: &str, f: F)
     where
         F: FnOnce(String) -> O,
         O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
     {
-        if let Some(group_action_handler) = self.action_handler.as_ref() {
-            let field_id = group_action_handler.read().await.field_id().to_owned();
+        if let Some(group_action) = self.group_action.as_ref() {
+            let field_id = group_action.read().await.field_id().to_owned();
             match f(field_id).await {
                 None => {}
                 Some(field_rev) => {
-                    group_action_handler
-                        .write()
-                        .await
-                        .update_card(row_rev, &field_rev, group_id);
+                    group_action.write().await.fill_row(row_rev, &field_rev, group_id);
                 }
             }
         }
     }
-    #[allow(dead_code)]
-    pub async fn move_card(&self, _group_id: &str, _from: i32, _to: i32) {
-        // BoardCardChangesetPB {
-        //     group_id: "".to_string(),
-        //     inserted_cards: vec![],
-        //     deleted_cards: vec![],
-        //     updated_cards: vec![]
-        // }
-        // let row_pb = make_row_from_row_rev(row_rev);
-        todo!()
+
+    pub(crate) async fn did_update_row(&self, row_rev: Arc<RowRevision>) {
+        if let Some(group_action) = self.group_action.as_ref() {}
     }
 
     #[tracing::instrument(level = "trace", skip_all, err)]
@@ -98,15 +92,15 @@ impl GroupService {
             }
             FieldType::SingleSelect => {
                 let controller = SingleSelectGroupController::new(field_rev, configuration)?;
-                self.action_handler = Some(Arc::new(RwLock::new(controller)));
+                self.group_action = Some(Arc::new(RwLock::new(controller)));
             }
             FieldType::MultiSelect => {
                 let controller = MultiSelectGroupController::new(field_rev, configuration)?;
-                self.action_handler = Some(Arc::new(RwLock::new(controller)));
+                self.group_action = Some(Arc::new(RwLock::new(controller)));
             }
             FieldType::Checkbox => {
                 let controller = CheckboxGroupController::new(field_rev, configuration)?;
-                self.action_handler = Some(Arc::new(RwLock::new(controller)));
+                self.group_action = Some(Arc::new(RwLock::new(controller)));
             }
             FieldType::URL => {
                 // let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
@@ -114,7 +108,7 @@ impl GroupService {
         };
 
         let mut groups = vec![];
-        if let Some(group_action_handler) = self.action_handler.as_ref() {
+        if let Some(group_action_handler) = self.group_action.as_ref() {
             let mut write_guard = group_action_handler.write().await;
             let _ = write_guard.group_rows(&row_revs, field_rev)?;
             groups = write_guard.build_groups();

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

@@ -2,11 +2,13 @@ mod util;
 
 pub mod block_editor;
 mod block_manager;
+mod block_manager_trait_impl;
 pub mod cell;
 pub mod field;
 mod filter;
 pub mod grid_editor;
 mod grid_editor_task;
+mod grid_editor_trait_impl;
 pub mod grid_view_editor;
 pub mod grid_view_manager;
 pub mod group;

+ 0 - 1
frontend/rust-lib/flowy-revision/src/cache/reset.rs

@@ -38,7 +38,6 @@ where
     pub async fn run(&self) -> FlowyResult<()> {
         match KV::get_str(self.target.target_id()) {
             None => {
-                tracing::trace!("😁 reset object");
                 let _ = self.reset_object().await?;
                 let _ = self.save_migrate_record()?;
             }