From 074c497d576c2184ad23e31dc52746623d2523f3 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 22 Aug 2022 16:16:15 +0800 Subject: [PATCH] fix: fix some bugs --- frontend/.vscode/launch.json | 2 +- .../plugins/board/application/board_bloc.dart | 32 +++-- .../board/application/group_controller.dart | 17 +++ .../app_flowy/lib/plugins/board/board.dart | 2 +- .../grid/application/row/row_service.dart | 30 +++++ .../example/lib/multi_board_list_example.dart | 2 +- .../board_column/board_column_data.dart | 3 +- .../lib/src/widgets/board_data.dart | 15 ++- .../flowy-grid/src/entities/grid_entities.rs | 43 ++++++ .../rust-lib/flowy-grid/src/event_handler.rs | 11 ++ frontend/rust-lib/flowy-grid/src/event_map.rs | 4 + .../flowy-grid/src/services/grid_editor.rs | 39 ++++-- .../src/services/grid_view_editor.rs | 19 ++- .../src/services/grid_view_manager.rs | 11 +- .../flowy-grid/src/services/group/action.rs | 12 +- .../src/services/group/configuration.rs | 25 ++-- .../src/services/group/controller.rs | 31 ++--- .../controller_impls/checkbox_controller.rs | 13 +- .../multi_select_controller.rs | 25 +--- .../single_select_controller.rs | 25 +--- .../select_option_controller/util.rs | 78 ++++++----- .../src/services/group/group_service.rs | 123 ++++++++--------- .../tests/grid/group_test/script.rs | 14 +- .../flowy-grid/tests/grid/group_test/test.rs | 125 +++++++++++++++--- .../src/revision/grid_setting_rev.rs | 5 +- .../src/revision/group_rev.rs | 24 ++++ .../src/client_grid/view_revision_pad.rs | 8 +- 27 files changed, 486 insertions(+), 252 deletions(-) diff --git a/frontend/.vscode/launch.json b/frontend/.vscode/launch.json index e70b9ffb97..0efc79b00e 100644 --- a/frontend/.vscode/launch.json +++ b/frontend/.vscode/launch.json @@ -29,7 +29,7 @@ "program": "./lib/main.dart", "type": "dart", "env": { - "RUST_LOG": "trace" + "RUST_LOG": "debug" }, "cwd": "${workspaceRoot}/app_flowy" }, diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index ac72b6e24e..f84c2a2bd1 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -23,7 +23,7 @@ class BoardBloc extends Bloc { final BoardDataController _dataController; late final AFBoardDataController afBoardDataController; final MoveRowFFIService _rowService; - Map groupControllers = {}; + LinkedHashMap groupControllers = LinkedHashMap.new(); GridFieldCache get fieldCache => _dataController.fieldCache; String get gridId => _dataController.gridId; @@ -34,9 +34,13 @@ class BoardBloc extends Bloc { super(BoardState.initial(view.id)) { afBoardDataController = AFBoardDataController( onMoveColumn: ( + fromColumnId, fromIndex, + toColumnId, toIndex, - ) {}, + ) { + _moveGroup(fromColumnId, toColumnId); + }, onMoveColumnItem: ( columnId, fromIndex, @@ -44,7 +48,7 @@ class BoardBloc extends Bloc { ) { final fromRow = groupControllers[columnId]?.rowAtIndex(fromIndex); final toRow = groupControllers[columnId]?.rowAtIndex(toIndex); - _moveRow(fromRow, toRow); + _moveRow(fromRow, columnId, toRow); }, onMoveColumnItemToColumn: ( fromColumnId, @@ -54,7 +58,7 @@ class BoardBloc extends Bloc { ) { final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex); final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex); - _moveRow(fromRow, toRow); + _moveRow(fromRow, toColumnId, toRow); }, ); @@ -95,12 +99,13 @@ class BoardBloc extends Bloc { ); } - void _moveRow(RowPB? fromRow, RowPB? toRow) { - if (fromRow != null && toRow != null) { + void _moveRow(RowPB? fromRow, String columnId, RowPB? toRow) { + if (fromRow != null) { _rowService - .moveRow( + .moveGroupRow( fromRowId: fromRow.id, - toRowId: toRow.id, + toGroupId: columnId, + toRowId: toRow?.id, ) .then((result) { result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r))); @@ -108,6 +113,17 @@ class BoardBloc extends Bloc { } } + void _moveGroup(String fromColumnId, String toColumnId) { + _rowService + .moveGroup( + fromGroupId: fromColumnId, + toGroupId: toColumnId, + ) + .then((result) { + result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r))); + }); + } + @override Future close() async { await _dataController.dispose(); diff --git a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart index 3f545dae3b..6fd68b1df8 100644 --- a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart @@ -37,6 +37,14 @@ class GroupController { (GroupRowsChangesetPB changeset) { for (final insertedRow in changeset.insertedRows) { final index = insertedRow.hasIndex() ? insertedRow.index : null; + + if (insertedRow.hasIndex() && + group.rows.length > insertedRow.index) { + group.rows.insert(insertedRow.index, insertedRow.row); + } else { + group.rows.add(insertedRow.row); + } + delegate.insertRow( group.groupId, insertedRow.row, @@ -45,10 +53,19 @@ class GroupController { } for (final deletedRow in changeset.deletedRows) { + group.rows.removeWhere((rowPB) => rowPB.id == deletedRow); delegate.removeRow(group.groupId, deletedRow); } for (final updatedRow in changeset.updatedRows) { + final index = group.rows.indexWhere( + (rowPB) => rowPB.id == updatedRow.id, + ); + + if (index != -1) { + group.rows[index] = updatedRow; + } + delegate.updateRow(group.groupId, updatedRow); } }, diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index 213cc8bc3c..c55d7f2e17 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder { class BoardPluginConfig implements PluginConfig { @override - bool get creatable => true; + bool get creatable => false; } class BoardPlugin extends Plugin { diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart index a18c0c8e75..2612f5975c 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart @@ -3,6 +3,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; class RowFFIService { @@ -68,4 +69,33 @@ class MoveRowFFIService { return GridEventMoveRow(payload).send(); } + + Future> moveGroupRow({ + required String fromRowId, + required String toGroupId, + required String? toRowId, + }) { + var payload = MoveGroupRowPayloadPB.create() + ..viewId = gridId + ..fromRowId = fromRowId + ..toGroupId = toGroupId; + + if (toRowId != null) { + payload.toRowId = toRowId; + } + + return GridEventMoveGroupRow(payload).send(); + } + + Future> moveGroup({ + required String fromGroupId, + required String toGroupId, + }) { + final payload = MoveGroupPayloadPB.create() + ..viewId = gridId + ..fromGroupId = fromGroupId + ..toGroupId = toGroupId; + + return GridEventMoveGroup(payload).send(); + } } diff --git a/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart b/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart index 83f75d2a0e..01aba725a5 100644 --- a/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart +++ b/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart @@ -10,7 +10,7 @@ class MultiBoardListExample extends StatefulWidget { class _MultiBoardListExampleState extends State { final AFBoardDataController boardDataController = AFBoardDataController( - onMoveColumn: (fromIndex, toIndex) { + onMoveColumn: (fromColumnId, fromIndex, toColumnId, toIndex) { debugPrint('Move column from $fromIndex to $toIndex'); }, onMoveColumnItem: (columnId, fromIndex, toIndex) { diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart index 6e184761c5..f26bd16c50 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart @@ -145,7 +145,8 @@ class AFBoardColumnData extends ReoderFlexItem with EquatableMixin { }) : _items = items; /// Returns the readonly List - UnmodifiableListView get items => UnmodifiableListView(_items); + UnmodifiableListView get items => + UnmodifiableListView([..._items]); @override List get props => [id, ..._items]; diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart index 6208dbd0f0..e8d5471939 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart @@ -8,7 +8,12 @@ import 'reorder_flex/reorder_flex.dart'; import 'package:flutter/material.dart'; import 'reorder_phantom/phantom_controller.dart'; -typedef OnMoveColumn = void Function(int fromIndex, int toIndex); +typedef OnMoveColumn = void Function( + String fromColumnId, + int fromIndex, + String toColumnId, + int toIndex, +); typedef OnMoveColumnItem = void Function( String columnId, @@ -98,9 +103,11 @@ class AFBoardDataController extends ChangeNotifier } void moveColumn(int fromIndex, int toIndex, {bool notify = true}) { - final columnData = _columnDatas.removeAt(fromIndex); - _columnDatas.insert(toIndex, columnData); - onMoveColumn?.call(fromIndex, toIndex); + final toColumnData = _columnDatas[toIndex]; + final fromColumnData = _columnDatas.removeAt(fromIndex); + + _columnDatas.insert(toIndex, fromColumnData); + onMoveColumn?.call(fromColumnData.id, fromIndex, toColumnData.id, toIndex); if (notify) notifyListeners(); } diff --git a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs index be8cfdeae1..c012376f55 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs @@ -123,3 +123,46 @@ impl TryInto for MoveRowPayloadPB { }) } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct MoveGroupRowPayloadPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2)] + pub from_row_id: String, + + #[pb(index = 3)] + pub to_group_id: String, + + #[pb(index = 4, one_of)] + pub to_row_id: Option, +} + +pub struct MoveGroupRowParams { + pub view_id: String, + pub from_row_id: String, + pub to_group_id: String, + pub to_row_id: Option, +} + +impl TryInto for MoveGroupRowPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::GridViewIdIsEmpty)?; + let from_row_id = NotEmptyStr::parse(self.from_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + let to_group_id = NotEmptyStr::parse(self.to_group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; + + let to_row_id = match self.to_row_id { + None => None, + Some(to_row_id) => Some(NotEmptyStr::parse(to_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?.0), + }; + + Ok(MoveGroupRowParams { + view_id: view_id.0, + from_row_id: from_row_id.0, + to_group_id: to_group_id.0, + to_row_id, + }) + } +} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 149f7017a3..a9060aa87e 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -436,3 +436,14 @@ pub(crate) async fn move_group_handler( let _ = editor.move_group(params).await?; Ok(()) } + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn move_group_row_handler( + data: Data, + manager: AppData>, +) -> FlowyResult<()> { + let params: MoveGroupRowParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(params.view_id.as_ref())?; + let _ = editor.move_group_row(params).await?; + Ok(()) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 844ae7f5c3..a78bcb5ed3 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -42,6 +42,7 @@ pub fn create(grid_manager: Arc) -> Module { // Group .event(GridEvent::CreateBoardCard, create_board_card_handler) .event(GridEvent::MoveGroup, move_group_handler) + .event(GridEvent::MoveGroupRow, move_group_row_handler) .event(GridEvent::GetGroup, get_groups_handler); module @@ -221,4 +222,7 @@ pub enum GridEvent { #[event(input = "MoveGroupPayloadPB")] MoveGroup = 111, + + #[event(input = "MoveGroupRowPayloadPB")] + MoveGroupRow = 112, } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 93c48b0880..485bf6930c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -560,16 +560,6 @@ impl GridRevisionEditor { .block_manager .move_row(row_rev.clone(), from_index, to_index) .await?; - - if let Some(row_changeset) = self.view_manager.move_row(row_rev, to_row_id.clone()).await { - tracing::trace!("Receive row changeset after moving the row"); - match self.block_manager.update_row(row_changeset).await { - Ok(_) => {} - Err(e) => { - tracing::error!("Apply row changeset error:{:?}", e); - } - } - } } (_, None) => tracing::warn!("Can not find the from row id: {}", from_row_id), (None, _) => tracing::warn!("Can not find the to row id: {}", to_row_id), @@ -579,6 +569,35 @@ impl GridRevisionEditor { Ok(()) } + pub async fn move_group_row(&self, params: MoveGroupRowParams) -> FlowyResult<()> { + let MoveGroupRowParams { + view_id: _, + from_row_id, + to_group_id, + to_row_id, + } = params; + + match self.block_manager.get_row_rev(&from_row_id).await? { + None => tracing::warn!("Move row failed, can not find the row:{}", from_row_id), + Some(row_rev) => { + if let Some(row_changeset) = self + .view_manager + .move_group_row(row_rev, to_group_id, to_row_id.clone()) + .await + { + match self.block_manager.update_row(row_changeset).await { + Ok(_) => {} + Err(e) => { + tracing::error!("Apply row changeset error:{:?}", e); + } + } + } + } + } + + Ok(()) + } + pub async fn move_field(&self, params: MoveFieldParams) -> FlowyResult<()> { let MoveFieldParams { grid_id: _, diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index fb8706b175..4e23d9be19 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -80,7 +80,7 @@ impl GridViewRevisionEditor { None => {} Some(group_id) => { self.group_service - .read() + .write() .await .will_create_row(row_rev, group_id, |field_id| { self.field_delegate.get_field_rev(&field_id) @@ -109,7 +109,7 @@ impl GridViewRevisionEditor { // Send the group notification if the current view has groups; if let Some(changesets) = self .group_service - .read() + .write() .await .did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) .await @@ -123,7 +123,7 @@ impl GridViewRevisionEditor { pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) { if let Some(changesets) = self .group_service - .read() + .write() .await .did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) .await @@ -134,23 +134,23 @@ impl GridViewRevisionEditor { } } - pub(crate) async fn did_move_row( + pub(crate) async fn move_group_row( &self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, - upper_row_id: &str, + to_group_id: &str, + to_row_id: Option, ) { if let Some(changesets) = self .group_service - .read() + .write() .await - .did_move_row(row_rev, row_changeset, upper_row_id, |field_id| { + .move_group_row(row_rev, row_changeset, to_group_id, to_row_id, |field_id| { self.field_delegate.get_field_rev(&field_id) }) .await { for changeset in changesets { - tracing::trace!("Group: {} changeset: {}", changeset.group_id, changeset); self.notify_did_update_group_rows(changeset).await; } } @@ -184,7 +184,7 @@ impl GridViewRevisionEditor { pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { let _ = self .group_service - .read() + .write() .await .move_group(¶ms.from_group_id, ¶ms.to_group_id) .await?; @@ -326,7 +326,6 @@ impl GroupConfigurationReader for GroupConfigurationReaderImpl { let view_pad = self.0.clone(); wrap_future(async move { let mut groups = view_pad.read().await.groups.get_objects(&field_rev.id, &field_rev.ty)?; - if groups.is_empty() { None } else { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index a1265d0e25..b0e578f804 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -129,10 +129,17 @@ impl GridViewManager { /// It may generate a RowChangeset when the Row was moved from one group to another. /// The return value, [RowChangeset], contains the changes made by the groups. /// - pub(crate) async fn move_row(&self, row_rev: Arc, to_row_id: String) -> Option { + pub(crate) async fn move_group_row( + &self, + row_rev: Arc, + to_group_id: String, + to_row_id: Option, + ) -> Option { let mut row_changeset = RowChangeset::new(row_rev.id.clone()); for view_editor in self.view_editors.iter() { - view_editor.did_move_row(&row_rev, &mut row_changeset, &to_row_id).await; + view_editor + .move_group_row(&row_rev, &mut row_changeset, &to_group_id, to_row_id.clone()) + .await; } if row_changeset.has_changed() { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/action.rs b/frontend/rust-lib/flowy-grid/src/services/group/action.rs index a495fe0a1f..29dc51cc37 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/action.rs @@ -1,6 +1,7 @@ use crate::entities::GroupRowsChangesetPB; -use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; +use crate::services::group::controller::MoveGroupRowContext; +use flowy_grid_data_model::revision::RowRevision; pub trait GroupAction: Send + Sync { type CellDataType; @@ -12,12 +13,5 @@ pub trait GroupAction: Send + Sync { cell_data: &Self::CellDataType, ) -> Vec; - fn move_row_if_match( - &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &Self::CellDataType, - to_row_id: &str, - ) -> Vec; + fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec; } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 36d49a10e1..a462278d2b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -101,9 +101,9 @@ where Ok(()) } - pub(crate) fn with_mut_groups(&mut self, mut mut_groups_fn: impl FnMut(&mut Group)) { + pub(crate) fn with_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) { self.groups_map.iter_mut().for_each(|(_, group)| { - mut_groups_fn(group); + each(group); }) } @@ -111,22 +111,16 @@ where self.groups_map.get_mut(group_id) } - pub(crate) fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { - let from_group_index = self.groups_map.get_index_of(from_group_id); - let to_group_index = self.groups_map.get_index_of(to_group_id); - match (from_group_index, to_group_index) { + pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> { + let from_index = self.groups_map.get_index_of(from_id); + let to_index = self.groups_map.get_index_of(to_id); + match (from_index, to_index) { (Some(from_index), Some(to_index)) => { self.groups_map.swap_indices(from_index, to_index); self.mut_configuration(|configuration| { - let from_index = configuration - .groups - .iter() - .position(|group| group.group_id == from_group_id); - let to_index = configuration - .groups - .iter() - .position(|group| group.group_id == to_group_id); + let from_index = configuration.groups.iter().position(|group| group.group_id == from_id); + let to_index = configuration.groups.iter().position(|group| group.group_id == to_id); if let (Some(from), Some(to)) = (from_index, to_index) { configuration.groups.swap(from, to); } @@ -150,7 +144,7 @@ where let configuration = (&*self.configuration).clone(); let writer = self.writer.clone(); let field_id = self.field_rev.id.clone(); - let field_type = self.field_rev.ty.clone(); + let field_type = self.field_rev.ty; tokio::spawn(async move { match writer .save_group_configuration(&field_id, field_type, configuration) @@ -196,7 +190,6 @@ where } fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> (Vec, Vec) { - tracing::trace!("Merge group: old: {}, new: {}", old_group_revs.len(), groups.len()); if old_group_revs.is_empty() { let new_groups = groups .iter() diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index 13b4ccce63..1a5ee23694 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -31,6 +31,14 @@ pub trait GroupGenerator { ) -> Vec; } +pub struct MoveGroupRowContext<'a> { + pub row_rev: &'a RowRevision, + pub row_changeset: &'a mut RowChangeset, + pub field_rev: &'a FieldRevision, + pub to_group_id: &'a str, + pub to_row_id: Option, +} + // Defines the shared actions each group controller can perform. pub trait GroupControllerSharedOperation: Send + Sync { // The field that is used for grouping the rows @@ -51,13 +59,7 @@ pub trait GroupControllerSharedOperation: Send + Sync { field_rev: &FieldRevision, ) -> FlowyResult>; - fn did_move_row( - &mut self, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - field_rev: &FieldRevision, - to_row_id: &str, - ) -> FlowyResult>; + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult>; } /// C: represents the group configuration that impl [GroupConfigurationSerde] @@ -195,18 +197,11 @@ where } } - fn did_move_row( - &mut self, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - field_rev: &FieldRevision, - to_row_id: &str, - ) -> FlowyResult> { - 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); + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult> { + if let Some(cell_rev) = context.row_rev.cells.get(&self.field_id) { + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), context.field_rev); let cell_data = cell_bytes.parser::

()?; - 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)) + Ok(self.move_row(&cell_data, context)) } else { Ok(vec![]) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index 59a53ae72a..ffcbf117fe 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -2,10 +2,12 @@ use crate::entities::GroupRowsChangesetPB; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::group::action::GroupAction; use crate::services::group::configuration::GenericGroupConfiguration; -use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; +use crate::services::group::controller::{ + GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, +}; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, RowChangeset, RowRevision}; +use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, RowRevision}; pub type CheckboxGroupController = GenericGroupController< CheckboxGroupConfigurationRevision, @@ -38,13 +40,10 @@ impl GroupAction for CheckboxGroupController { todo!() } - fn move_row_if_match( + fn move_row( &mut self, - _field_rev: &FieldRevision, - _row_rev: &RowRevision, - _row_changeset: &mut RowChangeset, _cell_data: &Self::CellDataType, - _to_row_id: &str, + _context: MoveGroupRowContext, ) -> Vec { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index 7a208a884f..cce2698158 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -3,12 +3,12 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser}; use crate::services::group::action::GroupAction; -use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; +use crate::services::group::controller::{ + GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, +}; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{ - FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // MultiSelect pub type MultiSelectGroupController = GenericGroupController< @@ -45,25 +45,14 @@ impl GroupAction for MultiSelectGroupController { changesets } - fn move_row_if_match( + fn move_row( &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, - to_row_id: &str, + mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; self.configuration.with_mut_groups(|group| { - move_row( - group, - &mut group_changeset, - field_rev, - row_rev, - row_changeset, - cell_data, - to_row_id, - ); + move_select_option_row(group, &mut group_changeset, cell_data, &mut context); }); group_changeset } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index 2eb1e4a60f..d48cdd8ee7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -3,13 +3,13 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB}; use crate::services::group::action::GroupAction; -use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; +use crate::services::group::controller::{ + GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, +}; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{ - FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // SingleSelect pub type SingleSelectGroupController = GenericGroupController< @@ -45,25 +45,14 @@ impl GroupAction for SingleSelectGroupController { changesets } - fn move_row_if_match( + fn move_row( &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, - to_row_id: &str, + mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; self.configuration.with_mut_groups(|group| { - move_row( - group, - &mut group_changeset, - field_rev, - row_rev, - row_changeset, - cell_data, - to_row_id, - ); + move_select_option_row(group, &mut group_changeset, cell_data, &mut context); }); group_changeset } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs index 6675f26aa4..bdca688531 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -4,9 +4,8 @@ use crate::services::field::SelectOptionCellDataPB; use crate::services::group::configuration::GenericGroupConfiguration; use crate::services::group::Group; -use flowy_grid_data_model::revision::{ - FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use crate::services::group::controller::MoveGroupRowContext; +use flowy_grid_data_model::revision::{RowRevision, SelectOptionGroupConfigurationRevision}; pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; @@ -47,45 +46,60 @@ pub fn remove_row( }); } -pub fn move_row( +pub fn move_select_option_row( group: &mut Group, group_changeset: &mut Vec, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &SelectOptionCellDataPB, - to_row_id: &str, + _cell_data: &SelectOptionCellDataPB, + context: &mut MoveGroupRowContext, ) { - cell_data.select_options.iter().for_each(|option| { - // Remove the row in which group contains the row - let is_group_contains = group.contains_row(&row_rev.id); - let to_index = group.index_of_row(to_row_id); + let MoveGroupRowContext { + row_rev, + row_changeset, + field_rev, + to_group_id, + to_row_id, + } = context; - if option.id == group.id && is_group_contains { - group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } + let from_index = group.index_of_row(&row_rev.id); + let to_index = match to_row_id { + None => None, + Some(to_row_id) => group.index_of_row(to_row_id), + }; - // Find the inserted group - if let Some(to_index) = to_index { - let row_pb = RowPB::from(row_rev); - let inserted_row = InsertedRowPB { - row: row_pb.clone(), - index: Some(to_index as i32), - }; - group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); - if group.number_of_row() == to_index { + // Remove the row in which group contains it + if from_index.is_some() { + group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + tracing::debug!("Group:{} remove row:{}", group.id, row_rev.id); + group.remove_row(&row_rev.id); + } + + if group.id == *to_group_id { + let row_pb = RowPB::from(*row_rev); + let mut inserted_row = InsertedRowPB::new(row_pb.clone()); + match to_index { + None => { + group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); + tracing::debug!("Group:{} append row:{}", group.id, row_rev.id); group.add_row(row_pb); - } else { - group.insert_row(to_index, row_pb); + } + Some(to_index) => { + if to_index < group.number_of_row() { + tracing::debug!("Group:{} insert row:{} at {} ", group.id, row_rev.id, to_index); + inserted_row.index = Some(to_index as i32); + group.insert_row(to_index, row_pb); + } else { + tracing::debug!("Group:{} append row:{}", group.id, row_rev.id); + group.add_row(row_pb); + } + group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); } } - // If the inserted row comes from other group, it needs to update the corresponding cell content. - if to_index.is_some() && option.id != group.id { - // Update the corresponding row's cell content. + // Update the corresponding row's cell content. + if from_index.is_none() { + tracing::debug!("Mark row:{} belong to group:{}", row_rev.id, group.id); 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); } - }); + } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index 63a3b4b67b..6afec9dd82 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -1,5 +1,6 @@ +use crate::entities::{FieldType, GroupRowsChangesetPB}; use crate::services::group::configuration::GroupConfigurationReader; -use crate::services::group::controller::GroupController; +use crate::services::group::controller::{GroupController, MoveGroupRowContext}; use crate::services::group::{ CheckboxGroupConfiguration, CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController, SelectOptionGroupConfiguration, SingleSelectGroupController, @@ -10,16 +11,13 @@ use flowy_grid_data_model::revision::{ NumberGroupConfigurationRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, TextGroupConfigurationRevision, UrlGroupConfigurationRevision, }; - -use crate::entities::{FieldType, GroupRowsChangesetPB}; use std::future::Future; use std::sync::Arc; -use tokio::sync::RwLock; pub(crate) struct GroupService { configuration_reader: Arc, configuration_writer: Arc, - group_controller: Option>>, + group_controller: Option>, } impl GroupService { @@ -36,19 +34,16 @@ impl GroupService { } pub(crate) async fn groups(&self) -> Vec { - if let Some(group_controller) = self.group_controller.as_ref() { - group_controller.read().await.groups() - } else { - vec![] - } + self.group_controller + .as_ref() + .and_then(|group_controller| Some(group_controller.groups())) + .unwrap_or(vec![]) } pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { - if let Some(group_controller) = self.group_controller.as_ref() { - group_controller.read().await.get_group(group_id) - } else { - None - } + self.group_controller + .as_ref() + .and_then(|group_controller| group_controller.get_group(group_id)) } pub(crate) async fn load_groups( @@ -58,51 +53,37 @@ impl GroupService { ) -> Option> { let field_rev = find_group_field(field_revs)?; let field_type: FieldType = field_rev.ty.into(); - match self.make_group_controller(&field_type, &field_rev).await { - Ok(group_controller) => { - self.group_controller = group_controller; - let mut groups = vec![]; - if let Some(group_action_handler) = self.group_controller.as_ref() { - let mut write_guard = group_action_handler.write().await; - groups = match write_guard.fill_groups(&row_revs, &field_rev) { - Ok(groups) => groups, - Err(e) => { - tracing::error!("Fill groups failed:{:?}", e); - vec![] - } - }; - drop(write_guard); - } - Some(groups) + + let mut group_controller = self.make_group_controller(&field_type, &field_rev).await.ok()??; + let groups = match group_controller.fill_groups(&row_revs, &field_rev) { + Ok(groups) => groups, + Err(e) => { + tracing::error!("Fill groups failed:{:?}", e); + vec![] } - Err(err) => { - tracing::error!("Load group failed: {}", err); - Some(vec![]) - } - } + }; + self.group_controller = Some(group_controller); + Some(groups) } - pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F) + pub(crate) async fn will_create_row(&mut self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F) where F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - if let Some(group_controller) = self.group_controller.as_ref() { - let field_id = group_controller.read().await.field_id().to_owned(); + if let Some(group_controller) = self.group_controller.as_mut() { + let field_id = group_controller.field_id().to_owned(); match get_field_fn(field_id).await { None => {} Some(field_rev) => { - group_controller - .write() - .await - .will_create_row(row_rev, &field_rev, group_id); + group_controller.will_create_row(row_rev, &field_rev, group_id); } } } } pub(crate) async fn did_delete_row( - &self, + &mut self, row_rev: &RowRevision, get_field_fn: F, ) -> Option> @@ -110,11 +91,11 @@ impl GroupService { F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - let group_controller = self.group_controller.as_ref()?; - let field_id = group_controller.read().await.field_id().to_owned(); + let group_controller = self.group_controller.as_mut()?; + let field_id = group_controller.field_id().to_owned(); let field_rev = get_field_fn(field_id).await?; - match group_controller.write().await.did_delete_row(row_rev, &field_rev) { + match group_controller.did_delete_row(row_rev, &field_rev) { Ok(changesets) => Some(changesets), Err(e) => { tracing::error!("Delete group data failed, {:?}", e); @@ -123,26 +104,30 @@ impl GroupService { } } - pub(crate) async fn did_move_row( - &self, + pub(crate) async fn move_group_row( + &mut self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, - upper_row_id: &str, + to_group_id: &str, + to_row_id: Option, get_field_fn: F, ) -> Option> where F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - let group_controller = self.group_controller.as_ref()?; - let field_id = group_controller.read().await.field_id().to_owned(); + let group_controller = self.group_controller.as_mut()?; + let field_id = group_controller.field_id().to_owned(); let field_rev = get_field_fn(field_id).await?; + let move_row_context = MoveGroupRowContext { + row_rev, + row_changeset, + field_rev: field_rev.as_ref(), + to_group_id, + to_row_id, + }; - match group_controller - .write() - .await - .did_move_row(row_rev, row_changeset, &field_rev, upper_row_id) - { + match group_controller.move_group_row(move_row_context) { Ok(changesets) => Some(changesets), Err(e) => { tracing::error!("Move group data failed, {:?}", e); @@ -153,7 +138,7 @@ impl GroupService { #[tracing::instrument(level = "trace", skip_all)] pub(crate) async fn did_update_row( - &self, + &mut self, row_rev: &RowRevision, get_field_fn: F, ) -> Option> @@ -161,11 +146,11 @@ impl GroupService { F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - let group_controller = self.group_controller.as_ref()?; - let field_id = group_controller.read().await.field_id().to_owned(); + let group_controller = self.group_controller.as_mut()?; + let field_id = group_controller.field_id().to_owned(); let field_rev = get_field_fn(field_id).await?; - match group_controller.write().await.did_update_row(row_rev, &field_rev) { + match group_controller.did_update_row(row_rev, &field_rev) { Ok(changeset) => Some(changeset), Err(e) => { tracing::error!("Update group data failed, {:?}", e); @@ -175,11 +160,11 @@ impl GroupService { } #[tracing::instrument(level = "trace", skip_all)] - pub(crate) async fn move_group(&self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { - match self.group_controller.as_ref() { + pub(crate) async fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { + match self.group_controller.as_mut() { None => Ok(()), Some(group_controller) => { - let _ = group_controller.write().await.move_group(from_group_id, to_group_id)?; + let _ = group_controller.move_group(from_group_id, to_group_id)?; Ok(()) } } @@ -190,8 +175,8 @@ impl GroupService { &self, field_type: &FieldType, field_rev: &Arc, - ) -> FlowyResult>>> { - let mut group_controller: Option>> = None; + ) -> FlowyResult>> { + let mut group_controller: Option> = None; match field_type { FieldType::RichText => { // let generator = GroupGenerator::::from_configuration(configuration); @@ -210,7 +195,7 @@ impl GroupService { ) .await?; let controller = SingleSelectGroupController::new(field_rev, configuration).await?; - group_controller = Some(Arc::new(RwLock::new(controller))); + group_controller = Some(Box::new(controller)); } FieldType::MultiSelect => { let configuration = SelectOptionGroupConfiguration::new( @@ -220,7 +205,7 @@ impl GroupService { ) .await?; let controller = MultiSelectGroupController::new(field_rev, configuration).await?; - group_controller = Some(Arc::new(RwLock::new(controller))); + group_controller = Some(Box::new(controller)); } FieldType::Checkbox => { let configuration = CheckboxGroupConfiguration::new( @@ -230,7 +215,7 @@ impl GroupService { ) .await?; let controller = CheckboxGroupController::new(field_rev, configuration).await?; - group_controller = Some(Arc::new(RwLock::new(controller))) + group_controller = Some(Box::new(controller)); } FieldType::URL => { // let generator = GroupGenerator::::from_configuration(configuration); diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs index d284e69c76..94ef4dff1b 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs @@ -1,5 +1,7 @@ use crate::grid::grid_editor::GridEditorTest; -use flowy_grid::entities::{CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveRowParams, RowPB}; +use flowy_grid::entities::{ + CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB, +}; use flowy_grid::services::cell::insert_select_option_cell; use flowy_grid_data_model::revision::RowChangeset; @@ -75,14 +77,16 @@ impl GridGroupTest { } => { let groups: Vec = self.editor.load_groups().await.unwrap().items; let from_row = groups.get(from_group_index).unwrap().rows.get(from_row_index).unwrap(); - let to_row = groups.get(to_group_index).unwrap().rows.get(to_row_index).unwrap(); - let params = MoveRowParams { + let to_group = groups.get(to_group_index).unwrap(); + let to_row = to_group.rows.get(to_row_index).unwrap(); + let params = MoveGroupRowParams { view_id: self.inner.grid_id.clone(), from_row_id: from_row.id.clone(), - to_row_id: to_row.id.clone(), + to_group_id: to_group.group_id.clone(), + to_row_id: Some(to_row.id.clone()), }; - self.editor.move_row(params).await.unwrap(); + self.editor.move_group_row(params).await.unwrap(); } GroupScript::AssertRow { group_index, diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs index 6092e97a5e..bebf499773 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs @@ -2,7 +2,7 @@ use crate::grid::group_test::script::GridGroupTest; use crate::grid::group_test::script::GroupScript::*; #[tokio::test] -async fn board_init_test() { +async fn group_init_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ AssertGroupCount(3), @@ -23,7 +23,7 @@ async fn board_init_test() { } #[tokio::test] -async fn board_move_row_test() { +async fn group_move_row_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -48,7 +48,7 @@ async fn board_move_row_test() { } #[tokio::test] -async fn board_move_row_to_other_group_test() { +async fn group_move_row_to_other_group_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -76,7 +76,7 @@ async fn board_move_row_to_other_group_test() { } #[tokio::test] -async fn board_move_row_to_other_group_and_reorder_test() { +async fn group_move_two_row_to_other_group_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -86,15 +86,41 @@ async fn board_move_row_to_other_group_and_reorder_test() { to_group_index: 1, to_row_index: 1, }, - MoveRow { - from_group_index: 1, - from_row_index: 1, - to_group_index: 1, - to_row_index: 2, + AssertGroupRowCount { + group_index: 0, + row_count: 1, + }, + AssertGroupRowCount { + group_index: 1, + row_count: 3, }, AssertRow { group_index: 1, - row_index: 2, + row_index: 1, + row: group.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; + + let group = test.group_at_index(0).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }, + AssertGroupRowCount { + group_index: 0, + row_count: 0, + }, + AssertGroupRowCount { + group_index: 1, + row_count: 4, + }, + AssertRow { + group_index: 1, + row_index: 1, row: group.rows.get(0).unwrap().clone(), }, ]; @@ -102,7 +128,74 @@ async fn board_move_row_to_other_group_and_reorder_test() { } #[tokio::test] -async fn board_create_row_test() { +async fn group_move_row_to_other_group_and_reorder_from_up_to_down_test() { + let mut test = GridGroupTest::new().await; + let group_0 = test.group_at_index(0).await; + let group_1 = test.group_at_index(1).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }, + AssertRow { + group_index: 1, + row_index: 1, + row: group_0.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; + + let scripts = vec![ + MoveRow { + from_group_index: 1, + from_row_index: 0, + to_group_index: 1, + to_row_index: 2, + }, + AssertRow { + group_index: 1, + row_index: 2, + row: group_1.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn group_move_row_to_other_group_and_reorder_from_bottom_to_up_test() { + let mut test = GridGroupTest::new().await; + let scripts = vec![MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }]; + test.run_scripts(scripts).await; + + let group = test.group_at_index(1).await; + let scripts = vec![ + AssertGroupRowCount { + group_index: 1, + row_count: 3, + }, + MoveRow { + from_group_index: 1, + from_row_index: 2, + to_group_index: 1, + to_row_index: 0, + }, + AssertRow { + group_index: 1, + row_index: 0, + row: group.rows.get(2).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} +#[tokio::test] +async fn group_create_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ CreateRow { group_index: 0 }, @@ -121,7 +214,7 @@ async fn board_create_row_test() { } #[tokio::test] -async fn board_delete_row_test() { +async fn group_delete_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ DeleteRow { @@ -137,7 +230,7 @@ async fn board_delete_row_test() { } #[tokio::test] -async fn board_delete_all_row_test() { +async fn group_delete_all_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ DeleteRow { @@ -157,7 +250,7 @@ async fn board_delete_all_row_test() { } #[tokio::test] -async fn board_update_row_test() { +async fn group_update_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ // Update the row at 0 in group0 by setting the row's group field data @@ -179,7 +272,7 @@ async fn board_update_row_test() { } #[tokio::test] -async fn board_reorder_group_test() { +async fn group_reorder_group_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ // Update the row at 0 in group0 by setting the row's group field data @@ -201,7 +294,7 @@ async fn board_reorder_group_test() { } #[tokio::test] -async fn board_move_group_test() { +async fn group_move_group_test() { let mut test = GridGroupTest::new().await; let group_0 = test.group_at_index(0).await; let group_1 = test.group_at_index(1).await; diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs index 61a8a386d5..1f52ae93e2 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs @@ -76,7 +76,8 @@ where Some(objects_by_field_id) } - pub fn insert_object(&mut self, field_id: &str, field_type: &FieldTypeRevision, object: T) { + /// add object to the end of the list + pub fn add_object(&mut self, field_id: &str, field_type: &FieldTypeRevision, object: T) { let object_rev_map = self .inner .entry(field_id.to_string()) @@ -88,7 +89,7 @@ where .push(Arc::new(object)) } - pub fn remove_all(&mut self) { + pub fn clear(&mut self) { self.inner.clear() } } diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index 204bdf273f..97d45295fe 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -155,3 +155,27 @@ impl std::default::Default for DateCondition { DateCondition::Relative } } + +#[cfg(test)] +mod tests { + use crate::revision::{GroupConfigurationRevision, SelectOptionGroupConfigurationRevision}; + + #[test] + fn group_configuration_serde_test() { + let content = SelectOptionGroupConfigurationRevision { hide_empty: false }; + let rev = GroupConfigurationRevision::new("1".to_owned(), 2, content).unwrap(); + let json = serde_json::to_string(&rev).unwrap(); + + let rev: GroupConfigurationRevision = serde_json::from_str(&json).unwrap(); + let _content: SelectOptionGroupConfigurationRevision = serde_json::from_str(&rev.content).unwrap(); + } + + #[test] + fn group_configuration_serde_test2() { + let content = SelectOptionGroupConfigurationRevision { hide_empty: false }; + let content_json = serde_json::to_string(&content).unwrap(); + let rev = GroupConfigurationRevision::new("1".to_owned(), 2, content).unwrap(); + + assert_eq!(rev.content, content_json); + } +} diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index 57bd783d75..ddc9c6e05a 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -60,7 +60,9 @@ impl GridViewRevisionPad { group_rev: GroupConfigurationRevision, ) -> CollaborateResult> { self.modify(|view| { - view.groups.insert_object(field_id, field_type, group_rev); + // Only save one group + view.groups.clear(); + view.groups.add_object(field_id, field_type, group_rev); Ok(Some(())) }) } @@ -127,7 +129,7 @@ impl GridViewRevisionPad { filter_rev: FilterConfigurationRevision, ) -> CollaborateResult> { self.modify(|view| { - view.filters.insert_object(field_id, field_type, filter_rev); + view.filters.add_object(field_id, field_type, filter_rev); Ok(Some(())) }) } @@ -166,8 +168,6 @@ impl GridViewRevisionPad { None => Ok(None), Some(delta) => { self.delta = self.delta.compose(&delta)?; - tracing::info!("GridView: {:?}", delta); - let md5 = md5(&self.delta.json_bytes()); Ok(Some(GridViewRevisionChangeset { delta, md5 })) }