Bläddra i källkod

chore: support link/number/multiselect/checkbox board cell

appflowy 2 år sedan
förälder
incheckning
2282aa948e
19 ändrade filer med 195 tillägg och 63 borttagningar
  1. 39 1
      frontend/app_flowy/lib/plugins/board/presentation/card/board_checkbox_cell.dart
  2. 5 8
      frontend/app_flowy/lib/plugins/board/presentation/card/board_date_cell.dart
  3. 5 8
      frontend/app_flowy/lib/plugins/board/presentation/card/board_number_cell.dart
  4. 3 6
      frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart
  5. 5 8
      frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart
  6. 44 1
      frontend/app_flowy/lib/plugins/board/presentation/card/board_url_cell.dart
  7. 9 3
      frontend/app_flowy/lib/plugins/board/presentation/card/card.dart
  8. 1 0
      frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart
  9. 1 1
      frontend/app_flowy/lib/plugins/grid/application/cell/checkbox_cell_bloc.dart
  10. 2 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart
  11. 2 2
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart
  12. 1 1
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board.dart
  13. 9 8
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart
  14. 5 5
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart
  15. 1 1
      frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart
  16. 4 4
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs
  17. 2 2
      frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs
  18. 54 0
      frontend/rust-lib/flowy-grid/src/util.rs
  19. 3 3
      frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs

+ 39 - 1
frontend/app_flowy/lib/plugins/board/presentation/card/board_checkbox_cell.dart

@@ -1,5 +1,9 @@
+import 'package:app_flowy/plugins/board/application/card/board_checkbox_cell_bloc.dart';
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
+import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 
 class BoardCheckboxCell extends StatefulWidget {
 class BoardCheckboxCell extends StatefulWidget {
   final GridCellControllerBuilder cellControllerBuilder;
   final GridCellControllerBuilder cellControllerBuilder;
@@ -14,8 +18,42 @@ class BoardCheckboxCell extends StatefulWidget {
 }
 }
 
 
 class _BoardCheckboxCellState extends State<BoardCheckboxCell> {
 class _BoardCheckboxCellState extends State<BoardCheckboxCell> {
+  late BoardCheckboxCellBloc _cellBloc;
+
+  @override
+  void initState() {
+    final cellController =
+        widget.cellControllerBuilder.build() as GridCheckboxCellController;
+    _cellBloc = BoardCheckboxCellBloc(cellController: cellController);
+    _cellBloc.add(const BoardCheckboxCellEvent.initial());
+    super.initState();
+  }
+
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return Container();
+    return BlocProvider.value(
+      value: _cellBloc,
+      child: BlocBuilder<BoardCheckboxCellBloc, BoardCheckboxCellState>(
+        builder: (context, state) {
+          final icon = state.isSelected
+              ? svgWidget('editor/editor_check')
+              : svgWidget('editor/editor_uncheck');
+          return Align(
+            alignment: Alignment.centerLeft,
+            child: FlowyIconButton(
+              iconPadding: EdgeInsets.zero,
+              icon: icon,
+              width: 20,
+            ),
+          );
+        },
+      ),
+    );
+  }
+
+  @override
+  Future<void> dispose() async {
+    _cellBloc.close();
+    super.dispose();
   }
   }
 }
 }

+ 5 - 8
frontend/app_flowy/lib/plugins/board/presentation/card/board_date_cell.dart

@@ -38,14 +38,11 @@ class _BoardDateCellState extends State<BoardDateCell> {
           if (state.dateStr.isEmpty) {
           if (state.dateStr.isEmpty) {
             return const SizedBox();
             return const SizedBox();
           } else {
           } else {
-            return Padding(
-              padding: const EdgeInsets.all(8.0),
-              child: Align(
-                alignment: Alignment.centerLeft,
-                child: FlowyText.regular(
-                  state.dateStr,
-                  fontSize: 14,
-                ),
+            return Align(
+              alignment: Alignment.centerLeft,
+              child: FlowyText.regular(
+                state.dateStr,
+                fontSize: 14,
               ),
               ),
             );
             );
           }
           }

+ 5 - 8
frontend/app_flowy/lib/plugins/board/presentation/card/board_number_cell.dart

@@ -38,14 +38,11 @@ class _BoardNumberCellState extends State<BoardNumberCell> {
           if (state.content.isEmpty) {
           if (state.content.isEmpty) {
             return const SizedBox();
             return const SizedBox();
           } else {
           } else {
-            return Padding(
-              padding: const EdgeInsets.all(8.0),
-              child: Align(
-                alignment: Alignment.centerLeft,
-                child: FlowyText.regular(
-                  state.content,
-                  fontSize: 14,
-                ),
+            return Align(
+              alignment: Alignment.centerLeft,
+              child: FlowyText.regular(
+                state.content,
+                fontSize: 14,
               ),
               ),
             );
             );
           }
           }

+ 3 - 6
frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart

@@ -40,12 +40,9 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
                     option: option,
                     option: option,
                   ))
                   ))
               .toList();
               .toList();
