mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00: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",
|
"program": "./lib/main.dart",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"env": {
|
"env": {
|
||||||
"RUST_LOG": "trace"
|
"RUST_LOG": "debug"
|
||||||
},
|
},
|
||||||
"cwd": "${workspaceRoot}/app_flowy"
|
"cwd": "${workspaceRoot}/app_flowy"
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
final BoardDataController _dataController;
|
final BoardDataController _dataController;
|
||||||
late final AFBoardDataController afBoardDataController;
|
late final AFBoardDataController afBoardDataController;
|
||||||
final MoveRowFFIService _rowService;
|
final MoveRowFFIService _rowService;
|
||||||
Map<String, GroupController> groupControllers = {};
|
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap.new();
|
||||||
|
|
||||||
GridFieldCache get fieldCache => _dataController.fieldCache;
|
GridFieldCache get fieldCache => _dataController.fieldCache;
|
||||||
String get gridId => _dataController.gridId;
|
String get gridId => _dataController.gridId;
|
||||||
@ -34,9 +34,13 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
super(BoardState.initial(view.id)) {
|
super(BoardState.initial(view.id)) {
|
||||||
afBoardDataController = AFBoardDataController(
|
afBoardDataController = AFBoardDataController(
|
||||||
onMoveColumn: (
|
onMoveColumn: (
|
||||||
|
fromColumnId,
|
||||||
fromIndex,
|
fromIndex,
|
||||||
|
toColumnId,
|
||||||
toIndex,
|
toIndex,
|
||||||
) {},
|
) {
|
||||||
|
_moveGroup(fromColumnId, toColumnId);
|
||||||
|
},
|
||||||
onMoveColumnItem: (
|
onMoveColumnItem: (
|
||||||
columnId,
|
columnId,
|
||||||
fromIndex,
|
fromIndex,
|
||||||
@ -44,7 +48,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
) {
|
) {
|
||||||
final fromRow = groupControllers[columnId]?.rowAtIndex(fromIndex);
|
final fromRow = groupControllers[columnId]?.rowAtIndex(fromIndex);
|
||||||
final toRow = groupControllers[columnId]?.rowAtIndex(toIndex);
|
final toRow = groupControllers[columnId]?.rowAtIndex(toIndex);
|
||||||
_moveRow(fromRow, toRow);
|
_moveRow(fromRow, columnId, toRow);
|
||||||
},
|
},
|
||||||
onMoveColumnItemToColumn: (
|
onMoveColumnItemToColumn: (
|
||||||
fromColumnId,
|
fromColumnId,
|
||||||
@ -54,7 +58,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
) {
|
) {
|
||||||
final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex);
|
final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex);
|
||||||
final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex);
|
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) {
|
void _moveRow(RowPB? fromRow, String columnId, RowPB? toRow) {
|
||||||
if (fromRow != null && toRow != null) {
|
if (fromRow != null) {
|
||||||
_rowService
|
_rowService
|
||||||
.moveRow(
|
.moveGroupRow(
|
||||||
fromRowId: fromRow.id,
|
fromRowId: fromRow.id,
|
||||||
toRowId: toRow.id,
|
toGroupId: columnId,
|
||||||
|
toRowId: toRow?.id,
|
||||||
)
|
)
|
||||||
.then((result) {
|
.then((result) {
|
||||||
result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r)));
|
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
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _dataController.dispose();
|
await _dataController.dispose();
|
||||||
|
@ -37,6 +37,14 @@ class GroupController {
|
|||||||
(GroupRowsChangesetPB changeset) {
|
(GroupRowsChangesetPB changeset) {
|
||||||
for (final insertedRow in changeset.insertedRows) {
|
for (final insertedRow in changeset.insertedRows) {
|
||||||
final index = insertedRow.hasIndex() ? insertedRow.index : null;
|
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(
|
delegate.insertRow(
|
||||||
group.groupId,
|
group.groupId,
|
||||||
insertedRow.row,
|
insertedRow.row,
|
||||||
@ -45,10 +53,19 @@ class GroupController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final deletedRow in changeset.deletedRows) {
|
for (final deletedRow in changeset.deletedRows) {
|
||||||
|
group.rows.removeWhere((rowPB) => rowPB.id == deletedRow);
|
||||||
delegate.removeRow(group.groupId, deletedRow);
|
delegate.removeRow(group.groupId, deletedRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final updatedRow in changeset.updatedRows) {
|
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);
|
delegate.updateRow(group.groupId, updatedRow);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder {
|
|||||||
|
|
||||||
class BoardPluginConfig implements PluginConfig {
|
class BoardPluginConfig implements PluginConfig {
|
||||||
@override
|
@override
|
||||||
bool get creatable => true;
|
bool get creatable => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardPlugin extends Plugin {
|
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-error/errors.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.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/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';
|
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
|
||||||
|
|
||||||
class RowFFIService {
|
class RowFFIService {
|
||||||
@ -68,4 +69,33 @@ class MoveRowFFIService {
|
|||||||
|
|
||||||
return GridEventMoveRow(payload).send();
|
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> {
|
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||||
final AFBoardDataController boardDataController = AFBoardDataController(
|
final AFBoardDataController boardDataController = AFBoardDataController(
|
||||||
onMoveColumn: (fromIndex, toIndex) {
|
onMoveColumn: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
||||||
debugPrint('Move column from $fromIndex to $toIndex');
|
debugPrint('Move column from $fromIndex to $toIndex');
|
||||||
},
|
},
|
||||||
onMoveColumnItem: (columnId, fromIndex, toIndex) {
|
onMoveColumnItem: (columnId, fromIndex, toIndex) {
|
||||||
|
@ -145,7 +145,8 @@ class AFBoardColumnData<CustomData> extends ReoderFlexItem with EquatableMixin {
|
|||||||
}) : _items = items;
|
}) : _items = items;
|
||||||
|
|
||||||
/// Returns the readonly List<ColumnItem>
|
/// Returns the readonly List<ColumnItem>
|
||||||
UnmodifiableListView<AFColumnItem> get items => UnmodifiableListView(_items);
|
UnmodifiableListView<AFColumnItem> get items =>
|
||||||
|
UnmodifiableListView([..._items]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [id, ..._items];
|
List<Object?> get props => [id, ..._items];
|
||||||
|
@ -8,7 +8,12 @@ import 'reorder_flex/reorder_flex.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'reorder_phantom/phantom_controller.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(
|
typedef OnMoveColumnItem = void Function(
|
||||||
String columnId,
|
String columnId,
|
||||||
@ -98,9 +103,11 @@ class AFBoardDataController extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
void moveColumn(int fromIndex, int toIndex, {bool notify = true}) {
|
void moveColumn(int fromIndex, int toIndex, {bool notify = true}) {
|
||||||
final columnData = _columnDatas.removeAt(fromIndex);
|
final toColumnData = _columnDatas[toIndex];
|
||||||
_columnDatas.insert(toIndex, columnData);
|
final fromColumnData = _columnDatas.removeAt(fromIndex);
|
||||||
onMoveColumn?.call(fromIndex, toIndex);
|
|
||||||
|
_columnDatas.insert(toIndex, fromColumnData);
|
||||||
|
onMoveColumn?.call(fromColumnData.id, fromIndex, toColumnData.id, toIndex);
|
||||||
if (notify) notifyListeners();
|
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?;
|
let _ = editor.move_group(params).await?;
|
||||||
Ok(())
|
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
|
// Group
|
||||||
.event(GridEvent::CreateBoardCard, create_board_card_handler)
|
.event(GridEvent::CreateBoardCard, create_board_card_handler)
|
||||||
.event(GridEvent::MoveGroup, move_group_handler)
|
.event(GridEvent::MoveGroup, move_group_handler)
|
||||||
|
.event(GridEvent::MoveGroupRow, move_group_row_handler)
|
||||||
.event(GridEvent::GetGroup, get_groups_handler);
|
.event(GridEvent::GetGroup, get_groups_handler);
|
||||||
|
|
||||||
module
|
module
|
||||||
@ -221,4 +222,7 @@ pub enum GridEvent {
|
|||||||
|
|
||||||
#[event(input = "MoveGroupPayloadPB")]
|
#[event(input = "MoveGroupPayloadPB")]
|
||||||
MoveGroup = 111,
|
MoveGroup = 111,
|
||||||
|
|
||||||
|
#[event(input = "MoveGroupRowPayloadPB")]
|
||||||
|
MoveGroupRow = 112,
|
||||||
}
|
}
|
||||||
|
@ -560,16 +560,6 @@ impl GridRevisionEditor {
|
|||||||
.block_manager
|
.block_manager
|
||||||
.move_row(row_rev.clone(), from_index, to_index)
|
.move_row(row_rev.clone(), from_index, to_index)
|
||||||
.await?;
|
.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 from row id: {}", from_row_id),
|
||||||
(None, _) => tracing::warn!("Can not find the to row id: {}", to_row_id),
|
(None, _) => tracing::warn!("Can not find the to row id: {}", to_row_id),
|
||||||
@ -579,6 +569,35 @@ impl GridRevisionEditor {
|
|||||||
Ok(())
|
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<()> {
|
pub async fn move_field(&self, params: MoveFieldParams) -> FlowyResult<()> {
|
||||||
let MoveFieldParams {
|
let MoveFieldParams {
|
||||||
grid_id: _,
|
grid_id: _,
|
||||||
|
@ -80,7 +80,7 @@ impl GridViewRevisionEditor {
|
|||||||
None => {}
|
None => {}
|
||||||
Some(group_id) => {
|
Some(group_id) => {
|
||||||
self.group_service
|
self.group_service
|
||||||
.read()
|
.write()
|
||||||
.await
|
.await
|
||||||
.will_create_row(row_rev, group_id, |field_id| {
|
.will_create_row(row_rev, group_id, |field_id| {
|
||||||
self.field_delegate.get_field_rev(&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;
|
// Send the group notification if the current view has groups;
|
||||||
if let Some(changesets) = self
|
if let Some(changesets) = self
|
||||||
.group_service
|
.group_service
|
||||||
.read()
|
.write()
|
||||||
.await
|
.await
|
||||||
.did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
.did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
||||||
.await
|
.await
|
||||||
@ -123,7 +123,7 @@ impl GridViewRevisionEditor {
|
|||||||
pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
|
pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
|
||||||
if let Some(changesets) = self
|
if let Some(changesets) = self
|
||||||
.group_service
|
.group_service
|
||||||
.read()
|
.write()
|
||||||
.await
|
.await
|
||||||
.did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
.did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
||||||
.await
|
.await
|
||||||
@ -134,23 +134,23 @@ impl GridViewRevisionEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn did_move_row(
|
pub(crate) async fn move_group_row(
|
||||||
&self,
|
&self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
row_changeset: &mut RowChangeset,
|
row_changeset: &mut RowChangeset,
|
||||||
upper_row_id: &str,
|
to_group_id: &str,
|
||||||
|
to_row_id: Option<String>,
|
||||||
) {
|
) {
|
||||||
if let Some(changesets) = self
|
if let Some(changesets) = self
|
||||||
.group_service
|
.group_service
|
||||||
.read()
|
.write()
|
||||||
.await
|
.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)
|
self.field_delegate.get_field_rev(&field_id)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
for changeset in changesets {
|
for changeset in changesets {
|
||||||
tracing::trace!("Group: {} changeset: {}", changeset.group_id, changeset);
|
|
||||||
self.notify_did_update_group_rows(changeset).await;
|
self.notify_did_update_group_rows(changeset).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ impl GridViewRevisionEditor {
|
|||||||
pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
|
pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
|
||||||
let _ = self
|
let _ = self
|
||||||
.group_service
|
.group_service
|
||||||
.read()
|
.write()
|
||||||
.await
|
.await
|
||||||
.move_group(¶ms.from_group_id, ¶ms.to_group_id)
|
.move_group(¶ms.from_group_id, ¶ms.to_group_id)
|
||||||
.await?;
|
.await?;
|
||||||
@ -326,7 +326,6 @@ impl GroupConfigurationReader for GroupConfigurationReaderImpl {
|
|||||||
let view_pad = self.0.clone();
|
let view_pad = self.0.clone();
|
||||||
wrap_future(async move {
|
wrap_future(async move {
|
||||||
let mut groups = view_pad.read().await.groups.get_objects(&field_rev.id, &field_rev.ty)?;
|
let mut groups = view_pad.read().await.groups.get_objects(&field_rev.id, &field_rev.ty)?;
|
||||||
|
|
||||||
if groups.is_empty() {
|
if groups.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,10 +129,17 @@ impl GridViewManager {
|
|||||||
/// It may generate a RowChangeset when the Row was moved from one group to another.
|
/// 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.
|
/// 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());
|
let mut row_changeset = RowChangeset::new(row_rev.id.clone());
|
||||||
for view_editor in self.view_editors.iter() {
|
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() {
|
if row_changeset.has_changed() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::entities::GroupRowsChangesetPB;
|
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 {
|
pub trait GroupAction: Send + Sync {
|
||||||
type CellDataType;
|
type CellDataType;
|
||||||
@ -12,12 +13,5 @@ pub trait GroupAction: Send + Sync {
|
|||||||
cell_data: &Self::CellDataType,
|
cell_data: &Self::CellDataType,
|
||||||
) -> Vec<GroupRowsChangesetPB>;
|
) -> Vec<GroupRowsChangesetPB>;
|
||||||
|
|
||||||
fn move_row_if_match(
|
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupRowsChangesetPB>;
|
||||||
&mut self,
|
|
||||||
field_rev: &FieldRevision,
|
|
||||||
row_rev: &RowRevision,
|
|
||||||
row_changeset: &mut RowChangeset,
|
|
||||||
cell_data: &Self::CellDataType,
|
|
||||||
to_row_id: &str,
|
|
||||||
) -> Vec<GroupRowsChangesetPB>;
|
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,9 @@ where
|
|||||||
Ok(())
|
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)| {
|
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)
|
self.groups_map.get_mut(group_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
|
pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> {
|
||||||
let from_group_index = self.groups_map.get_index_of(from_group_id);
|
let from_index = self.groups_map.get_index_of(from_id);
|
||||||
let to_group_index = self.groups_map.get_index_of(to_group_id);
|
let to_index = self.groups_map.get_index_of(to_id);
|
||||||
match (from_group_index, to_group_index) {
|
match (from_index, to_index) {
|
||||||
(Some(from_index), Some(to_index)) => {
|
(Some(from_index), Some(to_index)) => {
|
||||||
self.groups_map.swap_indices(from_index, to_index);
|
self.groups_map.swap_indices(from_index, to_index);
|
||||||
|
|
||||||
self.mut_configuration(|configuration| {
|
self.mut_configuration(|configuration| {
|
||||||
let from_index = configuration
|
let from_index = configuration.groups.iter().position(|group| group.group_id == from_id);
|
||||||
.groups
|
let to_index = configuration.groups.iter().position(|group| group.group_id == to_id);
|
||||||
.iter()
|
|
||||||
.position(|group| group.group_id == from_group_id);
|
|
||||||
let to_index = configuration
|
|
||||||
.groups
|
|
||||||
.iter()
|
|
||||||
.position(|group| group.group_id == to_group_id);
|
|
||||||
if let (Some(from), Some(to)) = (from_index, to_index) {
|
if let (Some(from), Some(to)) = (from_index, to_index) {
|
||||||
configuration.groups.swap(from, to);
|
configuration.groups.swap(from, to);
|
||||||
}
|
}
|
||||||
@ -150,7 +144,7 @@ where
|
|||||||
let configuration = (&*self.configuration).clone();
|
let configuration = (&*self.configuration).clone();
|
||||||
let writer = self.writer.clone();
|
let writer = self.writer.clone();
|
||||||
let field_id = self.field_rev.id.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 {
|
tokio::spawn(async move {
|
||||||
match writer
|
match writer
|
||||||
.save_group_configuration(&field_id, field_type, configuration)
|
.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>) {
|
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() {
|
if old_group_revs.is_empty() {
|
||||||
let new_groups = groups
|
let new_groups = groups
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -31,6 +31,14 @@ pub trait GroupGenerator {
|
|||||||
) -> Vec<Group>;
|
) -> 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.
|
// Defines the shared actions each group controller can perform.
|
||||||
pub trait GroupControllerSharedOperation: Send + Sync {
|
pub trait GroupControllerSharedOperation: Send + Sync {
|
||||||
// The field that is used for grouping the rows
|
// The field that is used for grouping the rows
|
||||||
@ -51,13 +59,7 @@ pub trait GroupControllerSharedOperation: Send + Sync {
|
|||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||||
|
|
||||||
fn did_move_row(
|
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||||
&mut self,
|
|
||||||
row_rev: &RowRevision,
|
|
||||||
row_changeset: &mut RowChangeset,
|
|
||||||
field_rev: &FieldRevision,
|
|
||||||
to_row_id: &str,
|
|
||||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// C: represents the group configuration that impl [GroupConfigurationSerde]
|
/// C: represents the group configuration that impl [GroupConfigurationSerde]
|
||||||
@ -195,18 +197,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_move_row(
|
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupRowsChangesetPB>> {
|
||||||
&mut self,
|
if let Some(cell_rev) = context.row_rev.cells.get(&self.field_id) {
|
||||||
row_rev: &RowRevision,
|
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), context.field_rev);
|
||||||
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);
|
|
||||||
let cell_data = cell_bytes.parser::<P>()?;
|
let cell_data = cell_bytes.parser::<P>()?;
|
||||||
tracing::trace!("Move row:{} to row:{}", row_rev.id, to_row_id);
|
Ok(self.move_row(&cell_data, context))
|
||||||
Ok(self.move_row_if_match(field_rev, row_rev, row_changeset, &cell_data, to_row_id))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@ use crate::entities::GroupRowsChangesetPB;
|
|||||||
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
||||||
use crate::services::group::action::GroupAction;
|
use crate::services::group::action::GroupAction;
|
||||||
use crate::services::group::configuration::GenericGroupConfiguration;
|
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 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<
|
pub type CheckboxGroupController = GenericGroupController<
|
||||||
CheckboxGroupConfigurationRevision,
|
CheckboxGroupConfigurationRevision,
|
||||||
@ -38,13 +40,10 @@ impl GroupAction for CheckboxGroupController {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_row_if_match(
|
fn move_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
_field_rev: &FieldRevision,
|
|
||||||
_row_rev: &RowRevision,
|
|
||||||
_row_changeset: &mut RowChangeset,
|
|
||||||
_cell_data: &Self::CellDataType,
|
_cell_data: &Self::CellDataType,
|
||||||
_to_row_id: &str,
|
_context: MoveGroupRowContext,
|
||||||
) -> Vec<GroupRowsChangesetPB> {
|
) -> Vec<GroupRowsChangesetPB> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ use crate::services::cell::insert_select_option_cell;
|
|||||||
use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser};
|
use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser};
|
||||||
use crate::services::group::action::GroupAction;
|
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::controller_impls::select_option_controller::util::*;
|
||||||
use crate::services::group::entities::Group;
|
use crate::services::group::entities::Group;
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision,
|
|
||||||
};
|
|
||||||
|
|
||||||
// MultiSelect
|
// MultiSelect
|
||||||
pub type MultiSelectGroupController = GenericGroupController<
|
pub type MultiSelectGroupController = GenericGroupController<
|
||||||
@ -45,25 +45,14 @@ impl GroupAction for MultiSelectGroupController {
|
|||||||
changesets
|
changesets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_row_if_match(
|
fn move_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
field_rev: &FieldRevision,
|
|
||||||
row_rev: &RowRevision,
|
|
||||||
row_changeset: &mut RowChangeset,
|
|
||||||
cell_data: &Self::CellDataType,
|
cell_data: &Self::CellDataType,
|
||||||
to_row_id: &str,
|
mut context: MoveGroupRowContext,
|
||||||
) -> Vec<GroupRowsChangesetPB> {
|
) -> Vec<GroupRowsChangesetPB> {
|
||||||
let mut group_changeset = vec![];
|
let mut group_changeset = vec![];
|
||||||
self.configuration.with_mut_groups(|group| {
|
self.configuration.with_mut_groups(|group| {
|
||||||
move_row(
|
move_select_option_row(group, &mut group_changeset, cell_data, &mut context);
|
||||||
group,
|
|
||||||
&mut group_changeset,
|
|
||||||
field_rev,
|
|
||||||
row_rev,
|
|
||||||
row_changeset,
|
|
||||||
cell_data,
|
|
||||||
to_row_id,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
group_changeset
|
group_changeset
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,13 @@ use crate::services::cell::insert_select_option_cell;
|
|||||||
use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB};
|
use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB};
|
||||||
use crate::services::group::action::GroupAction;
|
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::controller_impls::select_option_controller::util::*;
|
||||||
use crate::services::group::entities::Group;
|
use crate::services::group::entities::Group;
|
||||||
|
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision,
|
|
||||||
};
|
|
||||||
|
|
||||||
// SingleSelect
|
// SingleSelect
|
||||||
pub type SingleSelectGroupController = GenericGroupController<
|
pub type SingleSelectGroupController = GenericGroupController<
|
||||||
@ -45,25 +45,14 @@ impl GroupAction for SingleSelectGroupController {
|
|||||||
changesets
|
changesets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_row_if_match(
|
fn move_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
field_rev: &FieldRevision,
|
|
||||||
row_rev: &RowRevision,
|
|
||||||
row_changeset: &mut RowChangeset,
|
|
||||||
cell_data: &Self::CellDataType,
|
cell_data: &Self::CellDataType,
|
||||||
to_row_id: &str,
|
mut context: MoveGroupRowContext,
|
||||||
) -> Vec<GroupRowsChangesetPB> {
|
) -> Vec<GroupRowsChangesetPB> {
|
||||||
let mut group_changeset = vec![];
|
let mut group_changeset = vec![];
|
||||||
self.configuration.with_mut_groups(|group| {
|
self.configuration.with_mut_groups(|group| {
|
||||||
move_row(
|
move_select_option_row(group, &mut group_changeset, cell_data, &mut context);
|
||||||
group,
|
|
||||||
&mut group_changeset,
|
|
||||||
field_rev,
|
|
||||||
row_rev,
|
|
||||||
row_changeset,
|
|
||||||
cell_data,
|
|
||||||
to_row_id,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
group_changeset
|
group_changeset
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,8 @@ use crate::services::field::SelectOptionCellDataPB;
|
|||||||
use crate::services::group::configuration::GenericGroupConfiguration;
|
use crate::services::group::configuration::GenericGroupConfiguration;
|
||||||
use crate::services::group::Group;
|
use crate::services::group::Group;
|
||||||
|
|
||||||
use flowy_grid_data_model::revision::{
|
use crate::services::group::controller::MoveGroupRowContext;
|
||||||
FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision,
|
use flowy_grid_data_model::revision::{RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
};
|
|
||||||
|
|
||||||
pub type SelectOptionGroupConfiguration = GenericGroupConfiguration<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: &mut Group,
|
||||||
group_changeset: &mut Vec<GroupRowsChangesetPB>,
|
group_changeset: &mut Vec<GroupRowsChangesetPB>,
|
||||||
field_rev: &FieldRevision,
|
_cell_data: &SelectOptionCellDataPB,
|
||||||
row_rev: &RowRevision,
|
context: &mut MoveGroupRowContext,
|
||||||
row_changeset: &mut RowChangeset,
|
|
||||||
cell_data: &SelectOptionCellDataPB,
|
|
||||||
to_row_id: &str,
|
|
||||||
) {
|
) {
|
||||||
cell_data.select_options.iter().for_each(|option| {
|
let MoveGroupRowContext {
|
||||||
// Remove the row in which group contains the row
|
row_rev,
|
||||||
let is_group_contains = group.contains_row(&row_rev.id);
|
row_changeset,
|
||||||
let to_index = group.index_of_row(to_row_id);
|
field_rev,
|
||||||
|
to_group_id,
|
||||||
|
to_row_id,
|
||||||
|
} = context;
|
||||||
|
|
||||||
if option.id == group.id && is_group_contains {
|
let from_index = group.index_of_row(&row_rev.id);
|
||||||
group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
let to_index = match to_row_id {
|
||||||
group.remove_row(&row_rev.id);
|
None => None,
|
||||||
}
|
Some(to_row_id) => group.index_of_row(to_row_id),
|
||||||
|
};
|
||||||
|
|
||||||
// Find the inserted group
|
// Remove the row in which group contains it
|
||||||
if let Some(to_index) = to_index {
|
if from_index.is_some() {
|
||||||
let row_pb = RowPB::from(row_rev);
|
group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||||
let inserted_row = InsertedRowPB {
|
tracing::debug!("Group:{} remove row:{}", group.id, row_rev.id);
|
||||||
row: row_pb.clone(),
|
group.remove_row(&row_rev.id);
|
||||||
index: Some(to_index as i32),
|
}
|
||||||
};
|
|
||||||
group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row]));
|
if group.id == *to_group_id {
|
||||||
if group.number_of_row() == to_index {
|
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);
|
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.
|
// Update the corresponding row's cell content.
|
||||||
if to_index.is_some() && option.id != group.id {
|
if from_index.is_none() {
|
||||||
// Update the corresponding row's cell content.
|
tracing::debug!("Mark row:{} belong to group:{}", row_rev.id, group.id);
|
||||||
let cell_rev = insert_select_option_cell(group.id.clone(), field_rev);
|
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);
|
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::configuration::GroupConfigurationReader;
|
||||||
use crate::services::group::controller::GroupController;
|
use crate::services::group::controller::{GroupController, MoveGroupRowContext};
|
||||||
use crate::services::group::{
|
use crate::services::group::{
|
||||||
CheckboxGroupConfiguration, CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController,
|
CheckboxGroupConfiguration, CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController,
|
||||||
SelectOptionGroupConfiguration, SingleSelectGroupController,
|
SelectOptionGroupConfiguration, SingleSelectGroupController,
|
||||||
@ -10,16 +11,13 @@ use flowy_grid_data_model::revision::{
|
|||||||
NumberGroupConfigurationRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision,
|
NumberGroupConfigurationRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision,
|
||||||
TextGroupConfigurationRevision, UrlGroupConfigurationRevision,
|
TextGroupConfigurationRevision, UrlGroupConfigurationRevision,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::entities::{FieldType, GroupRowsChangesetPB};
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
pub(crate) struct GroupService {
|
pub(crate) struct GroupService {
|
||||||
configuration_reader: Arc<dyn GroupConfigurationReader>,
|
configuration_reader: Arc<dyn GroupConfigurationReader>,
|
||||||
configuration_writer: Arc<dyn GroupConfigurationWriter>,
|
configuration_writer: Arc<dyn GroupConfigurationWriter>,
|
||||||
group_controller: Option<Arc<RwLock<dyn GroupController>>>,
|
group_controller: Option<Box<dyn GroupController>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GroupService {
|
impl GroupService {
|
||||||
@ -36,19 +34,16 @@ impl GroupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn groups(&self) -> Vec<Group> {
|
pub(crate) async fn groups(&self) -> Vec<Group> {
|
||||||
if let Some(group_controller) = self.group_controller.as_ref() {
|
self.group_controller
|
||||||
group_controller.read().await.groups()
|
.as_ref()
|
||||||
} else {
|
.and_then(|group_controller| Some(group_controller.groups()))
|
||||||
vec![]
|
.unwrap_or(vec![])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
||||||
if let Some(group_controller) = self.group_controller.as_ref() {
|
self.group_controller
|
||||||
group_controller.read().await.get_group(group_id)
|
.as_ref()
|
||||||
} else {
|
.and_then(|group_controller| group_controller.get_group(group_id))
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn load_groups(
|
pub(crate) async fn load_groups(
|
||||||
@ -58,51 +53,37 @@ impl GroupService {
|
|||||||
) -> Option<Vec<Group>> {
|
) -> Option<Vec<Group>> {
|
||||||
let field_rev = find_group_field(field_revs)?;
|
let field_rev = find_group_field(field_revs)?;
|
||||||
let field_type: FieldType = field_rev.ty.into();
|
let field_type: FieldType = field_rev.ty.into();
|
||||||
match self.make_group_controller(&field_type, &field_rev).await {
|
|
||||||
Ok(group_controller) => {
|
let mut group_controller = self.make_group_controller(&field_type, &field_rev).await.ok()??;
|
||||||
self.group_controller = group_controller;
|
let groups = match group_controller.fill_groups(&row_revs, &field_rev) {
|
||||||
let mut groups = vec![];
|
Ok(groups) => groups,
|
||||||
if let Some(group_action_handler) = self.group_controller.as_ref() {
|
Err(e) => {
|
||||||
let mut write_guard = group_action_handler.write().await;
|
tracing::error!("Fill groups failed:{:?}", e);
|
||||||
groups = match write_guard.fill_groups(&row_revs, &field_rev) {
|
vec![]
|
||||||
Ok(groups) => groups,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("Fill groups failed:{:?}", e);
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
drop(write_guard);
|
|
||||||
}
|
|
||||||
Some(groups)
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
};
|
||||||
tracing::error!("Load group failed: {}", err);
|
self.group_controller = Some(group_controller);
|
||||||
Some(vec![])
|
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
|
where
|
||||||
F: FnOnce(String) -> O,
|
F: FnOnce(String) -> O,
|
||||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
if let Some(group_controller) = self.group_controller.as_ref() {
|
if let Some(group_controller) = self.group_controller.as_mut() {
|
||||||
let field_id = group_controller.read().await.field_id().to_owned();
|
let field_id = group_controller.field_id().to_owned();
|
||||||
match get_field_fn(field_id).await {
|
match get_field_fn(field_id).await {
|
||||||
None => {}
|
None => {}
|
||||||
Some(field_rev) => {
|
Some(field_rev) => {
|
||||||
group_controller
|
group_controller.will_create_row(row_rev, &field_rev, group_id);
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.will_create_row(row_rev, &field_rev, group_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn did_delete_row<F, O>(
|
pub(crate) async fn did_delete_row<F, O>(
|
||||||
&self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
get_field_fn: F,
|
get_field_fn: F,
|
||||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||||
@ -110,11 +91,11 @@ impl GroupService {
|
|||||||
F: FnOnce(String) -> O,
|
F: FnOnce(String) -> O,
|
||||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let group_controller = self.group_controller.as_ref()?;
|
let group_controller = self.group_controller.as_mut()?;
|
||||||
let field_id = group_controller.read().await.field_id().to_owned();
|
let field_id = group_controller.field_id().to_owned();
|
||||||
let field_rev = get_field_fn(field_id).await?;
|
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),
|
Ok(changesets) => Some(changesets),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Delete group data failed, {:?}", e);
|
tracing::error!("Delete group data failed, {:?}", e);
|
||||||
@ -123,26 +104,30 @@ impl GroupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn did_move_row<F, O>(
|
pub(crate) async fn move_group_row<F, O>(
|
||||||
&self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
row_changeset: &mut RowChangeset,
|
row_changeset: &mut RowChangeset,
|
||||||
upper_row_id: &str,
|
to_group_id: &str,
|
||||||
|
to_row_id: Option<String>,
|
||||||
get_field_fn: F,
|
get_field_fn: F,
|
||||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||||
where
|
where
|
||||||
F: FnOnce(String) -> O,
|
F: FnOnce(String) -> O,
|
||||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let group_controller = self.group_controller.as_ref()?;
|
let group_controller = self.group_controller.as_mut()?;
|
||||||
let field_id = group_controller.read().await.field_id().to_owned();
|
let field_id = group_controller.field_id().to_owned();
|
||||||
let field_rev = get_field_fn(field_id).await?;
|
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
|
match group_controller.move_group_row(move_row_context) {
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.did_move_row(row_rev, row_changeset, &field_rev, upper_row_id)
|
|
||||||
{
|
|
||||||
Ok(changesets) => Some(changesets),
|
Ok(changesets) => Some(changesets),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Move group data failed, {:?}", e);
|
tracing::error!("Move group data failed, {:?}", e);
|
||||||
@ -153,7 +138,7 @@ impl GroupService {
|
|||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all)]
|
#[tracing::instrument(level = "trace", skip_all)]
|
||||||
pub(crate) async fn did_update_row<F, O>(
|
pub(crate) async fn did_update_row<F, O>(
|
||||||
&self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
get_field_fn: F,
|
get_field_fn: F,
|
||||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||||
@ -161,11 +146,11 @@ impl GroupService {
|
|||||||
F: FnOnce(String) -> O,
|
F: FnOnce(String) -> O,
|
||||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let group_controller = self.group_controller.as_ref()?;
|
let group_controller = self.group_controller.as_mut()?;
|
||||||
let field_id = group_controller.read().await.field_id().to_owned();
|
let field_id = group_controller.field_id().to_owned();
|
||||||
let field_rev = get_field_fn(field_id).await?;
|
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),
|
Ok(changeset) => Some(changeset),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Update group data failed, {:?}", e);
|
tracing::error!("Update group data failed, {:?}", e);
|
||||||
@ -175,11 +160,11 @@ impl GroupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all)]
|
#[tracing::instrument(level = "trace", skip_all)]
|
||||||
pub(crate) async fn move_group(&self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
|
pub(crate) async fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
|
||||||
match self.group_controller.as_ref() {
|
match self.group_controller.as_mut() {
|
||||||
None => Ok(()),
|
None => Ok(()),
|
||||||
Some(group_controller) => {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,8 +175,8 @@ impl GroupService {
|
|||||||
&self,
|
&self,
|
||||||
field_type: &FieldType,
|
field_type: &FieldType,
|
||||||
field_rev: &Arc<FieldRevision>,
|
field_rev: &Arc<FieldRevision>,
|
||||||
) -> FlowyResult<Option<Arc<RwLock<dyn GroupController>>>> {
|
) -> FlowyResult<Option<Box<dyn GroupController>>> {
|
||||||
let mut group_controller: Option<Arc<RwLock<dyn GroupController>>> = None;
|
let mut group_controller: Option<Box<dyn GroupController>> = None;
|
||||||
match field_type {
|
match field_type {
|
||||||
FieldType::RichText => {
|
FieldType::RichText => {
|
||||||
// let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
|
// let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
|
||||||
@ -210,7 +195,7 @@ impl GroupService {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let controller = SingleSelectGroupController::new(field_rev, configuration).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 => {
|
FieldType::MultiSelect => {
|
||||||
let configuration = SelectOptionGroupConfiguration::new(
|
let configuration = SelectOptionGroupConfiguration::new(
|
||||||
@ -220,7 +205,7 @@ impl GroupService {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let controller = MultiSelectGroupController::new(field_rev, configuration).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 => {
|
FieldType::Checkbox => {
|
||||||
let configuration = CheckboxGroupConfiguration::new(
|
let configuration = CheckboxGroupConfiguration::new(
|
||||||
@ -230,7 +215,7 @@ impl GroupService {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let controller = CheckboxGroupController::new(field_rev, configuration).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 => {
|
FieldType::URL => {
|
||||||
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::grid::grid_editor::GridEditorTest;
|
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::services::cell::insert_select_option_cell;
|
||||||
use flowy_grid_data_model::revision::RowChangeset;
|
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 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 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 to_group = groups.get(to_group_index).unwrap();
|
||||||
let params = MoveRowParams {
|
let to_row = to_group.rows.get(to_row_index).unwrap();
|
||||||
|
let params = MoveGroupRowParams {
|
||||||
view_id: self.inner.grid_id.clone(),
|
view_id: self.inner.grid_id.clone(),
|
||||||
from_row_id: from_row.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 {
|
GroupScript::AssertRow {
|
||||||
group_index,
|
group_index,
|
||||||
|
@ -2,7 +2,7 @@ use crate::grid::group_test::script::GridGroupTest;
|
|||||||
use crate::grid::group_test::script::GroupScript::*;
|
use crate::grid::group_test::script::GroupScript::*;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn board_init_test() {
|
async fn group_init_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
AssertGroupCount(3),
|
AssertGroupCount(3),
|
||||||
@ -23,7 +23,7 @@ async fn board_init_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn board_move_row_test() {
|
async fn group_move_row_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let group = test.group_at_index(0).await;
|
let group = test.group_at_index(0).await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
@ -48,7 +48,7 @@ async fn board_move_row_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::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 mut test = GridGroupTest::new().await;
|
||||||
let group = test.group_at_index(0).await;
|
let group = test.group_at_index(0).await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
@ -76,7 +76,7 @@ async fn board_move_row_to_other_group_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::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 mut test = GridGroupTest::new().await;
|
||||||
let group = test.group_at_index(0).await;
|
let group = test.group_at_index(0).await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
@ -86,15 +86,41 @@ async fn board_move_row_to_other_group_and_reorder_test() {
|
|||||||
to_group_index: 1,
|
to_group_index: 1,
|
||||||
to_row_index: 1,
|
to_row_index: 1,
|
||||||
},
|
},
|
||||||
MoveRow {
|
AssertGroupRowCount {
|
||||||
from_group_index: 1,
|
group_index: 0,
|
||||||
from_row_index: 1,
|
row_count: 1,
|
||||||
to_group_index: 1,
|
},
|
||||||
to_row_index: 2,
|
AssertGroupRowCount {
|
||||||
|
group_index: 1,
|
||||||
|
row_count: 3,
|
||||||
},
|
},
|
||||||
AssertRow {
|
AssertRow {
|
||||||
group_index: 1,
|
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(),
|
row: group.rows.get(0).unwrap().clone(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -102,7 +128,74 @@ async fn board_move_row_to_other_group_and_reorder_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::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 mut test = GridGroupTest::new().await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
CreateRow { group_index: 0 },
|
CreateRow { group_index: 0 },
|
||||||
@ -121,7 +214,7 @@ async fn board_create_row_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn board_delete_row_test() {
|
async fn group_delete_row_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
DeleteRow {
|
DeleteRow {
|
||||||
@ -137,7 +230,7 @@ async fn board_delete_row_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn board_delete_all_row_test() {
|
async fn group_delete_all_row_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
DeleteRow {
|
DeleteRow {
|
||||||
@ -157,7 +250,7 @@ async fn board_delete_all_row_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn board_update_row_test() {
|
async fn group_update_row_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
// Update the row at 0 in group0 by setting the row's group field data
|
// 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]
|
#[tokio::test]
|
||||||
async fn board_reorder_group_test() {
|
async fn group_reorder_group_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
// Update the row at 0 in group0 by setting the row's group field data
|
// 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]
|
#[tokio::test]
|
||||||
async fn board_move_group_test() {
|
async fn group_move_group_test() {
|
||||||
let mut test = GridGroupTest::new().await;
|
let mut test = GridGroupTest::new().await;
|
||||||
let group_0 = test.group_at_index(0).await;
|
let group_0 = test.group_at_index(0).await;
|
||||||
let group_1 = test.group_at_index(1).await;
|
let group_1 = test.group_at_index(1).await;
|
||||||
|
@ -76,7 +76,8 @@ where
|
|||||||
Some(objects_by_field_id)
|
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
|
let object_rev_map = self
|
||||||
.inner
|
.inner
|
||||||
.entry(field_id.to_string())
|
.entry(field_id.to_string())
|
||||||
@ -88,7 +89,7 @@ where
|
|||||||
.push(Arc::new(object))
|
.push(Arc::new(object))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_all(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.inner.clear()
|
self.inner.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,3 +155,27 @@ impl std::default::Default for DateCondition {
|
|||||||
DateCondition::Relative
|
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,
|
group_rev: GroupConfigurationRevision,
|
||||||
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
|
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
|
||||||
self.modify(|view| {
|
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(()))
|
Ok(Some(()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -127,7 +129,7 @@ impl GridViewRevisionPad {
|
|||||||
filter_rev: FilterConfigurationRevision,
|
filter_rev: FilterConfigurationRevision,
|
||||||
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
|
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
|
||||||
self.modify(|view| {
|
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(()))
|
Ok(Some(()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -166,8 +168,6 @@ impl GridViewRevisionPad {
|
|||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
Some(delta) => {
|
Some(delta) => {
|
||||||
self.delta = self.delta.compose(&delta)?;
|
self.delta = self.delta.compose(&delta)?;
|
||||||
tracing::info!("GridView: {:?}", delta);
|
|
||||||
|
|
||||||
let md5 = md5(&self.delta.json_bytes());
|
let md5 = md5(&self.delta.json_bytes());
|
||||||
Ok(Some(GridViewRevisionChangeset { delta, md5 }))
|
Ok(Some(GridViewRevisionChangeset { delta, md5 }))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user