Selaa lähdekoodia

Merge pull request #951 from AppFlowy-IO/feat/create_card_from_header

chore: enable create card from header button
Nathan.fooo 2 vuotta sitten
vanhempi
commit
0225f0aa4d

+ 38 - 12
frontend/app_flowy/lib/plugins/board/application/board_bloc.dart

@@ -69,16 +69,31 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
             _startListening();
             await _loadGrid(emit);
           },
-          createRow: (groupId) async {
+          createBottomRow: (groupId) async {
+            final startRowId = groupControllers[groupId]?.lastRow()?.id;
+            final result = await _gridDataController.createBoardCard(
+              groupId,
+              startRowId: startRowId,
+            );
+            result.fold(
+              (_) {},
+              (err) => Log.error(err),
+            );
+          },
+          createHeaderRow: (String groupId) async {
             final result = await _gridDataController.createBoardCard(groupId);
             result.fold(
               (_) {},
               (err) => Log.error(err),
             );
           },
-          didCreateRow: (String groupId, RowPB row) {
+          didCreateRow: (String groupId, RowPB row, int? index) {
             emit(state.copyWith(
-              editingRow: Some(BoardEditingRow(columnId: groupId, row: row)),
+              editingRow: Some(BoardEditingRow(
+                columnId: groupId,
+                row: row,
+                index: index,
+              )),
             ));
           },
           endEditRow: (rowId) {
@@ -142,8 +157,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
     for (final group in groups) {
       final delegate = GroupControllerDelegateImpl(
         controller: boardController,
-        onNewColumnItem: (groupId, row) {
-          add(BoardEvent.didCreateRow(groupId, row));
+        onNewColumnItem: (groupId, row, index) {
+          add(BoardEvent.didCreateRow(groupId, row, index));
         },
       );
       final controller = GroupController(
@@ -231,9 +246,13 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
 @freezed
 class BoardEvent with _$BoardEvent {
   const factory BoardEvent.initial() = _InitialBoard;
-  const factory BoardEvent.createRow(String groupId) = _CreateRow;
-  const factory BoardEvent.didCreateRow(String groupId, RowPB row) =
-      _DidCreateRow;
+  const factory BoardEvent.createBottomRow(String groupId) = _CreateBottomRow;
+  const factory BoardEvent.createHeaderRow(String groupId) = _CreateHeaderRow;
+  const factory BoardEvent.didCreateRow(
+    String groupId,
+    RowPB row,
+    int? index,
+  ) = _DidCreateRow;
   const factory BoardEvent.endEditRow(String rowId) = _EndEditRow;
   const factory BoardEvent.didReceiveError(FlowyError error) = _DidReceiveError;
   const factory BoardEvent.didReceiveGridUpdate(
@@ -313,7 +332,7 @@ class BoardColumnItem extends AFColumnItem {
 
 class GroupControllerDelegateImpl extends GroupControllerDelegate {
   final AFBoardDataController controller;
-  final void Function(String, RowPB) onNewColumnItem;
+  final void Function(String, RowPB, int?) onNewColumnItem;
 
   GroupControllerDelegateImpl({
     required this.controller,
@@ -351,23 +370,30 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
   }
 
   @override
-  void addNewRow(GroupPB group, RowPB row) {
+  void addNewRow(GroupPB group, RowPB row, int? index) {
     final item = BoardColumnItem(
       row: row,
       fieldId: group.fieldId,
       requestFocus: true,
     );
-    controller.addColumnItem(group.groupId, item);
-    onNewColumnItem(group.groupId, row);
+
+    if (index != null) {
+      controller.insertColumnItem(group.groupId, index, item);
+    } else {
+      controller.addColumnItem(group.groupId, item);
+    }
+    onNewColumnItem(group.groupId, row, index);
   }
 }
 
 class BoardEditingRow {
   String columnId;
   RowPB row;
+  int? index;
 
   BoardEditingRow({
     required this.columnId,
     required this.row,
+    required this.index,
   });
 }

+ 3 - 2
frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart

@@ -119,8 +119,9 @@ class BoardDataController {
     );
   }
 
-  Future<Either<RowPB, FlowyError>> createBoardCard(String groupId) {
-    return _gridFFIService.createBoardCard(groupId);
+  Future<Either<RowPB, FlowyError>> createBoardCard(String groupId,
+      {String? startRowId}) {
+    return _gridFFIService.createBoardCard(groupId, startRowId);
   }
 
   Future<void> dispose() async {

+ 7 - 2
frontend/app_flowy/lib/plugins/board/application/group_controller.dart

@@ -9,7 +9,7 @@ abstract class GroupControllerDelegate {
   void removeRow(GroupPB group, String rowId);
   void insertRow(GroupPB group, RowPB row, int? index);
   void updateRow(GroupPB group, RowPB row);
-  void addNewRow(GroupPB group, RowPB row);
+  void addNewRow(GroupPB group, RowPB row, int? index);
 }
 
 class GroupController {
@@ -31,6 +31,11 @@ class GroupController {
     }
   }
 
+  RowPB? lastRow() {
+    if (group.rows.isEmpty) return null;
+    return group.rows.last;
+  }
+
   void startListening() {
     _listener.start(onGroupChanged: (result) {
       result.fold(
@@ -50,7 +55,7 @@ class GroupController {
             }
 
             if (insertedRow.isNew) {
-              delegate.addNewRow(group, insertedRow.row);
+              delegate.addNewRow(group, insertedRow.row, index);
             } else {
               delegate.insertRow(group, insertedRow.row, index);
             }

+ 35 - 19
frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

@@ -84,11 +84,14 @@ class _BoardContentState extends State<BoardContent> {
           () => null,
           (editingRow) {
             WidgetsBinding.instance.addPostFrameCallback((_) {
-              scrollManager.scrollToBottom(editingRow.columnId, () {
-                context
-                    .read<BoardBloc>()
-                    .add(BoardEvent.endEditRow(editingRow.row.id));
-              });
+              if (editingRow.index != null) {
+              } else {
+                scrollManager.scrollToBottom(editingRow.columnId, () {
+                  context
+                      .read<BoardBloc>()
+                      .add(BoardEvent.endEditRow(editingRow.row.id));
+                });
+              }
             });
           },
         );
@@ -131,26 +134,32 @@ class _BoardContentState extends State<BoardContent> {
   }
 
   Widget _buildHeader(
-      BuildContext context, AFBoardColumnHeaderData headerData) {
+    BuildContext context,
+    AFBoardColumnData columnData,
+  ) {
     return AppFlowyColumnHeader(
       title: Flexible(
         fit: FlexFit.tight,
         child: FlowyText.medium(
-          headerData.columnName,
+          columnData.headerData.columnName,
           fontSize: 14,
           overflow: TextOverflow.clip,
           color: context.read<AppTheme>().textColor,
         ),
       ),
-      // addIcon: const Icon(Icons.add, size: 20),
-      // moreIcon: SizedBox(
-      //   width: 20,
-      //   height: 20,
-      //   child: svgWidget(
-      //     'grid/details',
-      //     color: context.read<AppTheme>().iconColor,
-      //   ),
-      // ),
+      addIcon: SizedBox(
+        height: 20,
+        width: 20,
+        child: svgWidget(
+          "home/add",
+          color: context.read<AppTheme>().iconColor,
+        ),
+      ),
+      onAddButtonClick: () {
+        context.read<BoardBloc>().add(
+              BoardEvent.createHeaderRow(columnData.id),
+            );
+      },
       height: 50,
       margin: config.headerPadding,
     );
@@ -178,7 +187,9 @@ class _BoardContentState extends State<BoardContent> {
         height: 50,
         margin: config.footerPadding,
         onAddButtonClick: () {
-          context.read<BoardBloc>().add(BoardEvent.createRow(columnData.id));
+          context.read<BoardBloc>().add(
+                BoardEvent.createBottomRow(columnData.id),
+              );
         },
       );
     }
@@ -205,8 +216,13 @@ class _BoardContentState extends State<BoardContent> {
     );
 
     final cellBuilder = BoardCellBuilder(cardController);
-
-    final isEditing = context.read<BoardBloc>().state.editingRow.isSome();
+    bool isEditing = false;
+    context.read<BoardBloc>().state.editingRow.fold(
+      () => null,
+      (editingRow) {
+        isEditing = editingRow.row.id == columnItem.row.id;
+      },
+    );
 
     return AppFlowyColumnItemCard(
       key: ValueKey(columnItem.id),

+ 9 - 1
frontend/app_flowy/lib/plugins/grid/application/grid_service.dart

@@ -27,10 +27,18 @@ class GridFFIService {
     return GridEventCreateTableRow(payload).send();
   }
 
-  Future<Either<RowPB, FlowyError>> createBoardCard(String groupId) {
+  Future<Either<RowPB, FlowyError>> createBoardCard(
+    String groupId,
+    String? startRowId,
+  ) {
     CreateBoardCardPayloadPB payload = CreateBoardCardPayloadPB.create()
       ..gridId = gridId
       ..groupId = groupId;
+
+    if (startRowId != null) {
+      payload.startRowId = startRowId;
+    }
+
     return GridEventCreateBoardCard(payload).send();
   }
 

+ 3 - 3
frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart

@@ -73,17 +73,17 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
               margin: config.columnItemPadding,
             );
           },
-          headerBuilder: (context, headerData) {
+          headerBuilder: (context, columnData) {
             return AppFlowyColumnHeader(
               icon: const Icon(Icons.lightbulb_circle),
               title: SizedBox(
                 width: 60,
                 child: TextField(
                   controller: TextEditingController()
-                    ..text = headerData.columnName,
+                    ..text = columnData.headerData.columnName,
                   onSubmitted: (val) {
                     boardDataController
-                        .getColumnController(headerData.columnId)!
+                        .getColumnController(columnData.headerData.columnId)!
                         .updateColumnName(val);
                   },
                 ),

+ 4 - 2
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board.dart

@@ -282,14 +282,16 @@ class _AFBoardContentState extends State<AFBoardContent> {
   }
 
   Widget? _buildHeader(
-      BuildContext context, AFBoardColumnHeaderData headerData) {
+    BuildContext context,
+    AFBoardColumnData columnData,
+  ) {
     if (widget.headerBuilder == null) {
       return null;
     }
     return Selector<AFBoardColumnDataController, AFBoardColumnHeaderData>(
       selector: (context, controller) => controller.columnData.headerData,
       builder: (context, headerData, _) {
-        return widget.headerBuilder!(context, headerData)!;
+        return widget.headerBuilder!(context, columnData)!;
       },
     );
   }

+ 3 - 3
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart

@@ -31,7 +31,7 @@ typedef AFBoardColumnCardBuilder = Widget Function(
 
 typedef AFBoardColumnHeaderBuilder = Widget? Function(
   BuildContext context,
-  AFBoardColumnHeaderData headerData,
+  AFBoardColumnData headerData,
 );
 
 typedef AFBoardColumnFooterBuilder = Widget Function(
@@ -132,8 +132,8 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
             .map((item) => _buildWidget(context, item))
             .toList();
 
-        final header = widget.headerBuilder
-            ?.call(context, widget.dataSource.columnData.headerData);
+        final header =
+            widget.headerBuilder?.call(context, widget.dataSource.columnData);
 
         final footer =
             widget.footBuilder?.call(context, widget.dataSource.columnData);

+ 8 - 1
frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs

@@ -14,6 +14,9 @@ pub struct CreateBoardCardPayloadPB {
 
     #[pb(index = 2)]
     pub group_id: String,
+
+    #[pb(index = 3, one_of)]
+    pub start_row_id: Option<String>,
 }
 
 impl TryInto<CreateRowParams> for CreateBoardCardPayloadPB {
@@ -22,9 +25,13 @@ impl TryInto<CreateRowParams> for CreateBoardCardPayloadPB {
     fn try_into(self) -> Result<CreateRowParams, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
         let group_id = NotEmptyStr::parse(self.group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?;
+        let start_row_id = match self.start_row_id {
+            None => None,
+            Some(start_row_id) => Some(NotEmptyStr::parse(start_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?.0),
+        };
         Ok(CreateRowParams {
             grid_id: grid_id.0,
-            start_row_id: None,
+            start_row_id,
             group_id: Some(group_id.0),
             layout: GridLayout::Board,
         })

+ 5 - 1
frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs

@@ -95,9 +95,13 @@ impl GridViewRevisionEditor {
         match params.group_id.as_ref() {
             None => {}
             Some(group_id) => {
+                let index = match params.start_row_id {
+                    None => Some(0),
+                    Some(_) => None,
+                };
                 let inserted_row = InsertedRowPB {
                     row: row_pb.clone(),
-                    index: None,
+                    index,
                     is_new: true,
                 };
                 let changeset = GroupChangesetPB::insert(group_id.clone(), vec![inserted_row]);