-          return Padding(
-            padding: const EdgeInsets.all(8.0),
-            child: Align(
-              alignment: Alignment.centerLeft,
-              child: Wrap(children: children, spacing: 4, runSpacing: 2),
-            ),
+          return Align(
+            alignment: Alignment.centerLeft,
+            child: Wrap(children: children, spacing: 4, runSpacing: 2),
           );
           );
         },
         },
       ),
       ),

+ 5 - 8
frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart

@@ -35,14 +35,11 @@ class _BoardTextCellState extends State<BoardTextCell> {
           if (state.content.isEmpty) {
           if (state.content.isEmpty) {
             return const SizedBox();
             return const SizedBox();
           } else {
           } else {
-            return Padding(
-              padding: const EdgeInsets.all(8.0),
-              child: Align(
-                alignment: Alignment.centerLeft,
-                child: FlowyText.regular(
-                  state.content,
-                  fontSize: 14,
-                ),
+            return Align(
+              alignment: Alignment.centerLeft,
+              child: FlowyText.regular(
+                state.content,
+                fontSize: 14,
               ),
               ),
             );
             );
           }
           }

+ 44 - 1
frontend/app_flowy/lib/plugins/board/presentation/card/board_url_cell.dart

@@ -1,5 +1,8 @@
+import 'package:app_flowy/plugins/board/application/card/board_url_cell_bloc.dart';
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
+import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 
 
 class BoardUrlCell extends StatefulWidget {
 class BoardUrlCell extends StatefulWidget {
   final GridCellControllerBuilder cellControllerBuilder;
   final GridCellControllerBuilder cellControllerBuilder;
@@ -14,8 +17,48 @@ class BoardUrlCell extends StatefulWidget {
 }
 }
 
 
 class _BoardUrlCellState extends State<BoardUrlCell> {
 class _BoardUrlCellState extends State<BoardUrlCell> {
+  late BoardURLCellBloc _cellBloc;
+
+  @override
+  void initState() {
+    final cellController =
+        widget.cellControllerBuilder.build() as GridURLCellController;
+    _cellBloc = BoardURLCellBloc(cellController: cellController);
+    _cellBloc.add(const BoardURLCellEvent.initial());
+    super.initState();
+  }
+
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return Container();
+    final theme = context.watch<AppTheme>();
+    return BlocProvider.value(
+      value: _cellBloc,
+      child: BlocBuilder<BoardURLCellBloc, BoardURLCellState>(
+        builder: (context, state) {
+          final richText = RichText(
+            textAlign: TextAlign.left,
+            text: TextSpan(
+              text: state.content,
+              style: TextStyle(
+                color: theme.main2,
+                fontSize: 14,
+                decoration: TextDecoration.underline,
+              ),
+            ),
+          );
+
+          return Align(
+            alignment: Alignment.centerLeft,
+            child: richText,
+          );
+        },
+      ),
+    );
+  }
+
+  @override
+  Future<void> dispose() async {
+    _cellBloc.close();
+    super.dispose();
   }
   }
 }
 }

+ 9 - 3
frontend/app_flowy/lib/plugins/board/presentation/card/card.dart

