diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 09aa4a2378..64f34ac1ca 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -265,6 +265,9 @@ "panelTitle": "Select an option or create one", "searchOption": "Search for an option" }, + "checklist": { + "panelTitle": "Search an option or create one" + }, "menuName": "Grid" }, "document": { 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 0a40c0dd8b..0d736975ed 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -358,7 +358,7 @@ Widget? _buildHeaderIcon(GroupData customData) { break; case FieldType.URL: break; - case FieldType.CheckList: + case FieldType.Checklist: break; } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card_cell_builder.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/card_cell_builder.dart index 2118efdb87..4e7c2daa8d 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card_cell_builder.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card_cell_builder.dart @@ -59,7 +59,7 @@ class BoardCellBuilder { editableNotifier: cellNotifier, key: key, ); - case FieldType.CheckList: + case FieldType.Checklist: return BoardChecklistCell( key: key, ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart index 7935d1e630..a947ec327f 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart @@ -5,6 +5,8 @@ typedef GridCheckboxCellController = IGridCellController; typedef GridNumberCellController = IGridCellController; typedef GridSelectOptionCellController = IGridCellController; +typedef GridChecklistCellController + = IGridCellController; typedef GridDateCellController = IGridCellController; typedef GridURLCellController = IGridCellController; @@ -81,7 +83,7 @@ class GridCellControllerBuilder { ); case FieldType.MultiSelect: case FieldType.SingleSelect: - case FieldType.CheckList: + case FieldType.Checklist: final cellDataLoader = GridCellDataLoader( cellId: _cellId, parser: SelectOptionCellDataParser(), diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/checklist_cell_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/checklist_cell_bloc.dart new file mode 100644 index 0000000000..02a212ced6 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/checklist_cell_bloc.dart @@ -0,0 +1,93 @@ +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'cell_service/cell_service.dart'; +import 'select_option_service.dart'; +part 'checklist_cell_bloc.freezed.dart'; + +class ChecklistCellBloc extends Bloc { + final GridChecklistCellController cellController; + final SelectOptionFFIService _selectOptionService; + void Function()? _onCellChangedFn; + ChecklistCellBloc({ + required this.cellController, + }) : _selectOptionService = + SelectOptionFFIService(cellId: cellController.cellId), + super(ChecklistCellState.initial(cellController)) { + on( + (event, emit) async { + await event.when( + initial: () async { + _startListening(); + _loadOptions(); + }, + didReceiveOptions: (data) { + emit(state.copyWith( + allOptions: data.options, + selectedOptions: data.selectOptions, + percent: data.selectOptions.length.toDouble() / + data.options.length.toDouble(), + )); + }, + ); + }, + ); + } + + @override + Future close() async { + if (_onCellChangedFn != null) { + cellController.removeListener(_onCellChangedFn!); + _onCellChangedFn = null; + } + await cellController.dispose(); + return super.close(); + } + + void _startListening() { + _onCellChangedFn = cellController.startListening( + onCellFieldChanged: () { + _loadOptions(); + }, + onCellChanged: (_) {}, + ); + } + + void _loadOptions() { + _selectOptionService.getOptionContext().then((result) { + if (isClosed) return; + + return result.fold( + (data) => add(ChecklistCellEvent.didReceiveOptions(data)), + (err) => Log.error(err), + ); + }); + } +} + +@freezed +class ChecklistCellEvent with _$ChecklistCellEvent { + const factory ChecklistCellEvent.initial() = _InitialCell; + const factory ChecklistCellEvent.didReceiveOptions( + SelectOptionCellDataPB data) = _DidReceiveCellUpdate; +} + +@freezed +class ChecklistCellState with _$ChecklistCellState { + const factory ChecklistCellState({ + required List allOptions, + required List selectedOptions, + required double percent, + }) = _ChecklistCellState; + + factory ChecklistCellState.initial( + GridChecklistCellController cellController) { + return const ChecklistCellState( + allOptions: [], + selectedOptions: [], + percent: 0, + ); + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/checklist_cell_editor_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/checklist_cell_editor_bloc.dart new file mode 100644 index 0000000000..f0eb3b50b7 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/checklist_cell_editor_bloc.dart @@ -0,0 +1,194 @@ +import 'dart:async'; + +import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'select_option_service.dart'; + +part 'checklist_cell_editor_bloc.freezed.dart'; + +class ChecklistCellEditorBloc + extends Bloc { + final SelectOptionFFIService _selectOptionService; + final GridChecklistCellController cellController; + Timer? _delayOperation; + + ChecklistCellEditorBloc({ + required this.cellController, + }) : _selectOptionService = + SelectOptionFFIService(cellId: cellController.cellId), + super(ChecklistCellEditorState.initial(cellController)) { + on( + (event, emit) async { + await event.when( + initial: () async { + _startListening(); + _loadOptions(); + }, + didReceiveOptions: (data) { + emit(state.copyWith( + allOptions: _makeChecklistSelectOptions(data, state.predicate), + percent: _percentFromSelectOptionCellData(data), + )); + }, + newOption: (optionName) { + _createOption(optionName); + emit(state.copyWith( + predicate: '', + )); + }, + deleteOption: (option) { + _deleteOption([option]); + }, + updateOption: (option) { + _updateOption(option); + }, + selectOption: (optionId) { + _selectOptionService.select(optionIds: [optionId]); + }, + unSelectOption: (optionId) { + _selectOptionService.unSelect(optionIds: [optionId]); + }, + filterOption: (String predicate) {}, + ); + }, + ); + } + + @override + Future close() async { + _delayOperation?.cancel(); + await cellController.dispose(); + return super.close(); + } + + void _createOption(String name) async { + final result = await _selectOptionService.create( + name: name, + isSelected: false, + ); + result.fold((l) => {}, (err) => Log.error(err)); + } + + void _deleteOption(List options) async { + final result = await _selectOptionService.delete(options: options); + result.fold((l) => null, (err) => Log.error(err)); + } + + void _updateOption(SelectOptionPB option) async { + final result = await _selectOptionService.update( + option: option, + ); + + result.fold((l) => null, (err) => Log.error(err)); + } + + void _loadOptions() { + _selectOptionService.getOptionContext().then((result) { + if (isClosed) return; + + return result.fold( + (data) => add(ChecklistCellEditorEvent.didReceiveOptions(data)), + (err) => Log.error(err), + ); + }); + } + + void _startListening() { + cellController.startListening( + onCellChanged: ((data) { + if (!isClosed && data != null) { + add(ChecklistCellEditorEvent.didReceiveOptions(data)); + } + }), + onCellFieldChanged: () { + _loadOptions(); + }, + ); + } +} + +@freezed +class ChecklistCellEditorEvent with _$ChecklistCellEditorEvent { + const factory ChecklistCellEditorEvent.initial() = _Initial; + const factory ChecklistCellEditorEvent.didReceiveOptions( + SelectOptionCellDataPB data) = _DidReceiveOptions; + const factory ChecklistCellEditorEvent.newOption(String optionName) = + _NewOption; + const factory ChecklistCellEditorEvent.selectOption(String optionId) = + _SelectOption; + const factory ChecklistCellEditorEvent.unSelectOption(String optionId) = + _UnSelectOption; + const factory ChecklistCellEditorEvent.updateOption(SelectOptionPB option) = + _UpdateOption; + const factory ChecklistCellEditorEvent.deleteOption(SelectOptionPB option) = + _DeleteOption; + const factory ChecklistCellEditorEvent.filterOption(String predicate) = + _FilterOption; +} + +@freezed +class ChecklistCellEditorState with _$ChecklistCellEditorState { + const factory ChecklistCellEditorState({ + required List allOptions, + required Option createOption, + required double percent, + required String predicate, + }) = _ChecklistCellEditorState; + + factory ChecklistCellEditorState.initial( + GridSelectOptionCellController context) { + final data = context.getCellData(loadIfNotExist: true); + + return ChecklistCellEditorState( + allOptions: _makeChecklistSelectOptions(data, ''), + createOption: none(), + percent: _percentFromSelectOptionCellData(data), + predicate: '', + ); + } +} + +double _percentFromSelectOptionCellData(SelectOptionCellDataPB? data) { + if (data == null) return 0; + + final a = data.selectOptions.length.toDouble(); + final b = data.options.length.toDouble(); + + if (a > b) return 1.0; + + return a / b; +} + +List _makeChecklistSelectOptions( + SelectOptionCellDataPB? data, String predicate) { + if (data == null) { + return []; + } + + final List options = []; + final List allOptions = List.from(data.options); + if (predicate.isNotEmpty) { + allOptions.retainWhere((element) => element.name.contains(predicate)); + } + final selectedOptionIds = data.selectOptions.map((e) => e.id).toList(); + + for (final option in allOptions) { + options.add( + ChecklistSelectOption(selectedOptionIds.contains(option.id), option), + ); + } + + return options; +} + +class ChecklistSelectOption { + final bool isSelected; + final SelectOptionPB data; + + ChecklistSelectOption(this.isSelected, this.data); +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart index 9c3eb9cf23..1b60c0057d 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_editor_bloc.dart @@ -1,26 +1,24 @@ import 'dart:async'; - import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; - import 'select_option_service.dart'; part 'select_option_editor_bloc.freezed.dart'; class SelectOptionCellEditorBloc extends Bloc { - final SelectOptionService _selectOptionService; + final SelectOptionFFIService _selectOptionService; final GridSelectOptionCellController cellController; Timer? _delayOperation; SelectOptionCellEditorBloc({ required this.cellController, }) : _selectOptionService = - SelectOptionService(cellId: cellController.cellId), + SelectOptionFFIService(cellId: cellController.cellId), super(SelectOptionEditorState.initial(cellController)) { on( (event, emit) async { diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart index a179ccab30..5f8639967a 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart @@ -6,15 +6,16 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'cell_service/cell_service.dart'; -class SelectOptionService { +class SelectOptionFFIService { final GridCellIdentifier cellId; - SelectOptionService({required this.cellId}); + SelectOptionFFIService({required this.cellId}); String get gridId => cellId.gridId; String get fieldId => cellId.fieldInfo.id; String get rowId => cellId.rowId; - Future> create({required String name}) { + Future> create( + {required String name, bool isSelected = true}) { return TypeOptionFFIService(gridId: gridId, fieldId: fieldId) .newOption(name: name) .then( @@ -26,8 +27,13 @@ class SelectOptionService { ..fieldId = fieldId ..rowId = rowId; final payload = SelectOptionChangesetPB.create() - ..insertOptions.add(option) ..cellIdentifier = cellIdentifier; + + if (isSelected) { + payload.insertOptions.add(option); + } else { + payload.updateOptions.add(option); + } return GridEventUpdateSelectOption(payload).send(); }, (r) => right(r), diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart index e38eb49038..ffe50ffa72 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart @@ -503,7 +503,7 @@ class FieldInfo { bool get hasFilter => _hasFilter; - bool get canGroup { + bool get canBeGroup { switch (_field.fieldType) { case FieldType.Checkbox: case FieldType.MultiSelect: diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_create_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_create_bloc.dart index 7693a49321..4b5bb56f32 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_create_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_create_bloc.dart @@ -105,7 +105,7 @@ class GridCreateFilterBloc condition: SelectOptionCondition.OptionIs, fieldType: FieldType.MultiSelect, ); - case FieldType.CheckList: + case FieldType.Checklist: return _ffiService.insertChecklistFilter( fieldId: fieldId, condition: ChecklistFilterCondition.IsIncomplete, diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart index f57fef31ef..f30a9dc263 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart @@ -152,14 +152,12 @@ class FilterFFIService { String? filterId, List optionIds = const [], }) { - final filter = ChecklistFilterPB() - ..condition = condition - ..optionIds.addAll(optionIds); + final filter = ChecklistFilterPB()..condition = condition; return insertFilter( fieldId: fieldId, filterId: filterId, - fieldType: FieldType.CheckList, + fieldType: FieldType.Checklist, data: filter.writeToBuffer(), ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart index 887470bdbd..75ab94cad1 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'cell_accessory.dart'; import 'cell_shortcuts.dart'; import 'checkbox_cell.dart'; -import 'checklist_cell.dart'; +import 'checklist_cell/checklist_cell.dart'; import 'date_cell/date_cell.dart'; import 'number_cell.dart'; import 'select_option_cell/select_option_cell.dart'; @@ -56,8 +56,9 @@ class GridCellBuilder { style: style, key: key, ); - case FieldType.CheckList: + case FieldType.Checklist: return GridChecklistCell( + cellControllerBuilder: cellControllerBuilder, key: key, ); case FieldType.Number: diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell.dart deleted file mode 100644 index 6499789636..0000000000 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'cell_builder.dart'; - -class GridChecklistCell extends GridCellWidget { - GridChecklistCell({Key? key}) : super(key: key); - - @override - ChecklistCellState createState() => ChecklistCellState(); -} - -class ChecklistCellState extends State { - @override - Widget build(BuildContext context) { - return Container(); - } -} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell.dart new file mode 100644 index 0000000000..213aaef90e --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell.dart @@ -0,0 +1,91 @@ +import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_bloc.dart'; +import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import '../cell_builder.dart'; +import 'checklist_cell_editor.dart'; +import 'checklist_prograss_bar.dart'; + +class GridChecklistCell extends GridCellWidget { + final GridCellControllerBuilder cellControllerBuilder; + GridChecklistCell({required this.cellControllerBuilder, Key? key}) + : super(key: key); + + @override + GridChecklistCellState createState() => GridChecklistCellState(); +} + +class GridChecklistCellState extends State { + late PopoverController _popover; + late ChecklistCellBloc _cellBloc; + + @override + void initState() { + _popover = PopoverController(); + final cellController = + widget.cellControllerBuilder.build() as GridChecklistCellController; + _cellBloc = ChecklistCellBloc(cellController: cellController); + _cellBloc.add(const ChecklistCellEvent.initial()); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BlocProvider.value( + value: _cellBloc, + child: BlocBuilder( + builder: (context, state) { + return Stack( + alignment: AlignmentDirectional.center, + fit: StackFit.expand, + children: [ + Padding( + padding: GridSize.cellContentInsets, + child: _wrapPopover(const ChecklistProgressBar()), + ), + InkWell(onTap: () => _popover.show()), + ], + ); + }, + ), + ); + } + + Widget _wrapPopover(Widget child) { + return AppFlowyPopover( + controller: _popover, + constraints: BoxConstraints.loose(const Size(260, 400)), + direction: PopoverDirection.bottomWithLeftAligned, + triggerActions: PopoverTriggerFlags.none, + popupBuilder: (BuildContext context) { + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.onCellEditing.value = true; + }); + return GridChecklistCellEditor( + cellController: widget.cellControllerBuilder.build() + as GridChecklistCellController, + ); + }, + onClose: () => widget.onCellEditing.value = false, + child: child, + ); + } +} + +class ChecklistProgressBar extends StatelessWidget { + const ChecklistProgressBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return ChecklistPrograssBar( + percent: state.percent, + ); + }, + ); + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell_editor.dart new file mode 100644 index 0000000000..f3cb2fc4fb --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_cell_editor.dart @@ -0,0 +1,81 @@ +import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_editor_bloc.dart'; +import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; +import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_prograss_bar.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class GridChecklistCellEditor extends StatefulWidget { + final GridChecklistCellController cellController; + const GridChecklistCellEditor({required this.cellController, Key? key}) + : super(key: key); + + @override + State createState() => + _GridChecklistCellEditorState(); +} + +class _GridChecklistCellEditorState extends State { + late ChecklistCellEditorBloc bloc; + + @override + void initState() { + bloc = ChecklistCellEditorBloc(cellController: widget.cellController); + bloc.add(const ChecklistCellEditorEvent.initial()); + super.initState(); + } + + @override + void dispose() { + bloc.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocProvider.value( + value: bloc, + child: BlocBuilder( + builder: (context, state) { + final List slivers = [ + const SliverChecklistPrograssBar(), + SliverToBoxAdapter( + child: ListView.separated( + controller: ScrollController(), + shrinkWrap: true, + itemCount: state.allOptions.length, + itemBuilder: (BuildContext context, int index) { + return _ChecklistOptionCell(option: state.allOptions[index]); + }, + separatorBuilder: (BuildContext context, int index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + ), + ), + ]; + return CustomScrollView( + shrinkWrap: true, + slivers: slivers, + controller: ScrollController(), + physics: StyledScrollPhysics(), + ); + }, + ), + ); + } +} + +class _ChecklistOptionCell extends StatelessWidget { + final ChecklistSelectOption option; + const _ChecklistOptionCell({ + required this.option, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(height: 20, width: 100, color: Colors.red); + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_prograss_bar.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_prograss_bar.dart new file mode 100644 index 0000000000..bbb097309c --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_prograss_bar.dart @@ -0,0 +1,89 @@ +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_editor_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/color_extension.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:percent_indicator/percent_indicator.dart'; + +class ChecklistPrograssBar extends StatelessWidget { + final double percent; + const ChecklistPrograssBar({required this.percent, Key? key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return LinearPercentIndicator( + lineHeight: 10.0, + percent: percent, + progressColor: Theme.of(context).colorScheme.primary, + backgroundColor: AFThemeExtension.of(context).tint9, + barRadius: const Radius.circular(5), + ); + } +} + +class SliverChecklistPrograssBar extends StatelessWidget { + const SliverChecklistPrograssBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SliverPersistentHeader( + pinned: true, + delegate: _SliverChecklistPrograssBarDelegate(), + ); + } +} + +class _SliverChecklistPrograssBarDelegate + extends SliverPersistentHeaderDelegate { + _SliverChecklistPrograssBarDelegate(); + + double fixHeight = 80; + + @override + Widget build( + BuildContext context, double shrinkOffset, bool overlapsContent) { + return BlocBuilder( + builder: (context, state) { + return Column( + children: [ + if (state.percent != 0) + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: ChecklistPrograssBar(percent: state.percent), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: FlowyTextField( + hintText: LocaleKeys.grid_checklist_panelTitle.tr(), + onChanged: (text) { + context + .read() + .add(ChecklistCellEditorEvent.filterOption(text)); + }, + onSubmitted: (text) { + context + .read() + .add(ChecklistCellEditorEvent.newOption(text)); + }, + ), + ) + ], + ); + }, + ); + } + + @override + double get maxExtent => fixHeight; + + @override + double get minExtent => fixHeight; + + @override + bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { + return false; + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart index bfe9ffd65c..43fdcd647c 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart @@ -1,5 +1,4 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart index 99920837d5..37bd8668de 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart @@ -11,7 +11,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/log.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart index 7927002d73..bf4966dd51 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart @@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; // ignore: unused_import import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart index 1d244c85a3..36b114a350 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart @@ -9,7 +9,6 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/checkbox.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/checkbox.dart index 00f43fc01e..6f8edaa656 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/checkbox.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/checkbox.dart @@ -8,7 +8,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart index da78dcd09b..472abf7d8a 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart @@ -4,7 +4,6 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.d import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/text.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/text.dart index 8da46df633..1f591ef421 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/text.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/choicechip/text.dart @@ -3,13 +3,11 @@ import 'package:app_flowy/plugins/grid/application/filter/text_filter_editor_blo import 'package:app_flowy/plugins/grid/presentation/widgets/filter/condition_button.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/filter/disclosure_button.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart'; -import 'package:app_flowy/plugins/grid/presentation/widgets/filter/text_field.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; import 'package:flutter/material.dart'; @@ -151,7 +149,7 @@ class _TextFilterEditorState extends State { Widget _buildFilterTextField( BuildContext context, TextFilterEditorState state) { - return FilterTextField( + return FlowyTextField( text: state.filter.content, hintText: LocaleKeys.grid_settings_typeAValue.tr(), autoFucous: false, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/create_filter_list.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/create_filter_list.dart index 4a424ddb92..20fd1b4cca 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/create_filter_list.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/create_filter_list.dart @@ -2,13 +2,13 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/filter/filter_create_bloc.dart'; import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; -import 'package:app_flowy/plugins/grid/presentation/widgets/filter/text_field.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/style_widget/text_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -121,7 +121,7 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate { child: Container( color: Theme.of(context).colorScheme.background, height: fixHeight, - child: FilterTextField( + child: FlowyTextField( hintText: LocaleKeys.grid_settings_filterBy.tr(), onChanged: (text) { context diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu.dart index 1b12e6f862..54938a19f7 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu.dart @@ -7,7 +7,6 @@ import 'package:flowy_infra/color_extension.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu_item.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu_item.dart index 3c733443ab..062fc21cbd 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu_item.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/menu_item.dart @@ -36,7 +36,7 @@ Widget buildFilterChoicechip(FilterInfo filterInfo) { return SelectOptionFilterChoicechip(filterInfo: filterInfo); case FieldType.URL: return URLFilterChoicechip(filterInfo: filterInfo); - case FieldType.CheckList: + case FieldType.Checklist: return ChecklistFilterChoicechip(filterInfo: filterInfo); default: return const SizedBox(); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index 09d72aaba0..a0d2ed1092 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -6,7 +6,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_extension.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_extension.dart index afc7f1c74f..2c1a616d13 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_extension.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_extension.dart @@ -19,7 +19,7 @@ extension FieldTypeListExtension on FieldType { return "grid/field/single_select"; case FieldType.URL: return "grid/field/url"; - case FieldType.CheckList: + case FieldType.Checklist: return "grid/field/checklist"; } throw UnimplementedError; @@ -41,7 +41,7 @@ extension FieldTypeListExtension on FieldType { return LocaleKeys.grid_field_singleSelectFieldName.tr(); case FieldType.URL: return LocaleKeys.grid_field_urlFieldName.tr(); - case FieldType.CheckList: + case FieldType.Checklist: return LocaleKeys.grid_field_checklistFieldName.tr(); } throw UnimplementedError; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart index 55d495f0ec..5c69644f3e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart @@ -3,7 +3,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart index 8476a41e6f..2354b8ba7b 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart @@ -5,7 +5,6 @@ import 'package:dartz/dartz.dart' show Either; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart index 72870c2373..76de39b228 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart @@ -9,7 +9,6 @@ import 'package:flowy_infra/color_extension.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index d20658bbd2..0e2f45d9be 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -5,10 +5,10 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checklist_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart'; @@ -127,7 +127,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({ ), ); - case FieldType.CheckList: + case FieldType.Checklist: return ChecklistTypeOptionWidgetBuilder( makeTypeOptionContextWithDataController( gridId: gridId, @@ -217,7 +217,7 @@ TypeOptionContext dataController: dataController, dataParser: MultiSelectTypeOptionWidgetDataParser(), ) as TypeOptionContext; - case FieldType.CheckList: + case FieldType.Checklist: return ChecklistTypeOptionContext( dataController: dataController, dataParser: ChecklistTypeOptionWidgetDataParser(), diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart index 37ca30c412..92ab58e11b 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart @@ -7,7 +7,6 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart index 8fc17ee548..00be72ee50 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart @@ -5,7 +5,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart index fb3cb995cb..f78a3bc5a4 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart @@ -3,7 +3,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index 25011110a2..fc090eb914 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -9,7 +9,6 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; @@ -331,7 +330,7 @@ GridCellStyle? _customCellStyle(FieldType fieldType) { return SelectOptionCellStyle( placeholder: LocaleKeys.grid_row_textPlaceholder.tr(), ); - case FieldType.CheckList: + case FieldType.Checklist: return SelectOptionCellStyle( placeholder: LocaleKeys.grid_row_textPlaceholder.tr(), ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart index 472e9fa05c..1124175363 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart @@ -37,7 +37,7 @@ class GridGroupList extends StatelessWidget { key: ValueKey(fieldInfo.id), ); - if (!fieldInfo.canGroup) { + if (!fieldInfo.canBeGroup) { cell = IgnorePointer(child: Opacity(opacity: 0.3, child: cell)); } return cell; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index 01d5c20dcf..0cc07179b4 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -8,7 +8,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/settings/settings_dialog.dart b/frontend/app_flowy/lib/workspace/presentation/settings/settings_dialog.dart index bd987017cc..11c2956764 100644 --- a/frontend/app_flowy/lib/workspace/presentation/settings/settings_dialog.dart +++ b/frontend/app_flowy/lib/workspace/presentation/settings/settings_dialog.dart @@ -6,7 +6,6 @@ import 'package:app_flowy/workspace/presentation/settings/widgets/settings_user_ import 'package:app_flowy/workspace/presentation/settings/widgets/settings_menu.dart'; import 'package:app_flowy/workspace/application/settings/settings_dialog_bloc.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart index a2ce989b9d..f7c48fdaaa 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart @@ -1,7 +1,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:styled_widget/styled_widget.dart'; diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart index fa20e57294..3cf675207b 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart @@ -10,3 +10,5 @@ export 'src/flowy_overlay/list_overlay.dart'; export 'src/flowy_overlay/option_overlay.dart'; export 'src/flowy_overlay/flowy_dialog.dart'; export 'src/flowy_overlay/appflowy_popover.dart'; +export 'style_widget/text.dart'; +export 'style_widget/text_field.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/text_field.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text_field.dart similarity index 89% rename from frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/text_field.dart rename to frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text_field.dart index a76b7209b8..50f21bfbce 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/filter/text_field.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text_field.dart @@ -1,13 +1,13 @@ import 'package:flowy_infra/size.dart'; import 'package:flutter/material.dart'; -class FilterTextField extends StatefulWidget { +class FlowyTextField extends StatefulWidget { final String hintText; final String text; final void Function(String)? onChanged; final void Function(String)? onSubmitted; final bool autoFucous; - const FilterTextField({ + const FlowyTextField({ this.hintText = "", this.text = "", this.onChanged, @@ -17,10 +17,10 @@ class FilterTextField extends StatefulWidget { }) : super(key: key); @override - State createState() => FilterTextFieldState(); + State createState() => FlowyTextFieldState(); } -class FilterTextFieldState extends State { +class FlowyTextFieldState extends State { late FocusNode focusNode; late TextEditingController controller; diff --git a/frontend/app_flowy/pubspec.lock b/frontend/app_flowy/pubspec.lock index 1ea678f95c..9ccd2d3076 100644 --- a/frontend/app_flowy/pubspec.lock +++ b/frontend/app_flowy/pubspec.lock @@ -862,6 +862,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.6" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.2" petitparser: dependency: transitive description: diff --git a/frontend/app_flowy/pubspec.yaml b/frontend/app_flowy/pubspec.yaml index f2147d5777..2cdf5ca3f0 100644 --- a/frontend/app_flowy/pubspec.yaml +++ b/frontend/app_flowy/pubspec.yaml @@ -90,6 +90,7 @@ dependencies: shared_preferences: ^2.0.15 google_fonts: ^3.0.1 file_picker: <=5.0.0 + percent_indicator: ^4.0.1 dev_dependencies: flutter_lints: ^2.0.1 diff --git a/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs index c0127aa89c..ea432586b7 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs @@ -491,7 +491,7 @@ pub enum FieldType { MultiSelect = 4, Checkbox = 5, URL = 6, - CheckList = 7, + Checklist = 7, } pub const RICH_TEXT_FIELD: FieldType = FieldType::RichText; @@ -501,7 +501,7 @@ pub const SINGLE_SELECT_FIELD: FieldType = FieldType::SingleSelect; pub const MULTI_SELECT_FIELD: FieldType = FieldType::MultiSelect; pub const CHECKBOX_FIELD: FieldType = FieldType::Checkbox; pub const URL_FIELD: FieldType = FieldType::URL; -pub const CHECKLIST_FIELD: FieldType = FieldType::CheckList; +pub const CHECKLIST_FIELD: FieldType = FieldType::Checklist; impl std::default::Default for FieldType { fn default() -> Self { @@ -602,7 +602,7 @@ impl std::convert::From for FieldType { 4 => FieldType::MultiSelect, 5 => FieldType::Checkbox, 6 => FieldType::URL, - 7 => FieldType::CheckList, + 7 => FieldType::Checklist, _ => { tracing::error!("Can't convert FieldTypeRevision: {} to FieldType", ty); FieldType::RichText diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checklist_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checklist_filter.rs index 59c5ad885a..a697ebbe11 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checklist_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checklist_filter.rs @@ -1,4 +1,3 @@ -use crate::services::field::SelectOptionIds; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; use grid_rev_model::FilterRevision; @@ -7,9 +6,6 @@ use grid_rev_model::FilterRevision; pub struct ChecklistFilterPB { #[pb(index = 1)] pub condition: ChecklistFilterCondition, - - #[pb(index = 2)] - pub option_ids: Vec, } #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)] @@ -45,11 +41,9 @@ impl std::convert::TryFrom for ChecklistFilterCondition { impl std::convert::From<&FilterRevision> for ChecklistFilterPB { fn from(rev: &FilterRevision) -> Self { - let ids = SelectOptionIds::from(rev.content.clone()); ChecklistFilterPB { condition: ChecklistFilterCondition::try_from(rev.condition) .unwrap_or(ChecklistFilterCondition::IsIncomplete), - option_ids: ids.into_inner(), } } } diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs index d553fefd45..57c8db310e 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs @@ -36,7 +36,7 @@ impl std::convert::From<&FilterRevision> for FilterPB { FieldType::DateTime => DateFilterPB::from(rev).try_into().unwrap(), FieldType::SingleSelect => SelectOptionFilterPB::from(rev).try_into().unwrap(), FieldType::MultiSelect => SelectOptionFilterPB::from(rev).try_into().unwrap(), - FieldType::CheckList => ChecklistFilterPB::from(rev).try_into().unwrap(), + FieldType::Checklist => ChecklistFilterPB::from(rev).try_into().unwrap(), FieldType::Checkbox => CheckboxFilterPB::from(rev).try_into().unwrap(), FieldType::URL => TextFilterPB::from(rev).try_into().unwrap(), }; @@ -176,7 +176,7 @@ impl TryInto for AlterFilterPayloadPB { } .to_string(); } - FieldType::SingleSelect | FieldType::MultiSelect | FieldType::CheckList => { + FieldType::SingleSelect | FieldType::MultiSelect | FieldType::Checklist => { let filter = SelectOptionFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?; condition = filter.condition as u8; content = SelectOptionIds::from(filter.option_ids).to_string(); diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs b/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs index caa76f4b54..b623d784e0 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs +++ b/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs @@ -105,7 +105,7 @@ impl TypeCellData { self.field_type == FieldType::MultiSelect } pub fn is_checklist(&self) -> bool { - self.field_type == FieldType::CheckList + self.field_type == FieldType::Checklist } pub fn is_url(&self) -> bool { 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 31ec2a3d93..52c47f56ea 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 @@ -122,7 +122,7 @@ pub fn apply_cell_data_changeset>( SingleSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev) } FieldType::MultiSelect => MultiSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), - FieldType::CheckList => ChecklistTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), + FieldType::Checklist => ChecklistTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::Checkbox => CheckboxTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::URL => URLTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), }?; @@ -181,7 +181,7 @@ pub fn decode_cell_data_to_string( FieldType::MultiSelect => field_rev .get_type_option::(field_type)? .displayed_cell_string(cell_data.into(), from_field_type, field_rev), - FieldType::CheckList => field_rev + FieldType::Checklist => field_rev .get_type_option::(field_type)? .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::Checkbox => field_rev @@ -234,7 +234,7 @@ pub fn try_decode_cell_data( FieldType::MultiSelect => field_rev .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), from_field_type, field_rev), - FieldType::CheckList => field_rev + FieldType::Checklist => field_rev .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), from_field_type, field_rev), FieldType::Checkbox => field_rev diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_option_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_option_builder.rs index fcc5395686..10cb8b3630 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_option_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_option_builder.rs @@ -38,7 +38,7 @@ pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box MultiSelectTypeOptionPB::default().into(), FieldType::Checkbox => CheckboxTypeOptionPB::default().into(), FieldType::URL => URLTypeOptionPB::default().into(), - FieldType::CheckList => ChecklistTypeOptionPB::default().into(), + FieldType::Checklist => ChecklistTypeOptionPB::default().into(), }; type_option_builder_from_json_str(&s, field_type) @@ -53,7 +53,7 @@ pub fn type_option_builder_from_json_str(s: &str, field_type: &FieldType) -> Box FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_json_str(s)), FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_json_str(s)), FieldType::URL => Box::new(URLTypeOptionBuilder::from_json_str(s)), - FieldType::CheckList => Box::new(ChecklistTypeOptionBuilder::from_json_str(s)), + FieldType::Checklist => Box::new(ChecklistTypeOptionBuilder::from_json_str(s)), } } @@ -67,6 +67,6 @@ pub fn type_option_builder_from_bytes>(bytes: T, field_type: &Fie FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_protobuf_bytes(bytes)), FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_protobuf_bytes(bytes)), FieldType::URL => Box::new(URLTypeOptionBuilder::from_protobuf_bytes(bytes)), - FieldType::CheckList => Box::new(ChecklistTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::Checklist => Box::new(ChecklistTypeOptionBuilder::from_protobuf_bytes(bytes)), } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_filter.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_filter.rs index e69b2dfa2e..a5d1d98021 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_filter.rs @@ -1,8 +1,36 @@ -use crate::entities::ChecklistFilterPB; -use crate::services::field::SelectedSelectOptions; +use crate::entities::{ChecklistFilterCondition, ChecklistFilterPB}; +use crate::services::field::{SelectOptionPB, SelectedSelectOptions}; impl ChecklistFilterPB { - pub fn is_visible(&self, selected_options: &SelectedSelectOptions) -> bool { - true + pub fn is_visible(&self, all_options: &[SelectOptionPB], selected_options: &SelectedSelectOptions) -> bool { + let selected_option_ids = selected_options + .options + .iter() + .map(|option| option.id.as_str()) + .collect::>(); + + let mut all_option_ids = all_options + .iter() + .map(|option| option.id.as_str()) + .collect::>(); + + return match self.condition { + ChecklistFilterCondition::IsComplete => { + if selected_option_ids.is_empty() { + return false; + } + + all_option_ids.retain(|option_id| !selected_option_ids.contains(option_id)); + all_option_ids.is_empty() + } + ChecklistFilterCondition::IsIncomplete => { + if selected_option_ids.is_empty() { + return true; + } + + all_option_ids.retain(|option_id| !selected_option_ids.contains(option_id)); + !all_option_ids.is_empty() + } + }; } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_type_option.rs index a6975d8f7d..ae3c3b689d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/checklist_type_option.rs @@ -22,7 +22,7 @@ pub struct ChecklistTypeOptionPB { #[pb(index = 2)] pub disable_color: bool, } -impl_type_option!(ChecklistTypeOptionPB, FieldType::CheckList); +impl_type_option!(ChecklistTypeOptionPB, FieldType::Checklist); impl SelectTypeOptionSharedAction for ChecklistTypeOptionPB { fn number_of_max_options(&self) -> Option { @@ -101,7 +101,7 @@ impl ChecklistTypeOptionBuilder { impl TypeOptionBuilder for ChecklistTypeOptionBuilder { fn field_type(&self) -> FieldType { - FieldType::CheckList + FieldType::Checklist } fn serializer(&self) -> &dyn TypeOptionDataSerializer { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_filter.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_filter.rs index 28a4735605..239be335a4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_filter.rs @@ -67,7 +67,7 @@ impl CellFilterOperation for ChecklistTypeOptionPB { return Ok(true); } let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into())); - Ok(filter.is_visible(&selected_options)) + Ok(filter.is_visible(&self.options, &selected_options)) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs index 2dadb1248a..1f961b868a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs @@ -4,7 +4,7 @@ use crate::services::cell::{ CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString, }; use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer; -use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; +use crate::services::field::{ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{internal_error, ErrorCode, FlowyResult}; @@ -212,6 +212,10 @@ pub fn select_type_option_from_field_rev( let type_option = MultiSelectTypeOptionPB::from(field_rev); Ok(Box::new(type_option)) } + FieldType::Checklist => { + let type_option = ChecklistTypeOptionPB::from(field_rev); + Ok(Box::new(type_option)) + } ty => { tracing::error!("Unsupported field type: {:?} for this handler", ty); Err(ErrorCode::FieldInvalidOperation.into()) diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/cache.rs b/frontend/rust-lib/flowy-grid/src/services/filter/cache.rs index 73b4e6bcc8..caffc0d777 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/cache.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/cache.rs @@ -29,7 +29,7 @@ impl FilterMap { FieldType::MultiSelect => self.select_option_filter.get(filter_type).is_some(), FieldType::Checkbox => self.checkbox_filter.get(filter_type).is_some(), FieldType::URL => self.url_filter.get(filter_type).is_some(), - FieldType::CheckList => self.checklist_filter.get(filter_type).is_some(), + FieldType::Checklist => self.checklist_filter.get(filter_type).is_some(), } } @@ -61,6 +61,9 @@ impl FilterMap { if !self.checkbox_filter.is_empty() { return false; } + if !self.checklist_filter.is_empty() { + return false; + } true } @@ -87,7 +90,7 @@ impl FilterMap { FieldType::URL => { let _ = self.url_filter.remove(filter_id); } - FieldType::CheckList => { + FieldType::Checklist => { let _ = self.checklist_filter.remove(filter_id); } }; diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs b/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs index d855d00d04..49aaad8586 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs @@ -291,7 +291,7 @@ impl FilterController { .url_filter .insert(filter_type, TextFilterPB::from(filter_rev.as_ref())); } - FieldType::CheckList => { + FieldType::Checklist => { let _ = self .filter_map .checklist_filter @@ -419,7 +419,7 @@ fn filter_cell( .ok(), ) }), - FieldType::CheckList => filter_map.checklist_filter.get(filter_id).and_then(|filter| { + FieldType::Checklist => filter_map.checklist_filter.get(filter_id).and_then(|filter| { Some( field_rev .get_type_option::(field_rev.ty)? diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs index ed9a36abc8..b8d94100e9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs @@ -123,7 +123,7 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat SelectOptionGroupConfigurationRevision::default(), ) .unwrap(), - FieldType::CheckList => GroupConfigurationRevision::new( + FieldType::Checklist => GroupConfigurationRevision::new( field_id, field_type_rev, SelectOptionGroupConfigurationRevision::default(), diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs index 5ececf4b05..2a3aa12add 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs @@ -226,7 +226,7 @@ impl GridRowTest { assert_eq!(s, expected); } - FieldType::CheckList => { + FieldType::Checklist => { let cell_data = self .editor .get_cell_bytes(&cell_id) 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 dfc5e5aa23..7f3e43275b 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 @@ -94,12 +94,12 @@ impl<'a> GridRowTestBuilder<'a> { where F: Fn(Vec) -> Vec, { - let checklist_field = self.field_rev_with_type(&FieldType::CheckList); + let checklist_field = self.field_rev_with_type(&FieldType::Checklist); let type_option = ChecklistTypeOptionPB::from(&checklist_field); let options = f(type_option.options); let ops_ids = options.iter().map(|option| option.id.clone()).collect::>(); self.inner_builder - .insert_select_option_cell(&multi_select_field.id, ops_ids); + .insert_select_option_cell(&checklist_field.id, ops_ids); checklist_field.id.clone() } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs index 5885d4ad37..81d99256c7 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs @@ -31,7 +31,7 @@ async fn grid_cell_update() { let type_option = MultiSelectTypeOptionPB::from(field_rev); SelectOptionCellChangeset::from_insert_option_id(&type_option.options.first().unwrap().id).to_str() } - FieldType::CheckList => { + FieldType::Checklist => { let type_option = ChecklistTypeOptionPB::from(field_rev); SelectOptionCellChangeset::from_insert_option_id(&type_option.options.first().unwrap().id).to_str() } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/checklist_filter_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/checklist_filter_test.rs new file mode 100644 index 0000000000..c7688cacbc --- /dev/null +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/checklist_filter_test.rs @@ -0,0 +1,27 @@ +use crate::grid::filter_test::script::FilterScript::*; +use crate::grid::filter_test::script::GridFilterTest; +use flowy_grid::entities::{ChecklistFilterCondition, SelectOptionCondition}; + +#[tokio::test] +async fn grid_filter_checklist_is_incomplete_test() { + let mut test = GridFilterTest::new().await; + let scripts = vec![ + CreateChecklistFilter { + condition: ChecklistFilterCondition::IsIncomplete, + }, + AssertNumberOfVisibleRows { expected: 4 }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_filter_checklist_is_complete_test() { + let mut test = GridFilterTest::new().await; + let scripts = vec![ + CreateChecklistFilter { + condition: ChecklistFilterCondition::IsComplete, + }, + AssertNumberOfVisibleRows { expected: 1 }, + ]; + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/mod.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/mod.rs index c26a66ea3b..160bf3427f 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/mod.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/mod.rs @@ -1,4 +1,5 @@ mod checkbox_filter_test; +mod checklist_filter_test; mod date_filter_test; mod number_filter_test; mod script; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index e9d6ab49c6..d09c910d19 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -6,7 +6,7 @@ use std::time::Duration; use bytes::Bytes; use futures::TryFutureExt; -use flowy_grid::entities::{AlterFilterParams, AlterFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB, RowPB, TextFilterCondition, FieldType, NumberFilterCondition, CheckboxFilterCondition, DateFilterCondition, DateFilterContent, SelectOptionCondition, TextFilterPB, NumberFilterPB, CheckboxFilterPB, DateFilterPB, SelectOptionFilterPB, CellChangesetPB, FilterPB}; +use flowy_grid::entities::{AlterFilterParams, AlterFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB, RowPB, TextFilterCondition, FieldType, NumberFilterCondition, CheckboxFilterCondition, DateFilterCondition, DateFilterContent, SelectOptionCondition, TextFilterPB, NumberFilterPB, CheckboxFilterPB, DateFilterPB, SelectOptionFilterPB, CellChangesetPB, FilterPB, ChecklistFilterCondition, ChecklistFilterPB}; use flowy_grid::services::field::{SelectOptionCellChangeset, SelectOptionIds}; use flowy_grid::services::setting::GridSettingChangesetBuilder; use grid_rev_model::{FieldRevision, FieldTypeRevision}; @@ -57,6 +57,9 @@ pub enum FilterScript { condition: SelectOptionCondition, option_ids: Vec, }, + CreateChecklistFilter { + condition: ChecklistFilterCondition, + }, AssertFilterCount { count: i32, }, @@ -184,6 +187,14 @@ impl GridFilterTest { AlterFilterPayloadPB::new(field_rev, filter); self.insert_filter(payload).await; } + FilterScript::CreateChecklistFilter { condition} => { + let field_rev = self.get_first_field_rev(FieldType::Checklist); + // let type_option = self.get_checklist_type_option(&field_rev.id); + let filter = ChecklistFilterPB { condition }; + let payload = + AlterFilterPayloadPB::new(field_rev, filter); + self.insert_filter(payload).await; + } FilterScript::AssertFilterCount { count } => { let filters = self.editor.get_all_filters().await.unwrap(); assert_eq!(count as usize, filters.len()); diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs index a43ddde209..487a283ea2 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -131,6 +131,14 @@ impl GridEditorTest { type_option } + pub fn get_checklist_type_option(&self, field_id: &str) -> ChecklistTypeOptionPB { + let field_type = FieldType::Checklist; + let field_rev = self.get_field_rev(field_id, field_type.clone()); + let type_option = field_rev + .get_type_option::(field_type.into()) + .unwrap(); + type_option + } pub fn get_checkbox_type_option(&self, field_id: &str) -> CheckboxTypeOptionPB { let field_type = FieldType::Checkbox; let field_rev = self.get_field_rev(field_id, field_type.clone()); @@ -220,7 +228,7 @@ fn make_test_grid() -> BuildGridContext { let url_field = FieldBuilder::new(url).name("link").visibility(true).build(); grid_builder.add_field(url_field); } - FieldType::CheckList => { + FieldType::Checklist => { let checklist = ChecklistTypeOptionBuilder::default() .add_option(SelectOptionPB::new(FIRST_THING)) .add_option(SelectOptionPB::new(SECOND_THING)) @@ -245,7 +253,7 @@ fn make_test_grid() -> BuildGridContext { FieldType::DateTime => row_builder.insert_date_cell("1647251762"), FieldType::MultiSelect => row_builder .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]), - FieldType::CheckList => row_builder.insert_checklist_cell(|options| options), + FieldType::Checklist => row_builder.insert_checklist_cell(|options| options), FieldType::Checkbox => row_builder.insert_checkbox_cell("true"), _ => "".to_owned(), }; @@ -382,7 +390,7 @@ fn make_test_board() -> BuildGridContext { let url_field = FieldBuilder::new(url).name("link").visibility(true).build(); grid_builder.add_field(url_field); } - FieldType::CheckList => {} + FieldType::Checklist => {} } }