diff --git a/frontend/app_flowy/assets/images/grid/details.svg b/frontend/app_flowy/assets/images/grid/details.svg
new file mode 100644
index 0000000000..e4c9f58f27
--- /dev/null
+++ b/frontend/app_flowy/assets/images/grid/details.svg
@@ -0,0 +1,4 @@
+
diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json
index fbd672c04f..b751bb6d3e 100644
--- a/frontend/app_flowy/assets/translations/en.json
+++ b/frontend/app_flowy/assets/translations/en.json
@@ -167,6 +167,17 @@
"addSelectOption": "Add an option",
"optionTitle": "Options",
"addOption": "Add option"
+ },
+ "selectOption": {
+ "purpleColor": "Purple",
+ "pinkColor": "Pink",
+ "lightPinkColor": "Light Pink",
+ "orangeColor": "Orange",
+ "yellowColor": "Yellow",
+ "limeColor": "Lime",
+ "greenColor": "Green",
+ "aquaColor": "Aqua",
+ "blueColor": "Blue"
}
}
}
diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart
index 5d78cbdf2a..8bab77150a 100644
--- a/frontend/app_flowy/lib/startup/deps_resolver.dart
+++ b/frontend/app_flowy/lib/startup/deps_resolver.dart
@@ -3,6 +3,7 @@ import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/application/user_service.dart';
import 'package:app_flowy/workspace/application/app/prelude.dart';
import 'package:app_flowy/workspace/application/doc/prelude.dart';
+import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:app_flowy/workspace/application/grid/row/row_listener.dart';
import 'package:app_flowy/workspace/application/trash/prelude.dart';
@@ -20,6 +21,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
import 'package:get_it/get_it.dart';
@@ -215,8 +217,12 @@ void _resolveGridDeps(GetIt getIt) {
(context, _) => FieldTypeSwitchBloc(context),
);
- getIt.registerFactory(
- () => SelectionTypeOptionBloc(),
+ getIt.registerFactoryParam(
+ (typeOption, fieldId) => SingleSelectTypeOptionBloc(typeOption, fieldId),
+ );
+
+ getIt.registerFactoryParam(
+ (typeOption, _) => MultiSelectTypeOptionBloc(typeOption),
);
getIt.registerFactoryParam(
diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
index 6824ce0b1b..24644f0fae 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
@@ -1,5 +1,3 @@
-import 'dart:typed_data';
-
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
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
new file mode 100644
index 0000000000..75ac80c47c
--- /dev/null
+++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_bloc.dart
@@ -0,0 +1,42 @@
+import 'dart:typed_data';
+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';
+
+part 'multi_select_bloc.freezed.dart';
+
+class MultiSelectTypeOptionBloc extends Bloc {
+ MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption) : super(MultiSelectTypeOptionState.initial(typeOption)) {
+ on(
+ (event, emit) async {
+ await event.map(
+ createOption: (_CreateOption value) {},
+ updateOptions: (_UpdateOptions value) async {},
+ );
+ },
+ );
+ }
+
+ @override
+ Future close() async {
+ return super.close();
+ }
+}
+
+@freezed
+class MultiSelectTypeOptionEvent with _$MultiSelectTypeOptionEvent {
+ const factory MultiSelectTypeOptionEvent.createOption(String optionName) = _CreateOption;
+ const factory MultiSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions;
+}
+
+@freezed
+class MultiSelectTypeOptionState with _$MultiSelectTypeOptionState {
+ const factory MultiSelectTypeOptionState({
+ required MultiSelectTypeOption typeOption,
+ }) = _MultiSelectTypeOptionState;
+
+ factory MultiSelectTypeOptionState.initial(MultiSelectTypeOption typeOption) => MultiSelectTypeOptionState(
+ typeOption: typeOption,
+ );
+}
diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart
index aacf06c98d..445db413c0 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/option_pannel_bloc.dart
@@ -1,13 +1,8 @@
-import 'dart:typed_data';
-
-import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.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:dartz/dartz.dart';
-
part 'option_pannel_bloc.freezed.dart';
class OptionPannelBloc extends Bloc {
@@ -16,13 +11,13 @@ class OptionPannelBloc extends Bloc {
(event, emit) async {
await event.map(
createOption: (_CreateOption value) async {
- emit(state.copyWith(isAddingOption: false));
+ emit(state.copyWith(isEditingOption: false, newOptionName: Some(value.optionName)));
},
beginAddingOption: (_BeginAddingOption value) {
- emit(state.copyWith(isAddingOption: true));
+ emit(state.copyWith(isEditingOption: true, newOptionName: none()));
},
endAddingOption: (_EndAddingOption value) {
- emit(state.copyWith(isAddingOption: false));
+ emit(state.copyWith(isEditingOption: false, newOptionName: none()));
},
);
},
@@ -46,11 +41,13 @@ class OptionPannelEvent with _$OptionPannelEvent {
class OptionPannelState with _$OptionPannelState {
const factory OptionPannelState({
required List options,
- required bool isAddingOption,
+ required bool isEditingOption,
+ required Option newOptionName,
}) = _OptionPannelState;
factory OptionPannelState.initial(List options) => OptionPannelState(
options: options,
- isAddingOption: false,
+ isEditingOption: false,
+ newOptionName: none(),
);
}
diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart
deleted file mode 100644
index ac6d3fb6d4..0000000000
--- a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/selection_bloc.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'dart:typed_data';
-
-import 'package:flowy_sdk/log.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-import 'dart:async';
-import 'package:dartz/dartz.dart';
-
-part 'selection_bloc.freezed.dart';
-
-class SelectionTypeOptionBloc extends Bloc {
- SelectionTypeOptionBloc() : super(SelectionTypeOptionState.initial()) {
- on(
- (event, emit) async {
- await event.map(
- initial: (_InitialField value) async {},
- );
- },
- );
- }
-
- @override
- Future close() async {
- return super.close();
- }
-}
-
-@freezed
-class SelectionTypeOptionEvent with _$SelectionTypeOptionEvent {
- const factory SelectionTypeOptionEvent.initial(Uint8List? typeOptionData) = _InitialField;
-}
-
-@freezed
-class SelectionTypeOptionState with _$SelectionTypeOptionState {
- const factory SelectionTypeOptionState() = _SelectionTypeOptionState;
-
- factory SelectionTypeOptionState.initial() => SelectionTypeOptionState();
-}
diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart
new file mode 100644
index 0000000000..07a26439f3
--- /dev/null
+++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_bloc.dart
@@ -0,0 +1,57 @@
+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 'type_option_service.dart';
+
+part 'single_select_bloc.freezed.dart';
+
+class SingleSelectTypeOptionBloc extends Bloc {
+ final TypeOptionService service;
+
+ SingleSelectTypeOptionBloc(SingleSelectTypeOption typeOption, String fieldId)
+ : service = TypeOptionService(fieldId: fieldId),
+ super(SingleSelectTypeOptionState.initial(typeOption)) {
+ on(
+ (event, emit) async {
+ await event.map(
+ createOption: (_CreateOption value) async {
+ final result = await service.createOption(value.optionName);
+ result.fold(
+ (option) {
+ state.typeOption.options.insert(0, option);
+ emit(state);
+ },
+ (err) => Log.error(err),
+ );
+ },
+ updateOptions: (_UpdateOptions value) async {},
+ );
+ },
+ );
+ }
+
+ @override
+ Future close() async {
+ return super.close();
+ }
+}
+
+@freezed
+class SingleSelectTypeOptionEvent with _$SingleSelectTypeOptionEvent {
+ const factory SingleSelectTypeOptionEvent.createOption(String optionName) = _CreateOption;
+ const factory SingleSelectTypeOptionEvent.updateOptions(List options) = _UpdateOptions;
+}
+
+@freezed
+class SingleSelectTypeOptionState with _$SingleSelectTypeOptionState {
+ const factory SingleSelectTypeOptionState({
+ required SingleSelectTypeOption typeOption,
+ }) = _SingleSelectTypeOptionState;
+
+ factory SingleSelectTypeOptionState.initial(SingleSelectTypeOption typeOption) => SingleSelectTypeOptionState(
+ typeOption: typeOption,
+ );
+}
diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
new file mode 100644
index 0000000000..8ab3460b82
--- /dev/null
+++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
@@ -0,0 +1,17 @@
+import 'package:dartz/dartz.dart';
+import 'package:flowy_sdk/dispatch/dispatch.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
+
+class TypeOptionService {
+ String fieldId;
+ TypeOptionService({
+ required this.fieldId,
+ });
+
+ Future> createOption(String name) {
+ final payload = CreateSelectOptionPayload.create()..optionName = name;
+ return GridEventCreateSelectOption(payload).send();
+ }
+}
diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart
index 38135f75f6..e1d3020ae0 100644
--- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart
+++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart
@@ -14,7 +14,7 @@ export 'field/switch_field_type_bloc.dart';
// Field Type Option
export 'field/type_option/date_bloc.dart';
export 'field/type_option/number_bloc.dart';
-export 'field/type_option/selection_bloc.dart';
+export 'field/type_option/single_select_bloc.dart';
// Cell
export 'cell_bloc/text_cell_bloc.dart';
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart
index 031edb93fd..5983102047 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/src/document_page.dart
@@ -61,6 +61,7 @@ class _DocumentPageState extends State {
@override
Future dispose() async {
documentBloc.close();
+ _focusNode.dispose();
super.dispose();
}
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart
index c282f10b40..8b2b74d9ae 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/create_field_pannel.dart
@@ -20,7 +20,7 @@ class CreateFieldPannel extends FlowyOverlayDelegate {
FlowyOverlay.of(context).insertWithAnchor(
widget: OverlayContainer(
child: _CreateFieldPannelWidget(_createFieldBloc),
- constraints: BoxConstraints.loose(const Size(220, 500)),
+ constraints: BoxConstraints.loose(const Size(220, 400)),
),
identifier: identifier(),
anchorContext: context,
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 6e03b4243d..1a418cf543 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
@@ -2,7 +2,6 @@ import 'dart:typed_data';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@@ -14,12 +13,13 @@ import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart
import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
-
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart';
+import 'type_option/multi_select.dart';
import 'type_option/number.dart';
+import 'type_option/single_select.dart';
typedef SelectFieldCallback = void Function(Field, Uint8List);
@@ -50,7 +50,7 @@ class _FieldTypeSwitcherState extends State {
final typeOptionWidget = _typeOptionWidget(
context: context,
- fieldType: state.field.fieldType,
+ field: state.field,
data: state.typeOptionData,
);
@@ -89,7 +89,7 @@ class _FieldTypeSwitcherState extends State {
Widget? _typeOptionWidget({
required BuildContext context,
- required FieldType fieldType,
+ required Field field,
required TypeOptionData data,
}) {
final delegate = TypeOptionOperationDelegate(
@@ -97,8 +97,9 @@ class _FieldTypeSwitcherState extends State {
context.read().add(FieldTypeSwitchEvent.didUpdateTypeOptionData(data));
},
requireToShowOverlay: _showOverlay,
+ hideOverlay: _hideOverlay,
);
- final builder = _makeTypeOptionBuild(fieldType: fieldType, data: data, delegate: delegate);
+ final builder = _makeTypeOptionBuild(field: field, data: data, delegate: delegate);
return builder.customWidget;
}
@@ -120,6 +121,12 @@ class _FieldTypeSwitcherState extends State {
anchorOffset: const Offset(-20, 0),
);
}
+
+ void _hideOverlay(BuildContext context) {
+ if (currentOverlayIdentifier != null) {
+ FlowyOverlay.of(context).remove(currentOverlayIdentifier!);
+ }
+ }
}
abstract class TypeOptionBuilder {
@@ -127,23 +134,24 @@ abstract class TypeOptionBuilder {
}
TypeOptionBuilder _makeTypeOptionBuild({
- required FieldType fieldType,
+ required Field field,
required TypeOptionData data,
required TypeOptionOperationDelegate delegate,
}) {
- switch (fieldType) {
+ switch (field.fieldType) {
case FieldType.Checkbox:
return CheckboxTypeOptionBuilder(data);
case FieldType.DateTime:
return DateTypeOptionBuilder(data, delegate);
+ case FieldType.SingleSelect:
+ return SingleSelectTypeOptionBuilder(field.id, data, delegate);
case FieldType.MultiSelect:
- return MultiSelectTypeOptionBuilder(data);
+ return MultiSelectTypeOptionBuilder(data, delegate);
case FieldType.Number:
return NumberTypeOptionBuilder(data, delegate);
case FieldType.RichText:
return RichTextTypeOptionBuilder(data);
- case FieldType.SingleSelect:
- return SingleSelectTypeOptionBuilder(data);
+
default:
throw UnimplementedError;
}
@@ -156,13 +164,16 @@ abstract class TypeOptionWidget extends StatelessWidget {
typedef TypeOptionData = Uint8List;
typedef TypeOptionDataCallback = void Function(TypeOptionData typeOptionData);
typedef ShowOverlayCallback = void Function(BuildContext anchorContext, String overlayIdentifier, Widget child);
+typedef HideOverlayCallback = void Function(BuildContext anchorContext);
class TypeOptionOperationDelegate {
TypeOptionDataCallback didUpdateTypeOptionData;
ShowOverlayCallback requireToShowOverlay;
+ HideOverlayCallback hideOverlay;
TypeOptionOperationDelegate({
required this.didUpdateTypeOptionData,
required this.requireToShowOverlay,
+ required this.hideOverlay,
});
}
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart
new file mode 100644
index 0000000000..31f9570602
--- /dev/null
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart
@@ -0,0 +1,115 @@
+import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra_ui/style_widget/button.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:app_flowy/generated/locale_keys.g.dart';
+
+class SelectOptionColorList extends StatelessWidget {
+ const SelectOptionColorList({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+
+class _SelectOptionColorItem extends StatelessWidget {
+ final SelectOptionColor option;
+ final bool isSelected;
+ const _SelectOptionColorItem({required this.option, required this.isSelected, Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = context.watch();
+
+ Widget? checkmark;
+ if (isSelected) {
+ checkmark = svg("grid/details", color: theme.iconColor);
+ }
+
+ final colorIcon = SizedBox.square(
+ dimension: 16,
+ child: Container(
+ decoration: BoxDecoration(
+ color: option.color(context),
+ shape: BoxShape.circle,
+ ),
+ ),
+ );
+
+ return FlowyButton(
+ text: FlowyText.medium(
+ option.name(),
+ fontSize: 12,
+ ),
+ hoverColor: theme.hover,
+ leftIcon: colorIcon,
+ rightIcon: checkmark,
+ onTap: () {},
+ );
+ }
+}
+
+enum SelectOptionColor {
+ purple,
+ pink,
+ lightPink,
+ orange,
+ yellow,
+ lime,
+ green,
+ aqua,
+ blue,
+}
+
+extension SelectOptionColorExtension on SelectOptionColor {
+ Color color(BuildContext context) {
+ final theme = context.watch();
+ switch (this) {
+ case SelectOptionColor.purple:
+ return theme.tint1;
+ case SelectOptionColor.pink:
+ return theme.tint2;
+ case SelectOptionColor.lightPink:
+ return theme.tint3;
+ case SelectOptionColor.orange:
+ return theme.tint4;
+ case SelectOptionColor.yellow:
+ return theme.tint5;
+ case SelectOptionColor.lime:
+ return theme.tint6;
+ case SelectOptionColor.green:
+ return theme.tint7;
+ case SelectOptionColor.aqua:
+ return theme.tint8;
+ case SelectOptionColor.blue:
+ return theme.tint9;
+ }
+ }
+
+ String name() {
+ switch (this) {
+ case SelectOptionColor.purple:
+ return LocaleKeys.grid_selectOption_purpleColor.tr();
+ case SelectOptionColor.pink:
+ return LocaleKeys.grid_selectOption_pinkColor.tr();
+ case SelectOptionColor.lightPink:
+ return LocaleKeys.grid_selectOption_lightPinkColor.tr();
+ case SelectOptionColor.orange:
+ return LocaleKeys.grid_selectOption_orangeColor.tr();
+ case SelectOptionColor.yellow:
+ return LocaleKeys.grid_selectOption_yellowColor.tr();
+ case SelectOptionColor.lime:
+ return LocaleKeys.grid_selectOption_limeColor.tr();
+ case SelectOptionColor.green:
+ return LocaleKeys.grid_selectOption_greenColor.tr();
+ case SelectOptionColor.aqua:
+ return LocaleKeys.grid_selectOption_aquaColor.tr();
+ case SelectOptionColor.blue:
+ return LocaleKeys.grid_selectOption_blueColor.tr();
+ }
+ }
+}
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
new file mode 100644
index 0000000000..4a3694b5fc
--- /dev/null
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart
@@ -0,0 +1,48 @@
+import 'package:app_flowy/startup/startup.dart';
+import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'option_pannel.dart';
+
+class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
+ MultiSelectTypeOption typeOption;
+ TypeOptionOperationDelegate delegate;
+
+ MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate)
+ : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData);
+
+ @override
+ Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption, delegate);
+}
+
+class MultiSelectTypeOptionWidget extends TypeOptionWidget {
+ final MultiSelectTypeOption typeOption;
+ final TypeOptionOperationDelegate delegate;
+ const MultiSelectTypeOptionWidget(this.typeOption, this.delegate, {Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocProvider(
+ create: (context) => getIt(param1: typeOption),
+ child: BlocBuilder(
+ builder: (context, state) {
+ return OptionPannel(
+ options: state.typeOption.options,
+ beginEdit: () {
+ delegate.hideOverlay(context);
+ },
+ createOptionCallback: (name) {
+ context.read().add(MultiSelectTypeOptionEvent.createOption(name));
+ },
+ updateOptionsCallback: (options) {
+ context.read().add(MultiSelectTypeOptionEvent.updateOptions(options));
+ },
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart
similarity index 55%
rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart
rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart
index 2d5c963fc5..736d03d96d 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/selection.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/option_pannel.dart
@@ -1,8 +1,5 @@
-import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/field/type_option/option_pannel_bloc.dart';
-import 'package:app_flowy/workspace/application/grid/field/type_option/selection_bloc.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
-import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
@@ -16,73 +13,48 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
import 'widget.dart';
-class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
- SingleSelectTypeOption typeOption;
-
- SingleSelectTypeOptionBuilder(TypeOptionData typeOptionData)
- : typeOption = SingleSelectTypeOption.fromBuffer(typeOptionData);
-
- @override
- Widget? get customWidget => SingleSelectTypeOptionWidget(typeOption);
-}
-
-class SingleSelectTypeOptionWidget extends TypeOptionWidget {
- final SingleSelectTypeOption typeOption;
- const SingleSelectTypeOptionWidget(this.typeOption, {Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return BlocProvider(
- create: (context) => getIt(),
- child: OptionPannel(options: typeOption.options),
- );
- }
-}
-
-class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
- MultiSelectTypeOption typeOption;
-
- MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData)
- : typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData);
-
- @override
- Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption);
-}
-
-class MultiSelectTypeOptionWidget extends TypeOptionWidget {
- final MultiSelectTypeOption typeOption;
- const MultiSelectTypeOptionWidget(this.typeOption, {Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return BlocProvider(
- create: (context) => getIt(),
- child: OptionPannel(options: typeOption.options),
- );
- }
-}
-
class OptionPannel extends StatelessWidget {
final List options;
- const OptionPannel({required this.options, Key? key}) : super(key: key);
+ final VoidCallback beginEdit;
+ final Function(String optionName) createOptionCallback;
+ final Function(List) updateOptionsCallback;
+ const OptionPannel({
+ required this.options,
+ required this.beginEdit,
+ required this.createOptionCallback,
+ required this.updateOptionsCallback,
+ Key? key,
+ }) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => OptionPannelBloc(options: options),
- child: BlocBuilder(
+ child: BlocConsumer(
+ listener: (context, state) {
+ if (state.isEditingOption) {
+ beginEdit();
+ }
+ state.newOptionName.fold(
+ () => null,
+ (optionName) => createOptionCallback(optionName),
+ );
+ },
builder: (context, state) {
- List children = [const OptionTitle()];
- if (state.isAddingOption) {
+ List children = [
+ const TypeOptionSeparator(),
+ const OptionTitle(),
+ ];
+ if (state.isEditingOption) {
children.add(const _AddOptionTextField());
}
- if (state.options.isEmpty && !state.isAddingOption) {
+ if (state.options.isEmpty && !state.isEditingOption) {
children.add(const _AddOptionButton());
}
if (state.options.isNotEmpty) {
- children.add(const _OptionList());
+ children.add(_OptionList(key: ObjectKey(state.options)));
}
return Column(children: children);
@@ -100,19 +72,27 @@ class OptionTitle extends StatelessWidget {
final theme = context.watch();
return BlocBuilder(
- buildWhen: (previous, current) => previous.options.length != current.options.length,
builder: (context, state) {
List children = [FlowyText.medium(LocaleKeys.grid_field_optionTitle.tr(), fontSize: 12)];
-
- if (state.options.isNotEmpty && state.isAddingOption == false) {
- children.add(FlowyButton(
- text: FlowyText.medium(LocaleKeys.grid_field_addOption.tr(), fontSize: 12),
- hoverColor: theme.hover,
- onTap: () {
- context.read().add(const OptionPannelEvent.beginAddingOption());
- },
- rightIcon: svg("grid/more", color: theme.iconColor),
- ));
+ if (state.options.isNotEmpty) {
+ children.add(const Spacer());
+ children.add(
+ SizedBox(
+ width: 100,
+ height: 26,
+ child: FlowyButton(
+ text: FlowyText.medium(
+ LocaleKeys.grid_field_addOption.tr(),
+ fontSize: 12,
+ textAlign: TextAlign.center,
+ ),
+ hoverColor: theme.hover,
+ onTap: () {
+ context.read().add(const OptionPannelEvent.beginAddingOption());
+ },
+ ),
+ ),
+ );
}
return SizedBox(
@@ -135,19 +115,16 @@ class _OptionList extends StatelessWidget {
return _OptionItem(option: option);
}).toList();
- return SizedBox(
- width: 120,
- child: ListView.separated(
- shrinkWrap: true,
- controller: ScrollController(),
- separatorBuilder: (context, index) {
- return VSpace(GridSize.typeOptionSeparatorHeight);
- },
- itemCount: optionItems.length,
- itemBuilder: (BuildContext context, int index) {
- return optionItems[index];
- },
- ),
+ return ListView.separated(
+ shrinkWrap: true,
+ controller: ScrollController(),
+ separatorBuilder: (context, index) {
+ return VSpace(GridSize.typeOptionSeparatorHeight);
+ },
+ itemCount: optionItems.length,
+ itemBuilder: (BuildContext context, int index) {
+ return optionItems[index];
+ },
);
},
);
@@ -167,7 +144,7 @@ class _OptionItem extends StatelessWidget {
text: FlowyText.medium(option.name, fontSize: 12),
hoverColor: theme.hover,
onTap: () {},
- rightIcon: svg("grid/more", color: theme.iconColor),
+ rightIcon: svg("grid/details", color: theme.iconColor),
),
);
}
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart
new file mode 100644
index 0000000000..6690729ff0
--- /dev/null
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart
@@ -0,0 +1,55 @@
+import 'package:app_flowy/startup/startup.dart';
+import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart';
+import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_tyep_switcher.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'option_pannel.dart';
+
+class SingleSelectTypeOptionBuilder extends TypeOptionBuilder {
+ final SingleSelectTypeOptionWidget _widget;
+
+ SingleSelectTypeOptionBuilder(
+ String fieldId,
+ TypeOptionData typeOptionData,
+ TypeOptionOperationDelegate delegate,
+ ) : _widget = SingleSelectTypeOptionWidget(
+ fieldId,
+ SingleSelectTypeOption.fromBuffer(typeOptionData),
+ delegate,
+ );
+
+ @override
+ Widget? get customWidget => _widget;
+}
+
+class SingleSelectTypeOptionWidget extends TypeOptionWidget {
+ final String fieldId;
+ final SingleSelectTypeOption typeOption;
+ final TypeOptionOperationDelegate delegate;
+ const SingleSelectTypeOptionWidget(this.fieldId, this.typeOption, this.delegate, {Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocProvider(
+ create: (context) => getIt(param1: typeOption, param2: fieldId),
+ child: BlocConsumer(
+ listener: (context, state) => delegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()),
+ builder: (context, state) {
+ return OptionPannel(
+ options: state.typeOption.options,
+ beginEdit: () {
+ delegate.hideOverlay(context);
+ },
+ createOptionCallback: (name) {
+ context.read().add(SingleSelectTypeOptionEvent.createOption(name));
+ },
+ updateOptionsCallback: (options) {
+ context.read().add(SingleSelectTypeOptionEvent.updateOptions(options));
+ },
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart
index f357c9afea..6f4e86a4e1 100644
--- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart
+++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart
@@ -21,6 +21,7 @@ class NameTextField extends StatefulWidget {
class _NameTextFieldState extends State {
late FocusNode _focusNode;
+ var isEdited = false;
late TextEditingController _controller;
@override
@@ -35,31 +36,53 @@ class _NameTextFieldState extends State {
@override
Widget build(BuildContext context) {
final theme = context.watch();
+
return RoundedInputField(
- controller: _controller,
- focusNode: _focusNode,
- height: 36,
- style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500),
- normalBorderColor: theme.shader4,
- errorBorderColor: theme.red,
- focusBorderColor: theme.main1,
- cursorColor: theme.main1,
- onChanged: (text) {
- print(text);
- });
+ controller: _controller,
+ focusNode: _focusNode,
+ autoFocus: true,
+ height: 36,
+ style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500),
+ normalBorderColor: theme.shader4,
+ focusBorderColor: theme.main1,
+ cursorColor: theme.main1,
+ onEditingComplete: () {
+ widget.onDone(_controller.text);
+ },
+ );
}
@override
void dispose() {
_focusNode.removeListener(notifyDidEndEditing);
+ _focusNode.dispose();
super.dispose();
}
void notifyDidEndEditing() {
if (_controller.text.isEmpty) {
- // widget.onCanceled();
+ if (isEdited) {
+ widget.onCanceled();
+ }
+ isEdited = true;
} else {
widget.onDone(_controller.text);
}
}
}
+
+class TypeOptionSeparator extends StatelessWidget {
+ const TypeOptionSeparator({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = context.watch();
+ return Padding(
+ padding: const EdgeInsets.symmetric(vertical: 6),
+ child: Container(
+ color: theme.shader4,
+ height: 0.25,
+ ),
+ );
+ }
+}
diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart
index 0bcd05f56e..13d02a0ea8 100644
--- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart
+++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart
@@ -15,7 +15,7 @@ class FlowyButton extends StatelessWidget {
Key? key,
required this.text,
this.onTap,
- this.padding = const EdgeInsets.symmetric(horizontal: 3, vertical: 2),
+ this.padding = const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
this.leftIcon,
this.rightIcon,
this.hoverColor = Colors.transparent,
@@ -44,12 +44,13 @@ class FlowyButton extends StatelessWidget {
if (rightIcon != null) {
children.add(SizedBox.fromSize(size: const Size.square(16), child: rightIcon!));
- children.add(const HSpace(6));
}
return Padding(
padding: padding,
child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart
index b6bf1daf4b..0af5e4ec89 100644
--- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart
+++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart
@@ -15,6 +15,7 @@ class RoundedInputField extends StatefulWidget {
final String errorText;
final TextStyle style;
final ValueChanged? onChanged;
+ final VoidCallback? onEditingComplete;
final String? initialValue;
final EdgeInsets margin;
final EdgeInsets padding;
@@ -22,6 +23,7 @@ class RoundedInputField extends StatefulWidget {
final double height;
final FocusNode? focusNode;
final TextEditingController? controller;
+ final bool autoFocus;
const RoundedInputField({
Key? key,
@@ -32,6 +34,7 @@ class RoundedInputField extends StatefulWidget {
this.obscureIcon,
this.obscureHideIcon,
this.onChanged,
+ this.onEditingComplete,
this.normalBorderColor = Colors.transparent,
this.errorBorderColor = Colors.transparent,
this.focusBorderColor,
@@ -43,6 +46,7 @@ class RoundedInputField extends StatefulWidget {
this.height = 48,
this.focusNode,
this.controller,
+ this.autoFocus = false,
}) : super(key: key);
@override
@@ -78,6 +82,7 @@ class _RoundedInputFieldState extends State {
controller: widget.controller,
initialValue: widget.initialValue,
focusNode: widget.focusNode,
+ autofocus: widget.autoFocus,
onChanged: (value) {
inputText = value;
if (widget.onChanged != null) {
@@ -85,6 +90,7 @@ class _RoundedInputFieldState extends State {
}
setState(() {});
},
+ onEditingComplete: widget.onEditingComplete,
cursorColor: widget.cursorColor,
obscureText: obscuteText,
style: widget.style,
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
index 7f25329284..04098b288e 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
@@ -137,6 +137,23 @@ class GridEventCreateEditFieldContext {
}
}
+class GridEventCreateSelectOption {
+ CreateSelectOptionPayload request;
+ GridEventCreateSelectOption(this.request);
+
+ Future> send() {
+ final request = FFIRequest.create()
+ ..event = GridEvent.CreateSelectOption.toString()
+ ..payload = requestToBytes(this.request);
+
+ return Dispatch.asyncRequest(request)
+ .then((bytesResult) => bytesResult.fold(
+ (okBytes) => left(SelectOption.fromBuffer(okBytes)),
+ (errBytes) => right(FlowyError.fromBuffer(errBytes)),
+ ));
+ }
+}
+
class GridEventCreateRow {
CreateRowPayload request;
GridEventCreateRow(this.request);
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart
index b068956465..e2be9f11a2 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart
@@ -4,6 +4,7 @@ import 'package:flowy_sdk/log.dart';
// ignore: unnecessary_import
import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-net/event.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/event_map.pb.dart';
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart
index 307b9f86f2..9c4e31eeea 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart
@@ -47,6 +47,7 @@ class ErrorCode extends $pb.ProtobufEnum {
static const ErrorCode RowIdIsEmpty = ErrorCode._(430, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty');
static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty');
static const ErrorCode FieldDoesNotExist = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldDoesNotExist');
+ static const ErrorCode SelectOptionNameIsEmpty = ErrorCode._(442, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SelectOptionNameIsEmpty');
static const ErrorCode TypeOptionDataIsEmpty = ErrorCode._(450, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionDataIsEmpty');
static const ErrorCode InvalidData = ErrorCode._(500, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData');
@@ -88,6 +89,7 @@ class ErrorCode extends $pb.ProtobufEnum {
RowIdIsEmpty,
FieldIdIsEmpty,
FieldDoesNotExist,
+ SelectOptionNameIsEmpty,
TypeOptionDataIsEmpty,
InvalidData,
];
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart
index 9345118baa..b3efa2c0ad 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart
@@ -49,10 +49,11 @@ const ErrorCode$json = const {
const {'1': 'RowIdIsEmpty', '2': 430},
const {'1': 'FieldIdIsEmpty', '2': 440},
const {'1': 'FieldDoesNotExist', '2': 441},
+ const {'1': 'SelectOptionNameIsEmpty', '2': 442},
const {'1': 'TypeOptionDataIsEmpty', '2': 450},
const {'1': 'InvalidData', '2': 500},
],
};
/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM=');
+final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIcChdTZWxlY3RPcHRpb25OYW1lSXNFbXB0eRC6AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM=');
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
index bd9afe2243..3dafd193b3 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart
@@ -1536,3 +1536,50 @@ class QueryRowPayload extends $pb.GeneratedMessage {
void clearRowId() => clearField(3);
}
+class CreateSelectOptionPayload extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateSelectOptionPayload', createEmptyInstance: create)
+ ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'optionName')
+ ..hasRequiredFields = false
+ ;
+
+ CreateSelectOptionPayload._() : super();
+ factory CreateSelectOptionPayload({
+ $core.String? optionName,
+ }) {
+ final _result = create();
+ if (optionName != null) {
+ _result.optionName = optionName;
+ }
+ return _result;
+ }
+ factory CreateSelectOptionPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory CreateSelectOptionPayload.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ CreateSelectOptionPayload clone() => CreateSelectOptionPayload()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ CreateSelectOptionPayload copyWith(void Function(CreateSelectOptionPayload) updates) => super.copyWith((message) => updates(message as CreateSelectOptionPayload)) as CreateSelectOptionPayload; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static CreateSelectOptionPayload create() => CreateSelectOptionPayload._();
+ CreateSelectOptionPayload createEmptyInstance() => create();
+ static $pb.PbList createRepeated() => $pb.PbList();
+ @$core.pragma('dart2js:noInline')
+ static CreateSelectOptionPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create);
+ static CreateSelectOptionPayload? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get optionName => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set optionName($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasOptionName() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearOptionName() => clearField(1);
+}
+
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
index 0b900d46f9..3b7c58924e 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart
@@ -302,3 +302,13 @@ const QueryRowPayload$json = const {
/// Descriptor for `QueryRowPayload`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List queryRowPayloadDescriptor = $convert.base64Decode('Cg9RdWVyeVJvd1BheWxvYWQSFwoHZ3JpZF9pZBgBIAEoCVIGZ3JpZElkEhkKCGJsb2NrX2lkGAIgASgJUgdibG9ja0lkEhUKBnJvd19pZBgDIAEoCVIFcm93SWQ=');
+@$core.Deprecated('Use createSelectOptionPayloadDescriptor instead')
+const CreateSelectOptionPayload$json = const {
+ '1': 'CreateSelectOptionPayload',
+ '2': const [
+ const {'1': 'option_name', '3': 1, '4': 1, '5': 9, '10': 'optionName'},
+ ],
+};
+
+/// Descriptor for `CreateSelectOptionPayload`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List createSelectOptionPayloadDescriptor = $convert.base64Decode('ChlDcmVhdGVTZWxlY3RPcHRpb25QYXlsb2FkEh8KC29wdGlvbl9uYW1lGAEgASgJUgpvcHRpb25OYW1l');
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
index 46291923e0..25319128d8 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
@@ -18,9 +18,10 @@ class GridEvent extends $pb.ProtobufEnum {
static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField');
static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField');
static const GridEvent CreateEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext');
- static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
- static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
- static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
+ static const GridEvent CreateSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateSelectOption');
+ static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
+ static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
+ static const GridEvent UpdateCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
static const $core.List values = [
GetGridData,
@@ -31,6 +32,7 @@ class GridEvent extends $pb.ProtobufEnum {
DeleteField,
DuplicateField,
CreateEditFieldContext,
+ CreateSelectOption,
CreateRow,
GetRow,
UpdateCell,
diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
index 278e0b14c3..747a591a02 100644
--- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
+++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
@@ -20,11 +20,12 @@ const GridEvent$json = const {
const {'1': 'DeleteField', '2': 13},
const {'1': 'DuplicateField', '2': 15},
const {'1': 'CreateEditFieldContext', '2': 16},
- const {'1': 'CreateRow', '2': 21},
- const {'1': 'GetRow', '2': 22},
- const {'1': 'UpdateCell', '2': 30},
+ const {'1': 'CreateSelectOption', '2': 30},
+ const {'1': 'CreateRow', '2': 50},
+ const {'1': 'GetRow', '2': 51},
+ const {'1': 'UpdateCell', '2': 70},
],
};
/// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASDQoJQ3JlYXRlUm93EBUSCgoGR2V0Um93EBYSDgoKVXBkYXRlQ2VsbBAe');
+final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASFgoSQ3JlYXRlU2VsZWN0T3B0aW9uEB4SDQoJQ3JlYXRlUm93EDISCgoGR2V0Um93EDMSDgoKVXBkYXRlQ2VsbBBG');
diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs
index 97b91e5557..d29c2aec48 100644
--- a/frontend/rust-lib/flowy-grid/src/event_handler.rs
+++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs
@@ -1,5 +1,5 @@
use crate::manager::GridManager;
-use crate::services::field::type_option_data_from_str;
+use crate::services::field::{type_option_data_from_str, SelectOption};
use flowy_error::FlowyError;
use flowy_grid_data_model::entities::*;
use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
@@ -88,6 +88,14 @@ pub(crate) async fn duplicate_field_handler(
Ok(())
}
+#[tracing::instrument(level = "debug", skip(data), err)]
+pub(crate) async fn create_select_option_handler(
+ data: Data,
+) -> DataResult {
+ let params: CreateSelectOptionParams = data.into_inner().try_into()?;
+ data_result(SelectOption::new(¶ms.option_name))
+}
+
#[tracing::instrument(level = "debug", skip(data, manager), err)]
pub(crate) async fn create_edit_field_context_handler(
data: Data,
diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs
index efe5ddc094..966423c7c7 100644
--- a/frontend/rust-lib/flowy-grid/src/event_map.rs
+++ b/frontend/rust-lib/flowy-grid/src/event_map.rs
@@ -16,6 +16,7 @@ pub fn create(grid_manager: Arc) -> Module {
.event(GridEvent::DeleteField, delete_field_handler)
.event(GridEvent::DuplicateField, duplicate_field_handler)
.event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler)
+ .event(GridEvent::CreateSelectOption, create_select_option_handler)
.event(GridEvent::CreateRow, create_row_handler)
.event(GridEvent::GetRow, get_row_handler)
.event(GridEvent::UpdateCell, update_cell_handler);
@@ -50,12 +51,15 @@ pub enum GridEvent {
#[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")]
CreateEditFieldContext = 16,
+ #[event(input = "CreateSelectOptionPayload", output = "SelectOption")]
+ CreateSelectOption = 30,
+
#[event(input = "CreateRowPayload", output = "Row")]
- CreateRow = 21,
+ CreateRow = 50,
#[event(input = "QueryRowPayload", output = "Row")]
- GetRow = 22,
+ GetRow = 51,
#[event(input = "CellMetaChangeset")]
- UpdateCell = 30,
+ UpdateCell = 70,
}
diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
index 13ee0705cc..2eab7357c5 100644
--- a/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
+++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
@@ -33,9 +33,10 @@ pub enum GridEvent {
DeleteField = 13,
DuplicateField = 15,
CreateEditFieldContext = 16,
- CreateRow = 21,
- GetRow = 22,
- UpdateCell = 30,
+ CreateSelectOption = 30,
+ CreateRow = 50,
+ GetRow = 51,
+ UpdateCell = 70,
}
impl ::protobuf::ProtobufEnum for GridEvent {
@@ -53,9 +54,10 @@ impl ::protobuf::ProtobufEnum for GridEvent {
13 => ::std::option::Option::Some(GridEvent::DeleteField),
15 => ::std::option::Option::Some(GridEvent::DuplicateField),
16 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext),
- 21 => ::std::option::Option::Some(GridEvent::CreateRow),
- 22 => ::std::option::Option::Some(GridEvent::GetRow),
- 30 => ::std::option::Option::Some(GridEvent::UpdateCell),
+ 30 => ::std::option::Option::Some(GridEvent::CreateSelectOption),
+ 50 => ::std::option::Option::Some(GridEvent::CreateRow),
+ 51 => ::std::option::Option::Some(GridEvent::GetRow),
+ 70 => ::std::option::Option::Some(GridEvent::UpdateCell),
_ => ::std::option::Option::None
}
}
@@ -70,6 +72,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
GridEvent::DeleteField,
GridEvent::DuplicateField,
GridEvent::CreateEditFieldContext,
+ GridEvent::CreateSelectOption,
GridEvent::CreateRow,
GridEvent::GetRow,
GridEvent::UpdateCell,
@@ -101,12 +104,13 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
}
static file_descriptor_proto_data: &'static [u8] = b"\
- \n\x0fevent_map.proto*\xcc\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
+ \n\x0fevent_map.proto*\xe4\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
\0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\
\x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\
leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x1a\n\x16CreateE\
- ditFieldContext\x10\x10\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\
- \x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\
+ ditFieldContext\x10\x10\x12\x16\n\x12CreateSelectOption\x10\x1e\x12\r\n\
+ \tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\x0e\n\nUpdateCell\x10Fb\x06p\
+ roto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
index 327a1e3aee..ebc7ae6782 100644
--- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
+++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
@@ -9,7 +9,8 @@ enum GridEvent {
DeleteField = 13;
DuplicateField = 15;
CreateEditFieldContext = 16;
- CreateRow = 21;
- GetRow = 22;
- UpdateCell = 30;
+ CreateSelectOption = 30;
+ CreateRow = 50;
+ GetRow = 51;
+ UpdateCell = 70;
}
diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs
index 7c813bd1e0..3b0cf331ee 100644
--- a/shared-lib/flowy-error-code/src/code.rs
+++ b/shared-lib/flowy-error-code/src/code.rs
@@ -99,6 +99,8 @@ pub enum ErrorCode {
FieldIdIsEmpty = 440,
#[display(fmt = "Field doesn't exist")]
FieldDoesNotExist = 441,
+ #[display(fmt = "The name of the option should not be empty")]
+ SelectOptionNameIsEmpty = 442,
#[display(fmt = "Field's type option data should not be empty")]
TypeOptionDataIsEmpty = 450,
diff --git a/shared-lib/flowy-error-code/src/protobuf/model/code.rs b/shared-lib/flowy-error-code/src/protobuf/model/code.rs
index 8e6e1b9621..6e6db9139b 100644
--- a/shared-lib/flowy-error-code/src/protobuf/model/code.rs
+++ b/shared-lib/flowy-error-code/src/protobuf/model/code.rs
@@ -62,6 +62,7 @@ pub enum ErrorCode {
RowIdIsEmpty = 430,
FieldIdIsEmpty = 440,
FieldDoesNotExist = 441,
+ SelectOptionNameIsEmpty = 442,
TypeOptionDataIsEmpty = 450,
InvalidData = 500,
}
@@ -110,6 +111,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
430 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty),
440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty),
441 => ::std::option::Option::Some(ErrorCode::FieldDoesNotExist),
+ 442 => ::std::option::Option::Some(ErrorCode::SelectOptionNameIsEmpty),
450 => ::std::option::Option::Some(ErrorCode::TypeOptionDataIsEmpty),
500 => ::std::option::Option::Some(ErrorCode::InvalidData),
_ => ::std::option::Option::None
@@ -155,6 +157,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
ErrorCode::RowIdIsEmpty,
ErrorCode::FieldIdIsEmpty,
ErrorCode::FieldDoesNotExist,
+ ErrorCode::SelectOptionNameIsEmpty,
ErrorCode::TypeOptionDataIsEmpty,
ErrorCode::InvalidData,
];
@@ -185,7 +188,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode {
}
static file_descriptor_proto_data: &'static [u8] = b"\
- \n\ncode.proto*\x80\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\
+ \n\ncode.proto*\x9e\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\
\n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\
\x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\
\x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\
@@ -205,8 +208,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\
erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x12\n\rG\
ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\
\n\x0cRowIdIsEmpty\x10\xae\x03\x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\
- \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1a\n\x15TypeOptionDataI\
- sEmpty\x10\xc2\x03\x12\x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\
+ \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1c\n\x17SelectOptionNam\
+ eIsEmpty\x10\xba\x03\x12\x1a\n\x15TypeOptionDataIsEmpty\x10\xc2\x03\x12\
+ \x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
diff --git a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto
index e01c42aa8b..d435d558dc 100644
--- a/shared-lib/flowy-error-code/src/protobuf/proto/code.proto
+++ b/shared-lib/flowy-error-code/src/protobuf/proto/code.proto
@@ -38,6 +38,7 @@ enum ErrorCode {
RowIdIsEmpty = 430;
FieldIdIsEmpty = 440;
FieldDoesNotExist = 441;
+ SelectOptionNameIsEmpty = 442;
TypeOptionDataIsEmpty = 450;
InvalidData = 500;
}
diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs
index dfd5dc397f..a85b8d382a 100644
--- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs
+++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs
@@ -1,5 +1,5 @@
use crate::entities::{FieldMeta, FieldType, RowMeta};
-use crate::parser::NotEmptyUuid;
+use crate::parser::{NotEmptyStr, NotEmptyUuid};
use flowy_derive::ProtoBuf;
use flowy_error_code::ErrorCode;
use std::collections::HashMap;
@@ -494,3 +494,24 @@ impl TryInto for QueryRowPayload {
})
}
}
+
+#[derive(ProtoBuf, Default)]
+pub struct CreateSelectOptionPayload {
+ #[pb(index = 1)]
+ pub option_name: String,
+}
+
+pub struct CreateSelectOptionParams {
+ pub option_name: String,
+}
+
+impl TryInto for CreateSelectOptionPayload {
+ type Error = ErrorCode;
+
+ fn try_into(self) -> Result {
+ let option_name = NotEmptyStr::parse(self.option_name).map_err(|_| ErrorCode::SelectOptionNameIsEmpty)?;
+ Ok(CreateSelectOptionParams {
+ option_name: option_name.0,
+ })
+ }
+}
diff --git a/shared-lib/flowy-grid-data-model/src/parser/mod.rs b/shared-lib/flowy-grid-data-model/src/parser/mod.rs
index 7cb72eb859..3c43c76f39 100644
--- a/shared-lib/flowy-grid-data-model/src/parser/mod.rs
+++ b/shared-lib/flowy-grid-data-model/src/parser/mod.rs
@@ -1,3 +1,3 @@
-mod id_parser;
+mod str_parser;
-pub use id_parser::*;
+pub use str_parser::*;
diff --git a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs b/shared-lib/flowy-grid-data-model/src/parser/str_parser.rs
similarity index 54%
rename from shared-lib/flowy-grid-data-model/src/parser/id_parser.rs
rename to shared-lib/flowy-grid-data-model/src/parser/str_parser.rs
index 5003ab2ce4..3e5e3c622b 100644
--- a/shared-lib/flowy-grid-data-model/src/parser/id_parser.rs
+++ b/shared-lib/flowy-grid-data-model/src/parser/str_parser.rs
@@ -19,3 +19,21 @@ impl AsRef for NotEmptyUuid {
&self.0
}
}
+
+#[derive(Debug)]
+pub struct NotEmptyStr(pub String);
+
+impl NotEmptyStr {
+ pub fn parse(s: String) -> Result {
+ if s.trim().is_empty() {
+ return Err("Input string is empty".to_owned());
+ }
+ Ok(Self(s))
+ }
+}
+
+impl AsRef for NotEmptyStr {
+ fn as_ref(&self) -> &str {
+ &self.0
+ }
+}
diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
index c18043184f..d55c5dac10 100644
--- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
+++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs
@@ -5258,6 +5258,165 @@ impl ::protobuf::reflect::ProtobufValue for QueryRowPayload {
}
}
+#[derive(PartialEq,Clone,Default)]
+pub struct CreateSelectOptionPayload {
+ // message fields
+ pub option_name: ::std::string::String,
+ // special fields
+ pub unknown_fields: ::protobuf::UnknownFields,
+ pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a CreateSelectOptionPayload {
+ fn default() -> &'a CreateSelectOptionPayload {
+ ::default_instance()
+ }
+}
+
+impl CreateSelectOptionPayload {
+ pub fn new() -> CreateSelectOptionPayload {
+ ::std::default::Default::default()
+ }
+
+ // string option_name = 1;
+
+
+ pub fn get_option_name(&self) -> &str {
+ &self.option_name
+ }
+ pub fn clear_option_name(&mut self) {
+ self.option_name.clear();
+ }
+
+ // Param is passed by value, moved
+ pub fn set_option_name(&mut self, v: ::std::string::String) {
+ self.option_name = v;
+ }
+
+ // Mutable pointer to the field.
+ // If field is not initialized, it is initialized with default value first.
+ pub fn mut_option_name(&mut self) -> &mut ::std::string::String {
+ &mut self.option_name
+ }
+
+ // Take field
+ pub fn take_option_name(&mut self) -> ::std::string::String {
+ ::std::mem::replace(&mut self.option_name, ::std::string::String::new())
+ }
+}
+
+impl ::protobuf::Message for CreateSelectOptionPayload {
+ fn is_initialized(&self) -> bool {
+ true
+ }
+
+ fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+ while !is.eof()? {
+ let (field_number, wire_type) = is.read_tag_unpack()?;
+ match field_number {
+ 1 => {
+ ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.option_name)?;
+ },
+ _ => {
+ ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+ },
+ };
+ }
+ ::std::result::Result::Ok(())
+ }
+
+ // Compute sizes of nested messages
+ #[allow(unused_variables)]
+ fn compute_size(&self) -> u32 {
+ let mut my_size = 0;
+ if !self.option_name.is_empty() {
+ my_size += ::protobuf::rt::string_size(1, &self.option_name);
+ }
+ my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+ self.cached_size.set(my_size);
+ my_size
+ }
+
+ fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+ if !self.option_name.is_empty() {
+ os.write_string(1, &self.option_name)?;
+ }
+ os.write_unknown_fields(self.get_unknown_fields())?;
+ ::std::result::Result::Ok(())
+ }
+
+ fn get_cached_size(&self) -> u32 {
+ self.cached_size.get()
+ }
+
+ fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+ &self.unknown_fields
+ }
+
+ fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+ &mut self.unknown_fields
+ }
+
+ fn as_any(&self) -> &dyn (::std::any::Any) {
+ self as &dyn (::std::any::Any)
+ }
+ fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+ self as &mut dyn (::std::any::Any)
+ }
+ fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box {
+ self
+ }
+
+ fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+ Self::descriptor_static()
+ }
+
+ fn new() -> CreateSelectOptionPayload {
+ CreateSelectOptionPayload::new()
+ }
+
+ fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+ static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+ descriptor.get(|| {
+ let mut fields = ::std::vec::Vec::new();
+ fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+ "option_name",
+ |m: &CreateSelectOptionPayload| { &m.option_name },
+ |m: &mut CreateSelectOptionPayload| { &mut m.option_name },
+ ));
+ ::protobuf::reflect::MessageDescriptor::new_pb_name::(
+ "CreateSelectOptionPayload",
+ fields,
+ file_descriptor_proto()
+ )
+ })
+ }
+
+ fn default_instance() -> &'static CreateSelectOptionPayload {
+ static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT;
+ instance.get(CreateSelectOptionPayload::new)
+ }
+}
+
+impl ::protobuf::Clear for CreateSelectOptionPayload {
+ fn clear(&mut self) {
+ self.option_name.clear();
+ self.unknown_fields.clear();
+ }
+}
+
+impl ::std::fmt::Debug for CreateSelectOptionPayload {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ ::protobuf::text_format::fmt(self, f)
+ }
+}
+
+impl ::protobuf::reflect::ProtobufValue for CreateSelectOptionPayload {
+ fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+ ::protobuf::reflect::ReflectValueRef::Message(self)
+ }
+}
+
static file_descriptor_proto_data: &'static [u8] = b"\
\n\ngrid.proto\x1a\nmeta.proto\"z\n\x04Grid\x12\x0e\n\x02id\x18\x01\x20\
\x01(\tR\x02id\x12.\n\x0cfield_orders\x18\x02\x20\x03(\x0b2\x0b.FieldOrd\
@@ -5311,7 +5470,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\
ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\
\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\
\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\
- kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowIdb\x06proto3\
+ kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\"<\n\x19CreateSelec\
+ tOptionPayload\x12\x1f\n\x0boption_name\x18\x01\x20\x01(\tR\noptionNameb\
+ \x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto
index 3a74e23026..5c07b98d30 100644
--- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto
+++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto
@@ -103,3 +103,6 @@ message QueryRowPayload {
string block_id = 2;
string row_id = 3;
}
+message CreateSelectOptionPayload {
+ string option_name = 1;
+}