@@ -40,8 +40,11 @@ class _BoardCardState extends State<BoardCard> {
       value: _cardBloc,
       value: _cardBloc,
       child: BlocBuilder<BoardCardBloc, BoardCardState>(
       child: BlocBuilder<BoardCardBloc, BoardCardState>(
         builder: (context, state) {
         builder: (context, state) {
-          return Column(
-            children: _makeCells(context, state.gridCellMap),
+          return Padding(
+            padding: const EdgeInsets.all(8.0),
+            child: Column(
+              children: _makeCells(context, state.gridCellMap),
+            ),
           );
           );
         },
         },
       ),
       ),
@@ -53,7 +56,10 @@ class _BoardCardState extends State<BoardCard> {
       (cellId) {
       (cellId) {
         final child = widget.cellBuilder.buildCell(cellId);
         final child = widget.cellBuilder.buildCell(cellId);
 
 
-        return child;
+        return Padding(
+          padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
+          child: child,
+        );
       },
       },
     ).toList();
     ).toList();
   }
   }

+ 1 - 0
frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart

@@ -1,6 +1,7 @@
 part of 'cell_service.dart';
 part of 'cell_service.dart';
 
 
 typedef GridCellController = IGridCellController<String, String>;
 typedef GridCellController = IGridCellController<String, String>;
+typedef GridCheckboxCellController = IGridCellController<String, String>;
 typedef GridNumberCellController = IGridCellController<String, String>;
 typedef GridNumberCellController = IGridCellController<String, String>;
 typedef GridSelectOptionCellController
 typedef GridSelectOptionCellController
     = IGridCellController<SelectOptionCellDataPB, String>;
     = IGridCellController<SelectOptionCellDataPB, String>;

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/application/cell/checkbox_cell_bloc.dart

@@ -6,7 +6,7 @@ import 'cell_service/cell_service.dart';
 part 'checkbox_cell_bloc.freezed.dart';
 part 'checkbox_cell_bloc.freezed.dart';
 
 
 class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
 class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
