mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-09-11 11:15:53 +03:00
fix: fix some bugs
This commit is contained in:
parent
ffc6f141fa
commit
074c497d57
2
frontend/.vscode/launch.json
vendored
2
frontend/.vscode/launch.json
vendored
@ -29,7 +29,7 @@
|
||||
"program": "./lib/main.dart",
|
||||
"type": "dart",
|
||||
"env": {
|
||||
"RUST_LOG": "trace"
|
||||
"RUST_LOG": "debug"
|
||||
},
|
||||
"cwd": "${workspaceRoot}/app_flowy"
|
||||
},
|
||||
|
@ -23,7 +23,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
final BoardDataController _dataController;
|
||||
late final AFBoardDataController afBoardDataController;
|
||||
final MoveRowFFIService _rowService;
|
||||
Map<String, GroupController> groupControllers = {};
|
||||
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap.new();
|
||||
|
||||
GridFieldCache get fieldCache => _dataController.fieldCache;
|
||||
String get gridId => _dataController.gridId;
|
||||
@ -34,9 +34,13 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
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<BoardEvent, BoardState> {
|
||||
) {
|
||||
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<BoardEvent, BoardState> {
|
||||
) {
|
||||
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<BoardEvent, BoardState> {
|
||||
);
|
||||
}
|
||||
|
||||
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<BoardEvent, BoardState> {
|
||||
}
|
||||
}
|
||||
|
||||
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<void> close() async {
|
||||
await _dataController.dispose();
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
@ -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 {
|
||||
|
@ -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<Either<Unit, FlowyError>> 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<Either<Unit, FlowyError>> moveGroup({
|
||||
required String fromGroupId,
|
||||
required String toGroupId,
|
||||
}) {
|
||||
final payload = MoveGroupPayloadPB.create()
|
||||
..viewId = gridId
|
||||
..fromGroupId = fromGroupId
|
||||
..toGroupId = toGroupId;
|
||||
|
||||
return GridEventMoveGroup(payload).send();
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class MultiBoardListExample extends StatefulWidget {
|
||||
|
||||
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||
final AFBoardDataController boardDataController = AFBoardDataController(
|
||||
onMoveColumn: (fromIndex, toIndex) {
|
||||
onMoveColumn: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
||||
debugPrint('Move column from $fromIndex to $toIndex');
|
||||
},
|
||||
onMoveColumnItem: (columnId, fromIndex, toIndex) {
|
||||
|
@ -145,7 +145,8 @@ class AFBoardColumnData<CustomData> extends ReoderFlexItem with EquatableMixin {
|
||||
}) : _items = items;
|
||||
|
||||
/// Returns the readonly List<ColumnItem>
|
||||
UnmodifiableListView<AFColumnItem> get items => UnmodifiableListView(_items);
|
||||
UnmodifiableListView<AFColumnItem> get items =>
|
||||
UnmodifiableListView([..._items]);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, ..._items];
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -123,3 +123,46 @@ impl TryInto<MoveRowParams> 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<String>,
|
||||
}
|
||||
|
||||
pub struct MoveGroupRowParams {
|
||||
pub view_id: String,
|
||||
pub from_row_id: String,
|
||||
pub to_group_id: String,
|
||||
pub to_row_id: Option<String>,
|
||||
}
|
||||
|
||||
impl TryInto<MoveGroupRowParams> for MoveGroupRowPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<MoveGroupRowParams, Self::Error> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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<MoveGroupRowPayloadPB>,
|
||||
manager: AppData<Arc<GridManager>>,
|
||||
) -> 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(())
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> 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,
|
||||
}
|
||||
|
@ -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: _,
|
||||
|
@ -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<String>,
|
||||
) {
|
||||
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 {
|
||||
|
@ -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<RowRevision>, to_row_id: String) -> Option<RowChangeset> {
|
||||
pub(crate) async fn move_group_row(
|
||||
&self,
|
||||
row_rev: Arc<RowRevision>,
|
||||
to_group_id: String,
|
||||
to_row_id: Option<String>,
|
||||
) -> Option<RowChangeset> {
|
||||
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() {
|
||||
|
@ -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<GroupRowsChangesetPB>;
|
||||
|
||||
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<GroupRowsChangesetPB>;
|
||||
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupRowsChangesetPB>;
|
||||
}
|
||||
|
@ -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<Group>) -> (Vec<GroupRecordRevision>, Vec<Group>) {
|
||||
tracing::trace!("Merge group: old: {}, new: {}", old_group_revs.len(), groups.len());
|
||||
if old_group_revs.is_empty() {
|
||||
let new_groups = groups
|
||||
.iter()
|
||||
|
@ -31,6 +31,14 @@ pub trait GroupGenerator {
|
||||
) -> Vec<Group>;
|
||||
}
|
||||
|
||||
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<String>,
|
||||
}
|
||||
|
||||
// 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<Vec<GroupRowsChangesetPB>>;
|
||||
|
||||
fn did_move_row(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
field_rev: &FieldRevision,
|
||||
to_row_id: &str,
|
||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||
}
|
||||
|
||||
/// 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<Vec<GroupRowsChangesetPB>> {
|
||||
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<Vec<GroupRowsChangesetPB>> {
|
||||
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::<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))
|
||||
Ok(self.move_row(&cell_data, context))
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
@ -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<GroupRowsChangesetPB> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -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<GroupRowsChangesetPB> {
|
||||
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
|
||||
}
|
||||
|
@ -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<GroupRowsChangesetPB> {
|
||||
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
|
||||
}
|
||||
|
@ -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<SelectOptionGroupConfigurationRevision>;
|
||||
|
||||
@ -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<GroupRowsChangesetPB>,
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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<dyn GroupConfigurationReader>,
|
||||
configuration_writer: Arc<dyn GroupConfigurationWriter>,
|
||||
group_controller: Option<Arc<RwLock<dyn GroupController>>>,
|
||||
group_controller: Option<Box<dyn GroupController>>,
|
||||
}
|
||||
|
||||
impl GroupService {
|
||||
@ -36,19 +34,16 @@ impl GroupService {
|
||||
}
|
||||
|
||||
pub(crate) async fn groups(&self) -> Vec<Group> {
|
||||
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<Vec<Group>> {
|
||||
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<F, O>(&self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F)
|
||||
pub(crate) async fn will_create_row<F, O>(&mut self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F)
|
||||
where
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + 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<F, O>(
|
||||
&self,
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
@ -110,11 +91,11 @@ impl GroupService {
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + 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<F, O>(
|
||||
&self,
|
||||
pub(crate) async fn move_group_row<F, O>(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
upper_row_id: &str,
|
||||
to_group_id: &str,
|
||||
to_row_id: Option<String>,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
where
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + 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<F, O>(
|
||||
&self,
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
@ -161,11 +146,11 @@ impl GroupService {
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + 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<FieldRevision>,
|
||||
) -> FlowyResult<Option<Arc<RwLock<dyn GroupController>>>> {
|
||||
let mut group_controller: Option<Arc<RwLock<dyn GroupController>>> = None;
|
||||
) -> FlowyResult<Option<Box<dyn GroupController>>> {
|
||||
let mut group_controller: Option<Box<dyn GroupController>> = None;
|
||||
match field_type {
|
||||
FieldType::RichText => {
|
||||
// let generator = GroupGenerator::<TextGroupConfigurationPB>::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::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
||||
|
@ -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<GroupPB> = 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,
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,9 @@ impl GridViewRevisionPad {
|
||||
group_rev: GroupConfigurationRevision,
|
||||
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
|
||||
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<Option<GridViewRevisionChangeset>> {
|
||||
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 }))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user