diff --git a/frontend/app_flowy/assets/images/grid/checkmark.svg b/frontend/app_flowy/assets/images/grid/checkmark.svg
new file mode 100644
index 0000000000..f9c848f713
--- /dev/null
+++ b/frontend/app_flowy/assets/images/grid/checkmark.svg
@@ -0,0 +1,3 @@
+
diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart
index 8bab77150a..4cb0fda104 100644
--- a/frontend/app_flowy/lib/startup/deps_resolver.dart
+++ b/frontend/app_flowy/lib/startup/deps_resolver.dart
@@ -221,8 +221,8 @@ void _resolveGridDeps(GetIt getIt) {
(typeOption, fieldId) => SingleSelectTypeOptionBloc(typeOption, fieldId),
);
- getIt.registerFactoryParam(
- (typeOption, _) => MultiSelectTypeOptionBloc(typeOption),
+ getIt.registerFactoryParam(
+ (typeOption, fieldId) => MultiSelectTypeOptionBloc(typeOption, fieldId),
);
getIt.registerFactoryParam(
diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart
index 75ac80c47c..0a96f5f69b 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart
@@ -1,18 +1,37 @@
-import 'dart:typed_data';
+import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
+import 'package:protobuf/protobuf.dart';
+import 'type_option_service.dart';
part 'multi_select_bloc.freezed.dart';
class MultiSelectTypeOptionBloc extends Bloc {
- MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption) : super(MultiSelectTypeOptionState.initial(typeOption)) {
+ final TypeOptionService service;
+
+ MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption, String fieldId)
+ : service = TypeOptionService(fieldId: fieldId),
+ super(MultiSelectTypeOptionState.initial(typeOption)) {
on(
(event, emit) async {
await event.map(
- createOption: (_CreateOption value) {},
- updateOptions: (_UpdateOptions value) async {},
+ createOption: (_CreateOption value) async {
+ final result = await service.createOption(value.optionName);
+ result.fold(
+ (option) {
+ emit(state.copyWith(typeOption: _insertOption(option)));
+ },
+ (err) => Log.error(err),
+ );
+ },
+ updateOption: (_UpdateOption value) async {
+ emit(state.copyWith(typeOption: _updateOption(value.option)));
+ },
+ deleteOption: (_DeleteOption value) {
+ emit(state.copyWith(typeOption: _deleteOption(value.option)));
+ },
);
},
);
@@ -22,12 +41,40 @@ class MultiSelectTypeOptionBloc extends Bloc close() async {
return super.close();
}
+
+ MultiSelectTypeOption _insertOption(SelectOption option) {
+ state.typeOption.freeze();
+ return state.typeOption.rebuild((typeOption) {
+ typeOption.options.insert(0, option);
+ });
+ }
+
+ MultiSelectTypeOption _updateOption(SelectOption option) {
+ state.typeOption.freeze();
+ return state.typeOption.rebuild((typeOption) {
+ final index = typeOption.options.indexWhere((element) => element.id == option.id);
+ if (index != -1) {
+ typeOption.options[index] = option;
+ }
+ });
+ }
+
+ MultiSelectTypeOption _deleteOption(SelectOption option) {
+ state.typeOption.freeze();
+ return state.typeOption.rebuild((typeOption) {
+ final index = typeOption.options.indexWhere((element) => element.id == option.id);
+ if (index != -1) {
+ typeOption.options.removeAt(index);
+ }
+ });
+ }
}
@freezed
class MultiSelectTypeOptionEvent with _$MultiSelectTypeOptionEvent {
const factory MultiSelectTypeOptionEvent.createOption(String optionName) = _CreateOption;
- const factory MultiSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions;
+ const factory MultiSelectTypeOptionEvent.updateOption(SelectOption option) = _UpdateOption;
+ const factory MultiSelectTypeOptionEvent.deleteOption(SelectOption option) = _DeleteOption;
}
@freezed
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart
index ce34097118..e8eb5caee2 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart
@@ -156,7 +156,7 @@ TypeOptionBuilder _makeTypeOptionBuild({
case FieldType.SingleSelect:
return SingleSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate);
case FieldType.MultiSelect:
- return MultiSelectTypeOptionBuilder(data, overlayDelegate);
+ return MultiSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate);
case FieldType.Number:
return NumberTypeOptionBuilder(data, overlayDelegate, dataDelegate);
case FieldType.RichText:
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart
index 43cf2597fa..23881e9310 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart
@@ -8,26 +8,45 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'option_pannel.dart';
class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
- MultiSelectTypeOption typeOption;
- TypeOptionOverlayDelegate delegate;
+ MultiSelectTypeOptionWidget _widget;
- MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate)
- : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData);
+ MultiSelectTypeOptionBuilder(
+ String fieldId,
+ TypeOptionData typeOptionData,
+ TypeOptionOverlayDelegate overlayDelegate,
+ TypeOptionDataDelegate dataDelegate,
+ ) : _widget = MultiSelectTypeOptionWidget(
+ fieldId: fieldId,
+ typeOption: MultiSelectTypeOption.fromBuffer(typeOptionData),
+ overlayDelegate: overlayDelegate,
+ dataDelegate: dataDelegate,
+ );
@override
- Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption, delegate);
+ Widget? get customWidget => _widget;
}
class MultiSelectTypeOptionWidget extends TypeOptionWidget {
+ final String fieldId;
final MultiSelectTypeOption typeOption;
final TypeOptionOverlayDelegate overlayDelegate;
- const MultiSelectTypeOptionWidget(this.typeOption, this.overlayDelegate, {Key? key}) : super(key: key);
+ final TypeOptionDataDelegate dataDelegate;
+ const MultiSelectTypeOptionWidget({
+ required this.fieldId,
+ required this.typeOption,
+ required this.overlayDelegate,
+ required this.dataDelegate,
+ Key? key,
+ }) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
- create: (context) => getIt(param1: typeOption),
- child: BlocBuilder(
+ create: (context) => getIt(param1: typeOption, param2: fieldId),
+ child: BlocConsumer(
+ listener: (context, state) {
+ dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer());
+ },
builder: (context, state) {
return OptionPannel(
options: state.typeOption.options,
@@ -37,9 +56,14 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget {
createOptionCallback: (name) {
context.read().add(MultiSelectTypeOptionEvent.createOption(name));
},
- updateOptionCallback: (updateOption) {},
- deleteOptionCallback: (deleteOption) {},
+ updateOptionCallback: (updateOption) {
+ context.read().add(MultiSelectTypeOptionEvent.updateOption(updateOption));
+ },
+ deleteOptionCallback: (deleteOption) {
+ context.read().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption));
+ },
overlayDelegate: overlayDelegate,
+ key: ValueKey(state.typeOption.hashCode),
);
},
),