-  final GridCellController cellController;
+  final GridCheckboxCellController cellController;
   void Function()? _onCellChangedFn;
   void Function()? _onCellChangedFn;
 
 
   CheckboxCellBloc({
   CheckboxCellBloc({

+ 2 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart

@@ -22,7 +22,8 @@ class _CheckboxCellState extends GridCellState<GridCheckboxCell> {
 
 
   @override
   @override
   void initState() {
   void initState() {
-    final cellController = widget.cellControllerBuilder.build();
+    final cellController =
+        widget.cellControllerBuilder.build() as GridCheckboxCellController;
     _cellBloc = getIt<CheckboxCellBloc>(param1: cellController)
     _cellBloc = getIt<CheckboxCellBloc>(param1: cellController)
       ..add(const CheckboxCellEvent.initial());
       ..add(const CheckboxCellEvent.initial());
     super.initState();
     super.initState();

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart

@@ -90,9 +90,9 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
 
 
   @override
   @override
   void initState() {
   void initState() {
-    final cellContext =
+    final cellController =
         widget.cellControllerBuilder.build() as GridURLCellController;
         widget.cellControllerBuilder.build() as GridURLCellController;
-    _cellBloc = URLCellBloc(cellController: cellContext);
+    _cellBloc = URLCellBloc(cellController: cellController);
     _cellBloc.add(const URLCellEvent.initial());
     _cellBloc.add(const URLCellEvent.initial());
     super.initState();
     super.initState();
   }
   }

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

@@ -202,7 +202,7 @@ class _BoardContentState extends State<BoardContent> {
         return ChangeNotifierProvider.value(
         return ChangeNotifierProvider.value(
           key: ValueKey(columnData.id),
           key: ValueKey(columnData.id),
           value: widget.dataController.columnController(columnData.id),
           value: widget.dataController.columnController(columnData.id),
-          child: Consumer<BoardColumnDataController>(
+          child: Consumer<AFBoardColumnDataController>(
             builder: (context, value, child) {
             builder: (context, value, child) {
               return ConstrainedBox(
               return ConstrainedBox(
                 constraints: widget.columnConstraints,
                 constraints: widget.columnConstraints,

+ 9 - 8
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart

@@ -12,7 +12,7 @@ abstract class AFColumnItem extends ReoderFlexItem {
   String toString() => id;
   String toString() => id;
 }
 }
 
 
-/// [BoardColumnDataController] is used to handle the [AFBoardColumnData].
+/// [AFBoardColumnDataController] is used to handle the [AFBoardColumnData].
 /// * Remove an item by calling [removeAt] method.
 /// * Remove an item by calling [removeAt] method.
 /// * Move item to another position by calling [move] method.
 /// * Move item to another position by calling [move] method.
 /// * Insert item to index by calling [insert] method
 /// * Insert item to index by calling [insert] method
@@ -20,10 +20,10 @@ abstract class AFColumnItem extends ReoderFlexItem {
 ///
 ///
 /// All there operations will notify listeners by default.
 /// All there operations will notify listeners by default.
 ///
 ///
-class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
+class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
   final AFBoardColumnData columnData;
   final AFBoardColumnData columnData;
 
 
-  BoardColumnDataController({
+  AFBoardColumnDataController({
     required this.columnData,
     required this.columnData,
   });
   });
 
 
@@ -42,7 +42,8 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
   AFColumnItem removeAt(int index, {bool notify = true}) {
   AFColumnItem removeAt(int index, {bool notify = true}) {
     assert(index >= 0);
     assert(index >= 0);
 
 
-    Log.debug('[$BoardColumnDataController] $columnData remove item at $index');
+    Log.debug(
+        '[$AFBoardColumnDataController] $columnData remove item at $index');
     final item = columnData._items.removeAt(index);
     final item = columnData._items.removeAt(index);
     if (notify) {
     if (notify) {
       notifyListeners();
       notifyListeners();
@@ -64,7 +65,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
       return false;
       return false;
     }
     }
     Log.debug(
     Log.debug(
-        '[$BoardColumnDataController] $columnData move item from $fromIndex to $toIndex');
+        '[$AFBoardColumnDataController] $columnData move item from $fromIndex to $toIndex');
     final item = columnData._items.removeAt(fromIndex);
     final item = columnData._items.removeAt(fromIndex);
     columnData._items.insert(toIndex, item);
     columnData._items.insert(toIndex, item);
     notifyListeners();
     notifyListeners();
@@ -78,7 +79,7 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
   bool insert(int index, AFColumnItem item, {bool notify = true}) {
   bool insert(int index, AFColumnItem item, {bool notify = true}) {
     assert(index >= 0);
     assert(index >= 0);
     Log.debug(
     Log.debug(
-        '[$BoardColumnDataController] $columnData insert $item at $index');
+        '[$AFBoardColumnDataController] $columnData insert $item at $index');
 
 
     if (columnData._items.length > index) {
     if (columnData._items.length > index) {
       columnData._items.insert(index, item);
       columnData._items.insert(index, item);
@@ -100,12 +101,12 @@ class BoardColumnDataController extends ChangeNotifier with EquatableMixin {
   void replace(int index, AFColumnItem newItem) {
   void replace(int index, AFColumnItem newItem) {
     if (columnData._items.isEmpty) {
     if (columnData._items.isEmpty) {
       columnData._items.add(newItem);
       columnData._items.add(newItem);
-      Log.debug('[$BoardColumnDataController] $columnData add $newItem');
+      Log.debug('[$AFBoardColumnDataController] $columnData add $newItem');
     } else {
     } else {
       final removedItem = columnData._items.removeAt(index);
       final removedItem = columnData._items.removeAt(index);
       columnData._items.insert(index, newItem);
       columnData._items.insert(index, newItem);
       Log.debug(
       Log.debug(
-          '[$BoardColumnDataController] $columnData replace $removedItem with $newItem at $index');
+          '[$AFBoardColumnDataController] $columnData replace $removedItem with $newItem at $index');
     }
     }
 
 
     notifyListeners();
     notifyListeners();

+ 5 - 5
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart

@@ -35,7 +35,7 @@ class AFBoardDataController extends ChangeNotifier
   List<String> get columnIds =>
   List<String> get columnIds =>
       _columnDatas.map((columnData) => columnData.id).toList();
       _columnDatas.map((columnData) => columnData.id).toList();
 
 
-  final LinkedHashMap<String, BoardColumnDataController> _columnControllers =
+  final LinkedHashMap<String, AFBoardColumnDataController> _columnControllers =
       LinkedHashMap();
       LinkedHashMap();
 
 
   AFBoardDataController({
   AFBoardDataController({
@@ -47,7 +47,7 @@ class AFBoardDataController extends ChangeNotifier
   void addColumn(AFBoardColumnData columnData, {bool notify = true}) {
   void addColumn(AFBoardColumnData columnData, {bool notify = true}) {
     if (_columnControllers[columnData.id] != null) return;
     if (_columnControllers[columnData.id] != null) return;
 
 
-    final controller = BoardColumnDataController(columnData: columnData);
+    final controller = AFBoardColumnDataController(columnData: columnData);
     _columnDatas.add(columnData);
     _columnDatas.add(columnData);
     _columnControllers[columnData.id] = controller;
     _columnControllers[columnData.id] = controller;
     if (notify) notifyListeners();
     if (notify) notifyListeners();
@@ -84,11 +84,11 @@ class AFBoardDataController extends ChangeNotifier
     if (columnIds.isNotEmpty && notify) notifyListeners();
     if (columnIds.isNotEmpty && notify) notifyListeners();
   }
   }
 
 
-  BoardColumnDataController columnController(String columnId) {
+  AFBoardColumnDataController columnController(String columnId) {
     return _columnControllers[columnId]!;
     return _columnControllers[columnId]!;
   }
   }
 
 
-  BoardColumnDataController? getColumnController(String columnId) {
+  AFBoardColumnDataController? getColumnController(String columnId) {
     final columnController = _columnControllers[columnId];
     final columnController = _columnControllers[columnId];
     if (columnController == null) {
     if (columnController == null) {
       Log.warn('Column:[$columnId] \'s controller is not exist');
       Log.warn('Column:[$columnId] \'s controller is not exist');
@@ -153,7 +153,7 @@ class AFBoardDataController extends ChangeNotifier
   }
   }
 
 
   @override
   @override
-  BoardColumnDataController? controller(String columnId) {
+  AFBoardColumnDataController? controller(String columnId) {
     return _columnControllers[columnId];
     return _columnControllers[columnId];
   }
   }
 
 

+ 1 - 1
frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart

@@ -7,7 +7,7 @@ import '../reorder_flex/drag_target_inteceptor.dart';
 import 'phantom_state.dart';
 import 'phantom_state.dart';
 
 
 abstract class BoardPhantomControllerDelegate {
 abstract class BoardPhantomControllerDelegate {
-  BoardColumnDataController? controller(String columnId);
+  AFBoardColumnDataController? controller(String columnId);
 
 
   bool removePhantom(String columnId);
   bool removePhantom(String columnId);
 
 

+ 4 - 4
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs

@@ -97,7 +97,7 @@ pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOptionPB);
 impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder);
 impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder);
 impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB);
 impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB);
 impl MultiSelectTypeOptionBuilder {
 impl MultiSelectTypeOptionBuilder {
-    pub fn option(mut self, opt: SelectOptionPB) -> Self {
+    pub fn add_option(mut self, opt: SelectOptionPB) -> Self {
         self.0.options.push(opt);
         self.0.options.push(opt);
         self
         self
     }
     }
@@ -127,9 +127,9 @@ mod tests {
         let facebook_option = SelectOptionPB::new("Facebook");
         let facebook_option = SelectOptionPB::new("Facebook");
         let twitter_option = SelectOptionPB::new("Twitter");
         let twitter_option = SelectOptionPB::new("Twitter");
         let multi_select = MultiSelectTypeOptionBuilder::default()
         let multi_select = MultiSelectTypeOptionBuilder::default()
-            .option(google_option.clone())
-            .option(facebook_option.clone())
-            .option(twitter_option);
+            .add_option(google_option.clone())
+            .add_option(facebook_option.clone())
+            .add_option(twitter_option);
 
 
         let field_rev = FieldBuilder::new(multi_select)
         let field_rev = FieldBuilder::new(multi_select)
             .name("Platform")
             .name("Platform")

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs

@@ -156,8 +156,8 @@ mod tests {
         let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
         let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
         let cell_data_changeset = SelectOptionCellChangeset::from_insert(&ids).to_str();
         let cell_data_changeset = SelectOptionCellChangeset::from_insert(&ids).to_str();
         let multi_select = MultiSelectTypeOptionBuilder::default()
         let multi_select = MultiSelectTypeOptionBuilder::default()
-            .option(google_option.clone())
-            .option(facebook_option.clone());
+            .add_option(google_option.clone())
+            .add_option(facebook_option.clone());
         let multi_select_field_rev = FieldBuilder::new(multi_select).build();
         let multi_select_field_rev = FieldBuilder::new(multi_select).build();
         let multi_type_option = MultiSelectTypeOptionPB::from(&multi_select_field_rev);
         let multi_type_option = MultiSelectTypeOptionPB::from(&multi_select_field_rev);
         let cell_data = multi_type_option
         let cell_data = multi_type_option

+ 54 - 0
frontend/rust-lib/flowy-grid/src/util.rs

@@ -69,12 +69,66 @@ pub fn make_default_board() -> BuildGridContext {
     let single_select_field_id = single_select_field.id.clone();
     let single_select_field_id = single_select_field.id.clone();
     grid_builder.add_field(single_select_field);
     grid_builder.add_field(single_select_field);
 
 
+    // MultiSelect
+    let apple_option = SelectOptionPB::new("Apple");
+    let banana_option = SelectOptionPB::new("Banana");
+    let pear_option = SelectOptionPB::new("Pear");
+    let multi_select_type_option = MultiSelectTypeOptionBuilder::default()
+        .add_option(banana_option.clone())
+        .add_option(apple_option.clone())
+        .add_option(pear_option.clone());
+    let multi_select_field = FieldBuilder::new(multi_select_type_option)
+        .name("Fruit")
+        .visibility(true)
+        .build();
+    let multi_select_field_id = multi_select_field.id.clone();
+    grid_builder.add_field(multi_select_field);
+
+    // Number
+    let number_type_option = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
+    let number_field = FieldBuilder::new(number_type_option)
+        .name("Price")
+        .visibility(true)
+        .build();
+    let number_field_id = number_field.id.clone();
+    grid_builder.add_field(number_field);
+
+    // Checkbox
+    let checkbox_type_option = CheckboxTypeOptionBuilder::default();
+    let checkbox_field = FieldBuilder::new(checkbox_type_option).name("Reimbursement").build();
+    let checkbox_field_id = checkbox_field.id.clone();
+    grid_builder.add_field(checkbox_field);
+
+    // Url
+    let url_type_option = URLTypeOptionBuilder::default();
+    let url_field = FieldBuilder::new(url_type_option).name("Shop Link").build();
+    let url_field_id = url_field.id.clone();
+    grid_builder.add_field(url_field);
+
     // Insert rows
     // Insert rows
     for i in 0..10 {
     for i in 0..10 {
+        // insert single select
         let mut row_builder = RowRevisionBuilder::new(grid_builder.block_id(), grid_builder.field_revs());
         let mut row_builder = RowRevisionBuilder::new(grid_builder.block_id(), grid_builder.field_revs());
         row_builder.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone());
         row_builder.insert_select_option_cell(&single_select_field_id, not_started_option.id.clone());
+        // insert multi select
+        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_cell(&text_field_id, format!("Card {}", i));
+        // insert date
         row_builder.insert_date_cell(&date_field_id, timestamp);
         row_builder.insert_date_cell(&date_field_id, timestamp);
+        // number
+        row_builder.insert_cell(&number_field_id, format!("{}", 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);
+        // url
+        row_builder.insert_cell(&url_field_id, "https://appflowy.io".to_string());
+
         let row = row_builder.build();
         let row = row_builder.build();
         grid_builder.add_row(row);
         grid_builder.add_row(row);
     }
     }

+ 3 - 3
frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs

@@ -147,9 +147,9 @@ fn make_test_grid() -> BuildGridContext {
             FieldType::MultiSelect => {
             FieldType::MultiSelect => {
                 // MultiSelect
                 // MultiSelect
                 let multi_select = MultiSelectTypeOptionBuilder::default()
                 let multi_select = MultiSelectTypeOptionBuilder::default()
-                    .option(SelectOptionPB::new(GOOGLE))
-                    .option(SelectOptionPB::new(FACEBOOK))
-                    .option(SelectOptionPB::new(TWITTER));
+                    .add_option(SelectOptionPB::new(GOOGLE))
+                    .add_option(SelectOptionPB::new(FACEBOOK))
+                    .add_option(SelectOptionPB::new(TWITTER));
                 let multi_select_field = FieldBuilder::new(multi_select)
                 let multi_select_field = FieldBuilder::new(multi_select)
                     .name("Platform")
                     .name("Platform")
                     .visibility(true)
                     .visibility(true)