diff --git a/frontend/app_flowy/lib/plugins/board/application/card/board_select_option_cell_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/board_select_option_cell_bloc.dart index 1b70710a35..daa4dcc383 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/board_select_option_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/board_select_option_cell_bloc.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.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 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart index b0fbee15cd..759b7a1ed7 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart @@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_cell_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_cell_bloc.dart index fca90c9903..8ca25a6050 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_cell_bloc.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.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 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; 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 d5671e27d7..931e370855 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 @@ -4,7 +4,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic import 'package:collection/collection.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.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'; 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 5ed44debbf..22f3b02eb1 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 @@ -3,7 +3,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'cell_service/cell_service.dart'; class SelectOptionService { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/edit_select_option_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/edit_select_option_bloc.dart index 9f1dd4dd1d..f3ad6c80bc 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/edit_select_option_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/edit_select_option_bloc.dart @@ -1,4 +1,4 @@ -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.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'; @@ -6,8 +6,10 @@ import 'package:protobuf/protobuf.dart'; import 'package:dartz/dartz.dart'; part 'edit_select_option_bloc.freezed.dart'; -class EditSelectOptionBloc extends Bloc { - EditSelectOptionBloc({required SelectOptionPB option}) : super(EditSelectOptionState.initial(option)) { +class EditSelectOptionBloc + extends Bloc { + EditSelectOptionBloc({required SelectOptionPB option}) + : super(EditSelectOptionState.initial(option)) { on( (event, emit) async { event.map( @@ -48,7 +50,8 @@ class EditSelectOptionBloc extends Bloc deleted, }) = _EditSelectOptionState; - factory EditSelectOptionState.initial(SelectOptionPB option) => EditSelectOptionState( + factory EditSelectOptionState.initial(SelectOptionPB option) => + EditSelectOptionState( option: option, deleted: none(), ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart index 7fd50e5364..f1bb7bfecf 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart @@ -1,6 +1,6 @@ import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'dart:async'; import 'select_option_type_option_bloc.dart'; import 'type_option_context.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart index d1cdb3b2ec..39f1f31f06 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart @@ -1,4 +1,4 @@ -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.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'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart index 5cc50dad61..186f2d7602 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart @@ -1,5 +1,5 @@ import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart'; import 'dart:async'; import 'package:protobuf/protobuf.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart index 5407515f62..de6a000d75 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart @@ -2,7 +2,7 @@ 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/cell_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; class TypeOptionFFIService { final String gridId; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart index 3f60de4142..90aa59d23a 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart @@ -1,7 +1,7 @@ import 'package:flowy_infra/theme.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/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.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 d55825a0de..5ffea7dbb8 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 @@ -7,7 +7,7 @@ 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_option.pb.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/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 eab8693ff6..d6b08e507d 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 @@ -10,7 +10,7 @@ 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_option.pb.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'; import 'package:easy_localization/easy_localization.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart index b77088b810..7586709f2c 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart @@ -2,7 +2,7 @@ import 'dart:collection'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.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 002dda79f1..00d1ea6332 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 @@ -6,7 +6,7 @@ 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_option.pb.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'; import 'package:easy_localization/easy_localization.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart index ab9303b189..44200ba5c2 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart @@ -6,7 +6,7 @@ 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/select_option.pb.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'; import 'package:easy_localization/easy_localization.dart'; diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 460f29dec1..8d2ac8d9f0 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -2,7 +2,7 @@ use crate::entities::*; use crate::manager::GridManager; use crate::services::cell::AnyCellData; use crate::services::field::{ - default_type_option_builder_from_type, select_option_operation, type_option_builder_from_json_str, + default_type_option_builder_from_type, select_type_option_from_field_rev, type_option_builder_from_json_str, DateChangesetParams, DateChangesetPayloadPB, SelectOptionCellChangeset, SelectOptionCellChangesetParams, SelectOptionCellChangesetPayloadPB, SelectOptionCellDataPB, SelectOptionChangeset, SelectOptionChangesetPayloadPB, SelectOptionPB, @@ -321,7 +321,7 @@ pub(crate) async fn new_select_option_handler( match editor.get_field_rev(¶ms.field_id).await { None => Err(ErrorCode::InvalidData.into()), Some(field_rev) => { - let type_option = select_option_operation(&field_rev)?; + let type_option = select_type_option_from_field_rev(&field_rev)?; let select_option = type_option.create_option(¶ms.option_name); data_result(select_option) } @@ -338,7 +338,7 @@ pub(crate) async fn update_select_option_handler( let _ = editor .modify_field_rev(&changeset.cell_identifier.field_id, |field_rev| { - let mut type_option = select_option_operation(field_rev)?; + let mut type_option = select_type_option_from_field_rev(field_rev)?; let mut cell_content_changeset = None; let mut is_changed = None; @@ -400,7 +400,7 @@ pub(crate) async fn get_select_option_handler( Some(field_rev) => { // let cell_rev = editor.get_cell_rev(¶ms.row_id, ¶ms.field_id).await?; - let type_option = select_option_operation(&field_rev)?; + let type_option = select_type_option_from_field_rev(&field_rev)?; let any_cell_data: AnyCellData = match cell_rev { None => AnyCellData { data: "".to_string(), @@ -408,8 +408,8 @@ pub(crate) async fn get_select_option_handler( }, Some(cell_rev) => cell_rev.try_into()?, }; - let option_context = type_option.selected_select_option(any_cell_data.into()); - data_result(option_context) + let selected_options = type_option.get_selected_options(any_cell_data.into()); + data_result(selected_options) } } } 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 681e8beffe..95c9c2f5bb 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 @@ -18,14 +18,49 @@ pub trait CellGroupOperation { /// Return object that describes the cell. pub trait CellDisplayable { - fn display_data( + /// Serialize the cell data into `CellBytes` that will be posted to the `Dart` side. Using the + /// corresponding protobuf struct implement in `Dart` to deserialize the data. + /// + /// Using `utf8` to encode the cell data if the cell data use `String` as its data container. + /// Using `protobuf` to encode the cell data if the cell data use `Protobuf struct` as its data container. + /// + /// When switching the field type of the `FieldRevision` to another field type. The `field_type` + /// of the `FieldRevision` is not equal to the `decoded_field_type`. The cell data is need to do + /// some custom transformation. + /// + /// For example, the current field type of the `FieldRevision` is a checkbox. When switching the field + /// type from the checkbox to single select, the `TypeOptionBuilder`'s transform method gets called. + /// It will create two new options,`Yes` and `No`, if they don't exist. But the cell data didn't change, + /// because we can't iterate all the rows to transform the cell data that can be parsed by the current + /// field type. One approach is to transform the cell data when it get read. For the moment, + /// the cell data is a string, `Yes` or `No`. It needs to compare with the option's name, if match + /// return the id of the option. Otherwise, return a default value of `CellBytes`. + /// + /// # Arguments + /// + /// * `cell_data`: the generic annotation `CD` represents as the deserialize data type of the cell. + /// * `decoded_field_type`: the field type of the cell_data when doing serialization + /// + /// returns: Result + /// + fn displayed_cell_bytes( &self, cell_data: CellData, decoded_field_type: &FieldType, field_rev: &FieldRevision, ) -> FlowyResult; - fn display_string( + /// Serialize the cell data into `String` that is readable + /// + /// The cell data is not readable which means it can't display the cell data directly to user. + /// For example, + /// 1. the cell data is timestamp if its field type is FieldType::Date that is not readable. + /// It needs to be parsed as the date string. + /// + /// 2. the cell data is a commas separated id if its field type if FieldType::MultiSelect that is not readable. + /// It needs to be parsed as a commas separated option name. + /// + fn displayed_cell_string( &self, cell_data: CellData, decoded_field_type: &FieldType, @@ -33,16 +68,19 @@ pub trait CellDisplayable { ) -> FlowyResult; } -// CD: Short for CellData. This type is the type return by apply_changeset function. -// CS: Short for Changeset. Parse the string into specific Changeset type. pub trait CellDataOperation { - /// Decode the cell data into `CD` that is certain type of data. + /// The generic annotation `CD` represents as the deserialize data type of the cell data. + /// The Serialize/Deserialize struct of the cell is base on the field type of the cell. /// - /// Each `CD` type represents as a specific field type data. For example: + /// For example: /// FieldType::URL => URLCellData /// FieldType::Date=> DateCellData /// - /// `decoded_field_type`: the field type of the cell data + /// Each cell data is a opaque data, it needs to deserialized to a concrete data struct + /// + /// `cell_data`: the opaque data of the cell. + /// `decoded_field_type`: the field type of the cell data when doing serialization + /// `field_rev`: the field of the cell data /// /// Returns the error if the cell data can't be parsed into `CD`. /// @@ -53,9 +91,12 @@ pub trait CellDataOperation { field_rev: &FieldRevision, ) -> FlowyResult; - /// The changeset is able to parse into the specific data if CS impl the FromCellChangeset trait. + /// The changeset is able to parse into the concrete data struct if CS implements + /// the `FromCellChangeset` trait. + /// /// For example: - /// SelectOptionCellChangeset,DateCellChangeset. etc. + /// SelectOptionCellChangeset,DateCellChangeset. etc. + /// fn apply_changeset(&self, changeset: CellDataChangeset, cell_rev: Option) -> FlowyResult; } @@ -126,25 +167,25 @@ pub fn decode_cell_data_to_string( let result = match to_field_type { FieldType::RichText => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::Number => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::DateTime => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::SingleSelect => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::MultiSelect => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::Checkbox => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), FieldType::URL => field_rev .get_type_option::(field_type)? - .display_string(cell_data.into(), from_field_type, field_rev), + .displayed_cell_string(cell_data.into(), from_field_type, field_rev), }; Some(result) }; 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 d62f6ef974..c2b2c549fa 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 @@ -4,7 +4,10 @@ use bytes::Bytes; use flowy_grid_data_model::revision::TypeOptionDataSerializer; pub trait TypeOptionBuilder { + /// Returns the type of the type-option data fn field_type(&self) -> FieldType; + + /// Returns a serializer that can be used to serialize the type-option data fn serializer(&self) -> &dyn TypeOptionDataSerializer; /// Transform the data from passed-in type-option to current type-option diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs index 9c672bb941..399dffbb3a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs @@ -45,7 +45,7 @@ pub struct CheckboxTypeOptionPB { impl_type_option!(CheckboxTypeOptionPB, FieldType::Checkbox); impl CellDisplayable for CheckboxTypeOptionPB { - fn display_data( + fn displayed_cell_bytes( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -55,7 +55,7 @@ impl CellDisplayable for CheckboxTypeOptionPB { Ok(CellBytes::new(cell_data)) } - fn display_string( + fn displayed_cell_string( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -77,7 +77,7 @@ impl CellDataOperation for CheckboxTypeOptionPB { return Ok(CellBytes::default()); } - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } fn apply_changeset( diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs index 379e125345..6a468b92f9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs @@ -119,7 +119,7 @@ impl DateTypeOptionPB { } impl CellDisplayable for DateTypeOptionPB { - fn display_data( + fn displayed_cell_bytes( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -130,7 +130,7 @@ impl CellDisplayable for DateTypeOptionPB { CellBytes::from(date_cell_data) } - fn display_string( + fn displayed_cell_string( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -156,7 +156,7 @@ impl CellDataOperation for DateTypeOptionPB if !decoded_field_type.is_date() { return Ok(CellBytes::default()); } - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } fn apply_changeset( diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs index f8d6c96828..68cb6a1f2e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs @@ -108,7 +108,7 @@ pub(crate) fn strip_currency_symbol(s: T) -> String { } impl CellDisplayable for NumberTypeOptionPB { - fn display_data( + fn displayed_cell_bytes( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -121,7 +121,7 @@ impl CellDisplayable for NumberTypeOptionPB { } } - fn display_string( + fn displayed_cell_string( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -143,7 +143,7 @@ impl CellDataOperation for NumberTypeOptionPB { return Ok(CellBytes::default()); } - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } fn apply_changeset( diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/mod.rs index 45d2b96e83..c731d27b02 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/mod.rs @@ -1,7 +1,7 @@ mod multi_select_type_option; -mod select_option; +mod select_type_option; mod single_select_type_option; pub use multi_select_type_option::*; -pub use select_option::*; +pub use select_type_option::*; pub use single_select_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs index 21eb2b7a54..5ddf4d00f2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs @@ -3,8 +3,8 @@ use crate::impl_type_option; use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable}; use crate::services::field::type_options::util::get_cell_data; use crate::services::field::{ - make_selected_select_options, BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB, - SelectOptionColorPB, SelectOptionIds, SelectOptionOperation, SelectOptionPB, TypeOptionBuilder, CHECK, UNCHECK, + BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction, + TypeOptionBuilder, }; use bytes::Bytes; use flowy_derive::ProtoBuf; @@ -25,13 +25,9 @@ pub struct MultiSelectTypeOptionPB { } impl_type_option!(MultiSelectTypeOptionPB, FieldType::MultiSelect); -impl SelectOptionOperation for MultiSelectTypeOptionPB { - fn selected_select_option(&self, cell_data: CellData) -> SelectOptionCellDataPB { - let select_options = make_selected_select_options(cell_data, &self.options); - SelectOptionCellDataPB { - options: self.options.clone(), - select_options, - } +impl SelectTypeOptionSharedAction for MultiSelectTypeOptionPB { + fn number_of_max_options(&self) -> Option { + None } fn options(&self) -> &Vec { @@ -50,7 +46,7 @@ impl CellDataOperation for MultiSele decoded_field_type: &FieldType, field_rev: &FieldRevision, ) -> FlowyResult { - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } fn apply_changeset( @@ -113,23 +109,8 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { &self.0 } - fn transform(&mut self, field_type: &FieldType, _type_option_data: String) { - match field_type { - FieldType::Checkbox => { - //Add Yes and No options if it's not exist. - if !self.0.options.iter().any(|option| option.name == CHECK) { - let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green); - self.0.options.push(check_option); - } - - if !self.0.options.iter().any(|option| option.name == UNCHECK) { - let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow); - self.0.options.push(uncheck_option); - } - } - FieldType::SingleSelect => {} - _ => {} - } + fn transform(&mut self, field_type: &FieldType, type_option_data: String) { + self.0.transform_type_option(field_type, type_option_data); } } #[cfg(test)] @@ -154,6 +135,8 @@ mod tests { debug_assert_eq!(multi_select.0.options.len(), 2); } + // #[test] + #[test] fn multi_select_insert_multi_option_test() { let google = SelectOptionPB::new("Google"); diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs similarity index 82% rename from frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs rename to frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs index db8156b865..b52f60fd2d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs @@ -2,7 +2,7 @@ use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams use crate::services::cell::{ CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString, }; -use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; +use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB, CHECK, UNCHECK}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{internal_error, ErrorCode, FlowyResult}; @@ -64,10 +64,7 @@ impl std::default::Default for SelectOptionColorPB { } } -pub fn make_selected_select_options( - cell_data: CellData, - options: &[SelectOptionPB], -) -> Vec { +pub fn make_selected_options(cell_data: CellData, options: &[SelectOptionPB]) -> Vec { if let Ok(ids) = cell_data.try_into_inner() { ids.iter() .flat_map(|option_id| options.iter().find(|option| &option.id == option_id).cloned()) @@ -76,8 +73,11 @@ pub fn make_selected_select_options( vec![] } } +/// Defines the shared actions used by SingleSelect or Multi-Select. +pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync { + /// Returns `None` means there is no limited + fn number_of_max_options(&self) -> Option; -pub trait SelectOptionOperation: TypeOptionDataSerializer + Send + Sync { /// Insert the `SelectOptionPB` into corresponding type option. fn insert_option(&mut self, new_option: SelectOptionPB) { let options = self.mut_options(); @@ -104,7 +104,60 @@ pub trait SelectOptionOperation: TypeOptionDataSerializer + Send + Sync { SelectOptionPB::with_color(name, color) } - fn selected_select_option(&self, cell_data: CellData) -> SelectOptionCellDataPB; + /// Return a list of options that are selected by user + fn get_selected_options(&self, cell_data: CellData) -> SelectOptionCellDataPB { + let mut select_options = make_selected_options(cell_data, self.options()); + match self.number_of_max_options() { + None => {} + Some(number_of_max_options) => { + select_options.truncate(number_of_max_options); + } + } + SelectOptionCellDataPB { + options: self.options().clone(), + select_options, + } + } + + fn transform_type_option(&mut self, field_type: &FieldType, _type_option_data: String) { + match field_type { + FieldType::Checkbox => { + //add Yes and No options if it's not exist. + if !self.options().iter().any(|option| option.name == CHECK) { + let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green); + self.mut_options().push(check_option); + } + + if !self.options().iter().any(|option| option.name == UNCHECK) { + let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow); + self.mut_options().push(uncheck_option); + } + } + FieldType::MultiSelect => {} + _ => {} + } + } + + fn transform_cell_data( + &self, + cell_data: CellData, + decoded_field_type: &FieldType, + _field_rev: &FieldRevision, + ) -> FlowyResult { + match decoded_field_type { + FieldType::SingleSelect | FieldType::MultiSelect => { + // Do nothing + } + FieldType::Checkbox => { + // transform the cell data to the option id + } + _ => { + return Ok(CellBytes::default()); + } + } + + CellBytes::from(self.get_selected_options(cell_data)) + } fn options(&self) -> &Vec; @@ -113,29 +166,25 @@ pub trait SelectOptionOperation: TypeOptionDataSerializer + Send + Sync { impl CellDisplayable for T where - T: SelectOptionOperation, + T: SelectTypeOptionSharedAction, { - fn display_data( + fn displayed_cell_bytes( &self, cell_data: CellData, decoded_field_type: &FieldType, - _field_rev: &FieldRevision, + field_rev: &FieldRevision, ) -> FlowyResult { - if !decoded_field_type.is_select_option() { - return Ok(CellBytes::default()); - } - - CellBytes::from(self.selected_select_option(cell_data)) + self.transform_cell_data(cell_data, decoded_field_type, field_rev) } - fn display_string( + fn displayed_cell_string( &self, cell_data: CellData, _decoded_field_type: &FieldType, _field_rev: &FieldRevision, ) -> FlowyResult { Ok(self - .selected_select_option(cell_data) + .get_selected_options(cell_data) .select_options .into_iter() .map(|option| option.name) @@ -144,7 +193,9 @@ where } } -pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult> { +pub fn select_type_option_from_field_rev( + field_rev: &FieldRevision, +) -> FlowyResult> { let field_type: FieldType = field_rev.ty.into(); match &field_type { FieldType::SingleSelect => { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs index 2d6db7e61c..2f1dfa409c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs @@ -1,11 +1,10 @@ use crate::entities::FieldType; use crate::impl_type_option; use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable}; -use crate::services::field::{ - make_selected_select_options, SelectOptionCellChangeset, SelectOptionCellDataPB, SelectOptionColorPB, - SelectOptionIds, SelectOptionOperation, SelectOptionPB, CHECK, UNCHECK, -}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; +use crate::services::field::{ + SelectOptionCellChangeset, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction, +}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; @@ -25,15 +24,9 @@ pub struct SingleSelectTypeOptionPB { } impl_type_option!(SingleSelectTypeOptionPB, FieldType::SingleSelect); -impl SelectOptionOperation for SingleSelectTypeOptionPB { - fn selected_select_option(&self, cell_data: CellData) -> SelectOptionCellDataPB { - let mut select_options = make_selected_select_options(cell_data, &self.options); - // only keep option in single select - select_options.truncate(1); - SelectOptionCellDataPB { - options: self.options.clone(), - select_options, - } +impl SelectTypeOptionSharedAction for SingleSelectTypeOptionPB { + fn number_of_max_options(&self) -> Option { + Some(1) } fn options(&self) -> &Vec { @@ -52,7 +45,7 @@ impl CellDataOperation for SingleSel decoded_field_type: &FieldType, field_rev: &FieldRevision, ) -> FlowyResult { - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } fn apply_changeset( @@ -102,23 +95,8 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder { &self.0 } - fn transform(&mut self, field_type: &FieldType, _type_option_data: String) { - match field_type { - FieldType::Checkbox => { - //add Yes and No options if it's not exist. - if !self.0.options.iter().any(|option| option.name == CHECK) { - let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green); - self.0.options.push(check_option); - } - - if !self.0.options.iter().any(|option| option.name == UNCHECK) { - let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow); - self.0.options.push(uncheck_option); - } - } - FieldType::MultiSelect => {} - _ => {} - } + fn transform(&mut self, field_type: &FieldType, type_option_data: String) { + self.0.transform_type_option(field_type, type_option_data); } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs index d7a5b248c3..7614f5af37 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs @@ -40,7 +40,7 @@ pub struct RichTextTypeOptionPB { impl_type_option!(RichTextTypeOptionPB, FieldType::RichText); impl CellDisplayable for RichTextTypeOptionPB { - fn display_data( + fn displayed_cell_bytes( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -50,7 +50,7 @@ impl CellDisplayable for RichTextTypeOptionPB { Ok(CellBytes::new(cell_str)) } - fn display_string( + fn displayed_cell_string( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -77,7 +77,7 @@ impl CellDataOperation for RichTextTypeOptionPB { let s = decode_cell_data_to_string(cell_data, decoded_field_type, decoded_field_type, field_rev); Ok(CellBytes::new(s.unwrap_or_else(|_| "".to_owned()))) } else { - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs index c3bacd7480..760c480a05 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs @@ -39,7 +39,7 @@ pub struct URLTypeOptionPB { impl_type_option!(URLTypeOptionPB, FieldType::URL); impl CellDisplayable for URLTypeOptionPB { - fn display_data( + fn displayed_cell_bytes( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -49,7 +49,7 @@ impl CellDisplayable for URLTypeOptionPB { CellBytes::from(cell_data) } - fn display_string( + fn displayed_cell_string( &self, cell_data: CellData, _decoded_field_type: &FieldType, @@ -70,7 +70,7 @@ impl CellDataOperation for URLTypeOptionPB { if !decoded_field_type.is_url() { return Ok(CellBytes::default()); } - self.display_data(cell_data, decoded_field_type, field_rev) + self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) } fn apply_changeset( diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/impls/select_option_filter.rs b/frontend/rust-lib/flowy-grid/src/services/filter/impls/select_option_filter.rs index f48069911e..b8f330b72c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/impls/select_option_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/impls/select_option_filter.rs @@ -3,7 +3,7 @@ use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB}; use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; -use crate::services::field::{SelectOptionOperation, SelectedSelectOptions}; +use crate::services::field::{SelectTypeOptionSharedAction, SelectedSelectOptions}; use flowy_error::FlowyResult; impl SelectOptionFilterConfigurationPB { @@ -49,7 +49,7 @@ impl CellFilterOperation for MultiSelectTypeO return Ok(true); } - let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data.into())); + let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into())); Ok(filter.is_visible(&selected_options)) } } @@ -63,7 +63,7 @@ impl CellFilterOperation for SingleSelectType if !any_cell_data.is_single_select() { return Ok(true); } - let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data.into())); + let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into())); Ok(filter.is_visible(&selected_options)) } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs index bd117cd30b..2c3239370d 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/script.rs @@ -4,7 +4,7 @@ use flowy_grid::entities::{ }; use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell}; use flowy_grid::services::field::{ - edit_single_select_type_option, SelectOptionOperation, SelectOptionPB, SingleSelectTypeOptionPB, + edit_single_select_type_option, SelectOptionPB, SelectTypeOptionSharedAction, SingleSelectTypeOptionPB, }; use flowy_grid_data_model::revision::{FieldRevision, RowChangeset}; use std::sync::Arc;