From 57ede798d83b4f7488c2754e9cae6a3f3a643e4c Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 13 Aug 2022 14:59:50 +0800 Subject: [PATCH 1/6] refactor: remove UpdateRowPB, refactor RowInfo class --- .../plugins/board/application/board_bloc.dart | 12 ++- .../application/board_data_controller.dart | 45 ++++----- .../board/application/card/card_bloc.dart | 4 +- .../card/card_data_controller.dart | 2 +- .../app_flowy/lib/plugins/board/board.dart | 2 +- .../grid/application/block/block_cache.dart | 4 +- .../plugins/grid/application/grid_bloc.dart | 4 +- .../application/grid_data_controller.dart | 4 +- .../row/row_action_sheet_bloc.dart | 10 +- .../grid/application/row/row_bloc.dart | 6 +- .../grid/application/row/row_cache.dart | 92 ++++++++++--------- .../application/row/row_data_controller.dart | 6 +- .../plugins/grid/presentation/grid_page.dart | 4 +- .../presentation/widgets/row/grid_row.dart | 2 +- .../widgets/row/row_action_sheet.dart | 2 +- .../flowy-grid/src/entities/block_entities.rs | 45 ++------- .../rust-lib/flowy-grid/src/event_handler.rs | 2 +- .../flowy-grid/src/services/block_manager.rs | 27 +++--- .../flowy-grid/src/services/row/row_loader.rs | 4 +- 19 files changed, 118 insertions(+), 159 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index 09f85df732..baefecf723 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -52,8 +52,12 @@ class BoardBloc extends Bloc { _startListening(); await _loadGrid(emit); }, - createRow: () { - _dataController.createRow(); + createRow: () async { + final result = await _dataController.createRow(); + result.fold( + (rowPB) => null, + (err) => Log.error(err), + ); }, didReceiveGridUpdate: (GridPB grid) { emit(state.copyWith(grid: Some(grid))); @@ -99,7 +103,7 @@ class BoardBloc extends Bloc { boardDataController.addColumns(columns); }, - onRowsChanged: (List rowInfos, RowChangeReason reason) { + onRowsChanged: (List rowInfos, RowsChangedReason reason) { add(BoardEvent.didReceiveRows(rowInfos)); }, onError: (err) { @@ -156,6 +160,7 @@ class BoardState with _$BoardState { required String gridId, required Option grid, required List groups, + required Option editingRow, required List rowInfos, required GridLoadingState loadingState, }) = _BoardState; @@ -165,6 +170,7 @@ class BoardState with _$BoardState { groups: [], grid: none(), gridId: gridId, + editingRow: none(), loadingState: const _Loading(), ); } diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index da4cc54132..fe6e1b0bdf 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -4,7 +4,6 @@ import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'dart:async'; @@ -15,8 +14,8 @@ typedef OnFieldsChanged = void Function(UnmodifiableListView); typedef OnGridChanged = void Function(GridPB); typedef OnGroupChanged = void Function(List); typedef OnRowsChanged = void Function( - List rowInfos, - RowChangeReason, + List, + RowsChangedReason, ); typedef OnError = void Function(FlowyError); @@ -73,11 +72,11 @@ class BoardDataController { () => result.fold( (grid) async { _onGridChanged?.call(grid); - _initialBlocks(grid.blocks); + return await _loadFields(grid).then((result) { return result.fold( (l) { - _loadGroups(); + _loadGroups(grid.blocks); return left(l); }, (err) => right(err), @@ -102,29 +101,6 @@ class BoardDataController { } } - void _initialBlocks(List blocks) { - for (final block in blocks) { - if (_blocks[block.id] != null) { - Log.warn("Initial duplicate block's cache: ${block.id}"); - return; - } - - final cache = GridBlockCache( - gridId: gridId, - block: block, - fieldCache: fieldCache, - ); - - cache.addListener( - onChangeReason: (reason) { - _onRowsChanged?.call(rowInfos, reason); - }, - ); - - _blocks[block.id] = cache; - } - } - Future> _loadFields(GridPB grid) async { final result = await _gridFFIService.getFields(fieldIds: grid.fields); return Future( @@ -139,7 +115,18 @@ class BoardDataController { ); } - Future _loadGroups() async { + Future _loadGroups(List blocks) async { + for (final block in blocks) { + final cache = GridBlockCache( + gridId: gridId, + block: block, + fieldCache: fieldCache, + ); + + // cache.addListener(onRowsChanged: (rows, reason) {}) + _blocks[block.id] = cache; + } + final result = await _gridFFIService.loadGroups(); return Future( () => result.fold( diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart index 9ba66c2aab..1f66ebe335 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart @@ -74,7 +74,7 @@ class BoardCardEvent with _$BoardCardEvent { const factory BoardCardEvent.initial() = _InitialRow; const factory BoardCardEvent.createRow() = _CreateRow; const factory BoardCardEvent.didReceiveCells( - GridCellMap gridCellMap, RowChangeReason reason) = _DidReceiveCells; + GridCellMap gridCellMap, RowsChangedReason reason) = _DidReceiveCells; } @freezed @@ -83,7 +83,7 @@ class BoardCardState with _$BoardCardState { required RowPB rowPB, required GridCellMap gridCellMap, required UnmodifiableListView cells, - RowChangeReason? changeReason, + RowsChangedReason? changeReason, }) = _BoardCardState; factory BoardCardState.initial(RowPB rowPB, GridCellMap cellDataMap) => diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart index d9ac41f10b..f362fdf0e6 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart @@ -6,7 +6,7 @@ import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flutter/foundation.dart'; -typedef OnCardChanged = void Function(GridCellMap, RowChangeReason); +typedef OnCardChanged = void Function(GridCellMap, RowsChangedReason); class CardDataController extends BoardCellBuilderDelegate { final RowPB rowPB; diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index 2954a7cbf9..36d181ae3e 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder { class BoardPluginConfig implements PluginConfig { @override - bool get creatable => false; + bool get creatable => true; } class BoardPlugin extends Plugin { diff --git a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart index ecfea7e119..b639700b5f 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart @@ -42,7 +42,7 @@ class GridBlockCache { } void addListener({ - required void Function(RowChangeReason) onChangeReason, + required void Function(RowsChangedReason) onRowsChanged, bool Function()? listenWhen, }) { _rowCache.onRowsChanged((reason) { @@ -50,7 +50,7 @@ class GridBlockCache { return; } - onChangeReason(reason); + onRowsChanged(reason); }); } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart index 73d2079a6b..74f23a1b3e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart @@ -98,7 +98,7 @@ class GridEvent with _$GridEvent { const factory GridEvent.createRow() = _CreateRow; const factory GridEvent.didReceiveRowUpdate( List rows, - RowChangeReason listState, + RowsChangedReason listState, ) = _DidReceiveRowUpdate; const factory GridEvent.didReceiveFieldUpdate( UnmodifiableListView fields, @@ -117,7 +117,7 @@ class GridState with _$GridState { required GridFieldEquatable fields, required List rowInfos, required GridLoadingState loadingState, - required RowChangeReason reason, + required RowsChangedReason reason, }) = _GridState; factory GridState.initial(String gridId) => GridState( diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart index aae6dc684e..9de6c65997 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart @@ -18,7 +18,7 @@ typedef OnGridChanged = void Function(GridPB); typedef OnRowsChanged = void Function( List rowInfos, - RowChangeReason, + RowsChangedReason, ); typedef ListenOnRowChangedCondition = bool Function(); @@ -105,7 +105,7 @@ class GridDataController { ); cache.addListener( - onChangeReason: (reason) { + onRowsChanged: (reason) { _onRowChanged?.call(rowInfos, reason); }, ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart index 7e3e9a21bd..e586f65bd4 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart @@ -14,13 +14,13 @@ class RowActionSheetBloc extends Bloc { final RowFFIService _rowService; - RowActionSheetBloc({required RowInfo rowData}) + RowActionSheetBloc({required RowInfo rowInfo}) : _rowService = RowFFIService( - gridId: rowData.gridId, - blockId: rowData.blockId, - rowId: rowData.id, + gridId: rowInfo.gridId, + blockId: rowInfo.blockId, + rowId: rowInfo.rowPB.id, ), - super(RowActionSheetState.initial(rowData)) { + super(RowActionSheetState.initial(rowInfo)) { on( (event, emit) async { await event.map( diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart index 372287fd1f..6716967e5e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart @@ -21,7 +21,7 @@ class RowBloc extends Bloc { }) : _rowService = RowFFIService( gridId: rowInfo.gridId, blockId: rowInfo.blockId, - rowId: rowInfo.id, + rowId: rowInfo.rowPB.id, ), _dataController = dataController, super(RowState.initial(rowInfo, dataController.loadData())) { @@ -71,7 +71,7 @@ class RowEvent with _$RowEvent { const factory RowEvent.initial() = _InitialRow; const factory RowEvent.createRow() = _CreateRow; const factory RowEvent.didReceiveCells( - GridCellMap gridCellMap, RowChangeReason reason) = _DidReceiveCells; + GridCellMap gridCellMap, RowsChangedReason reason) = _DidReceiveCells; } @freezed @@ -80,7 +80,7 @@ class RowState with _$RowState { required RowInfo rowInfo, required GridCellMap gridCellMap, required UnmodifiableListView cells, - RowChangeReason? changeReason, + RowsChangedReason? changeReason, }) = _RowState; factory RowState.initial(RowInfo rowInfo, GridCellMap cellDataMap) => diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart index ec212148d1..74e11e409e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart @@ -51,11 +51,9 @@ class GridRowCache { _fieldNotifier = notifier { // notifier.onRowFieldsChanged(() => _rowChangeReasonNotifier - .receive(const RowChangeReason.fieldDidChange())); + .receive(const RowsChangedReason.fieldDidChange())); notifier.onRowFieldChanged((field) => _cellCache.remove(field.id)); - _rowInfos = block.rows - .map((rowInfo) => buildGridRow(rowInfo.id, rowInfo.height.toDouble())) - .toList(); + _rowInfos = block.rows.map((rowPB) => buildGridRow(rowPB)).toList(); } Future dispose() async { @@ -85,16 +83,16 @@ class GridRowCache { for (var rowId in deletedRows) rowId: rowId }; - _rowInfos.asMap().forEach((index, row) { - if (deletedRowByRowId[row.id] == null) { - newRows.add(row); + _rowInfos.asMap().forEach((index, RowInfo rowInfo) { + if (deletedRowByRowId[rowInfo.rowPB.id] == null) { + newRows.add(rowInfo); } else { - _rowByRowId.remove(row.id); - deletedIndex.add(DeletedIndex(index: index, row: row)); + _rowByRowId.remove(rowInfo.rowPB.id); + deletedIndex.add(DeletedIndex(index: index, row: rowInfo)); } }); _rowInfos = newRows; - _rowChangeReasonNotifier.receive(RowChangeReason.delete(deletedIndex)); + _rowChangeReasonNotifier.receive(RowsChangedReason.delete(deletedIndex)); } void _insertRows(List insertRows) { @@ -103,39 +101,42 @@ class GridRowCache { } InsertedIndexs insertIndexs = []; - for (final insertRow in insertRows) { + for (final InsertedRowPB insertRow in insertRows) { final insertIndex = InsertedIndex( index: insertRow.index, - rowId: insertRow.rowId, + rowId: insertRow.row.id, ); insertIndexs.add(insertIndex); - _rowInfos.insert(insertRow.index, - (buildGridRow(insertRow.rowId, insertRow.height.toDouble()))); + _rowInfos.insert( + insertRow.index, + (buildGridRow(insertRow.row)), + ); } - _rowChangeReasonNotifier.receive(RowChangeReason.insert(insertIndexs)); + _rowChangeReasonNotifier.receive(RowsChangedReason.insert(insertIndexs)); } - void _updateRows(List updatedRows) { + void _updateRows(List updatedRows) { if (updatedRows.isEmpty) { return; } final UpdatedIndexs updatedIndexs = UpdatedIndexs(); - for (final updatedRow in updatedRows) { - final rowId = updatedRow.rowId; - final index = _rowInfos.indexWhere((row) => row.id == rowId); + for (final RowPB updatedRow in updatedRows) { + final rowId = updatedRow.id; + final index = _rowInfos.indexWhere( + (rowInfo) => rowInfo.rowPB.id == rowId, + ); if (index != -1) { - _rowByRowId[rowId] = updatedRow.row; + _rowByRowId[rowId] = updatedRow; _rowInfos.removeAt(index); - _rowInfos.insert( - index, buildGridRow(rowId, updatedRow.row.height.toDouble())); + _rowInfos.insert(index, buildGridRow(updatedRow)); updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId); } } - _rowChangeReasonNotifier.receive(RowChangeReason.update(updatedIndexs)); + _rowChangeReasonNotifier.receive(RowsChangedReason.update(updatedIndexs)); } void _hideRows(List hideRows) {} @@ -143,7 +144,7 @@ class GridRowCache { void _showRows(List visibleRows) {} void onRowsChanged( - void Function(RowChangeReason) onRowChanged, + void Function(RowsChangedReason) onRowChanged, ) { _rowChangeReasonNotifier.addListener(() { onRowChanged(_rowChangeReasonNotifier.reason); @@ -152,7 +153,7 @@ class GridRowCache { RowUpdateCallback addListener({ required String rowId, - void Function(GridCellMap, RowChangeReason)? onCellUpdated, + void Function(GridCellMap, RowsChangedReason)? onCellUpdated, bool Function()? listenWhen, }) { listenerHandler() async { @@ -230,40 +231,43 @@ class GridRowCache { _rowByRowId[updatedRow.id] = updatedRow; final index = - _rowInfos.indexWhere((gridRow) => gridRow.id == updatedRow.id); + _rowInfos.indexWhere((rowInfo) => rowInfo.rowPB.id == updatedRow.id); if (index != -1) { // update the corresponding row in _rows if they are not the same - if (_rowInfos[index].rawRow != updatedRow) { - final row = _rowInfos.removeAt(index).copyWith(rawRow: updatedRow); - _rowInfos.insert(index, row); + if (_rowInfos[index].rowPB != updatedRow) { + final rowInfo = _rowInfos.removeAt(index).copyWith(rowPB: updatedRow); + _rowInfos.insert(index, rowInfo); // Calculate the update index final UpdatedIndexs updatedIndexs = UpdatedIndexs(); - updatedIndexs[row.id] = UpdatedIndex(index: index, rowId: row.id); + updatedIndexs[rowInfo.rowPB.id] = UpdatedIndex( + index: index, + rowId: rowInfo.rowPB.id, + ); // - _rowChangeReasonNotifier.receive(RowChangeReason.update(updatedIndexs)); + _rowChangeReasonNotifier + .receive(RowsChangedReason.update(updatedIndexs)); } } } - RowInfo buildGridRow(String rowId, double rowHeight) { + RowInfo buildGridRow(RowPB rowPB) { return RowInfo( gridId: gridId, blockId: block.id, fields: _fieldNotifier.fields, - id: rowId, - height: rowHeight, + rowPB: rowPB, ); } } class _RowChangesetNotifier extends ChangeNotifier { - RowChangeReason reason = const InitialListState(); + RowsChangedReason reason = const InitialListState(); _RowChangesetNotifier(); - void receive(RowChangeReason newReason) { + void receive(RowsChangedReason newReason) { reason = newReason; reason.map( insert: (_) => notifyListeners(), @@ -280,10 +284,8 @@ class RowInfo with _$RowInfo { const factory RowInfo({ required String gridId, required String blockId, - required String id, required UnmodifiableListView fields, - required double height, - RowPB? rawRow, + required RowPB rowPB, }) = _RowInfo; } @@ -292,12 +294,12 @@ typedef DeletedIndexs = List; typedef UpdatedIndexs = LinkedHashMap; @freezed -class RowChangeReason with _$RowChangeReason { - const factory RowChangeReason.insert(InsertedIndexs items) = _Insert; - const factory RowChangeReason.delete(DeletedIndexs items) = _Delete; - const factory RowChangeReason.update(UpdatedIndexs indexs) = _Update; - const factory RowChangeReason.fieldDidChange() = _FieldDidChange; - const factory RowChangeReason.initial() = InitialListState; +class RowsChangedReason with _$RowsChangedReason { + const factory RowsChangedReason.insert(InsertedIndexs items) = _Insert; + const factory RowsChangedReason.delete(DeletedIndexs items) = _Delete; + const factory RowsChangedReason.update(UpdatedIndexs indexs) = _Update; + const factory RowsChangedReason.fieldDidChange() = _FieldDidChange; + const factory RowsChangedReason.initial() = InitialListState; } class InsertedIndex { diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart index 78783fc894..b4618b397a 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart @@ -5,7 +5,7 @@ import '../cell/cell_service/cell_service.dart'; import '../field/field_cache.dart'; import 'row_cache.dart'; -typedef OnRowChanged = void Function(GridCellMap, RowChangeReason); +typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason); class GridRowDataController extends GridCellBuilderDelegate { final RowInfo rowInfo; @@ -21,12 +21,12 @@ class GridRowDataController extends GridCellBuilderDelegate { _rowCache = rowCache; GridCellMap loadData() { - return _rowCache.loadGridCells(rowInfo.id); + return _rowCache.loadGridCells(rowInfo.rowPB.id); } void addListener({OnRowChanged? onRowChanged}) { _onRowChangedListeners.add(_rowCache.addListener( - rowId: rowInfo.id, + rowId: rowInfo.rowPB.id, onCellUpdated: onRowChanged, )); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart index 8709b395b2..fe9b245567 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart @@ -240,7 +240,7 @@ class _GridRowsState extends State<_GridRows> { Animation animation, ) { final rowCache = - context.read().getRowCache(rowInfo.blockId, rowInfo.id); + context.read().getRowCache(rowInfo.blockId, rowInfo.rowPB.id); /// Return placeholder widget if the rowCache is null. if (rowCache == null) return const SizedBox(); @@ -267,7 +267,7 @@ class _GridRowsState extends State<_GridRows> { cellBuilder, ); }, - key: ValueKey(rowInfo.id), + key: ValueKey(rowInfo.rowPB.id), ), ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart index c96b5e1526..a4bf813fe5 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart @@ -52,7 +52,7 @@ class _GridRowWidgetState extends State { value: _rowBloc, child: _RowEnterRegion( child: BlocBuilder( - buildWhen: (p, c) => p.rowInfo.height != c.rowInfo.height, + buildWhen: (p, c) => p.rowInfo.rowPB.height != c.rowInfo.rowPB.height, builder: (context, state) { final children = [ const _RowLeading(), diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart index 720aac0dc0..8296add94e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart @@ -21,7 +21,7 @@ class GridRowActionSheet extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => RowActionSheetBloc(rowData: rowData), + create: (context) => RowActionSheetBloc(rowInfo: rowData), child: BlocBuilder( builder: (context, state) { final cells = _RowAction.values diff --git a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs index ad89532b02..b712a701df 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs @@ -106,48 +106,15 @@ impl std::convert::From> for RepeatedBlockPB { #[derive(Debug, Clone, Default, ProtoBuf)] pub struct InsertedRowPB { #[pb(index = 1)] - pub block_id: String, + pub row: RowPB, - #[pb(index = 2)] - pub row_id: String, - - #[pb(index = 3)] - pub height: i32, - - #[pb(index = 4, one_of)] + #[pb(index = 2, one_of)] pub index: Option, } -#[derive(Debug, Default, ProtoBuf)] -pub struct UpdatedRowPB { - #[pb(index = 1)] - pub block_id: String, - - #[pb(index = 2)] - pub row_id: String, - - #[pb(index = 3)] - pub row: RowPB, -} - -impl UpdatedRowPB { - pub fn new(row_rev: &RowRevision, row: RowPB) -> Self { - Self { - row_id: row_rev.id.clone(), - block_id: row_rev.block_id.clone(), - row, - } - } -} - impl std::convert::From for InsertedRowPB { - fn from(row_info: RowPB) -> Self { - Self { - row_id: row_info.id, - block_id: row_info.block_id, - height: row_info.height, - index: None, - } + fn from(row: RowPB) -> Self { + Self { row, index: None } } } @@ -170,7 +137,7 @@ pub struct GridBlockChangesetPB { pub deleted_rows: Vec, #[pb(index = 4)] - pub updated_rows: Vec, + pub updated_rows: Vec, #[pb(index = 5)] pub visible_rows: Vec, @@ -195,7 +162,7 @@ impl GridBlockChangesetPB { } } - pub fn update(block_id: &str, updated_rows: Vec) -> Self { + pub fn update(block_id: &str, updated_rows: Vec) -> Self { Self { block_id: block_id.to_owned(), updated_rows, diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 86b8e8892c..3c24564c6d 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -235,7 +235,7 @@ pub(crate) async fn get_row_handler( let row = editor .get_row_rev(¶ms.row_id) .await? - .and_then(make_row_from_row_rev); + .and_then(|row_rev| Some(make_row_from_row_rev(row_rev))); data_result(OptionalRowPB { row }) } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index d7c01a6a09..afeb58c5d4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -1,9 +1,9 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; -use crate::entities::{CellChangesetPB, GridBlockChangesetPB, InsertedRowPB, RowPB, UpdatedRowPB}; +use crate::entities::{CellChangesetPB, GridBlockChangesetPB, InsertedRowPB, RowPB}; use crate::manager::GridUser; use crate::services::block_revision_editor::{GridBlockRevisionCompactor, GridBlockRevisionEditor}; use crate::services::persistence::block_index::BlockIndexCache; -use crate::services::row::{block_from_row_orders, GridBlockSnapshot}; +use crate::services::row::{block_from_row_orders, make_row_from_row_rev, GridBlockSnapshot}; use dashmap::DashMap; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ @@ -110,20 +110,18 @@ impl GridBlockManager { pub async fn update_row(&self, changeset: RowMetaChangeset, row_builder: F) -> FlowyResult<()> where - F: FnOnce(Arc) -> Option, + F: FnOnce(Arc) -> RowPB, { let editor = self.get_editor_from_row_id(&changeset.row_id).await?; let _ = editor.update_row(changeset.clone()).await?; match editor.get_row_rev(&changeset.row_id).await? { None => tracing::error!("Internal error: can't find the row with id: {}", changeset.row_id), Some(row_rev) => { - if let Some(row) = row_builder(row_rev.clone()) { - let row_order = UpdatedRowPB::new(&row_rev, row); - let block_order_changeset = GridBlockChangesetPB::update(&editor.block_id, vec![row_order]); - let _ = self - .notify_did_update_block(&editor.block_id, block_order_changeset) - .await?; - } + let block_order_changeset = + GridBlockChangesetPB::update(&editor.block_id, vec![row_builder(row_rev.clone())]); + let _ = self + .notify_did_update_block(&editor.block_id, block_order_changeset) + .await?; } } Ok(()) @@ -170,17 +168,16 @@ impl GridBlockManager { match editor.get_row_revs(Some(vec![Cow::Borrowed(row_id)])).await?.pop() { None => {} Some(row_rev) => { + let delete_row_id = row_rev.id.clone(); let insert_row = InsertedRowPB { - block_id: row_rev.block_id.clone(), - row_id: row_rev.id.clone(), index: Some(to as i32), - height: row_rev.height, + row: make_row_from_row_rev(row_rev), }; let notified_changeset = GridBlockChangesetPB { block_id: editor.block_id.clone(), inserted_rows: vec![insert_row], - deleted_rows: vec![row_rev.id.clone()], + deleted_rows: vec![delete_row_id], ..Default::default() }; @@ -195,7 +192,7 @@ impl GridBlockManager { pub async fn update_cell(&self, changeset: CellChangesetPB, row_builder: F) -> FlowyResult<()> where - F: FnOnce(Arc) -> Option, + F: FnOnce(Arc) -> RowPB, { let row_changeset: RowMetaChangeset = changeset.clone().into(); let _ = self.update_row(row_changeset, row_builder).await?; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index 24c2cda68a..1a0d0eaff6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -39,8 +39,8 @@ pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc]) -> Ve row_revs.iter().map(RowPB::from).collect::>() } -pub(crate) fn make_row_from_row_rev(row_rev: Arc) -> Option { - make_rows_from_row_revs(&[row_rev]).pop() +pub(crate) fn make_row_from_row_rev(row_rev: Arc) -> RowPB { + make_rows_from_row_revs(&[row_rev]).pop().unwrap() } pub(crate) fn make_rows_from_row_revs(row_revs: &[Arc]) -> Vec { From dc53cb00dd1c209867db62623ab2505c7821d4dc Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 13 Aug 2022 16:23:44 +0800 Subject: [PATCH 2/6] chore: create the default group for the rows that are not belong to any groups --- .../plugins/board/application/board_bloc.dart | 12 ++++++- .../application/board_data_controller.dart | 4 ++- .../board/presentation/board_page.dart | 24 ++++++++++---- .../plugins/board/presentation/card/card.dart | 7 +++- .../presentation/card/card_container.dart | 6 +++- .../rust-lib/flowy-grid/src/event_handler.rs | 6 ++-- .../group/group_generator/generator.rs | 33 ++++++++++++++++--- 7 files changed, 73 insertions(+), 19 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index baefecf723..1db180d4e4 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -55,10 +55,19 @@ class BoardBloc extends Bloc { createRow: () async { final result = await _dataController.createRow(); result.fold( - (rowPB) => null, + (rowPB) { + emit(state.copyWith(editingRow: some(rowPB))); + }, (err) => Log.error(err), ); }, + endEditRow: (rowId) { + assert(state.editingRow.isSome()); + state.editingRow.fold(() => null, (row) { + assert(row.id == rowId); + emit(state.copyWith(editingRow: none())); + }); + }, didReceiveGridUpdate: (GridPB grid) { emit(state.copyWith(grid: Some(grid))); }, @@ -145,6 +154,7 @@ class BoardBloc extends Bloc { class BoardEvent with _$BoardEvent { const factory BoardEvent.initial() = InitialGrid; const factory BoardEvent.createRow() = _CreateRow; + const factory BoardEvent.endEditRow(String rowId) = _EndEditRow; const factory BoardEvent.didReceiveGroups(List groups) = _DidReceiveGroup; const factory BoardEvent.didReceiveRows(List rowInfos) = diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index fe6e1b0bdf..619d16f99e 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -123,7 +123,9 @@ class BoardDataController { fieldCache: fieldCache, ); - // cache.addListener(onRowsChanged: (rows, reason) {}) + cache.addListener(onRowsChanged: (reason) { + _onRowsChanged?.call(rowInfos, reason); + }); _blocks[block.id] = cache; } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 6dcfe8267c..bf04c22f57 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -53,7 +53,7 @@ class BoardContent extends StatelessWidget { child: Padding( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), child: AFBoard( - key: UniqueKey(), + // key: UniqueKey(), scrollController: ScrollController(), dataController: context.read().boardDataController, headerBuilder: _buildHeader, @@ -83,11 +83,13 @@ class BoardContent extends StatelessWidget { Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) { return AppFlowyColumnFooter( - icon: const Icon(Icons.add, size: 20), - title: const Text('New'), - height: 50, - margin: config.columnItemPadding, - ); + icon: const Icon(Icons.add, size: 20), + title: const Text('New'), + height: 50, + margin: config.columnItemPadding, + onAddButtonClick: () { + context.read().add(const BoardEvent.createRow()); + }); } Widget _buildCard(BuildContext context, AFColumnItem item) { @@ -106,13 +108,21 @@ class BoardContent extends StatelessWidget { ); final cellBuilder = BoardCellBuilder(cardController); + final isEditing = context.read().state.editingRow.fold( + () => false, + (editingRow) => editingRow.id == rowPB.id, + ); return AppFlowyColumnItemCard( key: ObjectKey(item), child: BoardCard( + gridId: gridId, + isEditing: isEditing, cellBuilder: cellBuilder, dataController: cardController, - gridId: gridId, + onEditEditing: (rowId) { + context.read().add(BoardEvent.endEditRow(rowId)); + }, ), ); } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart index dfb9ab42d7..2a4006e68c 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart @@ -9,15 +9,21 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'card_cell_builder.dart'; import 'card_container.dart'; +typedef OnEndEditing = void Function(String rowId); + class BoardCard extends StatefulWidget { final String gridId; + final bool isEditing; final CardDataController dataController; final BoardCellBuilder cellBuilder; + final OnEndEditing onEditEditing; const BoardCard({ required this.gridId, + required this.isEditing, required this.dataController, required this.cellBuilder, + required this.onEditEditing, Key? key, }) : super(key: key); @@ -60,7 +66,6 @@ class _BoardCardState extends State { return cellMap.values.map( (cellId) { final child = widget.cellBuilder.buildCell(cellId); - return Padding( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), child: child, diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart index 13f3af2195..ce8df101a5 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart @@ -29,9 +29,13 @@ class BoardCardContainer extends StatelessWidget { ); } } + return Padding( padding: const EdgeInsets.all(8), - child: container, + child: ConstrainedBox( + constraints: const BoxConstraints(minHeight: 30), + child: container, + ), ); }, ), diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 3c24564c6d..e834c4652e 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -266,11 +266,11 @@ pub(crate) async fn duplicate_row_handler( pub(crate) async fn create_row_handler( data: Data, manager: AppData>, -) -> Result<(), FlowyError> { +) -> DataResult { let params: CreateRowParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(params.grid_id.as_ref())?; - let _ = editor.create_row(params.start_row_id).await?; - Ok(()) + let row = editor.create_row(params.start_row_id).await?; + data_result(row) } // #[tracing::instrument(level = "debug", skip_all, err)] diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs index 4740e6e7bb..1682bd9fbb 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs @@ -34,9 +34,12 @@ pub trait GroupGenerator { ) -> Vec; } +const DEFAULT_GROUP_ID: &str = "default_group"; + pub struct GroupController { pub field_rev: Arc, pub groups: IndexMap, + pub default_group: Group, pub type_option: Option, pub configuration: Option, group_action_phantom: PhantomData, @@ -78,9 +81,18 @@ where let field_type_rev = field_rev.field_type_rev; let type_option = field_rev.get_type_option_entry::(field_type_rev); let groups = G::gen_groups(&configuration, &type_option, cell_content_provider); + + let default_group = Group { + id: DEFAULT_GROUP_ID.to_owned(), + desc: format!("No {}", field_rev.name), + rows: vec![], + content: "".to_string(), + }; + Ok(Self { field_rev, groups: groups.into_iter().map(|group| (group.id.clone(), group)).collect(), + default_group, type_option, configuration, group_action_phantom: PhantomData, @@ -89,7 +101,12 @@ where } pub fn take_groups(self) -> Vec { - self.groups.into_values().collect() + let default_group = self.default_group; + let mut groups: Vec = self.groups.into_values().collect(); + if !default_group.rows.is_empty() { + groups.push(default_group); + } + groups } } @@ -102,6 +119,7 @@ where if self.configuration.is_none() { return Ok(()); } + tracing::debug!("group {} rows", rows.len()); for row in rows { if let Some(cell_rev) = row.cells.get(&self.field_rev.id) { @@ -115,15 +133,20 @@ where row: row.into(), group_id: group.id.clone(), }); - break; } } - for record in records { - if let Some(group) = self.groups.get_mut(&record.group_id) { - group.rows.push(record.row); + if records.is_empty() { + self.default_group.rows.push(row.into()); + } else { + for record in records { + if let Some(group) = self.groups.get_mut(&record.group_id) { + group.rows.push(record.row); + } } } + } else { + self.default_group.rows.push(row.into()); } } From f0914cd6f1c343d14051cdc2e436ebbdc04e1612 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 13 Aug 2022 23:26:42 +0800 Subject: [PATCH 3/6] chore: add group action handler to intercept the create row progress --- .../flowy-grid/src/entities/block_entities.rs | 4 +- .../src/entities/group_entities/board_card.rs | 29 +++++ .../src/entities/group_entities/mod.rs | 2 + .../rust-lib/flowy-grid/src/event_handler.rs | 11 ++ frontend/rust-lib/flowy-grid/src/event_map.rs | 4 + .../flowy-grid/src/services/block_manager.rs | 26 ++-- .../flowy-grid/src/services/grid_editor.rs | 56 +++++--- .../group/group_generator/checkbox_group.rs | 40 ++++-- .../group/group_generator/generator.rs | 112 +++++++++------- .../group_generator/select_option_group.rs | 68 +++++++--- .../src/services/group/group_service.rs | 122 ++++++++++-------- shared-lib/flowy-error-code/src/code.rs | 3 + .../src/revision/grid_rev.rs | 4 +- 13 files changed, 313 insertions(+), 168 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs diff --git a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs index b712a701df..4d4fcc78c1 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/block_entities.rs @@ -146,9 +146,9 @@ pub struct GridBlockChangesetPB { pub hide_rows: Vec, } impl GridBlockChangesetPB { - pub fn insert(block_id: &str, inserted_rows: Vec) -> Self { + pub fn insert(block_id: String, inserted_rows: Vec) -> Self { Self { - block_id: block_id.to_owned(), + block_id, inserted_rows, ..Default::default() } diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs new file mode 100644 index 0000000000..d641c2d723 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs @@ -0,0 +1,29 @@ +use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use flowy_grid_data_model::parser::NotEmptyStr; + +#[derive(ProtoBuf, Debug, Default, Clone)] +pub struct CreateBoardCardPayloadPB { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub group_id: String, +} +pub struct CreateBoardCardParams { + pub grid_id: String, + pub group_id: String, +} + +impl TryInto for CreateBoardCardPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let group_id = NotEmptyStr::parse(self.group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; + Ok(CreateBoardCardParams { + grid_id: grid_id.0, + group_id: group_id.0, + }) + } +} diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs index c1834c1009..7aa3a1a43e 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs @@ -1,5 +1,7 @@ +mod board_card; mod configuration; mod group; +pub use board_card::*; pub use configuration::*; pub use group::*; diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index e834c4652e..7f8ae72773 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -416,3 +416,14 @@ pub(crate) async fn get_groups_handler( let group = editor.load_groups().await?; data_result(group) } + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn create_board_card_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: CreateBoardCardParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(params.grid_id.as_ref())?; + let row = editor.create_board_card().await?; + data_result(row) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 9e0b2ef5dd..9a5303220c 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -39,6 +39,7 @@ pub fn create(grid_manager: Arc) -> Module { // Date .event(GridEvent::UpdateDateCell, update_date_cell_handler) // Group + .event(GridEvent::CreateBoardCard, create_row_handler) .event(GridEvent::GetGroup, get_groups_handler); module @@ -209,4 +210,7 @@ pub enum GridEvent { #[event(input = "GridIdPB", output = "RepeatedGridGroupPB")] GetGroup = 100, + + #[event(input = "CreateBoardCardPayloadPB", output = "RowPB")] + CreateBoardCard = 110, } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index afeb58c5d4..8da912534f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -62,22 +62,16 @@ impl GridBlockManager { Ok(self.get_editor(&block_id).await?) } - pub(crate) async fn create_row( - &self, - block_id: &str, - row_rev: RowRevision, - start_row_id: Option, - ) -> FlowyResult { + pub(crate) async fn create_row(&self, row_rev: RowRevision, start_row_id: Option) -> FlowyResult { + let block_id = row_rev.block_id.clone(); let _ = self.persistence.insert(&row_rev.block_id, &row_rev.id)?; let editor = self.get_editor(&row_rev.block_id).await?; let mut index_row_order = InsertedRowPB::from(&row_rev); let (row_count, row_index) = editor.create_row(row_rev, start_row_id).await?; index_row_order.index = row_index; - - let _ = self - .notify_did_update_block(block_id, GridBlockChangesetPB::insert(block_id, vec![index_row_order])) - .await?; + let changeset = GridBlockChangesetPB::insert(block_id.clone(), vec![index_row_order]); + let _ = self.notify_did_update_block(&block_id, changeset).await?; Ok(row_count) } @@ -98,10 +92,16 @@ impl GridBlockManager { row_order.index = index; inserted_row_orders.push(row_order); } - changesets.push(GridBlockMetaRevisionChangeset::from_row_count(&block_id, row_count)); + changesets.push(GridBlockMetaRevisionChangeset::from_row_count( + block_id.clone(), + row_count, + )); let _ = self - .notify_did_update_block(&block_id, GridBlockChangesetPB::insert(&block_id, inserted_row_orders)) + .notify_did_update_block( + &block_id, + GridBlockChangesetPB::insert(block_id.clone(), inserted_row_orders), + ) .await?; } @@ -154,7 +154,7 @@ impl GridBlockManager { .map(|row_info| Cow::Owned(row_info.row_id().to_owned())) .collect::>>(); let row_count = editor.delete_rows(row_ids).await?; - let changeset = GridBlockMetaRevisionChangeset::from_row_count(&grid_block.id, row_count); + let changeset = GridBlockMetaRevisionChangeset::from_row_count(grid_block.id.clone(), row_count); changesets.push(changeset); } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index f2e28701df..82c4b23afb 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -37,7 +37,7 @@ pub struct GridRevisionEditor { pub(crate) filter_service: Arc, #[allow(dead_code)] - pub(crate) group_service: Arc, + pub(crate) group_service: Arc>, } impl Drop for GridRevisionEditor { @@ -62,17 +62,17 @@ impl GridRevisionEditor { let block_meta_revs = grid_pad.read().await.get_block_meta_revs(); let block_manager = Arc::new(GridBlockManager::new(grid_id, &user, block_meta_revs, persistence).await?); let filter_service = - Arc::new(GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await); + GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await; let group_service = - Arc::new(GridGroupService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await); + GridGroupService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await; let editor = Arc::new(Self { grid_id: grid_id.to_owned(), user, grid_pad, rev_manager, block_manager, - filter_service, - group_service, + filter_service: Arc::new(filter_service), + group_service: Arc::new(RwLock::new(group_service)), }); Ok(editor) @@ -275,20 +275,8 @@ impl GridRevisionEditor { } pub async fn create_row(&self, start_row_id: Option) -> FlowyResult { - let field_revs = self.grid_pad.read().await.get_field_revs(None)?; - let block_id = self.block_id().await?; - - // insert empty row below the row whose id is upper_row_id - let row_rev = RowRevisionBuilder::new(&block_id, &field_revs).build(); - let row_order = RowPB::from(&row_rev); - - // insert the row - let row_count = self.block_manager.create_row(&block_id, row_rev, start_row_id).await?; - - // update block row count - let changeset = GridBlockMetaRevisionChangeset::from_row_count(&block_id, row_count); - let _ = self.update_block(changeset).await?; - Ok(row_order) + let row_rev = self.create_row_rev().await?; + self.create_row_pb(row_rev, start_row_id).await } pub async fn insert_rows(&self, row_revs: Vec) -> FlowyResult> { @@ -564,12 +552,40 @@ impl GridRevisionEditor { }) } + pub async fn create_board_card(&self) -> FlowyResult { + let mut row_rev = self.create_row_rev().await?; + let _ = self.group_service.write().await.create_board_card(&mut row_rev).await; + self.create_row_pb(row_rev, None).await + } + #[tracing::instrument(level = "trace", skip_all, err)] pub async fn load_groups(&self) -> FlowyResult { - let groups = self.group_service.load_groups().await.unwrap_or_default(); + let groups = self.group_service.write().await.load_groups().await.unwrap_or_default(); Ok(RepeatedGridGroupPB { items: groups }) } + async fn create_row_rev(&self) -> FlowyResult { + let field_revs = self.grid_pad.read().await.get_field_revs(None)?; + let block_id = self.block_id().await?; + + // insert empty row below the row whose id is upper_row_id + let row_rev = RowRevisionBuilder::new(&block_id, &field_revs).build(); + Ok(row_rev) + } + + async fn create_row_pb(&self, row_rev: RowRevision, start_row_id: Option) -> FlowyResult { + let row_pb = RowPB::from(&row_rev); + let block_id = row_rev.block_id.clone(); + + // insert the row + let row_count = self.block_manager.create_row(row_rev, start_row_id).await?; + + // update block row count + let changeset = GridBlockMetaRevisionChangeset::from_row_count(block_id, row_count); + let _ = self.update_block(changeset).await?; + Ok(row_pb) + } + async fn modify(&self, f: F) -> FlowyResult<()> where F: for<'a> FnOnce(&'a mut GridRevisionPad) -> FlowyResult>, diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index 32b699d3a1..b976310bed 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -1,17 +1,43 @@ -use crate::entities::CheckboxGroupConfigurationPB; +use crate::entities::{CheckboxGroupConfigurationPB, RowPB}; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::RowRevision; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; -use crate::services::group::{Group, GroupAction, GroupCellContentProvider, GroupController, GroupGenerator}; +use crate::services::group::{ + Group, GroupActionHandler, GroupCellContentProvider, GroupController, GroupGenerator, Groupable, +}; pub type CheckboxGroupController = GroupController; +impl Groupable for CheckboxGroupController { + type CellDataType = CheckboxCellData; + + fn can_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool { + false + } +} + +impl GroupActionHandler for CheckboxGroupController { + fn get_groups(&self) -> Vec { + self.groups() + } + + fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> { + self.handle_row(row_rev) + } + + fn create_card(&self, row_rev: &mut RowRevision) { + todo!() + } +} + pub struct CheckboxGroupGenerator(); impl GroupGenerator for CheckboxGroupGenerator { type ConfigurationType = CheckboxGroupConfigurationPB; type TypeOptionType = CheckboxTypeOptionPB; - fn gen_groups( + fn generate_groups( _configuration: &Option, _type_option: &Option, _cell_content_provider: &dyn GroupCellContentProvider, @@ -33,11 +59,3 @@ impl GroupGenerator for CheckboxGroupGenerator { vec![check_group, uncheck_group] } } - -impl GroupAction for CheckboxGroupController { - type CellDataType = CheckboxCellData; - - fn should_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool { - false - } -} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs index 1682bd9fbb..b841e745e4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs @@ -9,12 +9,6 @@ use indexmap::IndexMap; use std::marker::PhantomData; use std::sync::Arc; -pub trait GroupAction { - type CellDataType; - - fn should_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; -} - pub trait GroupCellContentProvider { /// We need to group the rows base on the deduplication cell content when the field type is /// RichText. @@ -27,25 +21,47 @@ pub trait GroupGenerator { type ConfigurationType; type TypeOptionType; - fn gen_groups( + fn generate_groups( configuration: &Option, type_option: &Option, cell_content_provider: &dyn GroupCellContentProvider, ) -> Vec; } +pub trait Groupable { + type CellDataType; + fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; +} + +pub trait GroupActionHandler: Send + Sync { + fn get_groups(&self) -> Vec; + fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()>; + fn group_rows(&mut self, row_revs: &[Arc]) -> FlowyResult<()> { + for row_rev in row_revs { + let _ = self.group_row(row_rev)?; + } + Ok(()) + } + fn create_card(&self, row_rev: &mut RowRevision); +} + const DEFAULT_GROUP_ID: &str = "default_group"; -pub struct GroupController { +/// C: represents the group configuration structure +/// T: the type option data deserializer that impl [TypeOptionDataDeserializer] +/// G: the group container generator +/// P: the parser that impl [CellBytesParser] for the CellBytes +pub struct GroupController { pub field_rev: Arc, - pub groups: IndexMap, - pub default_group: Group, + groups: IndexMap, + default_group: Group, pub type_option: Option, pub configuration: Option, group_action_phantom: PhantomData, - cell_parser_phantom: PhantomData, + cell_parser_phantom: PhantomData

, } +#[derive(Clone)] pub struct Group { pub id: String, pub desc: String, @@ -63,7 +79,7 @@ impl std::convert::From for GroupPB { } } -impl GroupController +impl GroupController where C: TryFrom, T: TypeOptionDataDeserializer, @@ -80,7 +96,7 @@ where }; let field_type_rev = field_rev.field_type_rev; let type_option = field_rev.get_type_option_entry::(field_type_rev); - let groups = G::gen_groups(&configuration, &type_option, cell_content_provider); + let groups = G::generate_groups(&configuration, &type_option, cell_content_provider); let default_group = Group { id: DEFAULT_GROUP_ID.to_owned(), @@ -100,9 +116,9 @@ where }) } - pub fn take_groups(self) -> Vec { - let default_group = self.default_group; - let mut groups: Vec = self.groups.into_values().collect(); + pub fn groups(&self) -> Vec { + let default_group = self.default_group.clone(); + let mut groups: Vec = self.groups.values().cloned().collect(); if !default_group.rows.is_empty() { groups.push(default_group); } @@ -110,48 +126,50 @@ where } } -impl GroupController +impl GroupController where - CP: CellBytesParser, - Self: GroupAction, + P: CellBytesParser, + Self: Groupable, { - pub fn group_rows(&mut self, rows: &[Arc]) -> FlowyResult<()> { + pub fn handle_row(&mut self, row: &RowRevision) -> FlowyResult<()> { if self.configuration.is_none() { return Ok(()); } - tracing::debug!("group {} rows", rows.len()); - - for row in rows { - if let Some(cell_rev) = row.cells.get(&self.field_rev.id) { - let mut records: Vec = vec![]; - - let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &self.field_rev); - let cell_data = cell_bytes.parser::()?; - for group in self.groups.values() { - if self.should_group(&group.content, &cell_data) { - records.push(GroupRecord { - row: row.into(), - group_id: group.id.clone(), - }); - } + if let Some(cell_rev) = row.cells.get(&self.field_rev.id) { + let mut records: Vec = vec![]; + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &self.field_rev); + let cell_data = cell_bytes.parser::

()?; + for group in self.groups.values() { + if self.can_group(&group.content, &cell_data) { + records.push(GroupRecord { + row: row.into(), + group_id: group.id.clone(), + }); } - - if records.is_empty() { - self.default_group.rows.push(row.into()); - } else { - for record in records { - if let Some(group) = self.groups.get_mut(&record.group_id) { - group.rows.push(record.row); - } - } - } - } else { - self.default_group.rows.push(row.into()); } + + if records.is_empty() { + self.default_group.rows.push(row.into()); + } else { + for record in records { + if let Some(group) = self.groups.get_mut(&record.group_id) { + group.rows.push(record.row); + } + } + } + } else { + self.default_group.rows.push(row.into()); } Ok(()) } + + pub fn group_rows(&mut self, rows: &[Arc]) -> FlowyResult<()> { + for row in rows { + let _ = self.handle_row(row)?; + } + Ok(()) + } } struct GroupRecord { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index bc4f1c4709..6666808ee5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -1,9 +1,13 @@ -use crate::entities::SelectOptionGroupConfigurationPB; +use crate::entities::{RowPB, SelectOptionGroupConfigurationPB}; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::RowRevision; use crate::services::field::{ MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB, }; -use crate::services::group::{Group, GroupAction, GroupCellContentProvider, GroupController, GroupGenerator}; +use crate::services::group::{ + Group, GroupActionHandler, GroupCellContentProvider, GroupController, GroupGenerator, Groupable, +}; // SingleSelect pub type SingleSelectGroupController = GroupController< @@ -13,11 +17,32 @@ pub type SingleSelectGroupController = GroupController< SelectOptionCellDataParser, >; +impl Groupable for SingleSelectGroupController { + type CellDataType = SelectOptionCellDataPB; + fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { + cell_data.select_options.iter().any(|option| option.id == content) + } +} + +impl GroupActionHandler for SingleSelectGroupController { + fn get_groups(&self) -> Vec { + self.groups() + } + + fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> { + self.handle_row(row_rev) + } + + fn create_card(&self, row_rev: &mut RowRevision) { + todo!() + } +} + pub struct SingleSelectGroupGenerator(); impl GroupGenerator for SingleSelectGroupGenerator { type ConfigurationType = SelectOptionGroupConfigurationPB; type TypeOptionType = SingleSelectTypeOptionPB; - fn gen_groups( + fn generate_groups( _configuration: &Option, type_option: &Option, _cell_content_provider: &dyn GroupCellContentProvider, @@ -38,13 +63,6 @@ impl GroupGenerator for SingleSelectGroupGenerator { } } -impl GroupAction for SingleSelectGroupController { - type CellDataType = SelectOptionCellDataPB; - fn should_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { - cell_data.select_options.iter().any(|option| option.id == content) - } -} - // MultiSelect pub type MultiSelectGroupController = GroupController< SelectOptionGroupConfigurationPB, @@ -53,12 +71,33 @@ pub type MultiSelectGroupController = GroupController< SelectOptionCellDataParser, >; +impl Groupable for MultiSelectGroupController { + type CellDataType = SelectOptionCellDataPB; + fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { + cell_data.select_options.iter().any(|option| option.id == content) + } +} + +impl GroupActionHandler for MultiSelectGroupController { + fn get_groups(&self) -> Vec { + self.groups() + } + + fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> { + self.handle_row(row_rev) + } + + fn create_card(&self, row_rev: &mut RowRevision) { + todo!() + } +} + pub struct MultiSelectGroupGenerator(); impl GroupGenerator for MultiSelectGroupGenerator { type ConfigurationType = SelectOptionGroupConfigurationPB; type TypeOptionType = MultiSelectTypeOptionPB; - fn gen_groups( + fn generate_groups( _configuration: &Option, type_option: &Option, _cell_content_provider: &dyn GroupCellContentProvider, @@ -78,10 +117,3 @@ impl GroupGenerator for MultiSelectGroupGenerator { } } } - -impl GroupAction for MultiSelectGroupController { - type CellDataType = SelectOptionCellDataPB; - fn should_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { - cell_data.select_options.iter().any(|option| option.id == content) - } -} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index 5be0141ca9..573ffcea75 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -1,12 +1,14 @@ use crate::services::block_manager::GridBlockManager; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::group::{ - CheckboxGroupController, Group, GroupCellContentProvider, MultiSelectGroupController, SingleSelectGroupController, + CheckboxGroupController, Group, GroupActionHandler, GroupCellContentProvider, MultiSelectGroupController, + SingleSelectGroupController, }; use crate::entities::{ - CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupPB, NumberGroupConfigurationPB, - SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB, + CheckboxGroupConfigurationPB, CreateBoardCardParams, DateGroupConfigurationPB, FieldType, GroupPB, + NumberGroupConfigurationPB, RowPB, SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, + UrlGroupConfigurationPB, }; use bytes::Bytes; use flowy_error::FlowyResult; @@ -18,10 +20,9 @@ use tokio::sync::RwLock; pub(crate) struct GridGroupService { #[allow(dead_code)] scheduler: Arc, - #[allow(dead_code)] grid_pad: Arc>, - #[allow(dead_code)] block_manager: Arc, + group_action_handler: Option>>, } impl GridGroupService { @@ -35,14 +36,14 @@ impl GridGroupService { scheduler, grid_pad, block_manager, + group_action_handler: None, } } - pub(crate) async fn load_groups(&self) -> Option> { - let grid_pad = self.grid_pad.read().await; - let field_rev = find_group_field(grid_pad.fields()).unwrap(); + pub(crate) async fn load_groups(&mut self) -> Option> { + let field_rev = find_group_field(self.grid_pad.read().await.fields()).unwrap(); let field_type: FieldType = field_rev.field_type_rev.into(); - let configuration = self.get_group_configuration(field_rev).await; + let configuration = self.get_group_configuration(&field_rev).await; let blocks = self.block_manager.get_block_snapshots(None).await.unwrap(); let row_revs = blocks @@ -51,19 +52,28 @@ impl GridGroupService { .flatten() .collect::>>(); - match self.build_groups(&field_type, field_rev, row_revs, configuration) { + match self + .build_groups(&field_type, &field_rev, row_revs, configuration) + .await + { Ok(groups) => Some(groups), Err(_) => None, } } - async fn get_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision { + pub(crate) async fn create_board_card(&self, row_rev: &mut RowRevision) { + if let Some(group_action_handler) = self.group_action_handler.as_ref() { + group_action_handler.write().await.create_card(row_rev); + } + } + + pub(crate) async fn get_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision { let grid_pad = self.grid_pad.read().await; let setting = grid_pad.get_setting_rev(); let layout = &setting.layout; let configurations = setting.get_groups(layout, &field_rev.id, &field_rev.field_type_rev); match configurations { - None => self.default_group_configuration(field_rev), + None => default_group_configuration(field_rev), Some(mut configurations) => { assert_eq!(configurations.len(), 1); (&*configurations.pop().unwrap()).clone() @@ -71,79 +81,81 @@ impl GridGroupService { } } - fn default_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision { - let field_type: FieldType = field_rev.field_type_rev.clone().into(); - let bytes: Bytes = match field_type { - FieldType::RichText => TextGroupConfigurationPB::default().try_into().unwrap(), - FieldType::Number => NumberGroupConfigurationPB::default().try_into().unwrap(), - FieldType::DateTime => DateGroupConfigurationPB::default().try_into().unwrap(), - FieldType::SingleSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(), - FieldType::MultiSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(), - FieldType::Checkbox => CheckboxGroupConfigurationPB::default().try_into().unwrap(), - FieldType::URL => UrlGroupConfigurationPB::default().try_into().unwrap(), - }; - GroupConfigurationRevision { - id: gen_grid_group_id(), - field_id: field_rev.id.clone(), - field_type_rev: field_rev.field_type_rev.clone(), - content: Some(bytes.to_vec()), - } - } - #[tracing::instrument(level = "trace", skip_all, err)] - fn build_groups( - &self, + async fn build_groups( + &mut self, field_type: &FieldType, field_rev: &Arc, row_revs: Vec>, configuration: GroupConfigurationRevision, ) -> FlowyResult> { - let groups: Vec = match field_type { + match field_type { FieldType::RichText => { // let generator = GroupGenerator::::from_configuration(configuration); - vec![] } FieldType::Number => { // let generator = GroupGenerator::::from_configuration(configuration); - vec![] } FieldType::DateTime => { // let generator = GroupGenerator::::from_configuration(configuration); - vec![] } FieldType::SingleSelect => { - let mut group_controller = - SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; - let _ = group_controller.group_rows(&row_revs)?; - group_controller.take_groups() + let controller = SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; + self.group_action_handler = Some(Arc::new(RwLock::new(controller))); } FieldType::MultiSelect => { - let mut group_controller = - MultiSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; - let _ = group_controller.group_rows(&row_revs)?; - group_controller.take_groups() + let controller = MultiSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; + self.group_action_handler = Some(Arc::new(RwLock::new(controller))); } FieldType::Checkbox => { - let mut group_controller = - CheckboxGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; - let _ = group_controller.group_rows(&row_revs)?; - group_controller.take_groups() + let controller = CheckboxGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; + self.group_action_handler = Some(Arc::new(RwLock::new(controller))); } FieldType::URL => { // let generator = GroupGenerator::::from_configuration(configuration); - vec![] } }; + let mut groups = vec![]; + if let Some(group_action_handler) = self.group_action_handler.as_ref() { + let mut write_guard = group_action_handler.write().await; + let _ = write_guard.group_rows(&row_revs)?; + groups = write_guard.get_groups(); + drop(write_guard); + } + Ok(groups.into_iter().map(GroupPB::from).collect()) } } -fn find_group_field(field_revs: &[Arc]) -> Option<&Arc> { - field_revs.iter().find(|field_rev| { - let field_type: FieldType = field_rev.field_type_rev.into(); - field_type.can_be_group() - }) +fn find_group_field(field_revs: &[Arc]) -> Option> { + let field_rev = field_revs + .iter() + .find(|field_rev| { + let field_type: FieldType = field_rev.field_type_rev.into(); + field_type.can_be_group() + }) + .cloned(); + field_rev } impl GroupCellContentProvider for Arc> {} + +fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision { + let field_type: FieldType = field_rev.field_type_rev.clone().into(); + let bytes: Bytes = match field_type { + FieldType::RichText => TextGroupConfigurationPB::default().try_into().unwrap(), + FieldType::Number => NumberGroupConfigurationPB::default().try_into().unwrap(), + FieldType::DateTime => DateGroupConfigurationPB::default().try_into().unwrap(), + FieldType::SingleSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(), + FieldType::MultiSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(), + FieldType::Checkbox => CheckboxGroupConfigurationPB::default().try_into().unwrap(), + FieldType::URL => UrlGroupConfigurationPB::default().try_into().unwrap(), + }; + GroupConfigurationRevision { + id: gen_grid_group_id(), + field_id: field_rev.id.clone(), + field_type_rev: field_rev.field_type_rev.clone(), + content: Some(bytes.to_vec()), + } +} diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index 352c4abbdb..5b676073da 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -111,6 +111,9 @@ pub enum ErrorCode { #[display(fmt = "Field's type option data should not be empty")] TypeOptionDataIsEmpty = 450, + #[display(fmt = "Group id is empty")] + GroupIdIsEmpty = 460, + #[display(fmt = "Invalid date time format")] InvalidDateTimeFormat = 500, diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs index b60baff811..184f5266ed 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs @@ -88,9 +88,9 @@ pub struct GridBlockMetaRevisionChangeset { } impl GridBlockMetaRevisionChangeset { - pub fn from_row_count(block_id: &str, row_count: i32) -> Self { + pub fn from_row_count(block_id: String, row_count: i32) -> Self { Self { - block_id: block_id.to_string(), + block_id, start_row_index: None, row_count: Some(row_count), } From 43eaa2748d45532d94765581427c670df6e1028b Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 14 Aug 2022 11:05:55 +0800 Subject: [PATCH 4/6] chore: insert cell content when creating card --- .../plugins/board/application/board_bloc.dart | 6 +- .../application/board_data_controller.dart | 8 +- .../board/presentation/board_page.dart | 2 +- .../application/grid_data_controller.dart | 4 +- .../grid/application/grid_service.dart | 12 ++- .../src/entities/group_entities/board_card.rs | 41 ++++++++++ .../rust-lib/flowy-grid/src/event_handler.rs | 2 +- frontend/rust-lib/flowy-grid/src/event_map.rs | 2 +- .../src/services/cell/cell_operation.rs | 41 ++++++++++ .../flowy-grid/src/services/grid_editor.rs | 11 ++- .../group/group_generator/checkbox_group.rs | 15 ++-- .../group/group_generator/generator.rs | 81 ++++++++++--------- .../group_generator/select_option_group.rs | 49 ++++++++--- .../src/services/group/group_service.rs | 28 +++++-- .../src/services/row/row_builder.rs | 76 +++++++++++------ frontend/rust-lib/flowy-grid/src/util.rs | 13 +-- .../flowy-grid/tests/grid/block_test/util.rs | 11 +-- .../src/client_grid/grid_revision_pad.rs | 2 +- 18 files changed, 286 insertions(+), 118 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index 1db180d4e4..a4a892a7fc 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -52,8 +52,8 @@ class BoardBloc extends Bloc { _startListening(); await _loadGrid(emit); }, - createRow: () async { - final result = await _dataController.createRow(); + createRow: (groupId) async { + final result = await _dataController.createBoardCard(groupId); result.fold( (rowPB) { emit(state.copyWith(editingRow: some(rowPB))); @@ -153,7 +153,7 @@ class BoardBloc extends Bloc { @freezed class BoardEvent with _$BoardEvent { const factory BoardEvent.initial() = InitialGrid; - const factory BoardEvent.createRow() = _CreateRow; + const factory BoardEvent.createRow(String groupId) = _CreateRow; const factory BoardEvent.endEditRow(String rowId) = _EndEditRow; const factory BoardEvent.didReceiveGroups(List groups) = _DidReceiveGroup; diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index 619d16f99e..e4b4f90520 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -21,7 +21,7 @@ typedef OnError = void Function(FlowyError); class BoardDataController { final String gridId; - final GridService _gridFFIService; + final GridFFIService _gridFFIService; final GridFieldCache fieldCache; // key: the block id @@ -45,7 +45,7 @@ class BoardDataController { BoardDataController({required ViewPB view}) : gridId = view.id, _blocks = LinkedHashMap.new(), - _gridFFIService = GridService(gridId: view.id), + _gridFFIService = GridFFIService(gridId: view.id), fieldCache = GridFieldCache(gridId: view.id); void addListener({ @@ -88,8 +88,8 @@ class BoardDataController { ); } - Future> createRow() { - return _gridFFIService.createRow(); + Future> createBoardCard(String groupId) { + return _gridFFIService.createBoardCard(groupId); } Future dispose() async { diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index bf04c22f57..faf7e193b0 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -88,7 +88,7 @@ class BoardContent extends StatelessWidget { height: 50, margin: config.columnItemPadding, onAddButtonClick: () { - context.read().add(const BoardEvent.createRow()); + context.read().add(BoardEvent.createRow(columnData.id)); }); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart index 9de6c65997..f11db25167 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart @@ -24,7 +24,7 @@ typedef ListenOnRowChangedCondition = bool Function(); class GridDataController { final String gridId; - final GridService _gridFFIService; + final GridFFIService _gridFFIService; final GridFieldCache fieldCache; // key: the block id @@ -47,7 +47,7 @@ class GridDataController { GridDataController({required ViewPB view}) : gridId = view.id, _blocks = LinkedHashMap.new(), - _gridFFIService = GridService(gridId: view.id), + _gridFFIService = GridFFIService(gridId: view.id), fieldCache = GridFieldCache(gridId: view.id); void addListener({ diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart index 093782d32f..4315fff38b 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart @@ -3,14 +3,15 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/board_card.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; -class GridService { +class GridFFIService { final String gridId; - GridService({ + GridFFIService({ required this.gridId, }); @@ -27,6 +28,13 @@ class GridService { return GridEventCreateRow(payload).send(); } + Future> createBoardCard(String groupId) { + CreateBoardCardPayloadPB payload = CreateBoardCardPayloadPB.create() + ..gridId = gridId + ..groupId = groupId; + return GridEventCreateBoardCard(payload).send(); + } + Future> getFields( {required List fieldIds}) { final payload = QueryFieldPayloadPB.create() diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs index d641c2d723..e2dac9069d 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs @@ -1,3 +1,4 @@ +use crate::entities::RowPB; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; @@ -27,3 +28,43 @@ impl TryInto for CreateBoardCardPayloadPB { }) } } + +#[derive(Debug, Default, ProtoBuf)] +pub struct BoardCardChangesetPB { + #[pb(index = 1)] + pub group_id: String, + + #[pb(index = 2)] + pub inserted_cards: Vec, + + #[pb(index = 3)] + pub deleted_cards: Vec, + + #[pb(index = 4)] + pub updated_cards: Vec, +} +impl BoardCardChangesetPB { + pub fn insert(group_id: String, inserted_cards: Vec) -> Self { + Self { + group_id, + inserted_cards, + ..Default::default() + } + } + + pub fn delete(group_id: String, deleted_cards: Vec) -> Self { + Self { + group_id, + deleted_cards, + ..Default::default() + } + } + + pub fn update(group_id: String, updated_cards: Vec) -> Self { + Self { + group_id, + updated_cards, + ..Default::default() + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 7f8ae72773..fa23e1f4cf 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -424,6 +424,6 @@ pub(crate) async fn create_board_card_handler( ) -> DataResult { let params: CreateBoardCardParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(params.grid_id.as_ref())?; - let row = editor.create_board_card().await?; + let row = editor.create_board_card(¶ms.group_id).await?; data_result(row) } diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 9a5303220c..980087fee0 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -39,7 +39,7 @@ pub fn create(grid_manager: Arc) -> Module { // Date .event(GridEvent::UpdateDateCell, update_date_cell_handler) // Group - .event(GridEvent::CreateBoardCard, create_row_handler) + .event(GridEvent::CreateBoardCard, create_board_card_handler) .event(GridEvent::GetGroup, get_groups_handler); module diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs b/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs index 4a12bfd613..cb84a4f8f4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs @@ -135,6 +135,47 @@ pub fn try_decode_cell_data( } } +pub fn insert_text_cell(s: String, field_rev: &FieldRevision) -> CellRevision { + let data = apply_cell_data_changeset(s, None, field_rev).unwrap(); + CellRevision::new(data) +} + +pub fn insert_number_cell(num: i64, field_rev: &FieldRevision) -> CellRevision { + let data = apply_cell_data_changeset(num, None, field_rev).unwrap(); + CellRevision::new(data) +} + +pub fn insert_url_cell(url: String, field_rev: &FieldRevision) -> CellRevision { + let data = apply_cell_data_changeset(url, None, field_rev).unwrap(); + CellRevision::new(data) +} + +pub fn insert_checkbox_cell(is_check: bool, field_rev: &FieldRevision) -> CellRevision { + let s = if is_check { + CHECK.to_string() + } else { + UNCHECK.to_string() + }; + let data = apply_cell_data_changeset(s, None, field_rev).unwrap(); + CellRevision::new(data) +} + +pub fn insert_date_cell(timestamp: i64, field_rev: &FieldRevision) -> CellRevision { + let cell_data = serde_json::to_string(&DateCellChangesetPB { + date: Some(timestamp.to_string()), + time: None, + }) + .unwrap(); + let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap(); + CellRevision::new(data) +} + +pub fn insert_select_option_cell(option_id: String, field_rev: &FieldRevision) -> CellRevision { + let cell_data = SelectOptionCellChangeset::from_insert(&option_id).to_str(); + let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap(); + CellRevision::new(data) +} + /// If the cell data is not String type, it should impl this trait. /// Deserialize the String into cell specific data type. pub trait FromCellString { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 82c4b23afb..53c9a681bd 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -552,9 +552,15 @@ impl GridRevisionEditor { }) } - pub async fn create_board_card(&self) -> FlowyResult { + pub async fn create_board_card(&self, group_id: &str) -> FlowyResult { let mut row_rev = self.create_row_rev().await?; - let _ = self.group_service.write().await.create_board_card(&mut row_rev).await; + let _ = self + .group_service + .write() + .await + .create_board_card(&mut row_rev, group_id) + .await; + self.create_row_pb(row_rev, None).await } @@ -573,6 +579,7 @@ impl GridRevisionEditor { Ok(row_rev) } + #[tracing::instrument(level = "trace", skip_all, err)] async fn create_row_pb(&self, row_rev: RowRevision, start_row_id: Option) -> FlowyResult { let row_pb = RowPB::from(&row_rev); let block_id = row_rev.block_id.clone(); diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index b976310bed..acc8cf8715 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -1,6 +1,7 @@ use crate::entities::{CheckboxGroupConfigurationPB, RowPB}; use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::RowRevision; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use std::sync::Arc; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::group::{ @@ -19,15 +20,19 @@ impl Groupable for CheckboxGroupController { } impl GroupActionHandler for CheckboxGroupController { + fn field_id(&self) -> &str { + &self.field_id + } + fn get_groups(&self) -> Vec { - self.groups() + self.make_groups() } - fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> { - self.handle_row(row_rev) + fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { + self.handle_rows(row_revs, field_rev) } - fn create_card(&self, row_rev: &mut RowRevision) { + fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { todo!() } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs index b841e745e4..856c026a80 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs @@ -1,11 +1,13 @@ use crate::entities::{GroupPB, RowPB}; use crate::services::cell::{decode_any_cell_data, CellBytesParser}; use bytes::Bytes; -use flowy_error::FlowyResult; +use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer, }; +use futures::future::BoxFuture; use indexmap::IndexMap; +use lib_infra::future::{BoxResultFuture, FutureResult}; use std::marker::PhantomData; use std::sync::Arc; @@ -34,15 +36,14 @@ pub trait Groupable { } pub trait GroupActionHandler: Send + Sync { + fn field_id(&self) -> &str; fn get_groups(&self) -> Vec; - fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()>; - fn group_rows(&mut self, row_revs: &[Arc]) -> FlowyResult<()> { - for row_rev in row_revs { - let _ = self.group_row(row_rev)?; - } - Ok(()) - } - fn create_card(&self, row_rev: &mut RowRevision); + fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()>; + fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); +} + +pub trait GroupActionHandler2: Send + Sync { + fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); } const DEFAULT_GROUP_ID: &str = "default_group"; @@ -52,8 +53,8 @@ const DEFAULT_GROUP_ID: &str = "default_group"; /// G: the group container generator /// P: the parser that impl [CellBytesParser] for the CellBytes pub struct GroupController { - pub field_rev: Arc, - groups: IndexMap, + pub field_id: String, + pub groups_map: IndexMap, default_group: Group, pub type_option: Option, pub configuration: Option, @@ -86,7 +87,7 @@ where G: GroupGenerator, { pub fn new( - field_rev: Arc, + field_rev: &Arc, configuration: GroupConfigurationRevision, cell_content_provider: &dyn GroupCellContentProvider, ) -> FlowyResult { @@ -106,8 +107,8 @@ where }; Ok(Self { - field_rev, - groups: groups.into_iter().map(|group| (group.id.clone(), group)).collect(), + field_id: field_rev.id.clone(), + groups_map: groups.into_iter().map(|group| (group.id.clone(), group)).collect(), default_group, type_option, configuration, @@ -116,9 +117,9 @@ where }) } - pub fn groups(&self) -> Vec { + pub fn make_groups(&self) -> Vec { let default_group = self.default_group.clone(); - let mut groups: Vec = self.groups.values().cloned().collect(); + let mut groups: Vec = self.groups_map.values().cloned().collect(); if !default_group.rows.is_empty() { groups.push(default_group); } @@ -131,34 +132,38 @@ where P: CellBytesParser, Self: Groupable, { - pub fn handle_row(&mut self, row: &RowRevision) -> FlowyResult<()> { + pub fn handle_rows(&mut self, rows: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { + // The field_rev might be None if corresponding field_rev is deleted. if self.configuration.is_none() { return Ok(()); } - if let Some(cell_rev) = row.cells.get(&self.field_rev.id) { - let mut records: Vec = vec![]; - let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &self.field_rev); - let cell_data = cell_bytes.parser::

()?; - for group in self.groups.values() { - if self.can_group(&group.content, &cell_data) { - records.push(GroupRecord { - row: row.into(), - group_id: group.id.clone(), - }); - } - } - if records.is_empty() { - self.default_group.rows.push(row.into()); - } else { - for record in records { - if let Some(group) = self.groups.get_mut(&record.group_id) { - group.rows.push(record.row); + for row in rows { + if let Some(cell_rev) = row.cells.get(&self.field_id) { + let mut records: Vec = vec![]; + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &field_rev); + let cell_data = cell_bytes.parser::

()?; + for group in self.groups_map.values() { + if self.can_group(&group.content, &cell_data) { + records.push(GroupRecord { + row: row.into(), + group_id: group.id.clone(), + }); } } + + if records.is_empty() { + self.default_group.rows.push(row.into()); + } else { + for record in records { + if let Some(group) = self.groups_map.get_mut(&record.group_id) { + group.rows.push(record.row); + } + } + } + } else { + self.default_group.rows.push(row.into()); } - } else { - self.default_group.rows.push(row.into()); } Ok(()) @@ -166,7 +171,7 @@ where pub fn group_rows(&mut self, rows: &[Arc]) -> FlowyResult<()> { for row in rows { - let _ = self.handle_row(row)?; + // let _ = self.handle_row(row)?; } Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index 6666808ee5..a3a133b24c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -1,6 +1,9 @@ use crate::entities::{RowPB, SelectOptionGroupConfigurationPB}; -use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::RowRevision; +use crate::services::cell::insert_select_option_cell; +use flowy_error::{FlowyError, FlowyResult}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use lib_infra::future::FutureResult; +use std::sync::Arc; use crate::services::field::{ MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB, @@ -25,16 +28,27 @@ impl Groupable for SingleSelectGroupController { } impl GroupActionHandler for SingleSelectGroupController { + fn field_id(&self) -> &str { + &self.field_id + } + fn get_groups(&self) -> Vec { - self.groups() + self.make_groups() } - fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> { - self.handle_row(row_rev) + fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { + self.handle_rows(row_revs, field_rev) } - fn create_card(&self, row_rev: &mut RowRevision) { - todo!() + fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + let group: Option<&Group> = self.groups_map.get(group_id); + match group { + None => {} + Some(group) => { + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_rev.cells.insert(field_rev.id.clone(), cell_rev); + } + } } } @@ -79,16 +93,27 @@ impl Groupable for MultiSelectGroupController { } impl GroupActionHandler for MultiSelectGroupController { + fn field_id(&self) -> &str { + &self.field_id + } + fn get_groups(&self) -> Vec { - self.groups() + self.make_groups() } - fn group_row(&mut self, row_rev: &RowRevision) -> FlowyResult<()> { - self.handle_row(row_rev) + fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { + self.handle_rows(row_revs, field_rev) } - fn create_card(&self, row_rev: &mut RowRevision) { - todo!() + fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + let group: Option<&Group> = self.groups_map.get(group_id); + match group { + None => tracing::warn!("Can not find the group: {}", group_id), + Some(group) => { + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_rev.cells.insert(field_rev.id.clone(), cell_rev); + } + } } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index 573ffcea75..fa5f805b7f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -14,6 +14,7 @@ use bytes::Bytes; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision}; use flowy_sync::client_grid::GridRevisionPad; +use futures::future::BoxFuture; use std::sync::Arc; use tokio::sync::RwLock; @@ -61,9 +62,24 @@ impl GridGroupService { } } - pub(crate) async fn create_board_card(&self, row_rev: &mut RowRevision) { + #[tracing::instrument(level = "debug", skip(self, row_rev))] + pub(crate) async fn create_board_card(&self, row_rev: &mut RowRevision, group_id: &str) { if let Some(group_action_handler) = self.group_action_handler.as_ref() { - group_action_handler.write().await.create_card(row_rev); + match self + .grid_pad + .read() + .await + .get_field_rev(group_action_handler.read().await.field_id()) + { + None => tracing::warn!("Fail to create card because the field does not exist"), + Some((_, field_rev)) => { + tracing::trace!("Create card"); + group_action_handler + .write() + .await + .create_card(row_rev, field_rev, group_id); + } + } } } @@ -100,15 +116,15 @@ impl GridGroupService { // let generator = GroupGenerator::::from_configuration(configuration); } FieldType::SingleSelect => { - let controller = SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; + let controller = SingleSelectGroupController::new(field_rev, configuration, &self.grid_pad)?; self.group_action_handler = Some(Arc::new(RwLock::new(controller))); } FieldType::MultiSelect => { - let controller = MultiSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; + let controller = MultiSelectGroupController::new(field_rev, configuration, &self.grid_pad)?; self.group_action_handler = Some(Arc::new(RwLock::new(controller))); } FieldType::Checkbox => { - let controller = CheckboxGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?; + let controller = CheckboxGroupController::new(field_rev, configuration, &self.grid_pad)?; self.group_action_handler = Some(Arc::new(RwLock::new(controller))); } FieldType::URL => { @@ -119,7 +135,7 @@ impl GridGroupService { let mut groups = vec![]; if let Some(group_action_handler) = self.group_action_handler.as_ref() { let mut write_guard = group_action_handler.write().await; - let _ = write_guard.group_rows(&row_revs)?; + let _ = write_guard.group_rows(&row_revs, field_rev)?; groups = write_guard.get_groups(); drop(write_guard); } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs index 3db4c0b550..016bbea128 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -1,4 +1,7 @@ -use crate::services::cell::apply_cell_data_changeset; +use crate::services::cell::{ + apply_cell_data_changeset, insert_checkbox_cell, insert_date_cell, insert_number_cell, insert_select_option_cell, + insert_text_cell, insert_url_cell, +}; use crate::services::field::{DateCellChangesetPB, SelectOptionCellChangeset}; use flowy_grid_data_model::revision::{gen_row_id, CellRevision, FieldRevision, RowRevision, DEFAULT_ROW_HEIGHT}; use indexmap::IndexMap; @@ -34,47 +37,68 @@ impl<'a> RowRevisionBuilder<'a> { } } - pub fn insert_cell(&mut self, field_id: &str, data: String) { + pub fn insert_text_cell(&mut self, field_id: &str, data: String) { match self.field_rev_map.get(&field_id.to_owned()) { - None => { - tracing::warn!("Can't find the field with id: {}", field_id); - } + None => tracing::warn!("Can't find the text field with id: {}", field_id), Some(field_rev) => { - let data = apply_cell_data_changeset(data, None, field_rev).unwrap(); - let cell = CellRevision::new(data); - self.payload.cell_by_field_id.insert(field_id.to_owned(), cell); + self.payload + .cell_by_field_id + .insert(field_id.to_owned(), insert_text_cell(data, field_rev)); + } + } + } + + pub fn insert_url_cell(&mut self, field_id: &str, data: String) { + match self.field_rev_map.get(&field_id.to_owned()) { + None => tracing::warn!("Can't find the url field with id: {}", field_id), + Some(field_rev) => { + self.payload + .cell_by_field_id + .insert(field_id.to_owned(), insert_url_cell(data, field_rev)); + } + } + } + + pub fn insert_number_cell(&mut self, field_id: &str, num: i64) { + match self.field_rev_map.get(&field_id.to_owned()) { + None => tracing::warn!("Can't find the number field with id: {}", field_id), + Some(field_rev) => { + self.payload + .cell_by_field_id + .insert(field_id.to_owned(), insert_number_cell(num, field_rev)); + } + } + } + + pub fn insert_checkbox_cell(&mut self, field_id: &str, is_check: bool) { + match self.field_rev_map.get(&field_id.to_owned()) { + None => tracing::warn!("Can't find the checkbox field with id: {}", field_id), + Some(field_rev) => { + self.payload + .cell_by_field_id + .insert(field_id.to_owned(), insert_checkbox_cell(is_check, field_rev)); } } } pub fn insert_date_cell(&mut self, field_id: &str, timestamp: i64) { match self.field_rev_map.get(&field_id.to_owned()) { - None => { - tracing::warn!("Invalid field_id: {}", field_id); - } + None => tracing::warn!("Can't find the date field with id: {}", field_id), Some(field_rev) => { - let cell_data = serde_json::to_string(&DateCellChangesetPB { - date: Some(timestamp.to_string()), - time: None, - }) - .unwrap(); - let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap(); - let cell = CellRevision::new(data); - self.payload.cell_by_field_id.insert(field_id.to_owned(), cell); + self.payload + .cell_by_field_id + .insert(field_id.to_owned(), insert_date_cell(timestamp, field_rev)); } } } pub fn insert_select_option_cell(&mut self, field_id: &str, data: String) { match self.field_rev_map.get(&field_id.to_owned()) { - None => { - tracing::warn!("Invalid field_id: {}", field_id); - } + None => tracing::warn!("Can't find the select option field with id: {}", field_id), Some(field_rev) => { - let cell_data = SelectOptionCellChangeset::from_insert(&data).to_str(); - let data = apply_cell_data_changeset(cell_data, None, field_rev).unwrap(); - let cell = CellRevision::new(data); - self.payload.cell_by_field_id.insert(field_id.to_owned(), cell); + self.payload + .cell_by_field_id + .insert(field_id.to_owned(), insert_select_option_cell(data, field_rev)); } } } diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index ca1d92a54c..047c81ab02 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -114,20 +114,15 @@ pub fn make_default_board() -> BuildGridContext { row_builder.insert_select_option_cell(&multi_select_field_id, apple_option.id.clone()); row_builder.insert_select_option_cell(&multi_select_field_id, banana_option.id.clone()); // insert text - row_builder.insert_cell(&text_field_id, format!("Card {}", i)); + row_builder.insert_text_cell(&text_field_id, format!("Card {}", i)); // insert date row_builder.insert_date_cell(&date_field_id, timestamp); // number - row_builder.insert_cell(&number_field_id, format!("{}", i)); + row_builder.insert_number_cell(&number_field_id, i); // checkbox - let is_check = if i % 2 == 0 { - CHECK.to_string() - } else { - UNCHECK.to_string() - }; - row_builder.insert_cell(&checkbox_field_id, is_check); + row_builder.insert_checkbox_cell(&checkbox_field_id, i % 2 == 0); // url - row_builder.insert_cell(&url_field_id, "https://appflowy.io".to_string()); + row_builder.insert_url_cell(&url_field_id, "https://appflowy.io".to_string()); let row = row_builder.build(); grid_builder.add_row(row); diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs index a733926228..848b2876fa 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs @@ -26,14 +26,14 @@ impl<'a> GridRowTestBuilder<'a> { pub fn insert_text_cell(&mut self, data: &str) -> String { let text_field = self.field_rev_with_type(&FieldType::RichText); - self.inner_builder.insert_cell(&text_field.id, data.to_string()); + self.inner_builder.insert_text_cell(&text_field.id, data.to_string()); text_field.id.clone() } pub fn insert_number_cell(&mut self, data: &str) -> String { let number_field = self.field_rev_with_type(&FieldType::Number); - self.inner_builder.insert_cell(&number_field.id, data.to_string()); + self.inner_builder.insert_text_cell(&number_field.id, data.to_string()); number_field.id.clone() } @@ -44,20 +44,21 @@ impl<'a> GridRowTestBuilder<'a> { }) .unwrap(); let date_field = self.field_rev_with_type(&FieldType::DateTime); - self.inner_builder.insert_cell(&date_field.id, value); + self.inner_builder.insert_text_cell(&date_field.id, value); date_field.id.clone() } pub fn insert_checkbox_cell(&mut self, data: &str) -> String { let checkbox_field = self.field_rev_with_type(&FieldType::Checkbox); - self.inner_builder.insert_cell(&checkbox_field.id, data.to_string()); + self.inner_builder + .insert_text_cell(&checkbox_field.id, data.to_string()); checkbox_field.id.clone() } pub fn insert_url_cell(&mut self, data: &str) -> String { let url_field = self.field_rev_with_type(&FieldType::URL); - self.inner_builder.insert_cell(&url_field.id, data.to_string()); + self.inner_builder.insert_text_cell(&url_field.id, data.to_string()); url_field.id.clone() } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs index 46b278a1af..e47cf1287d 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs @@ -44,7 +44,7 @@ impl GridRevisionPad { .blocks .iter() .map(|block| { - let mut duplicated_block = (&*block.clone()).clone(); + let mut duplicated_block = (&**block).clone(); duplicated_block.block_id = gen_block_id(); duplicated_block }) From 24ca8da8c82bf4ad6e246ddd1c9dc76a9ac0db0e Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 14 Aug 2022 15:15:56 +0800 Subject: [PATCH 5/6] chore: add create card notification --- .../flowy-grid/src/dart_notification.rs | 1 + .../rust-lib/flowy-grid/src/event_handler.rs | 5 +- .../flowy-grid/src/services/block_manager.rs | 39 +++++------ .../flowy-grid/src/services/grid_editor.rs | 22 ++++-- .../group/group_generator/checkbox_group.rs | 4 +- .../group/group_generator/generator.rs | 17 ++--- .../group_generator/select_option_group.rs | 10 +-- .../src/services/group/group_service.rs | 68 +++++++++++++------ .../src/services/row/row_builder.rs | 6 +- frontend/rust-lib/flowy-grid/src/util.rs | 2 +- 10 files changed, 101 insertions(+), 73 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 202b12eb81..4108da1f11 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -11,6 +11,7 @@ pub enum GridNotification { DidUpdateRow = 30, DidUpdateCell = 40, DidUpdateField = 50, + DidUpdateBoard = 60, } impl std::default::Default for GridNotification { diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index fa23e1f4cf..2c119c55dc 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -232,10 +232,7 @@ pub(crate) async fn get_row_handler( ) -> DataResult { let params: RowIdParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let row = editor - .get_row_rev(¶ms.row_id) - .await? - .and_then(|row_rev| Some(make_row_from_row_rev(row_rev))); + let row = editor.get_row_rev(¶ms.row_id).await?.map(make_row_from_row_rev); data_result(OptionalRowPB { row }) } diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index 8da912534f..b2b6ce63fc 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -161,31 +161,26 @@ impl GridBlockManager { Ok(changesets) } - pub(crate) async fn move_row(&self, row_id: &str, from: usize, to: usize) -> FlowyResult<()> { - let editor = self.get_editor_from_row_id(row_id).await?; - let _ = editor.move_row(row_id, from, to).await?; + pub(crate) async fn move_row(&self, row_rev: Arc, from: usize, to: usize) -> FlowyResult<()> { + let editor = self.get_editor_from_row_id(&row_rev.id).await?; + let _ = editor.move_row(&row_rev.id, from, to).await?; - match editor.get_row_revs(Some(vec![Cow::Borrowed(row_id)])).await?.pop() { - None => {} - Some(row_rev) => { - let delete_row_id = row_rev.id.clone(); - let insert_row = InsertedRowPB { - index: Some(to as i32), - row: make_row_from_row_rev(row_rev), - }; + let delete_row_id = row_rev.id.clone(); + let insert_row = InsertedRowPB { + index: Some(to as i32), + row: make_row_from_row_rev(row_rev), + }; - let notified_changeset = GridBlockChangesetPB { - block_id: editor.block_id.clone(), - inserted_rows: vec![insert_row], - deleted_rows: vec![delete_row_id], - ..Default::default() - }; + let notified_changeset = GridBlockChangesetPB { + block_id: editor.block_id.clone(), + inserted_rows: vec![insert_row], + deleted_rows: vec![delete_row_id], + ..Default::default() + }; - let _ = self - .notify_did_update_block(&editor.block_id, notified_changeset) - .await?; - } - } + let _ = self + .notify_did_update_block(&editor.block_id, notified_changeset) + .await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 53c9a681bd..0bdf92ec96 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -326,6 +326,7 @@ impl GridRevisionEditor { pub async fn delete_row(&self, row_id: &str) -> FlowyResult<()> { let _ = self.block_manager.delete_row(row_id).await?; + self.group_service.read().await.did_delete_card(row_id.to_owned()).await; Ok(()) } @@ -517,10 +518,22 @@ impl GridRevisionEditor { } pub async fn move_row(&self, row_id: &str, from: i32, to: i32) -> FlowyResult<()> { - let _ = self.block_manager.move_row(row_id, from as usize, to as usize).await?; + match self.block_manager.get_row_rev(row_id).await? { + None => tracing::warn!("Move row failed, can not find the row:{}", row_id), + Some(row_rev) => { + let _ = self + .block_manager + .move_row(row_rev.clone(), from as usize, to as usize) + .await?; + } + } Ok(()) } + pub async fn move_board_card(&self, group_id: &str, from: i32, to: i32) -> FlowyResult<()> { + self.group_service.write().await.move_card(group_id, from, to).await; + Ok(()) + } pub async fn delta_bytes(&self) -> Bytes { self.grid_pad.read().await.delta_bytes() } @@ -558,10 +571,12 @@ impl GridRevisionEditor { .group_service .write() .await - .create_board_card(&mut row_rev, group_id) + .update_board_card(&mut row_rev, group_id) .await; - self.create_row_pb(row_rev, None).await + let row_pb = self.create_row_pb(row_rev, None).await?; + self.group_service.read().await.did_create_card(group_id, &row_pb).await; + Ok(row_pb) } #[tracing::instrument(level = "trace", skip_all, err)] @@ -579,7 +594,6 @@ impl GridRevisionEditor { Ok(row_rev) } - #[tracing::instrument(level = "trace", skip_all, err)] async fn create_row_pb(&self, row_rev: RowRevision, start_row_id: Option) -> FlowyResult { let row_pb = RowPB::from(&row_rev); let block_id = row_rev.block_id.clone(); diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs index acc8cf8715..85c135d0ee 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs @@ -1,4 +1,4 @@ -use crate::entities::{CheckboxGroupConfigurationPB, RowPB}; +use crate::entities::CheckboxGroupConfigurationPB; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use std::sync::Arc; @@ -32,7 +32,7 @@ impl GroupActionHandler for CheckboxGroupController { self.handle_rows(row_revs, field_rev) } - fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + fn update_card(&self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) { todo!() } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs index 856c026a80..a351913546 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/generator.rs @@ -1,13 +1,13 @@ use crate::entities::{GroupPB, RowPB}; use crate::services::cell::{decode_any_cell_data, CellBytesParser}; use bytes::Bytes; -use flowy_error::{FlowyError, FlowyResult}; +use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer, }; -use futures::future::BoxFuture; + use indexmap::IndexMap; -use lib_infra::future::{BoxResultFuture, FutureResult}; + use std::marker::PhantomData; use std::sync::Arc; @@ -39,7 +39,7 @@ pub trait GroupActionHandler: Send + Sync { fn field_id(&self) -> &str; fn get_groups(&self) -> Vec; fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()>; - fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); + fn update_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); } pub trait GroupActionHandler2: Send + Sync { @@ -141,7 +141,7 @@ where for row in rows { if let Some(cell_rev) = row.cells.get(&self.field_id) { let mut records: Vec = vec![]; - let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &field_rev); + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_data = cell_bytes.parser::

()?; for group in self.groups_map.values() { if self.can_group(&group.content, &cell_data) { @@ -168,13 +168,6 @@ where Ok(()) } - - pub fn group_rows(&mut self, rows: &[Arc]) -> FlowyResult<()> { - for row in rows { - // let _ = self.handle_row(row)?; - } - Ok(()) - } } struct GroupRecord { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index a3a133b24c..50628875a8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -1,8 +1,8 @@ -use crate::entities::{RowPB, SelectOptionGroupConfigurationPB}; +use crate::entities::SelectOptionGroupConfigurationPB; use crate::services::cell::insert_select_option_cell; -use flowy_error::{FlowyError, FlowyResult}; +use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; -use lib_infra::future::FutureResult; + use std::sync::Arc; use crate::services::field::{ @@ -40,7 +40,7 @@ impl GroupActionHandler for SingleSelectGroupController { self.handle_rows(row_revs, field_rev) } - fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + fn update_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { let group: Option<&Group> = self.groups_map.get(group_id); match group { None => {} @@ -105,7 +105,7 @@ impl GroupActionHandler for MultiSelectGroupController { self.handle_rows(row_revs, field_rev) } - fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + fn update_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { let group: Option<&Group> = self.groups_map.get(group_id); match group { None => tracing::warn!("Can not find the group: {}", group_id), diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index fa5f805b7f..3fd84d014c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -1,20 +1,21 @@ -use crate::services::block_manager::GridBlockManager; -use crate::services::grid_editor_task::GridServiceTaskScheduler; -use crate::services::group::{ - CheckboxGroupController, Group, GroupActionHandler, GroupCellContentProvider, MultiSelectGroupController, - SingleSelectGroupController, -}; - +use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::entities::{ - CheckboxGroupConfigurationPB, CreateBoardCardParams, DateGroupConfigurationPB, FieldType, GroupPB, + BoardCardChangesetPB, CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupPB, NumberGroupConfigurationPB, RowPB, SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB, }; +use crate::services::block_manager::GridBlockManager; +use crate::services::grid_editor_task::GridServiceTaskScheduler; +use crate::services::group::{ + CheckboxGroupController, GroupActionHandler, GroupCellContentProvider, MultiSelectGroupController, + SingleSelectGroupController, +}; + use bytes::Bytes; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision}; use flowy_sync::client_grid::GridRevisionPad; -use futures::future::BoxFuture; + use std::sync::Arc; use tokio::sync::RwLock; @@ -63,21 +64,17 @@ impl GridGroupService { } #[tracing::instrument(level = "debug", skip(self, row_rev))] - pub(crate) async fn create_board_card(&self, row_rev: &mut RowRevision, group_id: &str) { + pub(crate) async fn update_board_card(&self, row_rev: &mut RowRevision, group_id: &str) { if let Some(group_action_handler) = self.group_action_handler.as_ref() { - match self - .grid_pad - .read() - .await - .get_field_rev(group_action_handler.read().await.field_id()) - { + let field_id = group_action_handler.read().await.field_id().to_owned(); + + match self.grid_pad.read().await.get_field_rev(&field_id) { None => tracing::warn!("Fail to create card because the field does not exist"), Some((_, field_rev)) => { - tracing::trace!("Create card"); group_action_handler .write() .await - .create_card(row_rev, field_rev, group_id); + .update_card(row_rev, field_rev, group_id); } } } @@ -97,6 +94,37 @@ impl GridGroupService { } } + pub async fn move_card(&self, _group_id: &str, _from: i32, _to: i32) { + // BoardCardChangesetPB { + // group_id: "".to_string(), + // inserted_cards: vec![], + // deleted_cards: vec![], + // updated_cards: vec![] + // } + // let row_pb = make_row_from_row_rev(row_rev); + todo!() + } + + pub async fn did_delete_card(&self, _row_id: String) { + // let changeset = BoardCardChangesetPB::delete(group_id.to_owned(), vec![row_id]); + // self.notify_did_update_board(changeset).await; + todo!() + } + + pub async fn did_create_card(&self, group_id: &str, row_pb: &RowPB) { + let changeset = BoardCardChangesetPB::insert(group_id.to_owned(), vec![row_pb.clone()]); + self.notify_did_update_board(changeset).await; + } + + pub async fn notify_did_update_board(&self, changeset: BoardCardChangesetPB) { + if self.group_action_handler.is_none() { + return; + } + send_dart_notification(&changeset.group_id, GridNotification::DidUpdateBoard) + .payload(changeset) + .send(); + } + #[tracing::instrument(level = "trace", skip_all, err)] async fn build_groups( &mut self, @@ -158,7 +186,7 @@ fn find_group_field(field_revs: &[Arc]) -> Option> {} fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision { - let field_type: FieldType = field_rev.field_type_rev.clone().into(); + let field_type: FieldType = field_rev.field_type_rev.into(); let bytes: Bytes = match field_type { FieldType::RichText => TextGroupConfigurationPB::default().try_into().unwrap(), FieldType::Number => NumberGroupConfigurationPB::default().try_into().unwrap(), @@ -171,7 +199,7 @@ fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationR GroupConfigurationRevision { id: gen_grid_group_id(), field_id: field_rev.id.clone(), - field_type_rev: field_rev.field_type_rev.clone(), + field_type_rev: field_rev.field_type_rev, content: Some(bytes.to_vec()), } } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs index 016bbea128..ee586b3851 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -1,8 +1,8 @@ use crate::services::cell::{ - apply_cell_data_changeset, insert_checkbox_cell, insert_date_cell, insert_number_cell, insert_select_option_cell, - insert_text_cell, insert_url_cell, + insert_checkbox_cell, insert_date_cell, insert_number_cell, insert_select_option_cell, insert_text_cell, + insert_url_cell, }; -use crate::services::field::{DateCellChangesetPB, SelectOptionCellChangeset}; + use flowy_grid_data_model::revision::{gen_row_id, CellRevision, FieldRevision, RowRevision, DEFAULT_ROW_HEIGHT}; use indexmap::IndexMap; use std::collections::HashMap; diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 047c81ab02..90bf2f2a26 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -76,7 +76,7 @@ pub fn make_default_board() -> BuildGridContext { let multi_select_type_option = MultiSelectTypeOptionBuilder::default() .add_option(banana_option.clone()) .add_option(apple_option.clone()) - .add_option(pear_option.clone()); + .add_option(pear_option); let multi_select_field = FieldBuilder::new(multi_select_type_option) .name("Fruit") .visibility(true) From 445d5f6222437cbb6c911d3b0be1a9f24db06bb0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 14 Aug 2022 16:05:14 +0800 Subject: [PATCH 6/6] chore: disable create board --- frontend/app_flowy/lib/plugins/board/board.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index 36d181ae3e..2954a7cbf9 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder { class BoardPluginConfig implements PluginConfig { @override - bool get creatable => true; + bool get creatable => false; } class BoardPlugin extends Plugin {