diff --git a/frontend/app_flowy/lib/plugins/board/application/group.dart b/frontend/app_flowy/lib/plugins/board/application/group.dart new file mode 100644 index 0000000000..98f11b6b35 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/board/application/group.dart @@ -0,0 +1,20 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; + +class BoardGroupService { + final String gridId; + GridFieldPB? groupField; + + BoardGroupService(this.gridId); + + void setGroupField(GridFieldPB field) { + groupField = field; + } +} + +abstract class CanBeGroupField { + String get groupContent; +} + +// class SingleSelectGroup extends CanBeGroupField { +// final SingleSelectTypeOptionContext typeOptionContext; +// } 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 1e99859a27..7a54c43c3d 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 @@ -4,22 +4,29 @@ import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; import 'dart:async'; import 'select_option_type_option_bloc.dart'; import 'type_option_context.dart'; -import 'type_option_data_controller.dart'; import 'type_option_service.dart'; import 'package:protobuf/protobuf.dart'; -class MultiSelectTypeOptionContext - extends TypeOptionContext with ISelectOptionAction { +class MultiSelectAction with ISelectOptionAction { + final String gridId; + final String fieldId; final TypeOptionFFIService service; + final MultiSelectTypeOptionContext typeOptionContext; - MultiSelectTypeOptionContext({ - required MultiSelectTypeOptionWidgetDataParser dataParser, - required TypeOptionDataController dataController, - }) : service = TypeOptionFFIService( - gridId: dataController.gridId, - fieldId: dataController.field.id, - ), - super(dataParser: dataParser, dataController: dataController); + MultiSelectAction({ + required this.gridId, + required this.fieldId, + required this.typeOptionContext, + }) : service = TypeOptionFFIService( + gridId: gridId, + fieldId: fieldId, + ); + + MultiSelectTypeOptionPB get typeOption => typeOptionContext.typeOption; + + set typeOption(MultiSelectTypeOptionPB newTypeOption) { + typeOptionContext.typeOption = newTypeOption; + } @override List Function(SelectOptionPB) get deleteOption { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart new file mode 100644 index 0000000000..e3cd38f396 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart @@ -0,0 +1,195 @@ +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart'; +import 'package:protobuf/protobuf.dart'; + +import 'type_option_data_controller.dart'; + +abstract class TypeOptionDataParser { + T fromBuffer(List buffer); +} + +// Number +typedef NumberTypeOptionContext = TypeOptionContext; + +class NumberTypeOptionWidgetDataParser + extends TypeOptionDataParser { + @override + NumberTypeOption fromBuffer(List buffer) { + return NumberTypeOption.fromBuffer(buffer); + } +} + +// RichText +typedef RichTextTypeOptionContext = TypeOptionContext; + +class RichTextTypeOptionWidgetDataParser + extends TypeOptionDataParser { + @override + RichTextTypeOption fromBuffer(List buffer) { + return RichTextTypeOption.fromBuffer(buffer); + } +} + +// Checkbox +typedef CheckboxTypeOptionContext = TypeOptionContext; + +class CheckboxTypeOptionWidgetDataParser + extends TypeOptionDataParser { + @override + CheckboxTypeOption fromBuffer(List buffer) { + return CheckboxTypeOption.fromBuffer(buffer); + } +} + +// URL +typedef URLTypeOptionContext = TypeOptionContext; + +class URLTypeOptionWidgetDataParser + extends TypeOptionDataParser { + @override + URLTypeOption fromBuffer(List buffer) { + return URLTypeOption.fromBuffer(buffer); + } +} + +// Date +typedef DateTypeOptionContext = TypeOptionContext; + +class DateTypeOptionDataParser extends TypeOptionDataParser { + @override + DateTypeOption fromBuffer(List buffer) { + return DateTypeOption.fromBuffer(buffer); + } +} + +// SingleSelect +typedef SingleSelectTypeOptionContext + = TypeOptionContext; + +class SingleSelectTypeOptionWidgetDataParser + extends TypeOptionDataParser { + @override + SingleSelectTypeOptionPB fromBuffer(List buffer) { + return SingleSelectTypeOptionPB.fromBuffer(buffer); + } +} + +// Multi-select +typedef MultiSelectTypeOptionContext + = TypeOptionContext; + +class MultiSelectTypeOptionWidgetDataParser + extends TypeOptionDataParser { + @override + MultiSelectTypeOptionPB fromBuffer(List buffer) { + return MultiSelectTypeOptionPB.fromBuffer(buffer); + } +} + +class TypeOptionContext { + T? _typeOptionObject; + final TypeOptionDataParser dataParser; + final TypeOptionDataController _dataController; + + TypeOptionContext({ + required this.dataParser, + required TypeOptionDataController dataController, + }) : _dataController = dataController; + + String get gridId => _dataController.gridId; + + String get fieldId => _dataController.field.id; + + Future loadTypeOptionData({ + required void Function(T) onCompleted, + required void Function(FlowyError) onError, + }) async { + await _dataController.loadTypeOptionData().then((result) { + result.fold((l) => null, (err) => onError(err)); + }); + + onCompleted(typeOption); + } + + T get typeOption { + if (_typeOptionObject != null) { + return _typeOptionObject!; + } + + final T object = _dataController.getTypeOption(dataParser); + _typeOptionObject = object; + return object; + } + + set typeOption(T typeOption) { + _dataController.typeOptionData = typeOption.writeToBuffer(); + _typeOptionObject = typeOption; + } +} + +abstract class TypeOptionFieldDelegate { + void onFieldChanged(void Function(String) callback); + void dispose(); +} + +abstract class IFieldTypeOptionLoader { + String get gridId; + Future> load(); + + Future> switchToField( + String fieldId, FieldType fieldType) { + final payload = EditFieldPayloadPB.create() + ..gridId = gridId + ..fieldId = fieldId + ..fieldType = fieldType; + + return GridEventSwitchToField(payload).send(); + } +} + +class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader { + @override + final String gridId; + NewFieldTypeOptionLoader({ + required this.gridId, + }); + + @override + Future> load() { + final payload = CreateFieldPayloadPB.create() + ..gridId = gridId + ..fieldType = FieldType.RichText; + + return GridEventCreateFieldTypeOption(payload).send(); + } +} + +class FieldTypeOptionLoader extends IFieldTypeOptionLoader { + @override + final String gridId; + final GridFieldPB field; + + FieldTypeOptionLoader({ + required this.gridId, + required this.field, + }); + + @override + Future> load() { + final payload = GridFieldTypeOptionIdPB.create() + ..gridId = gridId + ..fieldId = field.id + ..fieldType = field.fieldType; + + return GridEventGetFieldTypeOption(payload).send(); + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index 8a6edcbf2c..40ce6fb82e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -92,11 +92,11 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({ ); case FieldType.MultiSelect: return MultiSelectTypeOptionWidgetBuilder( - makeTypeOptionContextWithDataController( + makeTypeOptionContextWithDataController( gridId: gridId, fieldType: fieldType, dataController: dataController, - ) as MultiSelectTypeOptionContext, + ), overlayDelegate, ); case FieldType.Number: diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart index e1b97fe087..9c0f860055 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/multi_select.dart @@ -9,7 +9,7 @@ class MultiSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { final MultiSelectTypeOptionWidget _widget; MultiSelectTypeOptionWidgetBuilder( - MultiSelectTypeOptionContext typeOptionContext, + MultiSelectAction typeOptionContext, TypeOptionOverlayDelegate overlayDelegate, ) : _widget = MultiSelectTypeOptionWidget( typeOptionContext: typeOptionContext, @@ -21,7 +21,7 @@ class MultiSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { } class MultiSelectTypeOptionWidget extends TypeOptionWidget { - final MultiSelectTypeOptionContext typeOptionContext; + final MultiSelectAction typeOptionContext; final TypeOptionOverlayDelegate overlayDelegate; const MultiSelectTypeOptionWidget({ diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 643237bfe6..868e04a211 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -981,6 +981,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "tracing", ] [[package]] diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs index 03cc3d6111..b085f6bdd3 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs @@ -11,33 +11,33 @@ use std::convert::TryInto; use std::sync::Arc; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct GridFilter { +pub struct GridFilterConfiguration { #[pb(index = 1)] pub id: String, } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct RepeatedGridFilterPB { +pub struct RepeatedGridConfigurationFilterPB { #[pb(index = 1)] - pub items: Vec, + pub items: Vec, } -impl std::convert::From<&GridFilterRevision> for GridFilter { +impl std::convert::From<&GridFilterRevision> for GridFilterConfiguration { fn from(rev: &GridFilterRevision) -> Self { Self { id: rev.id.clone() } } } -impl std::convert::From>> for RepeatedGridFilterPB { +impl std::convert::From>> for RepeatedGridConfigurationFilterPB { fn from(revs: Vec>) -> Self { - RepeatedGridFilterPB { + RepeatedGridConfigurationFilterPB { items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(), } } } -impl std::convert::From> for RepeatedGridFilterPB { - fn from(items: Vec) -> Self { +impl std::convert::From> for RepeatedGridConfigurationFilterPB { + fn from(items: Vec) -> Self { Self { items } } } diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs index d05c2ad966..cc89a11e59 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group.rs @@ -1,4 +1,4 @@ -use crate::entities::FieldType; +use crate::entities::{FieldType, GridRowPB}; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; @@ -8,7 +8,7 @@ use std::convert::TryInto; use std::sync::Arc; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct GridGroupPB { +pub struct GridGroupConfigurationPB { #[pb(index = 1)] pub id: String, @@ -19,9 +19,9 @@ pub struct GridGroupPB { pub sub_group_field_id: Option, } -impl std::convert::From<&GridGroupRevision> for GridGroupPB { +impl std::convert::From<&GridGroupRevision> for GridGroupConfigurationPB { fn from(rev: &GridGroupRevision) -> Self { - GridGroupPB { + GridGroupConfigurationPB { id: rev.id.clone(), group_field_id: rev.field_id.clone(), sub_group_field_id: rev.sub_field_id.clone(), @@ -29,21 +29,39 @@ impl std::convert::From<&GridGroupRevision> for GridGroupPB { } } -#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +#[derive(ProtoBuf, Debug, Default, Clone)] pub struct RepeatedGridGroupPB { #[pb(index = 1)] - pub items: Vec, + groups: Vec, } -impl std::convert::From> for RepeatedGridGroupPB { - fn from(items: Vec) -> Self { +#[derive(ProtoBuf, Debug, Default, Clone)] +pub struct GroupPB { + #[pb(index = 1)] + pub group_id: String, + + #[pb(index = 2)] + pub desc: String, + + #[pb(index = 3)] + pub rows: Vec, +} + +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct RepeatedGridGroupConfigurationPB { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::convert::From> for RepeatedGridGroupConfigurationPB { + fn from(items: Vec) -> Self { Self { items } } } -impl std::convert::From>> for RepeatedGridGroupPB { +impl std::convert::From>> for RepeatedGridGroupConfigurationPB { fn from(revs: Vec>) -> Self { - RepeatedGridGroupPB { + RepeatedGridGroupConfigurationPB { items: revs.iter().map(|rev| rev.as_ref().into()).collect(), } } diff --git a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs index 7828c144f0..4034e838aa 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs @@ -1,6 +1,6 @@ use crate::entities::{ CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, CreateGridSortPayloadPB, DeleteFilterPayloadPB, - DeleteGroupPayloadPB, RepeatedGridFilterPB, RepeatedGridGroupPB, RepeatedGridSortPB, + DeleteGroupPayloadPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RepeatedGridSortPB, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; @@ -22,10 +22,10 @@ pub struct GridSettingPB { pub current_layout_type: GridLayoutType, #[pb(index = 3)] - pub filters_by_field_id: HashMap, + pub filter_configuration_by_field_id: HashMap, #[pb(index = 4)] - pub groups_by_field_id: HashMap, + pub group_configuration_by_field_id: HashMap, #[pb(index = 5)] pub sorts_by_field_id: HashMap, diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index b0ef43f5ad..496ee5ed18 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -405,3 +405,14 @@ pub(crate) async fn update_date_cell_handler( let _ = editor.update_cell(params.into()).await?; Ok(()) } + +#[tracing::instrument(level = "trace", skip_all, err)] +pub(crate) async fn get_group_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: GridIdPB = data.into_inner(); + let editor = manager.get_grid_editor(¶ms.value)?; + let group = editor.get_group().await?; + data_result(group) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 0855ef0032..f9b0770174 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -37,7 +37,9 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetSelectOptionCellData, get_select_option_handler) .event(GridEvent::UpdateSelectOptionCell, update_select_option_cell_handler) // Date - .event(GridEvent::UpdateDateCell, update_date_cell_handler); + .event(GridEvent::UpdateDateCell, update_date_cell_handler) + // Group + .event(GridEvent::GetGroup, update_date_cell_handler); module } @@ -204,4 +206,7 @@ pub enum GridEvent { /// will be used by the `update_cell` function. #[event(input = "DateChangesetPayloadPB")] UpdateDateCell = 80, + + #[event(input = "GridIdPB", output = "RepeatedGridGroupPB")] + GetGroup = 100, } 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 e34f3a8430..e73dbb8bc3 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 @@ -61,7 +61,7 @@ pub fn apply_cell_data_changeset>( FieldType::SingleSelect => { SingleSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev) } - FieldType::MultiSelect => MultiSelectTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), + FieldType::MultiSelect => MultiSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::Checkbox => CheckboxTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::URL => URLTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), }?; @@ -109,7 +109,7 @@ pub fn try_decode_cell_data( .get_type_option_entry::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::MultiSelect => field_rev - .get_type_option_entry::(field_type)? + .get_type_option_entry::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::Checkbox => field_rev .get_type_option_entry::(field_type)? diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index de1f37b04f..6578ceb933 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -94,7 +94,7 @@ pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box NumberTypeOption::default().into(), FieldType::DateTime => DateTypeOption::default().into(), FieldType::SingleSelect => SingleSelectTypeOptionPB::default().into(), - FieldType::MultiSelect => MultiSelectTypeOption::default().into(), + FieldType::MultiSelect => MultiSelectTypeOptionPB::default().into(), FieldType::Checkbox => CheckboxTypeOption::default().into(), FieldType::URL => URLTypeOption::default().into(), }; 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 187b81d060..a09c81e97f 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 @@ -14,16 +14,16 @@ use serde::{Deserialize, Serialize}; // Multiple select #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] -pub struct MultiSelectTypeOption { +pub struct MultiSelectTypeOptionPB { #[pb(index = 1)] pub options: Vec, #[pb(index = 2)] pub disable_color: bool, } -impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); +impl_type_option!(MultiSelectTypeOptionPB, FieldType::MultiSelect); -impl SelectOptionOperation for MultiSelectTypeOption { +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 { @@ -41,7 +41,7 @@ impl SelectOptionOperation for MultiSelectTypeOption { } } -impl CellDataOperation for MultiSelectTypeOption { +impl CellDataOperation for MultiSelectTypeOptionPB { fn decode_cell_data( &self, cell_data: CellData, @@ -93,9 +93,9 @@ impl CellDataOperation for MultiSele } #[derive(Default)] -pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption); +pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOptionPB); impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder); -impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption); +impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB); impl MultiSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOptionPB) -> Self { self.0.options.push(opt); @@ -118,7 +118,7 @@ mod tests { use crate::services::cell::CellDataOperation; use crate::services::field::type_options::selection_type_option::*; use crate::services::field::FieldBuilder; - use crate::services::field::{MultiSelectTypeOption, MultiSelectTypeOptionBuilder}; + use crate::services::field::{MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB}; use flowy_grid_data_model::revision::FieldRevision; #[test] @@ -136,7 +136,7 @@ mod tests { .visibility(true) .build(); - let type_option = MultiSelectTypeOption::from(&field_rev); + let type_option = MultiSelectTypeOptionPB::from(&field_rev); let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR); let data = SelectOptionCellChangeset::from_insert(&option_ids).to_str(); @@ -170,7 +170,7 @@ mod tests { fn assert_multi_select_options( cell_data: String, - type_option: &MultiSelectTypeOption, + type_option: &MultiSelectTypeOptionPB, field_rev: &FieldRevision, expected: Vec, ) { 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_option.rs index d426844427..3e6c95c5ec 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_option.rs @@ -1,6 +1,6 @@ use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams}; use crate::services::cell::{CellBytes, CellBytesParser, CellData, CellDisplayable, FromCellChangeset, FromCellString}; -use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB}; +use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{internal_error, ErrorCode, FlowyResult}; @@ -130,7 +130,7 @@ pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult { - let type_option = MultiSelectTypeOption::from(field_rev); + let type_option = MultiSelectTypeOptionPB::from(field_rev); Ok(Box::new(type_option)) } ty => { 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 43e2b009d0..44ae81315d 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 @@ -159,7 +159,7 @@ mod tests { .option(google_option.clone()) .option(facebook_option.clone()); let multi_select_field_rev = FieldBuilder::new(multi_select).build(); - let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_rev); + let multi_type_option = MultiSelectTypeOptionPB::from(&multi_select_field_rev); let cell_data = multi_type_option .apply_changeset(cell_data_changeset.into(), None) .unwrap(); diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs b/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs index f3b1d72fb8..8ee5f6d99e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs @@ -3,7 +3,7 @@ use crate::entities::{FieldType, GridBlockChangesetPB}; use crate::services::block_manager::GridBlockManager; use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::field::{ - CheckboxTypeOption, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RichTextTypeOption, + CheckboxTypeOption, DateTypeOption, MultiSelectTypeOptionPB, NumberTypeOption, RichTextTypeOption, SingleSelectTypeOptionPB, URLTypeOption, }; use crate::services::filter::filter_cache::{ @@ -22,8 +22,6 @@ use std::sync::Arc; use tokio::sync::RwLock; pub(crate) struct GridFilterService { - #[allow(dead_code)] - grid_id: String, scheduler: Arc, grid_pad: Arc>, block_manager: Arc, @@ -36,12 +34,10 @@ impl GridFilterService { block_manager: Arc, scheduler: S, ) -> Self { - let grid_id = grid_pad.read().await.grid_id(); let scheduler = Arc::new(scheduler); let filter_cache = FilterCache::from_grid_pad(&grid_pad).await; let filter_result_cache = FilterResultCache::new(); Self { - grid_id, grid_pad, block_manager, scheduler, @@ -134,8 +130,9 @@ impl GridFilterService { } async fn notify(&self, changesets: Vec) { + let grid_id = self.grid_pad.read().await.grid_id(); for changeset in changesets { - send_dart_notification(&self.grid_id, GridNotification::DidUpdateGridBlock) + send_dart_notification(&grid_id, GridNotification::DidUpdateGridBlock) .payload(changeset) .send(); } @@ -217,7 +214,7 @@ fn filter_cell( FieldType::MultiSelect => filter_cache.select_option_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option_entry::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) 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 e6cb9ff846..5ae8210746 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 @@ -2,7 +2,7 @@ use crate::entities::{GridSelectOptionFilter, SelectOptionCondition}; use crate::services::cell::{AnyCellData, CellFilterOperation}; -use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB}; +use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use crate::services::field::{SelectOptionOperation, SelectedSelectOptions}; use flowy_error::FlowyResult; @@ -39,7 +39,7 @@ impl GridSelectOptionFilter { } } -impl CellFilterOperation for MultiSelectTypeOption { +impl CellFilterOperation for MultiSelectTypeOptionPB { fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult { if !any_cell_data.is_multi_select() { return Ok(true); diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index d98c9538d3..c50042edad 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -61,7 +61,8 @@ impl GridRevisionEditor { let block_manager = Arc::new(GridBlockManager::new(grid_id, &user, block_meta_revs, persistence).await?); let filter_service = Arc::new(GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await); - let group_service = Arc::new(GridGroupService::new()); + let group_service = + Arc::new(GridGroupService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await); let editor = Arc::new(Self { grid_id: grid_id.to_owned(), user, @@ -455,14 +456,14 @@ impl GridRevisionEditor { Ok(grid_setting) } - pub async fn get_grid_filter(&self, layout_type: &GridLayoutType) -> FlowyResult> { + pub async fn get_grid_filter(&self, layout_type: &GridLayoutType) -> FlowyResult> { let read_guard = self.grid_pad.read().await; let layout_rev = layout_type.clone().into(); match read_guard.get_filters(Some(&layout_rev), None) { Some(filter_revs) => Ok(filter_revs .iter() .map(|filter_rev| filter_rev.as_ref().into()) - .collect::>()), + .collect::>()), None => Ok(vec![]), } } @@ -561,6 +562,10 @@ impl GridRevisionEditor { }) } + pub async fn get_group(&self) -> FlowyResult { + todo!() + } + async fn modify(&self, f: F) -> FlowyResult<()> where F: for<'a> FnOnce(&'a mut GridRevisionPad) -> FlowyResult>, diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs index 255ec015d6..8bc8216cf9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs @@ -1,7 +1,26 @@ -pub struct GridGroupService {} +use crate::services::block_manager::GridBlockManager; +use crate::services::grid_editor_task::GridServiceTaskScheduler; +use flowy_sync::client_grid::GridRevisionPad; +use std::sync::Arc; +use tokio::sync::RwLock; + +pub(crate) struct GridGroupService { + scheduler: Arc, + grid_pad: Arc>, + block_manager: Arc, +} impl GridGroupService { - pub fn new() -> Self { - Self {} + pub(crate) async fn new( + grid_pad: Arc>, + block_manager: Arc, + scheduler: S, + ) -> Self { + let scheduler = Arc::new(scheduler); + Self { + scheduler, + grid_pad, + block_manager, + } } } diff --git a/frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs b/frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs index be283981cf..03ed8c760b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/setting/setting_builder.rs @@ -1,5 +1,6 @@ use crate::entities::{ - GridLayoutPB, GridLayoutType, GridSettingPB, RepeatedGridFilterPB, RepeatedGridGroupPB, RepeatedGridSortPB, + GridLayoutPB, GridLayoutType, GridSettingPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, + RepeatedGridSortPB, }; use flowy_grid_data_model::revision::{FieldRevision, GridSettingRevision}; use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams, GridSettingChangesetParams}; @@ -43,21 +44,21 @@ impl GridSettingChangesetBuilder { pub fn make_grid_setting(grid_setting_rev: &GridSettingRevision, field_revs: &[Arc]) -> GridSettingPB { let current_layout_type: GridLayoutType = grid_setting_rev.layout.clone().into(); let filters_by_field_id = grid_setting_rev - .get_all_filter(field_revs) + .get_all_filters(field_revs) .map(|filters_by_field_id| { filters_by_field_id .into_iter() .map(|(k, v)| (k, v.into())) - .collect::>() + .collect::>() }) .unwrap_or_default(); let groups_by_field_id = grid_setting_rev - .get_all_group() + .get_all_groups(field_revs) .map(|groups_by_field_id| { groups_by_field_id .into_iter() .map(|(k, v)| (k, v.into())) - .collect::>() + .collect::>() }) .unwrap_or_default(); let sorts_by_field_id = grid_setting_rev @@ -73,8 +74,8 @@ pub fn make_grid_setting(grid_setting_rev: &GridSettingRevision, field_revs: &[A GridSettingPB { layouts: GridLayoutPB::all(), current_layout_type, - filters_by_field_id, - groups_by_field_id, + filter_configuration_by_field_id: filters_by_field_id, + group_configuration_by_field_id: groups_by_field_id, sorts_by_field_id, } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs index d2a430f591..ddbf5c30fe 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/util.rs @@ -2,7 +2,7 @@ use flowy_grid::entities::FieldType; use std::sync::Arc; use flowy_grid::services::field::{ - DateCellChangesetPB, MultiSelectTypeOption, SelectOptionPB, SingleSelectTypeOptionPB, SELECTION_IDS_SEPARATOR, + DateCellChangesetPB, MultiSelectTypeOptionPB, SelectOptionPB, SingleSelectTypeOptionPB, SELECTION_IDS_SEPARATOR, }; use flowy_grid::services::row::RowRevisionBuilder; use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; @@ -87,7 +87,7 @@ impl<'a> GridRowTestBuilder<'a> { F: Fn(Vec) -> Vec, { let multi_select_field = self.field_rev_with_type(&FieldType::MultiSelect); - let type_option = MultiSelectTypeOption::from(&multi_select_field); + let type_option = MultiSelectTypeOptionPB::from(&multi_select_field); let options = f(type_option.options); let ops_ids = options .iter() diff --git a/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs index e8435c2d00..ccc779d17a 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/cell_test/test.rs @@ -3,7 +3,7 @@ use crate::grid::cell_test::script::GridCellTest; use crate::grid::field_test::util::make_date_cell_string; use flowy_grid::entities::{CellChangesetPB, FieldType}; use flowy_grid::services::field::selection_type_option::SelectOptionCellChangeset; -use flowy_grid::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB}; +use flowy_grid::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; #[tokio::test] async fn grid_cell_update() { @@ -28,7 +28,7 @@ async fn grid_cell_update() { SelectOptionCellChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() } FieldType::MultiSelect => { - let type_option = MultiSelectTypeOption::from(field_rev); + let type_option = MultiSelectTypeOptionPB::from(field_rev); SelectOptionCellChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() } FieldType::Checkbox => "1".to_string(), diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs index 09f52ddb15..f4a1528f8f 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -75,7 +75,7 @@ impl GridEditorTest { .row_revs } - pub async fn grid_filters(&self) -> Vec { + pub async fn grid_filters(&self) -> Vec { let layout_type = GridLayoutType::Table; self.editor.get_grid_filter(&layout_type).await.unwrap() } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 63bea4cc3d..11866b7d1c 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -2,7 +2,7 @@ use crate::grid::script::EditorScript::*; use crate::grid::script::*; use chrono::NaiveDateTime; use flowy_grid::services::field::{ - DateCellContentChangeset, DateCellData, MultiSelectTypeOption, SelectOption, SelectOptionCellContentChangeset, + DateCellContentChangeset, DateCellData, MultiSelectTypeOptionPB, SelectOption, SelectOptionCellContentChangeset, SingleSelectTypeOption, SELECTION_IDS_SEPARATOR, }; use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowMetaBuilder}; @@ -250,7 +250,7 @@ async fn grid_row_add_cells_test() { builder.add_select_option_cell(&field.id, option.id.clone()).unwrap(); } FieldType::MultiSelect => { - let type_option = MultiSelectTypeOption::from(field); + let type_option = MultiSelectTypeOptionPB::from(field); let ops_ids = type_option .options .iter() @@ -327,7 +327,7 @@ async fn grid_cell_update() { SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() } FieldType::MultiSelect => { - let type_option = MultiSelectTypeOption::from(field_meta); + let type_option = MultiSelectTypeOptionPB::from(field_meta); SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str() } FieldType::Checkbox => "1".to_string(), diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index 9b8e5f6081..da8bc0ff1c 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -436,6 +436,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "tracing", ] [[package]] diff --git a/shared-lib/flowy-grid-data-model/Cargo.toml b/shared-lib/flowy-grid-data-model/Cargo.toml index b0162c82a8..3e640ec1af 100644 --- a/shared-lib/flowy-grid-data-model/Cargo.toml +++ b/shared-lib/flowy-grid-data-model/Cargo.toml @@ -13,6 +13,7 @@ serde_repr = "0.1" nanoid = "0.4.0" flowy-error-code = { path = "../flowy-error-code"} indexmap = {version = "1.8.1", features = ["serde"]} +tracing = { version = "0.1", features = ["log"] } [build-dependencies] lib-infra = { path = "../lib-infra", features = ["protobuf_file_gen"] } diff --git a/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs index abf129c415..06e7971cf0 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs @@ -1,7 +1,4 @@ -use crate::revision::FieldTypeRevision; -use indexmap::IndexMap; use serde::{Deserialize, Serialize}; -use std::sync::Arc; #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] pub struct GridFilterRevision { diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_group.rs similarity index 72% rename from shared-lib/flowy-grid-data-model/src/revision/group_rev.rs rename to shared-lib/flowy-grid-data-model/src/revision/grid_group.rs index e856354f6c..268682d552 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_group.rs @@ -1,7 +1,4 @@ -use crate::revision::FieldTypeRevision; -use indexmap::IndexMap; use serde::{Deserialize, Serialize}; -use std::sync::Arc; #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GridGroupRevision { diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs index 095b0dcd97..153ee10961 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs @@ -1,5 +1,5 @@ use crate::revision::filter_rev::GridFilterRevision; -use crate::revision::group_rev::GridGroupRevision; +use crate::revision::grid_group::GridGroupRevision; use crate::revision::{FieldRevision, FieldTypeRevision}; use indexmap::IndexMap; use nanoid::nanoid; @@ -21,28 +21,28 @@ pub fn gen_grid_sort_id() -> String { nanoid!(6) } +pub type GridFilters = SettingContainer; +pub type GridFilterRevisionMap = GridObjectRevisionMap; +pub type FiltersByFieldId = HashMap>>; +// +pub type GridGroups = SettingContainer; +pub type GridGroupRevisionMap = GridObjectRevisionMap; +pub type GroupsByFieldId = HashMap>>; +// +pub type GridSorts = SettingContainer; +pub type GridSortRevisionMap = GridObjectRevisionMap; +pub type SortsByFieldId = HashMap>>; + #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] pub struct GridSettingRevision { pub layout: GridLayoutRevision, - /// Each layout contains multiple key/value. - /// Key: field_id - /// Value: this value contains key/value. - /// Key: FieldType, - /// Value: the corresponding filters. - #[serde(with = "indexmap::serde_seq")] - filters: IndexMap>, + pub filters: GridFilters, - /// Each layout contains multiple key/value. - /// Key: field_id - /// Value: this value contains key/value. - /// Key: FieldType, - /// Value: the corresponding groups. - #[serde(skip, with = "indexmap::serde_seq")] - pub groups: IndexMap>, + pub groups: GridGroups, - #[serde(skip, with = "indexmap::serde_seq")] - pub sorts: IndexMap>, + #[serde(skip)] + pub sorts: GridSorts, } #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)] @@ -65,12 +65,18 @@ impl std::default::Default for GridLayoutRevision { } } -pub type FiltersByFieldId = HashMap>>; -pub type GroupsByFieldId = HashMap>>; -pub type SortsByFieldId = HashMap>>; impl GridSettingRevision { - pub fn get_all_group(&self) -> Option { - None + pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { + self.groups.get_all_objects(&self.layout, field_revs) + } + + pub fn get_groups( + &self, + layout: &GridLayoutRevision, + field_id: &str, + field_type_rev: &FieldTypeRevision, + ) -> Option>> { + self.groups.get_objects(layout, field_id, field_type_rev) } pub fn get_mut_groups( @@ -79,10 +85,7 @@ impl GridSettingRevision { field_id: &str, field_type: &FieldTypeRevision, ) -> Option<&mut Vec>> { - self.groups - .get_mut(layout) - .and_then(|group_rev_map_by_field_id| group_rev_map_by_field_id.get_mut(field_id)) - .and_then(|group_rev_map| group_rev_map.get_mut(field_type)) + self.groups.get_mut_objects(layout, field_id, field_type) } pub fn insert_group( @@ -90,59 +93,13 @@ impl GridSettingRevision { layout: &GridLayoutRevision, field_id: &str, field_type: &FieldTypeRevision, - filter_rev: GridGroupRevision, + group_rev: GridGroupRevision, ) { - let filter_rev_map_by_field_id = self.groups.entry(layout.clone()).or_insert_with(IndexMap::new); - let filter_rev_map = filter_rev_map_by_field_id - .entry(field_id.to_string()) - .or_insert_with(GridGroupRevisionMap::new); - - filter_rev_map - .entry(field_type.to_owned()) - .or_insert_with(Vec::new) - .push(Arc::new(filter_rev)) + self.groups.insert_object(layout, field_id, field_type, group_rev); } - pub fn get_all_sort(&self) -> Option { - None - } - - /// Return the Filters of the current layout - pub fn get_all_filter(&self, field_revs: &[Arc]) -> Option { - let layout = &self.layout; - // Acquire the read lock of the filters. - let filter_rev_map_by_field_id = self.filters.get(layout)?; - // Get the filters according to the FieldType, so we need iterate the field_revs. - let filters_by_field_id = field_revs - .iter() - .flat_map(|field_rev| { - let field_type = &field_rev.field_type_rev; - let field_id = &field_rev.id; - - let filter_rev_map: &GridFilterRevisionMap = filter_rev_map_by_field_id.get(field_id)?; - let filters: Vec> = filter_rev_map.get(field_type)?.clone(); - Some((field_rev.id.clone(), filters)) - }) - .collect::(); - Some(filters_by_field_id) - } - - #[allow(dead_code)] - fn get_filter_rev_map(&self, layout: &GridLayoutRevision, field_id: &str) -> Option<&GridFilterRevisionMap> { - let filter_rev_map_by_field_id = self.filters.get(layout)?; - filter_rev_map_by_field_id.get(field_id) - } - - pub fn get_mut_filters( - &mut self, - layout: &GridLayoutRevision, - field_id: &str, - field_type: &FieldTypeRevision, - ) -> Option<&mut Vec>> { - self.filters - .get_mut(layout) - .and_then(|filter_rev_map_by_field_id| filter_rev_map_by_field_id.get_mut(field_id)) - .and_then(|filter_rev_map| filter_rev_map.get_mut(field_type)) + pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { + self.filters.get_all_objects(&self.layout, field_revs) } pub fn get_filters( @@ -151,11 +108,16 @@ impl GridSettingRevision { field_id: &str, field_type_rev: &FieldTypeRevision, ) -> Option>> { - self.filters - .get(layout) - .and_then(|filter_rev_map_by_field_id| filter_rev_map_by_field_id.get(field_id)) - .and_then(|filter_rev_map| filter_rev_map.get(field_type_rev)) - .cloned() + self.filters.get_objects(layout, field_id, field_type_rev) + } + + pub fn get_mut_filters( + &mut self, + layout: &GridLayoutRevision, + field_id: &str, + field_type: &FieldTypeRevision, + ) -> Option<&mut Vec>> { + self.filters.get_mut_objects(layout, field_id, field_type) } pub fn insert_filter( @@ -165,15 +127,11 @@ impl GridSettingRevision { field_type: &FieldTypeRevision, filter_rev: GridFilterRevision, ) { - let filter_rev_map_by_field_id = self.filters.entry(layout.clone()).or_insert_with(IndexMap::new); - let filter_rev_map = filter_rev_map_by_field_id - .entry(field_id.to_string()) - .or_insert_with(GridFilterRevisionMap::new); + self.filters.insert_object(layout, field_id, field_type, filter_rev); + } - filter_rev_map - .entry(field_type.to_owned()) - .or_insert_with(Vec::new) - .push(Arc::new(filter_rev)) + pub fn get_all_sort(&self) -> Option { + None } } @@ -183,8 +141,94 @@ pub struct GridSortRevision { pub field_id: Option, } -pub type GridFilterRevisionMap = GridObjectRevisionMap; -pub type GridGroupRevisionMap = GridObjectRevisionMap; +#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] +#[serde(transparent)] +pub struct SettingContainer +where + T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, +{ + /// Each layout contains multiple key/value. + /// Key: field_id + /// Value: this value contains key/value. + /// Key: FieldType, + /// Value: the corresponding objects. + #[serde(with = "indexmap::serde_seq")] + inner: IndexMap>>, +} + +impl SettingContainer +where + T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, +{ + pub fn get_mut_objects( + &mut self, + layout: &GridLayoutRevision, + field_id: &str, + field_type: &FieldTypeRevision, + ) -> Option<&mut Vec>> { + let value = self + .inner + .get_mut(layout) + .and_then(|object_rev_map_by_field_id| object_rev_map_by_field_id.get_mut(field_id)) + .and_then(|object_rev_map| object_rev_map.get_mut(field_type)); + if value.is_none() { + tracing::warn!("Can't find the {:?} with", std::any::type_name::()); + } + value + } + pub fn get_objects( + &self, + layout: &GridLayoutRevision, + field_id: &str, + field_type_rev: &FieldTypeRevision, + ) -> Option>> { + self.inner + .get(layout) + .and_then(|object_rev_map_by_field_id| object_rev_map_by_field_id.get(field_id)) + .and_then(|object_rev_map| object_rev_map.get(field_type_rev)) + .cloned() + } + + pub fn get_all_objects( + &self, + layout: &GridLayoutRevision, + field_revs: &[Arc], + ) -> Option>>> { + // Acquire the read lock. + let object_rev_map_by_field_id = self.inner.get(layout)?; + // Get the objects according to the FieldType, so we need iterate the field_revs. + let objects_by_field_id = field_revs + .iter() + .flat_map(|field_rev| { + let field_type = &field_rev.field_type_rev; + let field_id = &field_rev.id; + + let object_rev_map = object_rev_map_by_field_id.get(field_id)?; + let objects: Vec> = object_rev_map.get(field_type)?.clone(); + Some((field_rev.id.clone(), objects)) + }) + .collect::>>>(); + Some(objects_by_field_id) + } + + pub fn insert_object( + &mut self, + layout: &GridLayoutRevision, + field_id: &str, + field_type: &FieldTypeRevision, + object: T, + ) { + let object_rev_map_by_field_id = self.inner.entry(layout.clone()).or_insert_with(IndexMap::new); + let object_rev_map = object_rev_map_by_field_id + .entry(field_id.to_string()) + .or_insert_with(GridObjectRevisionMap::::new); + + object_rev_map + .entry(field_type.to_owned()) + .or_insert_with(Vec::new) + .push(Arc::new(object)) + } +} #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[serde(transparent)] diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_sort.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_sort.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/shared-lib/flowy-grid-data-model/src/revision/mod.rs b/shared-lib/flowy-grid-data-model/src/revision/mod.rs index 9f4b34300e..9736442557 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/mod.rs @@ -1,9 +1,11 @@ mod filter_rev; +mod grid_group; mod grid_rev; mod grid_setting_rev; -mod group_rev; +mod grid_sort; pub use filter_rev::*; +pub use grid_group::*; pub use grid_rev::*; pub use grid_setting_rev::*; -pub use group_rev::*; +pub use grid_sort::*; diff --git a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs index 28c8e087a1..63df0ce828 100644 --- a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs @@ -457,7 +457,6 @@ mod tests { AppRevision, FolderRevision, TrashRevision, ViewRevision, WorkspaceRevision, }; use lib_ot::core::{OperationTransform, TextDelta, TextDeltaBuilder}; - use serde_json::json; #[test] fn folder_add_workspace() { diff --git a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs index 0d793aff47..73c32834b1 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs @@ -1,4 +1,6 @@ -use crate::entities::grid::{FieldChangesetParams, GridSettingChangesetParams}; +use crate::entities::grid::{ + CreateGridFilterParams, CreateGridGroupParams, FieldChangesetParams, GridSettingChangesetParams, +}; use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; @@ -380,88 +382,65 @@ impl GridRevisionPad { self.modify_grid(|grid_rev| { let mut is_changed = None; let layout_rev = changeset.layout_type; - if let Some(params) = changeset.insert_filter { - let filter_rev = GridFilterRevision { - id: gen_grid_filter_id(), - field_id: params.field_id.clone(), - condition: params.condition, - content: params.content, - }; - - grid_rev - .setting - .insert_filter(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev, filter_rev); + grid_rev.setting.insert_filter( + &layout_rev, + ¶ms.field_id, + ¶ms.field_type_rev, + make_filter_revision(¶ms), + ); is_changed = Some(()) } if let Some(params) = changeset.delete_filter { - match grid_rev - .setting - .get_mut_filters(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev) + if let Some(filters) = + grid_rev + .setting + .get_mut_filters(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev) { - Some(filters) => { - filters.retain(|filter| filter.id != params.filter_id); - } - None => { - tracing::warn!("Can't find the filter with {:?}", layout_rev); - } + filters.retain(|filter| filter.id != params.filter_id); } } if let Some(params) = changeset.insert_group { - let group_rev = GridGroupRevision { - id: gen_grid_group_id(), - field_id: params.field_id.clone(), - sub_field_id: params.sub_field_id, - }; - - grid_rev - .setting - .insert_group(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev, group_rev); + grid_rev.setting.insert_group( + &layout_rev, + ¶ms.field_id, + ¶ms.field_type_rev, + make_group_revision(¶ms), + ); is_changed = Some(()); } if let Some(params) = changeset.delete_group { - // match grid_rev.setting.groups.get_mut(&layout_rev) { - // Some(groups) => groups.retain(|group| group.id != delete_group_id), - // None => { - // tracing::warn!("Can't find the group with {:?}", layout_rev); - // } - // } - - match grid_rev - .setting - .get_mut_groups(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev) + if let Some(groups) = + grid_rev + .setting + .get_mut_groups(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev) { - Some(groups) => { - groups.retain(|filter| filter.id != params.group_id); - } - None => { - tracing::warn!("Can't find the group with {:?}", layout_rev); - } + groups.retain(|filter| filter.id != params.group_id); } } if let Some(sort) = changeset.insert_sort { - let rev = GridSortRevision { - id: gen_grid_sort_id(), - field_id: sort.field_id, - }; - - grid_rev - .setting - .sorts - .entry(layout_rev.clone()) - .or_insert_with(std::vec::Vec::new) - .push(rev); + // let rev = GridSortRevision { + // id: gen_grid_sort_id(), + // field_id: sort.field_id, + // }; + // + // grid_rev + // .setting + // .sorts + // .entry(layout_rev.clone()) + // .or_insert_with(std::vec::Vec::new) + // .push(rev); is_changed = Some(()) } if let Some(delete_sort_id) = changeset.delete_sort { - match grid_rev.setting.sorts.get_mut(&layout_rev) { - Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id), - None => { - tracing::warn!("Can't find the sort with {:?}", layout_rev); - } - } + // match grid_rev.setting.sorts.get_mut(&layout_rev) { + // Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id), + // None => { + // tracing::warn!("Can't find the sort with {:?}", layout_rev); + // } + // } } Ok(is_changed) }) @@ -579,3 +558,20 @@ impl std::default::Default for GridRevisionPad { } } } + +fn make_filter_revision(params: &CreateGridFilterParams) -> GridFilterRevision { + GridFilterRevision { + id: gen_grid_filter_id(), + field_id: params.field_id.clone(), + condition: params.condition.clone(), + content: params.content.clone(), + } +} + +fn make_group_revision(params: &CreateGridGroupParams) -> GridGroupRevision { + GridGroupRevision { + id: gen_grid_group_id(), + field_id: params.field_id.clone(), + sub_field_id: params.sub_field_id.clone(), + } +}