From c81b6f10fa3ff421775d52a15ee3b8e7950407c3 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 19 Aug 2022 19:59:09 +0800 Subject: [PATCH 01/10] refactor: baord configuration --- .../flowy-grid/src/entities/field_entities.rs | 21 ++++++ .../src/entities/filter_entities/util.rs | 22 ++++-- .../entities/group_entities/configuration.rs | 31 +++++++++ .../src/entities/group_entities/group.rs | 24 ++++--- .../group_entities/group_changeset.rs | 56 +++++++++++++++- .../src/entities/setting_entities.rs | 22 +++++- .../flowy-grid/src/entities/sort_entities.rs | 11 +-- .../rust-lib/flowy-grid/src/event_handler.rs | 11 +++ frontend/rust-lib/flowy-grid/src/event_map.rs | 4 ++ .../flowy-grid/src/services/grid_editor.rs | 5 ++ .../src/services/grid_view_editor.rs | 9 ++- .../src/services/grid_view_manager.rs | 2 + .../group/group_generator/group_controller.rs | 10 +-- .../group_generator/select_option_group.rs | 1 - .../src/services/group/group_service.rs | 53 ++++++++++----- .../src/services/setting/setting_builder.rs | 4 +- .../tests/grid/filter_test/script.rs | 4 +- .../flowy-grid/tests/grid/grid_editor.rs | 2 +- .../src/revision/grid_setting_rev.rs | 19 +++++- .../src/revision/group_rev.rs | 59 ++++++++++++++++ .../flowy-grid-data-model/src/revision/mod.rs | 2 + .../src/client_grid/view_revision_pad.rs | 55 +-------------- shared-lib/flowy-sync/src/entities/grid.rs | 67 ------------------- shared-lib/flowy-sync/src/entities/mod.rs | 1 - 24 files changed, 326 insertions(+), 169 deletions(-) create mode 100644 shared-lib/flowy-grid-data-model/src/revision/group_rev.rs delete mode 100644 shared-lib/flowy-sync/src/entities/grid.rs diff --git a/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs index 8875b3fc26..0993853b8e 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs @@ -491,6 +491,27 @@ impl TryInto for FieldChangesetPayloadPB { } } +#[derive(Debug, Clone, Default)] +pub struct FieldChangesetParams { + pub field_id: String, + + pub grid_id: String, + + pub name: Option, + + pub desc: Option, + + pub field_type: Option, + + pub frozen: Option, + + pub visibility: Option, + + pub width: Option, + + pub type_option_data: Option>, +} + #[derive( Debug, Clone, 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 079b6fd6dc..7dff00bf56 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 @@ -5,8 +5,7 @@ use crate::entities::{ use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; -use flowy_grid_data_model::revision::{FieldRevision, FilterConfigurationRevision}; -use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams}; +use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision, FilterConfigurationRevision}; use std::convert::TryInto; use std::sync::Arc; @@ -72,6 +71,12 @@ impl TryInto for DeleteFilterPayloadPB { } } +pub struct DeleteFilterParams { + pub field_id: String, + pub filter_id: String, + pub field_type_rev: FieldTypeRevision, +} + #[derive(ProtoBuf, Debug, Default, Clone)] pub struct CreateGridFilterPayloadPB { #[pb(index = 1)] @@ -99,10 +104,10 @@ impl CreateGridFilterPayloadPB { } } -impl TryInto for CreateGridFilterPayloadPB { +impl TryInto for CreateGridFilterPayloadPB { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let field_id = NotEmptyStr::parse(self.field_id) .map_err(|_| ErrorCode::FieldIdIsEmpty)? .0; @@ -125,7 +130,7 @@ impl TryInto for CreateGridFilterPayloadPB { } } - Ok(CreateGridFilterParams { + Ok(CreateFilterParams { field_id, field_type_rev: self.field_type.into(), condition, @@ -133,3 +138,10 @@ impl TryInto for CreateGridFilterPayloadPB { }) } } + +pub struct CreateFilterParams { + pub field_id: String, + pub field_type_rev: FieldTypeRevision, + pub condition: u8, + pub content: Option, +} diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs index baa39d91a2..5797da3517 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs @@ -1,4 +1,5 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use flowy_grid_data_model::revision::{GroupRecordRevision, SelectOptionGroupConfigurationRevision}; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] pub struct UrlGroupConfigurationPB { @@ -16,6 +17,36 @@ pub struct TextGroupConfigurationPB { pub struct SelectOptionGroupConfigurationPB { #[pb(index = 1)] hide_empty: bool, + + #[pb(index = 2)] + groups: Vec, +} + +impl std::convert::From for SelectOptionGroupConfigurationPB { + fn from(rev: SelectOptionGroupConfigurationRevision) -> Self { + Self { + hide_empty: rev.hide_empty, + groups: rev.groups.into_iter().map(GroupRecordPB::from).collect(), + } + } +} + +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct GroupRecordPB { + #[pb(index = 1)] + group_id: String, + + #[pb(index = 2)] + visible: bool, +} + +impl std::convert::From for GroupRecordPB { + fn from(rev: GroupRecordRevision) -> Self { + Self { + group_id: rev.group_id, + visible: rev.visible, + } + } } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] 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 32f7c4543a..0024040078 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 @@ -2,8 +2,7 @@ use crate::entities::{FieldType, RowPB}; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; -use flowy_grid_data_model::revision::GroupConfigurationRevision; -use flowy_sync::entities::grid::{CreateGridGroupParams, DeleteGroupParams}; +use flowy_grid_data_model::revision::{FieldTypeRevision, GroupConfigurationRevision}; use std::convert::TryInto; use std::sync::Arc; @@ -86,27 +85,28 @@ pub struct CreateGridGroupPayloadPB { #[pb(index = 2)] pub field_type: FieldType, - - #[pb(index = 3, one_of)] - pub content: Option>, } -impl TryInto for CreateGridGroupPayloadPB { +impl TryInto for CreateGridGroupPayloadPB { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let field_id = NotEmptyStr::parse(self.field_id) .map_err(|_| ErrorCode::FieldIdIsEmpty)? .0; - Ok(CreateGridGroupParams { + Ok(CreatGroupParams { field_id, field_type_rev: self.field_type.into(), - content: self.content, }) } } +pub struct CreatGroupParams { + pub field_id: String, + pub field_type_rev: FieldTypeRevision, +} + #[derive(ProtoBuf, Debug, Default, Clone)] pub struct DeleteGroupPayloadPB { #[pb(index = 1)] @@ -137,3 +137,9 @@ impl TryInto for DeleteGroupPayloadPB { }) } } + +pub struct DeleteGroupParams { + pub field_id: String, + pub group_id: String, + pub field_type_rev: FieldTypeRevision, +} diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs index 743da70444..41d46e3cc7 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs @@ -1,5 +1,7 @@ -use crate::entities::{InsertedRowPB, RowPB}; +use crate::entities::{GroupPB, InsertedRowPB, RowPB}; use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use flowy_grid_data_model::parser::NotEmptyStr; use std::fmt::Formatter; #[derive(Debug, Default, ProtoBuf)] @@ -62,3 +64,55 @@ impl GroupRowsChangesetPB { } } } +#[derive(Debug, Default, ProtoBuf)] +pub struct MoveGroupPayloadPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2)] + pub from_group_id: String, + + #[pb(index = 3)] + pub to_group_id: String, +} + +pub struct MoveGroupParams { + pub view_id: String, + pub from_group_id: String, + pub to_group_id: String, +} + +impl TryInto for MoveGroupPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let view_id = NotEmptyStr::parse(self.view_id) + .map_err(|_| ErrorCode::GridViewIdIsEmpty)? + .0; + let from_group_id = NotEmptyStr::parse(self.from_group_id) + .map_err(|_| ErrorCode::GroupIdIsEmpty)? + .0; + let to_group_id = NotEmptyStr::parse(self.to_group_id) + .map_err(|_| ErrorCode::GroupIdIsEmpty)? + .0; + Ok(MoveGroupParams { + view_id, + from_group_id, + to_group_id, + }) + } +} + +#[derive(Debug, Default, ProtoBuf)] +pub struct GroupsChangesetPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2)] + pub inserted_groups: Vec, + + #[pb(index = 3)] + pub deleted_groups: Vec, +} + +impl GroupsChangesetPB {} 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 89f66dd433..67fcc884e9 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,7 @@ use crate::entities::{ - CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, CreateGridSortPayloadPB, DeleteFilterPayloadPB, - DeleteGroupPayloadPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RepeatedGridSortPB, + CreatGroupParams, CreateFilterParams, CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, CreateGridSortPayloadPB, + CreateSortParams, DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, + RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RepeatedGridSortPB, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; @@ -156,3 +157,20 @@ impl TryInto for GridSettingChangesetPayloadPB { }) } } + +pub struct GridSettingChangesetParams { + pub grid_id: String, + pub layout_type: LayoutRevision, + pub insert_filter: Option, + pub delete_filter: Option, + pub insert_group: Option, + pub delete_group: Option, + pub insert_sort: Option, + pub delete_sort: Option, +} + +impl GridSettingChangesetParams { + pub fn is_filter_changed(&self) -> bool { + self.insert_filter.is_some() || self.delete_filter.is_some() + } +} diff --git a/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs index f844b75066..28486a1ee6 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs @@ -2,7 +2,6 @@ use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::revision::SortConfigurationRevision; -use flowy_sync::entities::grid::CreateGridSortParams; use std::convert::TryInto; use std::sync::Arc; @@ -51,15 +50,19 @@ pub struct CreateGridSortPayloadPB { pub field_id: Option, } -impl TryInto for CreateGridSortPayloadPB { +impl TryInto for CreateGridSortPayloadPB { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let field_id = match self.field_id { None => None, Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), }; - Ok(CreateGridSortParams { field_id }) + Ok(CreateSortParams { field_id }) } } + +pub struct CreateSortParams { + pub field_id: Option, +} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 3108acd977..f9f5e39399 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -437,3 +437,14 @@ pub(crate) async fn create_board_card_handler( let row = editor.create_row(params).await?; data_result(row) } + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn move_group_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let params: MoveGroupParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(params.view_id.as_ref())?; + let changeset = editor.move_group(params).await?; + data_result(changeset) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 55ef3ff4db..76087fe64b 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -41,6 +41,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::UpdateDateCell, update_date_cell_handler) // Group .event(GridEvent::CreateBoardCard, create_board_card_handler) + .event(GridEvent::MoveGroup, move_group_handler) .event(GridEvent::GetGroup, get_groups_handler); module @@ -217,4 +218,7 @@ pub enum GridEvent { #[event(input = "CreateBoardCardPayloadPB", output = "RowPB")] CreateBoardCard = 110, + + #[event(input = "MoveGroupPayloadPB", output = "GroupsChangesetPB")] + MoveGroup = 111, } 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 92cf9da550..581f735994 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -294,6 +294,11 @@ impl GridRevisionEditor { Ok(row_pb) } + pub async fn move_group(&self, params: MoveGroupParams) -> FlowyResult { + // + todo!() + } + pub async fn insert_rows(&self, row_revs: Vec) -> FlowyResult> { let block_id = self.block_id().await?; let mut rows_by_block_id: HashMap> = HashMap::new(); diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index da3ea1be2d..ac1e905d8a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -172,10 +172,15 @@ impl GridViewRevisionEditor { } pub(crate) async fn update_setting(&self, changeset: GridSettingChangesetParams) -> FlowyResult<()> { - let _ = self.modify(|pad| Ok(pad.update_setting(changeset)?)).await; - Ok(()) + // let _ = self.modify(|pad| Ok(pad.update_setting(changeset)?)).await; + // Ok(()) + todo!() } + // pub(crate) async fn insert_group(&self, params: CreateGroupParams) -> FlowyResult<()> { + // + // } + pub(crate) async fn get_filters(&self) -> Vec { let field_revs = self.field_delegate.get_field_revs().await; match self.pad.read().await.get_setting_rev().get_all_filters(&field_revs) { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 5a8faad6a0..178befc10a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -130,6 +130,8 @@ impl GridViewManager { } } + pub(crate) async fn move_group(&self) {} + pub(crate) async fn get_view_editor(&self, view_id: &str) -> FlowyResult> { debug_assert!(!view_id.is_empty()); match self.view_editors.get(view_id) { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs index a1d5df2154..07dcff3f77 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs @@ -163,10 +163,12 @@ where G: GroupGenerator, { pub fn new(field_rev: &Arc, configuration: GroupConfigurationRevision) -> FlowyResult { - let configuration = match configuration.content { - None => None, - Some(content) => Some(C::try_from(Bytes::from(content))?), - }; + // let configuration = match configuration.content { + // None => None, + // Some(content) => Some(C::try_from(Bytes::from(content))?), + // }; + + let configuration = None; let field_type_rev = field_rev.ty; let type_option = field_rev.get_type_option_entry::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs index 6e569a7b54..29dc95891f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs @@ -4,7 +4,6 @@ use crate::services::field::{ MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB, }; use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable}; - use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; // SingleSelect 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 0e152bf27c..c07b3acec4 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 @@ -8,7 +8,9 @@ use crate::services::group::{ use bytes::Bytes; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision, + gen_grid_group_id, CheckboxGroupConfigurationRevision, DateGroupConfigurationRevision, FieldRevision, + GroupConfigurationRevision, NumberGroupConfigurationRevision, RowChangeset, RowRevision, + SelectOptionGroupConfigurationRevision, TextGroupConfigurationRevision, UrlGroupConfigurationRevision, }; use lib_infra::future::AFFuture; use std::future::Future; @@ -208,20 +210,41 @@ fn find_group_field(field_revs: &[Arc]) -> Option GroupConfigurationRevision { + let field_id = field_rev.id.clone(); + let field_type_rev = field_rev.ty.clone(); let field_type: FieldType = field_rev.ty.into(); - let bytes: Bytes = match field_type { - FieldType::RichText => TextGroupConfigurationPB::default().try_into().unwrap(), - FieldType::Number => NumberGroupConfigurationPB::default().try_into().unwrap(), - FieldType::DateTime => DateGroupConfigurationPB::default().try_into().unwrap(), - FieldType::SingleSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(), - FieldType::MultiSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(), - FieldType::Checkbox => CheckboxGroupConfigurationPB::default().try_into().unwrap(), - FieldType::URL => UrlGroupConfigurationPB::default().try_into().unwrap(), - }; - GroupConfigurationRevision { - id: gen_grid_group_id(), - field_id: field_rev.id.clone(), - field_type_rev: field_rev.ty, - content: Some(bytes.to_vec()), + match field_type { + FieldType::RichText => { + GroupConfigurationRevision::new(field_id, field_type_rev, TextGroupConfigurationRevision::default()) + .unwrap() + } + FieldType::Number => { + GroupConfigurationRevision::new(field_id, field_type_rev, NumberGroupConfigurationRevision::default()) + .unwrap() + } + FieldType::DateTime => { + GroupConfigurationRevision::new(field_id, field_type_rev, DateGroupConfigurationRevision::default()) + .unwrap() + } + + FieldType::SingleSelect => GroupConfigurationRevision::new( + field_id, + field_type_rev, + SelectOptionGroupConfigurationRevision::default(), + ) + .unwrap(), + FieldType::MultiSelect => GroupConfigurationRevision::new( + field_id, + field_type_rev, + SelectOptionGroupConfigurationRevision::default(), + ) + .unwrap(), + FieldType::Checkbox => { + GroupConfigurationRevision::new(field_id, field_type_rev, CheckboxGroupConfigurationRevision::default()) + .unwrap() + } + FieldType::URL => { + GroupConfigurationRevision::new(field_id, field_type_rev, UrlGroupConfigurationRevision::default()).unwrap() + } } } 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 7d285fbe2b..1cc16f7da7 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 @@ -3,7 +3,7 @@ use crate::entities::{ RepeatedGridSortPB, }; use flowy_grid_data_model::revision::{FieldRevision, SettingRevision}; -use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams, GridSettingChangesetParams}; +use flowy_sync::entities::grid::{CreateFilterParams, DeleteFilterParams, GridSettingChangesetParams}; use std::collections::HashMap; use std::sync::Arc; @@ -26,7 +26,7 @@ impl GridSettingChangesetBuilder { Self { params } } - pub fn insert_filter(mut self, params: CreateGridFilterParams) -> Self { + pub fn insert_filter(mut self, params: CreateFilterParams) -> Self { self.params.insert_filter = Some(params); self } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index 650564d8d5..459cf5f82d 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -6,7 +6,7 @@ use flowy_grid::entities::{CreateGridFilterPayloadPB, GridLayout, GridSettingPB}; use flowy_grid::services::setting::GridSettingChangesetBuilder; use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision}; -use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams, GridSettingChangesetParams}; +use flowy_sync::entities::grid::{CreateFilterParams, DeleteFilterParams, GridSettingChangesetParams}; use crate::grid::grid_editor::GridEditorTest; pub enum FilterScript { @@ -54,7 +54,7 @@ impl GridFilterTest { let _ = self.editor.update_grid_setting(params).await.unwrap(); } FilterScript::InsertGridTableFilter { payload } => { - let params: CreateGridFilterParams = payload.try_into().unwrap(); + let params: CreateFilterParams = payload.try_into().unwrap(); let layout_type = GridLayout::Table; let params = GridSettingChangesetBuilder::new(&self.grid_id, &layout_type) .insert_filter(params) 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 dbd5df1484..ea8de69056 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -13,7 +13,7 @@ use flowy_grid_data_model::revision::*; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::client_grid::GridBuilder; use flowy_sync::entities::grid::{ - CreateGridFilterParams, DeleteFilterParams, FieldChangesetParams, GridSettingChangesetParams, + CreateFilterParams, DeleteFilterParams, FieldChangesetParams, GridSettingChangesetParams, }; use flowy_test::helper::ViewTest; use flowy_test::FlowySDKTest; 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 da366f39ab..f91ec4c88b 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 @@ -240,12 +240,29 @@ where } } +pub trait GroupConfigurationSerde {} + #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GroupConfigurationRevision { pub id: String, pub field_id: String, pub field_type_rev: FieldTypeRevision, - pub content: Option>, + pub content: String, +} + +impl GroupConfigurationRevision { + pub fn new(field_id: String, field_type: FieldTypeRevision, content: T) -> Result + where + T: serde::Serialize, + { + let content = serde_json::to_string(&content)?; + Ok(Self { + id: gen_grid_group_id(), + field_id, + field_type_rev: field_type, + content, + }) + } } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs new file mode 100644 index 0000000000..932cc60033 --- /dev/null +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -0,0 +1,59 @@ +use serde::{Deserialize, Serialize}; +use serde_repr::*; + +#[derive(Default, Serialize, Deserialize)] +pub struct TextGroupConfigurationRevision { + pub hide_empty: bool, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct NumberGroupConfigurationRevision { + pub hide_empty: bool, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct UrlGroupConfigurationRevision { + pub hide_empty: bool, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct CheckboxGroupConfigurationRevision { + pub hide_empty: bool, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct SelectOptionGroupConfigurationRevision { + pub hide_empty: bool, + pub groups: Vec, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct GroupRecordRevision { + pub group_id: String, + + #[serde(default = "DEFAULT_GROUP_RECORD_VISIBILITY")] + pub visible: bool, +} +const DEFAULT_GROUP_RECORD_VISIBILITY: fn() -> bool = || true; + +#[derive(Default, Serialize, Deserialize)] +pub struct DateGroupConfigurationRevision { + pub hide_empty: bool, + pub condition: DateCondition, +} + +#[derive(Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum DateCondition { + Relative = 0, + Day = 1, + Week = 2, + Month = 3, + Year = 4, +} + +impl std::default::Default for DateCondition { + fn default() -> Self { + DateCondition::Relative + } +} 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 7ea98d78e3..d9df0910bd 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/mod.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/mod.rs @@ -2,8 +2,10 @@ mod grid_block; mod grid_rev; mod grid_setting_rev; mod grid_view; +mod group_rev; pub use grid_block::*; pub use grid_rev::*; pub use grid_setting_rev::*; pub use grid_view::*; +pub use group_rev::*; diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index dd6cc6f977..4220a4367b 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -1,4 +1,4 @@ -use crate::entities::grid::{CreateGridFilterParams, CreateGridGroupParams, GridSettingChangesetParams}; +use crate::entities::grid::{CreatGroupParams, CreateFilterParams, GridSettingChangesetParams}; use crate::entities::revision::{md5, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_text_delta_from_revisions}; @@ -54,55 +54,6 @@ impl GridViewRevisionPad { &self.view.setting } - pub fn update_setting( - &mut self, - changeset: GridSettingChangesetParams, - ) -> CollaborateResult> { - self.modify(|view| { - let mut is_changed = None; - if let Some(params) = changeset.insert_filter { - view.setting.filters.insert_object( - ¶ms.field_id, - ¶ms.field_type_rev, - make_filter_revision(¶ms), - ); - is_changed = Some(()) - } - if let Some(params) = changeset.delete_filter { - if let Some(filters) = view - .setting - .filters - .get_mut_objects(¶ms.field_id, ¶ms.field_type_rev) - { - filters.retain(|filter| filter.id != params.filter_id); - is_changed = Some(()) - } - } - if let Some(params) = changeset.insert_group { - view.setting.groups.remove_all(); - view.setting.groups.insert_object( - ¶ms.field_id, - ¶ms.field_type_rev, - make_group_revision(¶ms), - ); - - is_changed = Some(()); - } - if let Some(params) = changeset.delete_group { - if let Some(groups) = view - .setting - .groups - .get_mut_objects(¶ms.field_id, ¶ms.field_type_rev) - { - groups.retain(|group| group.id != params.group_id); - is_changed = Some(()); - } - } - - Ok(is_changed) - }) - } - pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { self.setting.groups.get_all_objects(field_revs) } @@ -216,7 +167,7 @@ impl GridViewRevisionPad { } } -fn make_filter_revision(params: &CreateGridFilterParams) -> FilterConfigurationRevision { +fn make_filter_revision(params: &CreateFilterParams) -> FilterConfigurationRevision { FilterConfigurationRevision { id: gen_grid_filter_id(), field_id: params.field_id.clone(), @@ -225,7 +176,7 @@ fn make_filter_revision(params: &CreateGridFilterParams) -> FilterConfigurationR } } -fn make_group_revision(params: &CreateGridGroupParams) -> GroupConfigurationRevision { +fn make_group_revision(params: &CreatGroupParams) -> GroupConfigurationRevision { GroupConfigurationRevision { id: gen_grid_group_id(), field_id: params.field_id.clone(), diff --git a/shared-lib/flowy-sync/src/entities/grid.rs b/shared-lib/flowy-sync/src/entities/grid.rs deleted file mode 100644 index 3be3d98267..0000000000 --- a/shared-lib/flowy-sync/src/entities/grid.rs +++ /dev/null @@ -1,67 +0,0 @@ -use flowy_grid_data_model::revision::{FieldTypeRevision, LayoutRevision}; - -pub struct GridSettingChangesetParams { - pub grid_id: String, - pub layout_type: LayoutRevision, - pub insert_filter: Option, - pub delete_filter: Option, - pub insert_group: Option, - pub delete_group: Option, - pub insert_sort: Option, - pub delete_sort: Option, -} - -impl GridSettingChangesetParams { - pub fn is_filter_changed(&self) -> bool { - self.insert_filter.is_some() || self.delete_filter.is_some() - } -} -pub struct CreateGridFilterParams { - pub field_id: String, - pub field_type_rev: FieldTypeRevision, - pub condition: u8, - pub content: Option, -} - -pub struct DeleteFilterParams { - pub field_id: String, - pub filter_id: String, - pub field_type_rev: FieldTypeRevision, -} - -pub struct CreateGridGroupParams { - pub field_id: String, - pub field_type_rev: FieldTypeRevision, - pub content: Option>, -} - -pub struct DeleteGroupParams { - pub field_id: String, - pub group_id: String, - pub field_type_rev: FieldTypeRevision, -} - -pub struct CreateGridSortParams { - pub field_id: Option, -} - -#[derive(Debug, Clone, Default)] -pub struct FieldChangesetParams { - pub field_id: String, - - pub grid_id: String, - - pub name: Option, - - pub desc: Option, - - pub field_type: Option, - - pub frozen: Option, - - pub visibility: Option, - - pub width: Option, - - pub type_option_data: Option>, -} diff --git a/shared-lib/flowy-sync/src/entities/mod.rs b/shared-lib/flowy-sync/src/entities/mod.rs index 768640454b..1c357df94c 100644 --- a/shared-lib/flowy-sync/src/entities/mod.rs +++ b/shared-lib/flowy-sync/src/entities/mod.rs @@ -1,5 +1,4 @@ pub mod folder; -pub mod grid; pub mod parser; pub mod revision; pub mod text_block; From 5fac1f044a24e281a5578bccd5ada8900af83127 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 19 Aug 2022 23:11:05 +0800 Subject: [PATCH 02/10] chore: move some structs --- .../src/entities/group_entities/board_card.rs | 28 ---- .../src/entities/group_entities/group.rs | 26 +++- .../src/entities/group_entities/mod.rs | 2 - .../flowy-grid/src/services/grid_editor.rs | 127 ++++++++++++------ .../checkbox_controller.rs} | 0 .../group_controller.rs | 0 .../src/services/group/controllers/mod.rs | 7 + .../select_option_controller.rs} | 0 .../src/services/group/group_generator/mod.rs | 7 - .../flowy-grid/src/services/group/mod.rs | 4 +- .../src/revision/grid_setting_rev.rs | 4 +- .../src/client_grid/grid_revision_pad.rs | 58 +------- .../src/client_grid/view_revision_pad.rs | 24 +--- 13 files changed, 128 insertions(+), 159 deletions(-) delete mode 100644 frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs rename frontend/rust-lib/flowy-grid/src/services/group/{group_generator/checkbox_group.rs => controllers/checkbox_controller.rs} (100%) rename frontend/rust-lib/flowy-grid/src/services/group/{group_generator => controllers}/group_controller.rs (100%) create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs rename frontend/rust-lib/flowy-grid/src/services/group/{group_generator/select_option_group.rs => controllers/select_option_controller.rs} (100%) delete mode 100644 frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs deleted file mode 100644 index 1ba3991f96..0000000000 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/board_card.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::entities::{CreateRowParams, GridLayout}; -use flowy_derive::ProtoBuf; -use flowy_error::ErrorCode; -use flowy_grid_data_model::parser::NotEmptyStr; - -#[derive(ProtoBuf, Debug, Default, Clone)] -pub struct CreateBoardCardPayloadPB { - #[pb(index = 1)] - pub grid_id: String, - - #[pb(index = 2)] - pub group_id: String, -} - -impl TryInto for CreateBoardCardPayloadPB { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; - let group_id = NotEmptyStr::parse(self.group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; - Ok(CreateRowParams { - grid_id: grid_id.0, - start_row_id: None, - group_id: Some(group_id.0), - layout: GridLayout::Board, - }) - } -} 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 0024040078..b769b18154 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, RowPB}; +use crate::entities::{CreateRowParams, FieldType, GridLayout, RowPB}; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; @@ -6,6 +6,30 @@ use flowy_grid_data_model::revision::{FieldTypeRevision, GroupConfigurationRevis use std::convert::TryInto; use std::sync::Arc; +#[derive(ProtoBuf, Debug, Default, Clone)] +pub struct CreateBoardCardPayloadPB { + #[pb(index = 1)] + pub grid_id: String, + + #[pb(index = 2)] + pub group_id: String, +} + +impl TryInto for CreateBoardCardPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?; + let group_id = NotEmptyStr::parse(self.group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; + Ok(CreateRowParams { + grid_id: grid_id.0, + start_row_id: None, + group_id: Some(group_id.0), + layout: GridLayout::Board, + }) + } +} + #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] pub struct GridGroupConfigurationPB { #[pb(index = 1)] diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs index f5daa803bc..778eff4cc9 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/mod.rs @@ -1,9 +1,7 @@ -mod board_card; mod configuration; mod group; mod group_changeset; -pub use board_card::*; pub use configuration::*; pub use group::*; pub use group_changeset::*; 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 581f735994..055501e117 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -96,23 +96,19 @@ impl GridRevisionEditor { } = params; let field_id = field.id.clone(); if self.contain_field(&field_id).await { - let _ = self - .modify(|grid| { - let deserializer = TypeOptionJsonDeserializer(field.field_type.clone()); - let changeset = FieldChangesetParams { - field_id: field.id, - grid_id, - name: Some(field.name), - desc: Some(field.desc), - field_type: Some(field.field_type.into()), - frozen: Some(field.frozen), - visibility: Some(field.visibility), - width: Some(field.width), - type_option_data: Some(type_option_data), - }; - Ok(grid.update_field_rev(changeset, deserializer)?) - }) - .await?; + let changeset = FieldChangesetParams { + field_id: field.id, + grid_id, + name: Some(field.name), + desc: Some(field.desc), + field_type: Some(field.field_type.into()), + frozen: Some(field.frozen), + visibility: Some(field.visibility), + width: Some(field.width), + type_option_data: Some(type_option_data), + }; + + let _ = self.update_field_rev(changeset, field.field_type.clone()).await?; let _ = self.notify_did_update_grid_field(&field_id).await?; } else { let _ = self @@ -140,19 +136,13 @@ impl GridRevisionEditor { return Ok(()); } let field_rev = result.unwrap(); - let _ = self - .modify(|grid| { - let field_type = field_rev.ty.into(); - let deserializer = TypeOptionJsonDeserializer(field_type); - let changeset = FieldChangesetParams { - field_id: field_id.to_owned(), - grid_id: grid_id.to_owned(), - type_option_data: Some(type_option_data), - ..Default::default() - }; - Ok(grid.update_field_rev(changeset, deserializer)?) - }) - .await?; + let changeset = FieldChangesetParams { + field_id: field_id.to_owned(), + grid_id: grid_id.to_owned(), + type_option_data: Some(type_option_data), + ..Default::default() + }; + let _ = self.update_field_rev(changeset, field_rev.ty.into()).await?; let _ = self.notify_did_update_grid_field(field_id).await?; Ok(()) } @@ -179,17 +169,19 @@ impl GridRevisionEditor { pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { let field_id = params.field_id.clone(); - let json_deserializer = match self.grid_pad.read().await.get_field_rev(params.field_id.as_str()) { - None => return Err(ErrorCode::FieldDoesNotExist.into()), - Some((_, field_rev)) => TypeOptionJsonDeserializer(field_rev.ty.into()), + let field_type: Option = match self.grid_pad.read().await.get_field_rev(params.field_id.as_str()) { + None => None, + Some((_, field_rev)) => Some(field_rev.ty.into()), }; - let _ = self - .modify(|grid| Ok(grid.update_field_rev(params, json_deserializer)?)) - .await?; - - let _ = self.notify_did_update_grid_field(&field_id).await?; - Ok(()) + match field_type { + None => Err(ErrorCode::FieldDoesNotExist.into()), + Some(field_type) => { + let _ = self.update_field_rev(params, field_type).await?; + let _ = self.notify_did_update_grid_field(&field_id).await?; + Ok(()) + } + } } pub async fn replace_field(&self, field_rev: Arc) -> FlowyResult<()> { @@ -269,6 +261,63 @@ impl GridRevisionEditor { Ok(field_revs) } + async fn update_field_rev(&self, params: FieldChangesetParams, field_type: FieldType) -> FlowyResult<()> { + let _ = self + .modify(|grid| { + let deserializer = TypeOptionJsonDeserializer(field_type); + + let changeset = grid.modify_field(¶ms.field_id, |field| { + let mut is_changed = None; + if let Some(name) = changeset.name { + field.name = name; + is_changed = Some(()) + } + + if let Some(desc) = changeset.desc { + field.desc = desc; + is_changed = Some(()) + } + + if let Some(field_type) = changeset.field_type { + field.ty = field_type; + is_changed = Some(()) + } + + if let Some(frozen) = changeset.frozen { + field.frozen = frozen; + is_changed = Some(()) + } + + if let Some(visibility) = changeset.visibility { + field.visibility = visibility; + is_changed = Some(()) + } + + if let Some(width) = changeset.width { + field.width = width; + is_changed = Some(()) + } + + if let Some(type_option_data) = changeset.type_option_data { + match deserializer.deserialize(type_option_data) { + Ok(json_str) => { + let field_type = field.ty; + field.insert_type_option_str(&field_type, json_str); + is_changed = Some(()) + } + Err(err) => { + tracing::error!("Deserialize data to type option json failed: {}", err); + } + } + } + + Ok(is_changed) + })?; + Ok(changeset) + }) + .await?; + } + pub async fn create_block(&self, block_meta_rev: GridBlockMetaRevision) -> FlowyResult<()> { let _ = self .modify(|grid_pad| Ok(grid_pad.create_block_meta_rev(block_meta_rev)?)) diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/controllers/checkbox_controller.rs similarity index 100% rename from frontend/rust-lib/flowy-grid/src/services/group/group_generator/checkbox_group.rs rename to frontend/rust-lib/flowy-grid/src/services/group/controllers/checkbox_controller.rs diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controllers/group_controller.rs similarity index 100% rename from frontend/rust-lib/flowy-grid/src/services/group/group_generator/group_controller.rs rename to frontend/rust-lib/flowy-grid/src/services/group/controllers/group_controller.rs diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs new file mode 100644 index 0000000000..29ce5d091e --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs @@ -0,0 +1,7 @@ +mod checkbox_controller; +mod group_controller; +mod select_option_controller; + +pub use checkbox_controller::*; +pub use group_controller::*; +pub use select_option_controller::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs b/frontend/rust-lib/flowy-grid/src/services/group/controllers/select_option_controller.rs similarity index 100% rename from frontend/rust-lib/flowy-grid/src/services/group/group_generator/select_option_group.rs rename to frontend/rust-lib/flowy-grid/src/services/group/controllers/select_option_controller.rs diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs deleted file mode 100644 index 08e691a75e..0000000000 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_generator/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod checkbox_group; -mod group_controller; -mod select_option_group; - -pub use checkbox_group::*; -pub use group_controller::*; -pub use select_option_group::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs index 15b401f4c0..f8b96c8bab 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs @@ -1,5 +1,5 @@ -mod group_generator; +mod controllers; mod group_service; -pub(crate) use group_generator::*; +pub(crate) use controllers::*; pub(crate) use group_service::*; 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 f91ec4c88b..ff15170932 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 @@ -240,7 +240,9 @@ where } } -pub trait GroupConfigurationSerde {} +pub trait GroupConfigurationSerde { + fn from_configuration(s: &str) -> Result; +} #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] pub struct GroupConfigurationRevision { 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 aad9c8b5f3..e079929aee 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,3 @@ -use crate::entities::grid::FieldChangesetParams; use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_text_delta_from_revisions}; @@ -162,61 +161,6 @@ impl GridRevisionPad { }) } - pub fn update_field_rev( - &mut self, - changeset: FieldChangesetParams, - deserializer: T, - ) -> CollaborateResult> { - let field_id = changeset.field_id.clone(); - self.modify_field(&field_id, |field| { - let mut is_changed = None; - if let Some(name) = changeset.name { - field.name = name; - is_changed = Some(()) - } - - if let Some(desc) = changeset.desc { - field.desc = desc; - is_changed = Some(()) - } - - if let Some(field_type) = changeset.field_type { - field.ty = field_type; - is_changed = Some(()) - } - - if let Some(frozen) = changeset.frozen { - field.frozen = frozen; - is_changed = Some(()) - } - - if let Some(visibility) = changeset.visibility { - field.visibility = visibility; - is_changed = Some(()) - } - - if let Some(width) = changeset.width { - field.width = width; - is_changed = Some(()) - } - - if let Some(type_option_data) = changeset.type_option_data { - match deserializer.deserialize(type_option_data) { - Ok(json_str) => { - let field_type = field.ty; - field.insert_type_option_str(&field_type, json_str); - is_changed = Some(()) - } - Err(err) => { - tracing::error!("Deserialize data to type option json failed: {}", err); - } - } - } - - Ok(is_changed) - }) - } - pub fn get_field_rev(&self, field_id: &str) -> Option<(usize, &Arc)> { self.grid_rev .fields @@ -399,7 +343,7 @@ impl GridRevisionPad { ) } - fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> + pub fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> where F: FnOnce(&mut FieldRevision) -> CollaborateResult>, { diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index 4220a4367b..db52d0b38b 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -1,11 +1,9 @@ -use crate::entities::grid::{CreatGroupParams, CreateFilterParams, GridSettingChangesetParams}; use crate::entities::revision::{md5, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_text_delta_from_revisions}; use flowy_grid_data_model::revision::{ - gen_grid_filter_id, gen_grid_group_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, - FilterConfigurationsByFieldId, GridViewRevision, GroupConfigurationRevision, GroupConfigurationsByFieldId, - SettingRevision, SortConfigurationsByFieldId, + FieldRevision, FieldTypeRevision, FilterConfigurationRevision, FilterConfigurationsByFieldId, GridViewRevision, + GroupConfigurationRevision, GroupConfigurationsByFieldId, SettingRevision, SortConfigurationsByFieldId, }; use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder}; use std::sync::Arc; @@ -167,24 +165,6 @@ impl GridViewRevisionPad { } } -fn make_filter_revision(params: &CreateFilterParams) -> FilterConfigurationRevision { - FilterConfigurationRevision { - id: gen_grid_filter_id(), - field_id: params.field_id.clone(), - condition: params.condition, - content: params.content.clone(), - } -} - -fn make_group_revision(params: &CreatGroupParams) -> GroupConfigurationRevision { - GroupConfigurationRevision { - id: gen_grid_group_id(), - field_id: params.field_id.clone(), - field_type_rev: params.field_type_rev, - content: params.content.clone(), - } -} - pub struct GridViewRevisionChangeset { pub delta: TextDelta, pub md5: String, From 91b2917d603b9dc674bca8f282abe34f0e7a1b42 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 20 Aug 2022 15:40:13 +0800 Subject: [PATCH 03/10] chore: reader and writter for group configuration --- .../flowy-grid/src/entities/field_entities.rs | 1 - .../rust-lib/flowy-grid/src/entities/mod.rs | 2 - .../src/entities/setting_entities.rs | 30 +- .../flowy-grid/src/entities/sort_entities.rs | 68 ----- .../rust-lib/flowy-grid/src/event_handler.rs | 1 - .../src/services/filter/filter_service.rs | 3 +- .../flowy-grid/src/services/grid_editor.rs | 92 +++--- .../src/services/grid_view_editor.rs | 143 ++++++--- .../src/services/grid_view_manager.rs | 5 +- .../flowy-grid/src/services/group/action.rs | 23 ++ .../src/services/group/configuration.rs | 76 +++++ .../checkbox_controller.rs | 44 ++- .../{controllers => controller_impls}/mod.rs | 2 - .../select_option_controller/mod.rs | 6 + .../multi_select_controller.rs | 110 +++++++ .../single_select_controller.rs | 111 +++++++ .../select_option_controller/util.rs | 108 +++++++ .../controllers/select_option_controller.rs | 286 ------------------ .../flowy-grid/src/services/group/entities.rs | 73 +++++ .../{controllers => }/group_controller.rs | 190 ++++-------- .../src/services/group/group_service.rs | 113 ++++--- .../flowy-grid/src/services/group/mod.rs | 10 +- .../src/services/setting/setting_builder.rs | 50 +-- .../src/revision/filter_rev.rs | 9 + .../src/revision/grid_setting_rev.rs | 147 +-------- .../src/revision/grid_view.rs | 104 ++++++- .../src/revision/group_rev.rs | 65 ++++ .../flowy-grid-data-model/src/revision/mod.rs | 2 + .../src/client_grid/view_revision_pad.rs | 36 +-- 29 files changed, 1015 insertions(+), 895 deletions(-) delete mode 100644 frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/action.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/configuration.rs rename frontend/rust-lib/flowy-grid/src/services/group/{controllers => controller_impls}/checkbox_controller.rs (59%) rename frontend/rust-lib/flowy-grid/src/services/group/{controllers => controller_impls}/mod.rs (71%) create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs delete mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controllers/select_option_controller.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/entities.rs rename frontend/rust-lib/flowy-grid/src/services/group/{controllers => }/group_controller.rs (57%) create mode 100644 shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs diff --git a/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs index 0993853b8e..271cbcf424 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/field_entities.rs @@ -2,7 +2,6 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision}; -use flowy_sync::entities::grid::FieldChangesetParams; use serde_repr::*; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-grid/src/entities/mod.rs b/frontend/rust-lib/flowy-grid/src/entities/mod.rs index 96c7a9ba60..eb11d982a4 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/mod.rs @@ -6,7 +6,6 @@ mod grid_entities; mod group_entities; mod row_entities; mod setting_entities; -mod sort_entities; pub use block_entities::*; pub use cell_entities::*; @@ -16,4 +15,3 @@ pub use grid_entities::*; pub use group_entities::*; pub use row_entities::*; pub use setting_entities::*; -pub use sort_entities::*; 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 67fcc884e9..9c02a2c692 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs @@ -1,13 +1,12 @@ use crate::entities::{ - CreatGroupParams, CreateFilterParams, CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, CreateGridSortPayloadPB, - CreateSortParams, DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, - RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RepeatedGridSortPB, + CreatGroupParams, CreateFilterParams, CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, DeleteFilterParams, + DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, RepeatedGridConfigurationFilterPB, + RepeatedGridGroupConfigurationPB, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::revision::LayoutRevision; -use flowy_sync::entities::grid::GridSettingChangesetParams; use std::collections::HashMap; use std::convert::TryInto; use strum::IntoEnumIterator; @@ -27,9 +26,6 @@ pub struct GridSettingPB { #[pb(index = 4)] pub group_configuration_by_field_id: HashMap, - - #[pb(index = 5)] - pub sorts_by_field_id: HashMap, } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] @@ -99,12 +95,6 @@ pub struct GridSettingChangesetPayloadPB { #[pb(index = 6, one_of)] pub delete_group: Option, - - #[pb(index = 7, one_of)] - pub insert_sort: Option, - - #[pb(index = 8, one_of)] - pub delete_sort: Option, } impl TryInto for GridSettingChangesetPayloadPB { @@ -135,16 +125,6 @@ impl TryInto for GridSettingChangesetPayloadPB { None => None, }; - let insert_sort = match self.insert_sort { - None => None, - Some(payload) => Some(payload.try_into()?), - }; - - let delete_sort = match self.delete_sort { - None => None, - Some(filter_id) => Some(NotEmptyStr::parse(filter_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), - }; - Ok(GridSettingChangesetParams { grid_id: view_id, layout_type: self.layout_type.into(), @@ -152,8 +132,6 @@ impl TryInto for GridSettingChangesetPayloadPB { delete_filter, insert_group, delete_group, - insert_sort, - delete_sort, }) } } @@ -165,8 +143,6 @@ pub struct GridSettingChangesetParams { pub delete_filter: Option, pub insert_group: Option, pub delete_group: Option, - pub insert_sort: Option, - pub delete_sort: Option, } impl GridSettingChangesetParams { diff --git a/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs deleted file mode 100644 index 28486a1ee6..0000000000 --- a/frontend/rust-lib/flowy-grid/src/entities/sort_entities.rs +++ /dev/null @@ -1,68 +0,0 @@ -use flowy_derive::ProtoBuf; -use flowy_error::ErrorCode; -use flowy_grid_data_model::parser::NotEmptyStr; -use flowy_grid_data_model::revision::SortConfigurationRevision; -use std::convert::TryInto; -use std::sync::Arc; - -#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct GridSort { - #[pb(index = 1)] - pub id: String, - - #[pb(index = 2, one_of)] - pub field_id: Option, -} - -impl std::convert::From<&SortConfigurationRevision> for GridSort { - fn from(rev: &SortConfigurationRevision) -> Self { - GridSort { - id: rev.id.clone(), - - field_id: rev.field_id.clone(), - } - } -} - -#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct RepeatedGridSortPB { - #[pb(index = 1)] - pub items: Vec, -} - -impl std::convert::From>> for RepeatedGridSortPB { - fn from(revs: Vec>) -> Self { - RepeatedGridSortPB { - items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(), - } - } -} - -impl std::convert::From> for RepeatedGridSortPB { - fn from(items: Vec) -> Self { - Self { items } - } -} - -#[derive(ProtoBuf, Debug, Default, Clone)] -pub struct CreateGridSortPayloadPB { - #[pb(index = 1, one_of)] - pub field_id: Option, -} - -impl TryInto for CreateGridSortPayloadPB { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let field_id = match self.field_id { - None => None, - Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0), - }; - - Ok(CreateSortParams { field_id }) - } -} - -pub struct CreateSortParams { - pub field_id: Option, -} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index f9f5e39399..47df88b976 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -10,7 +10,6 @@ use crate::services::field::{ use crate::services::row::make_row_from_row_rev; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::revision::FieldRevision; -use flowy_sync::entities::grid::{FieldChangesetParams, GridSettingChangesetParams}; use lib_dispatch::prelude::{data_result, AppData, Data, DataResult}; use std::sync::Arc; 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 a2831c0ad9..8335a36fb2 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 @@ -4,7 +4,7 @@ #![allow(unused_imports)] #![allow(unused_results)] use crate::dart_notification::{send_dart_notification, GridNotification}; -use crate::entities::{FieldType, GridBlockChangesetPB}; +use crate::entities::{FieldType, GridBlockChangesetPB, GridSettingChangesetParams}; use crate::services::block_manager::GridBlockManager; use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::field::{ @@ -20,7 +20,6 @@ use crate::services::tasks::{FilterTaskContext, Task, TaskContent}; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{CellRevision, FieldId, FieldRevision, RowRevision}; use flowy_sync::client_grid::GridRevisionPad; -use flowy_sync::entities::grid::GridSettingChangesetParams; use rayon::prelude::*; use std::collections::HashMap; use std::sync::Arc; 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 055501e117..0559cfa364 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -15,7 +15,6 @@ use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_grid_data_model::revision::*; use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridRevisionChangeset, GridRevisionPad, JsonDeserializer}; -use flowy_sync::entities::grid::{FieldChangesetParams, GridSettingChangesetParams}; use flowy_sync::entities::revision::Revision; use flowy_sync::errors::CollaborateResult; use flowy_sync::util::make_text_delta_from_revisions; @@ -101,14 +100,14 @@ impl GridRevisionEditor { grid_id, name: Some(field.name), desc: Some(field.desc), - field_type: Some(field.field_type.into()), + field_type: Some(field.field_type.clone().into()), frozen: Some(field.frozen), visibility: Some(field.visibility), width: Some(field.width), type_option_data: Some(type_option_data), }; - let _ = self.update_field_rev(changeset, field.field_type.clone()).await?; + let _ = self.update_field_rev(changeset, field.field_type).await?; let _ = self.notify_did_update_grid_field(&field_id).await?; } else { let _ = self @@ -262,60 +261,59 @@ impl GridRevisionEditor { } async fn update_field_rev(&self, params: FieldChangesetParams, field_type: FieldType) -> FlowyResult<()> { - let _ = self - .modify(|grid| { - let deserializer = TypeOptionJsonDeserializer(field_type); + self.modify(|grid| { + let deserializer = TypeOptionJsonDeserializer(field_type); - let changeset = grid.modify_field(¶ms.field_id, |field| { - let mut is_changed = None; - if let Some(name) = changeset.name { - field.name = name; - is_changed = Some(()) - } + let changeset = grid.modify_field(¶ms.field_id, |field| { + let mut is_changed = None; + if let Some(name) = params.name { + field.name = name; + is_changed = Some(()) + } - if let Some(desc) = changeset.desc { - field.desc = desc; - is_changed = Some(()) - } + if let Some(desc) = params.desc { + field.desc = desc; + is_changed = Some(()) + } - if let Some(field_type) = changeset.field_type { - field.ty = field_type; - is_changed = Some(()) - } + if let Some(field_type) = params.field_type { + field.ty = field_type; + is_changed = Some(()) + } - if let Some(frozen) = changeset.frozen { - field.frozen = frozen; - is_changed = Some(()) - } + if let Some(frozen) = params.frozen { + field.frozen = frozen; + is_changed = Some(()) + } - if let Some(visibility) = changeset.visibility { - field.visibility = visibility; - is_changed = Some(()) - } + if let Some(visibility) = params.visibility { + field.visibility = visibility; + is_changed = Some(()) + } - if let Some(width) = changeset.width { - field.width = width; - is_changed = Some(()) - } + if let Some(width) = params.width { + field.width = width; + is_changed = Some(()) + } - if let Some(type_option_data) = changeset.type_option_data { - match deserializer.deserialize(type_option_data) { - Ok(json_str) => { - let field_type = field.ty; - field.insert_type_option_str(&field_type, json_str); - is_changed = Some(()) - } - Err(err) => { - tracing::error!("Deserialize data to type option json failed: {}", err); - } + if let Some(type_option_data) = params.type_option_data { + match deserializer.deserialize(type_option_data) { + Ok(json_str) => { + let field_type = field.ty; + field.insert_type_option_str(&field_type, json_str); + is_changed = Some(()) + } + Err(err) => { + tracing::error!("Deserialize data to type option json failed: {}", err); } } + } - Ok(is_changed) - })?; - Ok(changeset) - }) - .await?; + Ok(is_changed) + })?; + Ok(changeset) + }) + .await } pub async fn create_block(&self, block_meta_rev: GridBlockMetaRevision) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index ac1e905d8a..9a7173035a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -1,18 +1,23 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::entities::{ - CreateRowParams, GridFilterConfiguration, GridSettingPB, GroupPB, GroupRowsChangesetPB, InsertedRowPB, RowPB, + CreateRowParams, GridFilterConfiguration, GridLayout, GridLayoutPB, GridSettingChangesetParams, GridSettingPB, + GroupPB, GroupRowsChangesetPB, InsertedRowPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, + RowPB, }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; -use crate::services::group::{default_group_configuration, GroupConfigurationDelegate, GroupService}; -use crate::services::setting::make_grid_setting; +use crate::services::group::{ + default_group_configuration, GroupConfigurationReader, GroupConfigurationWriter, GroupService, +}; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision}; +use flowy_grid_data_model::revision::{ + FieldRevision, FieldTypeRevision, GroupConfigurationRevision, RowChangeset, RowRevision, +}; use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad}; -use flowy_sync::entities::grid::GridSettingChangesetParams; use flowy_sync::entities::revision::Revision; use lib_infra::future::{wrap_future, AFFuture, FutureResult}; +use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; @@ -46,7 +51,14 @@ impl GridViewRevisionEditor { let view_revision_pad = rev_manager.load::(Some(cloud)).await?; let pad = Arc::new(RwLock::new(view_revision_pad)); let rev_manager = Arc::new(rev_manager); - let group_service = GroupService::new(Box::new(pad.clone())).await; + + let configuration_reader = GroupConfigurationReaderImpl(pad.clone()); + let configuration_writer = GroupConfigurationWriterImpl { + user_id: user_id.to_owned(), + rev_manager: rev_manager.clone(), + view_pad: pad.clone(), + }; + let group_service = GroupService::new(configuration_reader, configuration_writer).await; let user_id = user_id.to_owned(); let did_load_group = AtomicBool::new(false); Ok(Self { @@ -167,7 +179,7 @@ impl GridViewRevisionEditor { pub(crate) async fn get_setting(&self) -> GridSettingPB { let field_revs = self.field_delegate.get_field_revs().await; - let grid_setting = make_grid_setting(self.pad.read().await.get_setting_rev(), &field_revs); + let grid_setting = make_grid_setting(&*self.pad.read().await, &field_revs); grid_setting } @@ -177,13 +189,9 @@ impl GridViewRevisionEditor { todo!() } - // pub(crate) async fn insert_group(&self, params: CreateGroupParams) -> FlowyResult<()> { - // - // } - pub(crate) async fn get_filters(&self) -> Vec { let field_revs = self.field_delegate.get_field_revs().await; - match self.pad.read().await.get_setting_rev().get_all_filters(&field_revs) { + match self.pad.read().await.get_all_filters(&field_revs) { None => vec![], Some(filters) => filters .into_values() @@ -207,28 +215,24 @@ impl GridViewRevisionEditor { match f(&mut *write_guard)? { None => {} Some(change) => { - let _ = self.apply_change(change).await?; + let _ = apply_change(&self.user_id, self.rev_manager.clone(), change).await?; } } Ok(()) } +} - async fn apply_change(&self, change: GridViewRevisionChangeset) -> FlowyResult<()> { - let GridViewRevisionChangeset { delta, md5 } = change; - let user_id = self.user_id.clone(); - let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); - let delta_data = delta.json_bytes(); - let revision = Revision::new( - &self.rev_manager.object_id, - base_rev_id, - rev_id, - delta_data, - &user_id, - md5, - ); - let _ = self.rev_manager.add_local_revision(&revision).await?; - Ok(()) - } +async fn apply_change( + user_id: &str, + rev_manager: Arc, + change: GridViewRevisionChangeset, +) -> FlowyResult<()> { + let GridViewRevisionChangeset { delta, md5 } = change; + let (base_rev_id, rev_id) = rev_manager.next_rev_id_pair(); + let delta_data = delta.json_bytes(); + let revision = Revision::new(&rev_manager.object_id, base_rev_id, rev_id, delta_data, &user_id, md5); + let _ = rev_manager.add_local_revision(&revision).await?; + Ok(()) } struct GridViewRevisionCloudService { @@ -253,19 +257,82 @@ impl RevisionObjectBuilder for GridViewRevisionPadBuilder { } } -impl GroupConfigurationDelegate for Arc> { - fn get_group_configuration(&self, field_rev: Arc) -> AFFuture { - let view_pad = self.clone(); +struct GroupConfigurationReaderImpl(Arc>); + +impl GroupConfigurationReader for GroupConfigurationReaderImpl { + fn get_group_configuration(&self, field_rev: Arc) -> AFFuture> { + let view_pad = self.0.clone(); wrap_future(async move { - let grid_pad = view_pad.read().await; - let configurations = grid_pad.get_groups(&field_rev.id, &field_rev.ty); + let view_pad = view_pad.read().await; + let configurations = view_pad.get_groups(&field_rev.id, &field_rev.ty); match configurations { - None => default_group_configuration(&field_rev), - Some(mut configurations) => { - assert_eq!(configurations.len(), 1); - (&*configurations.pop().unwrap()).clone() + None => { + let default_configuration = default_group_configuration(&field_rev); + Arc::new(default_configuration) } + Some(configuration) => configuration, } }) } } + +struct GroupConfigurationWriterImpl { + user_id: String, + rev_manager: Arc, + view_pad: Arc>, +} + +impl GroupConfigurationWriter for GroupConfigurationWriterImpl { + fn save_group_configuration( + &self, + field_id: &str, + field_type: FieldTypeRevision, + configuration: Arc, + ) -> AFFuture> { + let user_id = self.user_id.clone(); + let rev_manager = self.rev_manager.clone(); + let view_pad = self.view_pad.clone(); + let field_id = field_id.to_owned(); + + wrap_future(async move { + let configuration = (&*configuration).clone(); + match view_pad + .write() + .await + .insert_group_configuration(&field_id, &field_type, configuration)? + { + None => Ok(()), + Some(changeset) => apply_change(&user_id, rev_manager, changeset).await, + } + }) + } +} + +pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc]) -> GridSettingPB { + let current_layout_type: GridLayout = view_pad.layout.clone().into(); + let filters_by_field_id = view_pad + .get_all_filters(field_revs) + .map(|filters_by_field_id| { + filters_by_field_id + .into_iter() + .map(|(k, v)| (k, v.into())) + .collect::>() + }) + .unwrap_or_default(); + let groups_by_field_id = view_pad + .get_all_groups(field_revs) + .map(|groups_by_field_id| { + groups_by_field_id + .into_iter() + .map(|(k, v)| (k, v.into())) + .collect::>() + }) + .unwrap_or_default(); + + GridSettingPB { + layouts: GridLayoutPB::all(), + current_layout_type, + filter_configuration_by_field_id: filters_by_field_id, + group_configuration_by_field_id: groups_by_field_id, + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 178befc10a..42c4ff1c65 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -1,4 +1,6 @@ -use crate::entities::{CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB}; +use crate::entities::{ + CreateRowParams, GridFilterConfiguration, GridSettingChangesetParams, GridSettingPB, RepeatedGridGroupPB, RowPB, +}; use crate::manager::GridUser; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_editor::GridViewRevisionEditor; @@ -8,7 +10,6 @@ use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; use flowy_revision::disk::SQLiteGridViewRevisionPersistence; use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence}; -use flowy_sync::entities::grid::GridSettingChangesetParams; use flowy_sync::entities::revision::Revision; use flowy_sync::util::make_text_delta_from_revisions; use lib_infra::future::AFFuture; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/action.rs b/frontend/rust-lib/flowy-grid/src/services/group/action.rs new file mode 100644 index 0000000000..a495fe0a1f --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/action.rs @@ -0,0 +1,23 @@ +use crate::entities::GroupRowsChangesetPB; + +use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; + +pub trait GroupAction: Send + Sync { + type CellDataType; + fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; + fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec; + + fn move_row_if_match( + &mut self, + field_rev: &FieldRevision, + row_rev: &RowRevision, + row_changeset: &mut RowChangeset, + cell_data: &Self::CellDataType, + to_row_id: &str, + ) -> Vec; +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs new file mode 100644 index 0000000000..3d737c307f --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -0,0 +1,76 @@ +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::{ + FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRecordRevision, +}; +use lib_infra::future::AFFuture; +use std::sync::Arc; + +pub trait GroupConfigurationReader: Send + Sync + 'static { + fn get_group_configuration(&self, field_rev: Arc) -> AFFuture>; +} + +pub trait GroupConfigurationWriter: Send + Sync + 'static { + fn save_group_configuration( + &self, + field_id: &str, + field_type: FieldTypeRevision, + configuration: Arc, + ) -> AFFuture>; +} + +pub trait GroupConfigurationAction: Send + Sync { + fn group_records(&self) -> &[GroupRecordRevision]; + fn save_groups(&self) -> FlowyResult<()>; + fn hide_group(&self, group_id: &str) -> FlowyResult<()>; + fn show_group(&self, group_id: &str) -> FlowyResult<()>; +} + +pub struct GenericGroupConfiguration { + field_rev: Arc, + reader: Arc, + writer: Arc, + configuration: C, +} + +impl GenericGroupConfiguration +where + C: GroupConfigurationContentSerde, +{ + pub async fn new( + field_rev: Arc, + reader: Arc, + writer: Arc, + ) -> FlowyResult { + let configuration = reader.get_group_configuration(field_rev.clone()).await; + let configuration = C::from_configuration(&configuration.content)?; + Ok(Self { + field_rev, + reader, + writer, + configuration, + }) + } +} + +impl GroupConfigurationReader for Arc +where + T: GroupConfigurationReader, +{ + fn get_group_configuration(&self, field_rev: Arc) -> AFFuture> { + (**self).get_group_configuration(field_rev) + } +} + +impl GroupConfigurationWriter for Arc +where + T: GroupConfigurationWriter, +{ + fn save_group_configuration( + &self, + field_id: &str, + field_type: FieldTypeRevision, + configuration: Arc, + ) -> AFFuture> { + (**self).save_group_configuration(field_id, field_type, configuration) + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controllers/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs similarity index 59% rename from frontend/rust-lib/flowy-grid/src/services/group/controllers/checkbox_controller.rs rename to frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index c1284dd659..fca49513c8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controllers/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -1,20 +1,42 @@ -use crate::entities::{CheckboxGroupConfigurationPB, GroupRowsChangesetPB}; - -use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; - +use crate::entities::GroupRowsChangesetPB; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; -use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable}; +use crate::services::group::action::GroupAction; +use crate::services::group::configuration::{GenericGroupConfiguration, GroupConfigurationAction}; +use crate::services::group::entities::Group; +use crate::services::group::group_controller::{GenericGroupController, GroupController, GroupGenerator}; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::{ + CheckboxGroupConfigurationRevision, FieldRevision, GroupRecordRevision, RowChangeset, RowRevision, +}; pub type CheckboxGroupController = GenericGroupController< - CheckboxGroupConfigurationPB, + CheckboxGroupConfigurationRevision, CheckboxTypeOptionPB, CheckboxGroupGenerator, CheckboxCellDataParser, >; -impl Groupable for CheckboxGroupController { - type CellDataType = CheckboxCellData; +pub type CheckboxGroupConfiguration = GenericGroupConfiguration; +impl GroupConfigurationAction for CheckboxGroupConfiguration { + fn group_records(&self) -> &[GroupRecordRevision] { + todo!() + } + fn save_groups(&self) -> FlowyResult<()> { + todo!() + } + + fn hide_group(&self, group_id: &str) -> FlowyResult<()> { + todo!() + } + + fn show_group(&self, group_id: &str) -> FlowyResult<()> { + todo!() + } +} + +impl GroupAction for CheckboxGroupController { + type CellDataType = CheckboxCellData; fn can_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool { false } @@ -55,13 +77,13 @@ impl GroupController for CheckboxGroupController { pub struct CheckboxGroupGenerator(); impl GroupGenerator for CheckboxGroupGenerator { - type ConfigurationType = CheckboxGroupConfigurationPB; + type ConfigurationType = CheckboxGroupConfiguration; type TypeOptionType = CheckboxTypeOptionPB; fn generate_groups( field_id: &str, - _configuration: &Option, - _type_option: &Option, + configuration: &Self::ConfigurationType, + type_option: &Option, ) -> Vec { let check_group = Group::new( "true".to_string(), diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs similarity index 71% rename from frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs rename to frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs index 29ce5d091e..974f311a48 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controllers/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs @@ -1,7 +1,5 @@ mod checkbox_controller; -mod group_controller; mod select_option_controller; pub use checkbox_controller::*; -pub use group_controller::*; pub use select_option_controller::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs new file mode 100644 index 0000000000..a2f393d093 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs @@ -0,0 +1,6 @@ +mod multi_select_controller; +mod single_select_controller; +mod util; + +pub use multi_select_controller::*; +pub use single_select_controller::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs new file mode 100644 index 0000000000..33cd0613cd --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -0,0 +1,110 @@ +use crate::entities::GroupRowsChangesetPB; +use crate::services::cell::insert_select_option_cell; +use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser}; +use crate::services::group::action::GroupAction; + +use crate::services::group::controller_impls::select_option_controller::util::*; +use crate::services::group::entities::Group; +use crate::services::group::group_controller::{GenericGroupController, GroupController, GroupGenerator}; +use flowy_grid_data_model::revision::{ + FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, +}; + +// MultiSelect +pub type MultiSelectGroupController = GenericGroupController< + SelectOptionGroupConfigurationRevision, + MultiSelectTypeOptionPB, + MultiSelectGroupGenerator, + SelectOptionCellDataParser, +>; + +impl GroupAction for MultiSelectGroupController { + type CellDataType = SelectOptionCellDataPB; + + fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { + cell_data.select_options.iter().any(|option| option.id == content) + } + + fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + add_row(group, &mut changesets, cell_data, row_rev); + }); + changesets + } + + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + remove_row(group, &mut changesets, cell_data, row_rev); + }); + changesets + } + + fn move_row_if_match( + &mut self, + field_rev: &FieldRevision, + row_rev: &RowRevision, + row_changeset: &mut RowChangeset, + cell_data: &Self::CellDataType, + to_row_id: &str, + ) -> Vec { + let mut group_changeset = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + move_row( + group, + &mut group_changeset, + field_rev, + row_rev, + row_changeset, + cell_data, + to_row_id, + ); + }); + group_changeset + } +} + +impl GroupController for MultiSelectGroupController { + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + let group: Option<&Group> = self.groups_map.get(group_id); + match group { + None => tracing::warn!("Can not find the group: {}", group_id), + Some(group) => { + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_rev.cells.insert(field_rev.id.clone(), cell_rev); + } + } + } +} + +pub struct MultiSelectGroupGenerator(); +impl GroupGenerator for MultiSelectGroupGenerator { + type ConfigurationType = SelectOptionGroupConfiguration; + type TypeOptionType = MultiSelectTypeOptionPB; + fn generate_groups( + field_id: &str, + configuration: &Self::ConfigurationType, + type_option: &Option, + ) -> Vec { + match type_option { + None => vec![], + Some(type_option) => type_option + .options + .iter() + .map(|option| { + Group::new( + option.id.clone(), + field_id.to_owned(), + option.name.clone(), + option.id.clone(), + ) + }) + .collect(), + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs new file mode 100644 index 0000000000..4c8360f427 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -0,0 +1,111 @@ +use crate::entities::{GroupRowsChangesetPB, RowPB}; +use crate::services::cell::insert_select_option_cell; +use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB}; +use crate::services::group::action::GroupAction; + +use crate::services::group::controller_impls::select_option_controller::util::*; +use crate::services::group::entities::Group; +use crate::services::group::group_controller::{GenericGroupController, GroupController, GroupGenerator}; + +use flowy_grid_data_model::revision::{ + FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, +}; + +// SingleSelect +pub type SingleSelectGroupController = GenericGroupController< + SelectOptionGroupConfigurationRevision, + SingleSelectTypeOptionPB, + SingleSelectGroupGenerator, + SelectOptionCellDataParser, +>; + +impl GroupAction for SingleSelectGroupController { + type CellDataType = SelectOptionCellDataPB; + fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { + cell_data.select_options.iter().any(|option| option.id == content) + } + + fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + add_row(group, &mut changesets, cell_data, row_rev); + }); + changesets + } + + fn remove_row_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { + let mut changesets = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + remove_row(group, &mut changesets, cell_data, row_rev); + }); + changesets + } + + fn move_row_if_match( + &mut self, + field_rev: &FieldRevision, + row_rev: &RowRevision, + row_changeset: &mut RowChangeset, + cell_data: &Self::CellDataType, + to_row_id: &str, + ) -> Vec { + let mut group_changeset = vec![]; + self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + move_row( + group, + &mut group_changeset, + field_rev, + row_rev, + row_changeset, + cell_data, + to_row_id, + ); + }); + group_changeset + } +} + +impl GroupController for SingleSelectGroupController { + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { + let group: Option<&mut Group> = self.groups_map.get_mut(group_id); + match group { + None => {} + Some(group) => { + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_rev.cells.insert(field_rev.id.clone(), cell_rev); + group.add_row(RowPB::from(row_rev)); + } + } + } +} + +pub struct SingleSelectGroupGenerator(); +impl GroupGenerator for SingleSelectGroupGenerator { + type ConfigurationType = SelectOptionGroupConfiguration; + type TypeOptionType = SingleSelectTypeOptionPB; + fn generate_groups( + field_id: &str, + configuration: &Self::ConfigurationType, + type_option: &Option, + ) -> Vec { + match type_option { + None => vec![], + Some(type_option) => type_option + .options + .iter() + .map(|option| { + Group::new( + option.id.clone(), + field_id.to_owned(), + option.name.clone(), + option.id.clone(), + ) + }) + .collect(), + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs new file mode 100644 index 0000000000..d95a39f60c --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -0,0 +1,108 @@ +use crate::entities::{GroupRowsChangesetPB, InsertedRowPB, RowPB}; +use crate::services::cell::insert_select_option_cell; +use crate::services::field::SelectOptionCellDataPB; +use crate::services::group::configuration::{GenericGroupConfiguration, GroupConfigurationAction}; +use crate::services::group::Group; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::{ + FieldRevision, GroupRecordRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, +}; + +pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; +impl GroupConfigurationAction for SelectOptionGroupConfiguration { + fn group_records(&self) -> &[GroupRecordRevision] { + todo!() + } + + fn save_groups(&self) -> FlowyResult<()> { + todo!() + } + + fn hide_group(&self, group_id: &str) -> FlowyResult<()> { + todo!() + } + + fn show_group(&self, group_id: &str) -> FlowyResult<()> { + todo!() + } +} + +pub fn add_row( + group: &mut Group, + changesets: &mut Vec, + cell_data: &SelectOptionCellDataPB, + row_rev: &RowRevision, +) { + cell_data.select_options.iter().for_each(|option| { + if option.id == group.id { + if !group.contains_row(&row_rev.id) { + let row_pb = RowPB::from(row_rev); + changesets.push(GroupRowsChangesetPB::insert( + group.id.clone(), + vec![InsertedRowPB::new(row_pb.clone())], + )); + group.add_row(row_pb); + } + } else if group.contains_row(&row_rev.id) { + changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); + } + }); +} + +pub fn remove_row( + group: &mut Group, + changesets: &mut Vec, + cell_data: &SelectOptionCellDataPB, + row_rev: &RowRevision, +) { + cell_data.select_options.iter().for_each(|option| { + if option.id == group.id && group.contains_row(&row_rev.id) { + changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); + } + }); +} + +pub fn move_row( + group: &mut Group, + group_changeset: &mut Vec, + field_rev: &FieldRevision, + row_rev: &RowRevision, + row_changeset: &mut RowChangeset, + cell_data: &SelectOptionCellDataPB, + to_row_id: &str, +) { + cell_data.select_options.iter().for_each(|option| { + // Remove the row in which group contains the row + let is_group_contains = group.contains_row(&row_rev.id); + let to_index = group.index_of_row(to_row_id); + + if option.id == group.id && is_group_contains { + group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + group.remove_row(&row_rev.id); + } + + // Find the inserted group + if let Some(to_index) = to_index { + let row_pb = RowPB::from(row_rev); + let inserted_row = InsertedRowPB { + row: row_pb.clone(), + index: Some(to_index as i32), + }; + group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); + if group.number_of_row() == to_index { + group.add_row(row_pb); + } else { + group.insert_row(to_index, row_pb); + } + } + + // If the inserted row comes from other group, it needs to update the corresponding cell content. + if to_index.is_some() && option.id != group.id { + // Update the corresponding row's cell content. + let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); + row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); + } + }); +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controllers/select_option_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controllers/select_option_controller.rs deleted file mode 100644 index 29dc95891f..0000000000 --- a/frontend/rust-lib/flowy-grid/src/services/group/controllers/select_option_controller.rs +++ /dev/null @@ -1,286 +0,0 @@ -use crate::entities::{GroupRowsChangesetPB, InsertedRowPB, RowPB, SelectOptionGroupConfigurationPB}; -use crate::services::cell::insert_select_option_cell; -use crate::services::field::{ - MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB, -}; -use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable}; -use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; - -// SingleSelect -pub type SingleSelectGroupController = GenericGroupController< - SelectOptionGroupConfigurationPB, - SingleSelectTypeOptionPB, - SingleSelectGroupGenerator, - SelectOptionCellDataParser, ->; - -impl Groupable for SingleSelectGroupController { - type CellDataType = SelectOptionCellDataPB; - fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { - cell_data.select_options.iter().any(|option| option.id == content) - } - - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { - let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - add_row(group, &mut changesets, cell_data, row_rev); - }); - changesets - } - - fn remove_row_if_match( - &mut self, - row_rev: &RowRevision, - cell_data: &Self::CellDataType, - ) -> Vec { - let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - remove_row(group, &mut changesets, cell_data, row_rev); - }); - changesets - } - - fn move_row_if_match( - &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &Self::CellDataType, - to_row_id: &str, - ) -> Vec { - let mut group_changeset = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - move_row( - group, - &mut group_changeset, - field_rev, - row_rev, - row_changeset, - cell_data, - to_row_id, - ); - }); - group_changeset - } -} - -impl GroupController for SingleSelectGroupController { - fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { - let group: Option<&mut Group> = self.groups_map.get_mut(group_id); - match group { - None => {} - Some(group) => { - let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); - row_rev.cells.insert(field_rev.id.clone(), cell_rev); - group.add_row(RowPB::from(row_rev)); - } - } - } -} - -pub struct SingleSelectGroupGenerator(); -impl GroupGenerator for SingleSelectGroupGenerator { - type ConfigurationType = SelectOptionGroupConfigurationPB; - type TypeOptionType = SingleSelectTypeOptionPB; - fn generate_groups( - field_id: &str, - _configuration: &Option, - type_option: &Option, - ) -> Vec { - match type_option { - None => vec![], - Some(type_option) => type_option - .options - .iter() - .map(|option| { - Group::new( - option.id.clone(), - field_id.to_owned(), - option.name.clone(), - option.id.clone(), - ) - }) - .collect(), - } - } -} - -// MultiSelect -pub type MultiSelectGroupController = GenericGroupController< - SelectOptionGroupConfigurationPB, - MultiSelectTypeOptionPB, - MultiSelectGroupGenerator, - SelectOptionCellDataParser, ->; - -impl Groupable for MultiSelectGroupController { - type CellDataType = SelectOptionCellDataPB; - - fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { - cell_data.select_options.iter().any(|option| option.id == content) - } - - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { - let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - add_row(group, &mut changesets, cell_data, row_rev); - }); - changesets - } - - fn remove_row_if_match( - &mut self, - row_rev: &RowRevision, - cell_data: &Self::CellDataType, - ) -> Vec { - let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - remove_row(group, &mut changesets, cell_data, row_rev); - }); - changesets - } - - fn move_row_if_match( - &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &Self::CellDataType, - to_row_id: &str, - ) -> Vec { - let mut group_changeset = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { - move_row( - group, - &mut group_changeset, - field_rev, - row_rev, - row_changeset, - cell_data, - to_row_id, - ); - }); - group_changeset - } -} - -impl GroupController for MultiSelectGroupController { - fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { - let group: Option<&Group> = self.groups_map.get(group_id); - match group { - None => tracing::warn!("Can not find the group: {}", group_id), - Some(group) => { - let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); - row_rev.cells.insert(field_rev.id.clone(), cell_rev); - } - } - } -} - -pub struct MultiSelectGroupGenerator(); -impl GroupGenerator for MultiSelectGroupGenerator { - type ConfigurationType = SelectOptionGroupConfigurationPB; - type TypeOptionType = MultiSelectTypeOptionPB; - - fn generate_groups( - field_id: &str, - _configuration: &Option, - type_option: &Option, - ) -> Vec { - match type_option { - None => vec![], - Some(type_option) => type_option - .options - .iter() - .map(|option| { - Group::new( - option.id.clone(), - field_id.to_owned(), - option.name.clone(), - option.id.clone(), - ) - }) - .collect(), - } - } -} - -fn add_row( - group: &mut Group, - changesets: &mut Vec, - cell_data: &SelectOptionCellDataPB, - row_rev: &RowRevision, -) { - cell_data.select_options.iter().for_each(|option| { - if option.id == group.id { - if !group.contains_row(&row_rev.id) { - let row_pb = RowPB::from(row_rev); - changesets.push(GroupRowsChangesetPB::insert( - group.id.clone(), - vec![InsertedRowPB::new(row_pb.clone())], - )); - group.add_row(row_pb); - } - } else if group.contains_row(&row_rev.id) { - changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } - }); -} - -fn remove_row( - group: &mut Group, - changesets: &mut Vec, - cell_data: &SelectOptionCellDataPB, - row_rev: &RowRevision, -) { - cell_data.select_options.iter().for_each(|option| { - if option.id == group.id && group.contains_row(&row_rev.id) { - changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } - }); -} - -fn move_row( - group: &mut Group, - group_changeset: &mut Vec, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &SelectOptionCellDataPB, - to_row_id: &str, -) { - cell_data.select_options.iter().for_each(|option| { - // Remove the row in which group contains the row - let is_group_contains = group.contains_row(&row_rev.id); - let to_index = group.index_of_row(to_row_id); - - if option.id == group.id && is_group_contains { - group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } - - // Find the inserted group - if let Some(to_index) = to_index { - let row_pb = RowPB::from(row_rev); - let inserted_row = InsertedRowPB { - row: row_pb.clone(), - index: Some(to_index as i32), - }; - group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); - if group.number_of_row() == to_index { - group.add_row(row_pb); - } else { - group.insert_row(to_index, row_pb); - } - } - - // If the inserted row comes from other group, it needs to update the corresponding cell content. - if to_index.is_some() && option.id != group.id { - // Update the corresponding row's cell content. - let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); - row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); - } - }); -} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/entities.rs b/frontend/rust-lib/flowy-grid/src/services/group/entities.rs new file mode 100644 index 0000000000..dd4171afb0 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/entities.rs @@ -0,0 +1,73 @@ +use crate::entities::{GroupPB, RowPB}; + +#[derive(Clone)] +pub struct Group { + pub id: String, + pub field_id: String, + pub desc: String, + rows: Vec, + + /// [content] is used to determine which group the cell belongs to. + pub content: String, +} + +impl std::convert::From for GroupPB { + fn from(group: Group) -> Self { + Self { + field_id: group.field_id, + group_id: group.id, + desc: group.desc, + rows: group.rows, + } + } +} + +impl Group { + pub fn new(id: String, field_id: String, desc: String, content: String) -> Self { + Self { + id, + field_id, + desc, + rows: vec![], + content, + } + } + + pub fn contains_row(&self, row_id: &str) -> bool { + self.rows.iter().any(|row| row.id == row_id) + } + + pub fn remove_row(&mut self, row_id: &str) { + match self.rows.iter().position(|row| row.id == row_id) { + None => {} + Some(pos) => { + self.rows.remove(pos); + } + } + } + + pub fn add_row(&mut self, row_pb: RowPB) { + match self.rows.iter().find(|row| row.id == row_pb.id) { + None => { + self.rows.push(row_pb); + } + Some(_) => {} + } + } + + pub fn insert_row(&mut self, index: usize, row_pb: RowPB) { + if index < self.rows.len() { + self.rows.insert(index, row_pb); + } else { + tracing::error!("Insert row index:{} beyond the bounds:{},", index, self.rows.len()); + } + } + + pub fn index_of_row(&self, row_id: &str) -> Option { + self.rows.iter().position(|row| row.id == row_id) + } + + pub fn number_of_row(&self) -> usize { + self.rows.len() + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controllers/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs similarity index 57% rename from frontend/rust-lib/flowy-grid/src/services/group/controllers/group_controller.rs rename to frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs index 07dcff3f77..fb2c0aaa6e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controllers/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs @@ -1,54 +1,43 @@ -use crate::entities::{GroupPB, GroupRowsChangesetPB, RowPB}; +use crate::entities::{GroupRowsChangesetPB, RowPB}; use crate::services::cell::{decode_any_cell_data, CellBytesParser}; -use bytes::Bytes; +use crate::services::group::action::GroupAction; +use crate::services::group::configuration::{GenericGroupConfiguration, GroupConfigurationReader}; +use crate::services::group::entities::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer, + FieldRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, RowChangeset, RowRevision, + TypeOptionDataDeserializer, }; use indexmap::IndexMap; +use lib_infra::future::AFFuture; use std::marker::PhantomData; use std::sync::Arc; +const DEFAULT_GROUP_ID: &str = "default_group"; + +// Each kind of group must implement this trait to provide custom group +// operations. For example, insert cell data to the row_rev when creating +// a new row. +pub trait GroupController: GroupControllerSharedAction + Send + Sync { + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); +} + pub trait GroupGenerator { type ConfigurationType; type TypeOptionType; fn generate_groups( field_id: &str, - configuration: &Option, + configuration: &Self::ConfigurationType, type_option: &Option, ) -> Vec; } -pub trait Groupable: Send + Sync { - type CellDataType; - fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; - fn remove_row_if_match( - &mut self, - row_rev: &RowRevision, - cell_data: &Self::CellDataType, - ) -> Vec; - - fn move_row_if_match( - &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &Self::CellDataType, - to_row_id: &str, - ) -> Vec; -} - -pub trait GroupController: GroupControllerSharedAction + Send + Sync { - fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); -} - +// Defines the shared actions each group controller can perform. pub trait GroupControllerSharedAction: Send + Sync { // The field that is used for grouping the rows fn field_id(&self) -> &str; - fn groups(&self) -> Vec; - fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()>; + fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult>; fn did_update_row( &mut self, row_rev: &RowRevision, @@ -70,105 +59,35 @@ pub trait GroupControllerSharedAction: Send + Sync { ) -> FlowyResult>; } -const DEFAULT_GROUP_ID: &str = "default_group"; - -/// C: represents the group configuration structure +/// C: represents the group configuration that impl [GroupConfigurationSerde] /// T: the type option data deserializer that impl [TypeOptionDataDeserializer] /// G: the group generator, [GroupGenerator] /// P: the parser that impl [CellBytesParser] for the CellBytes pub struct GenericGroupController { pub field_id: String, pub groups_map: IndexMap, + + /// default_group is used to store the rows that don't belong to any groups. default_group: Group, pub type_option: Option, - pub configuration: Option, + pub configuration: GenericGroupConfiguration, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData

, } -#[derive(Clone)] -pub struct Group { - pub id: String, - pub field_id: String, - pub desc: String, - rows: Vec, - pub content: String, -} - -impl std::convert::From for GroupPB { - fn from(group: Group) -> Self { - Self { - field_id: group.field_id, - group_id: group.id, - desc: group.desc, - rows: group.rows, - } - } -} - -impl Group { - pub fn new(id: String, field_id: String, desc: String, content: String) -> Self { - Self { - id, - field_id, - desc, - rows: vec![], - content, - } - } - - pub fn contains_row(&self, row_id: &str) -> bool { - self.rows.iter().any(|row| row.id == row_id) - } - - pub fn remove_row(&mut self, row_id: &str) { - match self.rows.iter().position(|row| row.id == row_id) { - None => {} - Some(pos) => { - self.rows.remove(pos); - } - } - } - - pub fn add_row(&mut self, row_pb: RowPB) { - match self.rows.iter().find(|row| row.id == row_pb.id) { - None => { - self.rows.push(row_pb); - } - Some(_) => {} - } - } - - pub fn insert_row(&mut self, index: usize, row_pb: RowPB) { - if index < self.rows.len() { - self.rows.insert(index, row_pb); - } else { - tracing::error!("Insert row index:{} beyond the bounds:{},", index, self.rows.len()); - } - } - - pub fn index_of_row(&self, row_id: &str) -> Option { - self.rows.iter().position(|row| row.id == row_id) - } - - pub fn number_of_row(&self) -> usize { - self.rows.len() - } -} - impl GenericGroupController where - C: TryFrom, + C: GroupConfigurationContentSerde, T: TypeOptionDataDeserializer, - G: GroupGenerator, + G: GroupGenerator, TypeOptionType = T>, { - pub fn new(field_rev: &Arc, configuration: GroupConfigurationRevision) -> FlowyResult { - // let configuration = match configuration.content { - // None => None, - // Some(content) => Some(C::try_from(Bytes::from(content))?), - // }; - - let configuration = None; + pub async fn new( + field_rev: &Arc, + configuration_reader: Arc, + configuration_writer: Arc, + ) -> FlowyResult { + let configuration = + GenericGroupConfiguration::::new(field_rev.clone(), configuration_reader, configuration_writer).await?; let field_type_rev = field_rev.ty; let type_option = field_rev.get_type_option_entry::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); @@ -195,55 +114,52 @@ where impl GroupControllerSharedAction for GenericGroupController where P: CellBytesParser, - Self: Groupable, + Self: GroupAction, { fn field_id(&self) -> &str { &self.field_id } - fn groups(&self) -> Vec { - let default_group = self.default_group.clone(); - let mut groups: Vec = self.groups_map.values().cloned().collect(); - if !default_group.rows.is_empty() { - groups.push(default_group); - } - groups - } - - fn group_rows(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { - if self.configuration.is_none() { - return Ok(()); - } + fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult> { + // if self.configuration.is_none() { + // return Ok(vec![]); + // } for row_rev in row_revs { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { - let mut records: Vec = vec![]; + let mut group_rows: Vec = vec![]; let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_data = cell_bytes.parser::

()?; for group in self.groups_map.values() { if self.can_group(&group.content, &cell_data) { - records.push(GroupRecord { + group_rows.push(GroupRow { row: row_rev.into(), group_id: group.id.clone(), }); } } - if records.is_empty() { - self.default_group.rows.push(row_rev.into()); + if group_rows.is_empty() { + self.default_group.add_row(row_rev.into()); } else { - for record in records { - if let Some(group) = self.groups_map.get_mut(&record.group_id) { - group.rows.push(record.row); + for group_row in group_rows { + if let Some(group) = self.groups_map.get_mut(&group_row.group_id) { + group.add_row(group_row.row); } } } } else { - self.default_group.rows.push(row_rev.into()); + self.default_group.add_row(row_rev.into()); } } - Ok(()) + let default_group = self.default_group.clone(); + let mut groups: Vec = self.groups_map.values().cloned().collect(); + if !default_group.number_of_row() == 0 { + groups.push(default_group); + } + + Ok(groups) } fn did_update_row( @@ -292,7 +208,7 @@ where } } -struct GroupRecord { +struct GroupRow { row: RowPB, group_id: String, } 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 c07b3acec4..42e687445d 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 @@ -2,44 +2,48 @@ use crate::entities::{ CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupRowsChangesetPB, NumberGroupConfigurationPB, SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB, }; +use crate::services::group::configuration::GroupConfigurationReader; +use crate::services::group::group_controller::GroupController; use crate::services::group::{ - CheckboxGroupController, Group, GroupController, MultiSelectGroupController, SingleSelectGroupController, + CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController, SingleSelectGroupController, }; -use bytes::Bytes; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - gen_grid_group_id, CheckboxGroupConfigurationRevision, DateGroupConfigurationRevision, FieldRevision, - GroupConfigurationRevision, NumberGroupConfigurationRevision, RowChangeset, RowRevision, - SelectOptionGroupConfigurationRevision, TextGroupConfigurationRevision, UrlGroupConfigurationRevision, + CheckboxGroupConfigurationRevision, DateGroupConfigurationRevision, FieldRevision, GroupConfigurationRevision, + NumberGroupConfigurationRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, + TextGroupConfigurationRevision, UrlGroupConfigurationRevision, }; -use lib_infra::future::AFFuture; + use std::future::Future; use std::sync::Arc; use tokio::sync::RwLock; -pub trait GroupConfigurationDelegate: Send + Sync + 'static { - fn get_group_configuration(&self, field_rev: Arc) -> AFFuture; -} - pub(crate) struct GroupService { - delegate: Box, + configuration_reader: Arc, + configuration_writer: Arc, group_controller: Option>>, } impl GroupService { - pub(crate) async fn new(delegate: Box) -> Self { + pub(crate) async fn new(configuration_reader: R, configuration_writer: W) -> Self + where + R: GroupConfigurationReader, + W: GroupConfigurationWriter, + { Self { - delegate, + configuration_reader: Arc::new(configuration_reader), + configuration_writer: Arc::new(configuration_writer), group_controller: None, } } pub(crate) async fn groups(&self) -> Vec { - if let Some(group_action_handler) = self.group_controller.as_ref() { - group_action_handler.read().await.groups() - } else { - vec![] - } + // if let Some(group_action_handler) = self.group_controller.as_ref() { + // group_action_handler.read().await.groups() + // } else { + // vec![] + // } + todo!() } pub(crate) async fn load_groups( @@ -49,13 +53,25 @@ impl GroupService { ) -> Option> { let field_rev = find_group_field(field_revs)?; let field_type: FieldType = field_rev.ty.into(); - let configuration = self.delegate.get_group_configuration(field_rev.clone()).await; - match self - .build_groups(&field_type, &field_rev, row_revs, configuration) - .await - { - Ok(groups) => Some(groups), - Err(_) => None, + match self.make_group_controller(&field_type, &field_rev).await { + Ok(group_controller) => { + self.group_controller = group_controller; + let mut groups = vec![]; + if let Some(group_action_handler) = self.group_controller.as_ref() { + let mut write_guard = group_action_handler.write().await; + groups = match write_guard.fill_groups(&row_revs, &field_rev) { + Ok(groups) => groups, + Err(e) => { + tracing::error!("Fill groups failed:{:?}", e); + vec![] + } + }; + + drop(write_guard); + } + Some(groups) + } + Err(_) => Some(vec![]), } } @@ -151,14 +167,13 @@ impl GroupService { } } - #[tracing::instrument(level = "trace", skip_all, err)] - async fn build_groups( + #[tracing::instrument(level = "trace", skip_all)] + async fn make_group_controller( &mut self, field_type: &FieldType, field_rev: &Arc, - row_revs: Vec>, - configuration: GroupConfigurationRevision, - ) -> FlowyResult> { + ) -> FlowyResult>>> { + let mut group_controller: Option>> = None; match field_type { FieldType::RichText => { // let generator = GroupGenerator::::from_configuration(configuration); @@ -170,31 +185,37 @@ impl GroupService { // let generator = GroupGenerator::::from_configuration(configuration); } FieldType::SingleSelect => { - let controller = SingleSelectGroupController::new(field_rev, configuration)?; - self.group_controller = Some(Arc::new(RwLock::new(controller))); + let controller = SingleSelectGroupController::new( + field_rev, + self.configuration_reader.clone(), + self.configuration_writer.clone(), + ) + .await?; + group_controller = Some(Arc::new(RwLock::new(controller))); } FieldType::MultiSelect => { - let controller = MultiSelectGroupController::new(field_rev, configuration)?; - self.group_controller = Some(Arc::new(RwLock::new(controller))); + let controller = MultiSelectGroupController::new( + field_rev, + self.configuration_reader.clone(), + self.configuration_writer.clone(), + ) + .await?; + group_controller = Some(Arc::new(RwLock::new(controller))); } FieldType::Checkbox => { - let controller = CheckboxGroupController::new(field_rev, configuration)?; - self.group_controller = Some(Arc::new(RwLock::new(controller))); + let controller = CheckboxGroupController::new( + field_rev, + self.configuration_reader.clone(), + self.configuration_writer.clone(), + ) + .await?; + group_controller = Some(Arc::new(RwLock::new(controller))) } FieldType::URL => { // let generator = GroupGenerator::::from_configuration(configuration); } - }; - - let mut groups = vec![]; - if let Some(group_action_handler) = self.group_controller.as_ref() { - let mut write_guard = group_action_handler.write().await; - let _ = write_guard.group_rows(&row_revs, field_rev)?; - groups = write_guard.groups(); - drop(write_guard); } - - Ok(groups) + Ok(group_controller) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs index f8b96c8bab..19536b8c5b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs @@ -1,5 +1,11 @@ -mod controllers; +mod action; +mod configuration; +mod controller_impls; +mod entities; +mod group_controller; mod group_service; -pub(crate) use controllers::*; +pub(crate) use configuration::*; +pub(crate) use controller_impls::*; +pub(crate) use entities::*; pub(crate) use group_service::*; 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 1cc16f7da7..16ee630cc7 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,11 +1,4 @@ -use crate::entities::{ - GridLayout, GridLayoutPB, GridSettingPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, - RepeatedGridSortPB, -}; -use flowy_grid_data_model::revision::{FieldRevision, SettingRevision}; -use flowy_sync::entities::grid::{CreateFilterParams, DeleteFilterParams, GridSettingChangesetParams}; -use std::collections::HashMap; -use std::sync::Arc; +use crate::entities::{CreateFilterParams, DeleteFilterParams, GridLayout, GridSettingChangesetParams}; pub struct GridSettingChangesetBuilder { params: GridSettingChangesetParams, @@ -20,8 +13,6 @@ impl GridSettingChangesetBuilder { delete_filter: None, insert_group: None, delete_group: None, - insert_sort: None, - delete_sort: None, }; Self { params } } @@ -40,42 +31,3 @@ impl GridSettingChangesetBuilder { self.params } } - -pub fn make_grid_setting(grid_setting_rev: &SettingRevision, field_revs: &[Arc]) -> GridSettingPB { - let current_layout_type: GridLayout = grid_setting_rev.layout.clone().into(); - let filters_by_field_id = grid_setting_rev - .get_all_filters(field_revs) - .map(|filters_by_field_id| { - filters_by_field_id - .into_iter() - .map(|(k, v)| (k, v.into())) - .collect::>() - }) - .unwrap_or_default(); - let groups_by_field_id = grid_setting_rev - .get_all_groups(field_revs) - .map(|groups_by_field_id| { - groups_by_field_id - .into_iter() - .map(|(k, v)| (k, v.into())) - .collect::>() - }) - .unwrap_or_default(); - let sorts_by_field_id = grid_setting_rev - .get_all_sort() - .map(|sorts_by_field_id| { - sorts_by_field_id - .into_iter() - .map(|(k, v)| (k, v.into())) - .collect::>() - }) - .unwrap_or_default(); - - GridSettingPB { - layouts: GridLayoutPB::all(), - current_layout_type, - 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/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs new file mode 100644 index 0000000000..7079b52229 --- /dev/null +++ b/shared-lib/flowy-grid-data-model/src/revision/filter_rev.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] +pub struct FilterConfigurationRevision { + pub id: String, + pub field_id: String, + pub condition: u8, + pub content: Option, +} 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 ff15170932..01ca80a380 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,8 +1,7 @@ -use crate::revision::{FieldRevision, FieldTypeRevision}; +use crate::revision::{FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision}; use indexmap::IndexMap; use nanoid::nanoid; use serde::{Deserialize, Serialize}; -use serde_repr::*; use std::collections::HashMap; use std::fmt::Debug; use std::sync::Arc; @@ -15,6 +14,7 @@ pub fn gen_grid_group_id() -> String { nanoid!(6) } +#[allow(dead_code)] pub fn gen_grid_sort_id() -> String { nanoid!(6) } @@ -24,114 +24,6 @@ pub type FilterConfigurationsByFieldId = HashMap; pub type GroupConfigurationsByFieldId = HashMap>>; -// -pub type SortConfiguration = Configuration; -pub type SortConfigurationsByFieldId = HashMap>>; - -#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] -pub struct SettingRevision { - pub layout: LayoutRevision, - - pub filters: FilterConfiguration, - - #[serde(default)] - pub groups: GroupConfiguration, - - #[serde(skip)] - pub sorts: SortConfiguration, -} - -#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)] -#[repr(u8)] -pub enum LayoutRevision { - Table = 0, - Board = 1, -} - -impl ToString for LayoutRevision { - fn to_string(&self) -> String { - let layout_rev = self.clone() as u8; - layout_rev.to_string() - } -} - -impl std::default::Default for LayoutRevision { - fn default() -> Self { - LayoutRevision::Table - } -} - -impl SettingRevision { - pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { - self.groups.get_all_objects(field_revs) - } - - pub fn get_groups( - &self, - field_id: &str, - field_type_rev: &FieldTypeRevision, - ) -> Option>> { - self.groups.get_objects(field_id, field_type_rev) - } - - pub fn get_mut_groups( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - ) -> Option<&mut Vec>> { - self.groups.get_mut_objects(field_id, field_type) - } - - pub fn insert_group( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - group_rev: GroupConfigurationRevision, - ) { - // only one group can be set - self.groups.remove_all(); - self.groups.insert_object(field_id, field_type, group_rev); - } - - pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { - self.filters.get_all_objects(field_revs) - } - - pub fn get_filters( - &self, - field_id: &str, - field_type_rev: &FieldTypeRevision, - ) -> Option>> { - self.filters.get_objects(field_id, field_type_rev) - } - - pub fn get_mut_filters( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - ) -> Option<&mut Vec>> { - self.filters.get_mut_objects(field_id, field_type) - } - - pub fn insert_filter( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - filter_rev: FilterConfigurationRevision, - ) { - self.filters.insert_object(field_id, field_type, filter_rev); - } - - pub fn get_all_sort(&self) -> Option { - None - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] -pub struct SortConfigurationRevision { - pub id: String, - pub field_id: Option, -} #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[serde(transparent)] @@ -239,38 +131,3 @@ where &mut self.object_by_field_type } } - -pub trait GroupConfigurationSerde { - fn from_configuration(s: &str) -> Result; -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] -pub struct GroupConfigurationRevision { - pub id: String, - pub field_id: String, - pub field_type_rev: FieldTypeRevision, - pub content: String, -} - -impl GroupConfigurationRevision { - pub fn new(field_id: String, field_type: FieldTypeRevision, content: T) -> Result - where - T: serde::Serialize, - { - let content = serde_json::to_string(&content)?; - Ok(Self { - id: gen_grid_group_id(), - field_id, - field_type_rev: field_type, - content, - }) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] -pub struct FilterConfigurationRevision { - pub id: String, - pub field_id: String, - pub condition: u8, - pub content: Option, -} diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs index 2fcc2fc4eb..9d4df3067e 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs @@ -1,19 +1,49 @@ -use crate::revision::SettingRevision; +use crate::revision::{ + FieldRevision, FieldTypeRevision, FilterConfiguration, FilterConfigurationRevision, FilterConfigurationsByFieldId, + GroupConfiguration, GroupConfigurationRevision, GroupConfigurationsByFieldId, +}; use nanoid::nanoid; use serde::{Deserialize, Serialize}; +use serde_repr::*; +use std::sync::Arc; #[allow(dead_code)] pub fn gen_grid_view_id() -> String { nanoid!(6) } +#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)] +#[repr(u8)] +pub enum LayoutRevision { + Table = 0, + Board = 1, +} + +impl ToString for LayoutRevision { + fn to_string(&self) -> String { + let layout_rev = self.clone() as u8; + layout_rev.to_string() + } +} + +impl std::default::Default for LayoutRevision { + fn default() -> Self { + LayoutRevision::Table + } +} + #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct GridViewRevision { pub view_id: String, pub grid_id: String, - pub setting: SettingRevision, + pub layout: LayoutRevision, + + pub filters: FilterConfiguration, + + #[serde(default)] + pub groups: GroupConfiguration, // For the moment, we just use the order returned from the GridRevision #[allow(dead_code)] @@ -26,10 +56,78 @@ impl GridViewRevision { GridViewRevision { view_id, grid_id, - setting: Default::default(), + layout: Default::default(), + filters: Default::default(), + groups: Default::default(), row_orders: vec![], } } + + pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { + self.groups.get_all_objects(field_revs) + } + + pub fn get_groups( + &self, + field_id: &str, + field_type_rev: &FieldTypeRevision, + ) -> Option> { + let mut groups = self.groups.get_objects(field_id, field_type_rev)?; + if groups.is_empty() { + debug_assert_eq!(groups.len(), 1); + Some(groups.pop().unwrap()) + } else { + None + } + } + + pub fn get_mut_groups( + &mut self, + field_id: &str, + field_type: &FieldTypeRevision, + ) -> Option<&mut Vec>> { + self.groups.get_mut_objects(field_id, field_type) + } + + pub fn insert_group( + &mut self, + field_id: &str, + field_type: &FieldTypeRevision, + group_rev: GroupConfigurationRevision, + ) { + // only one group can be set + self.groups.remove_all(); + self.groups.insert_object(field_id, field_type, group_rev); + } + + pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { + self.filters.get_all_objects(field_revs) + } + + pub fn get_filters( + &self, + field_id: &str, + field_type_rev: &FieldTypeRevision, + ) -> Option>> { + self.filters.get_objects(field_id, field_type_rev) + } + + pub fn get_mut_filters( + &mut self, + field_id: &str, + field_type: &FieldTypeRevision, + ) -> Option<&mut Vec>> { + self.filters.get_mut_objects(field_id, field_type) + } + + pub fn insert_filter( + &mut self, + field_id: &str, + field_type: &FieldTypeRevision, + filter_rev: FilterConfigurationRevision, + ) { + self.filters.insert_object(field_id, field_type, filter_rev); + } } #[derive(Debug, Clone, Default, Serialize, Deserialize)] diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index 932cc60033..83deeb2735 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -1,32 +1,91 @@ +use crate::revision::{gen_grid_group_id, FieldTypeRevision}; use serde::{Deserialize, Serialize}; +use serde_json::Error; use serde_repr::*; +pub trait GroupConfigurationContentSerde: Sized { + fn from_configuration(s: &str) -> Result; +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] +pub struct GroupConfigurationRevision { + pub id: String, + pub field_id: String, + pub field_type_rev: FieldTypeRevision, + pub content: String, +} + +impl GroupConfigurationRevision { + pub fn new(field_id: String, field_type: FieldTypeRevision, content: T) -> Result + where + T: serde::Serialize, + { + let content = serde_json::to_string(&content)?; + Ok(Self { + id: gen_grid_group_id(), + field_id, + field_type_rev: field_type, + content, + }) + } +} + #[derive(Default, Serialize, Deserialize)] pub struct TextGroupConfigurationRevision { pub hide_empty: bool, } +impl GroupConfigurationContentSerde for TextGroupConfigurationRevision { + fn from_configuration(s: &str) -> Result { + serde_json::from_str(s) + } +} + #[derive(Default, Serialize, Deserialize)] pub struct NumberGroupConfigurationRevision { pub hide_empty: bool, } +impl GroupConfigurationContentSerde for NumberGroupConfigurationRevision { + fn from_configuration(s: &str) -> Result { + serde_json::from_str(s) + } +} + #[derive(Default, Serialize, Deserialize)] pub struct UrlGroupConfigurationRevision { pub hide_empty: bool, } +impl GroupConfigurationContentSerde for UrlGroupConfigurationRevision { + fn from_configuration(s: &str) -> Result { + serde_json::from_str(s) + } +} + #[derive(Default, Serialize, Deserialize)] pub struct CheckboxGroupConfigurationRevision { pub hide_empty: bool, } +impl GroupConfigurationContentSerde for CheckboxGroupConfigurationRevision { + fn from_configuration(s: &str) -> Result { + serde_json::from_str(s) + } +} + #[derive(Default, Serialize, Deserialize)] pub struct SelectOptionGroupConfigurationRevision { pub hide_empty: bool, pub groups: Vec, } +impl GroupConfigurationContentSerde for SelectOptionGroupConfigurationRevision { + fn from_configuration(s: &str) -> Result { + serde_json::from_str(s) + } +} + #[derive(Default, Serialize, Deserialize)] pub struct GroupRecordRevision { pub group_id: String, @@ -42,6 +101,12 @@ pub struct DateGroupConfigurationRevision { pub condition: DateCondition, } +impl GroupConfigurationContentSerde for DateGroupConfigurationRevision { + fn from_configuration(s: &str) -> Result { + serde_json::from_str(s) + } +} + #[derive(Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum DateCondition { 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 d9df0910bd..460370b86b 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_block; mod grid_rev; mod grid_setting_rev; mod grid_view; mod group_rev; +pub use filter_rev::*; pub use grid_block::*; pub use grid_rev::*; pub use grid_setting_rev::*; diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index db52d0b38b..5ec4a87ef9 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -3,7 +3,7 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_text_delta_from_revisions}; use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, FilterConfigurationRevision, FilterConfigurationsByFieldId, GridViewRevision, - GroupConfigurationRevision, GroupConfigurationsByFieldId, SettingRevision, SortConfigurationsByFieldId, + GroupConfigurationRevision, GroupConfigurationsByFieldId, }; use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder}; use std::sync::Arc; @@ -48,23 +48,11 @@ impl GridViewRevisionPad { Self::from_delta(delta) } - pub fn get_setting_rev(&self) -> &SettingRevision { - &self.view.setting - } - pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { - self.setting.groups.get_all_objects(field_revs) + self.groups.get_all_objects(field_revs) } - pub fn get_groups( - &self, - field_id: &str, - field_type_rev: &FieldTypeRevision, - ) -> Option>> { - self.setting.groups.get_objects(field_id, field_type_rev) - } - - pub fn insert_group( + pub fn insert_group_configuration( &mut self, field_id: &str, field_type: &FieldTypeRevision, @@ -72,8 +60,8 @@ impl GridViewRevisionPad { ) -> CollaborateResult> { self.modify(|view| { // only one group can be set - view.setting.groups.remove_all(); - view.setting.groups.insert_object(field_id, field_type, group_rev); + view.groups.remove_all(); + view.groups.insert_object(field_id, field_type, group_rev); Ok(Some(())) }) } @@ -85,7 +73,7 @@ impl GridViewRevisionPad { group_id: &str, ) -> CollaborateResult> { self.modify(|view| { - if let Some(groups) = view.setting.groups.get_mut_objects(field_id, field_type) { + if let Some(groups) = view.groups.get_mut_objects(field_id, field_type) { groups.retain(|group| group.id != group_id); Ok(Some(())) } else { @@ -95,7 +83,7 @@ impl GridViewRevisionPad { } pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { - self.setting.filters.get_all_objects(field_revs) + self.filters.get_all_objects(field_revs) } pub fn get_filters( @@ -103,7 +91,7 @@ impl GridViewRevisionPad { field_id: &str, field_type_rev: &FieldTypeRevision, ) -> Option>> { - self.setting.filters.get_objects(field_id, field_type_rev) + self.filters.get_objects(field_id, field_type_rev) } pub fn insert_filter( @@ -113,7 +101,7 @@ impl GridViewRevisionPad { filter_rev: FilterConfigurationRevision, ) -> CollaborateResult> { self.modify(|view| { - view.setting.filters.insert_object(field_id, field_type, filter_rev); + view.filters.insert_object(field_id, field_type, filter_rev); Ok(Some(())) }) } @@ -125,7 +113,7 @@ impl GridViewRevisionPad { filter_id: &str, ) -> CollaborateResult> { self.modify(|view| { - if let Some(filters) = view.setting.filters.get_mut_objects(field_id, field_type) { + if let Some(filters) = view.filters.get_mut_objects(field_id, field_type) { filters.retain(|filter| filter.id != filter_id); Ok(Some(())) } else { @@ -134,10 +122,6 @@ impl GridViewRevisionPad { }) } - pub fn get_all_sort(&self) -> Option { - None - } - pub fn json_str(&self) -> CollaborateResult { make_grid_view_rev_json_str(&self.view) } From 49601b66efb30e7bfbf3585f930091f5e7b71beb Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 20 Aug 2022 16:44:44 +0800 Subject: [PATCH 04/10] chore: save group configuration --- .../src/services/grid_view_editor.rs | 3 +- .../src/services/group/configuration.rs | 17 +++++---- .../controller_impls/checkbox_controller.rs | 10 +++--- .../select_option_controller/util.rs | 5 +-- .../src/services/group/group_controller.rs | 8 ++--- .../src/services/group/group_service.rs | 5 +-- .../src/revision/group_rev.rs | 35 +++++++++++++++---- 7 files changed, 53 insertions(+), 30 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 9a7173035a..3a04a9946f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -287,7 +287,7 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { &self, field_id: &str, field_type: FieldTypeRevision, - configuration: Arc, + configuration: GroupConfigurationRevision, ) -> AFFuture> { let user_id = self.user_id.clone(); let rev_manager = self.rev_manager.clone(); @@ -295,7 +295,6 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { let field_id = field_id.to_owned(); wrap_future(async move { - let configuration = (&*configuration).clone(); match view_pad .write() .await diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 3d737c307f..0c120d477f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,3 +1,4 @@ +use crate::services::group::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRecordRevision, @@ -14,13 +15,13 @@ pub trait GroupConfigurationWriter: Send + Sync + 'static { &self, field_id: &str, field_type: FieldTypeRevision, - configuration: Arc, + configuration: GroupConfigurationRevision, ) -> AFFuture>; } pub trait GroupConfigurationAction: Send + Sync { fn group_records(&self) -> &[GroupRecordRevision]; - fn save_groups(&self) -> FlowyResult<()>; + fn merge_groups(&self, groups: Vec) -> FlowyResult<()>; fn hide_group(&self, group_id: &str) -> FlowyResult<()>; fn show_group(&self, group_id: &str) -> FlowyResult<()>; } @@ -28,8 +29,9 @@ pub trait GroupConfigurationAction: Send + Sync { pub struct GenericGroupConfiguration { field_rev: Arc, reader: Arc, + configuration_rev: Arc, writer: Arc, - configuration: C, + pub(crate) configuration: C, } impl GenericGroupConfiguration @@ -41,15 +43,18 @@ where reader: Arc, writer: Arc, ) -> FlowyResult { - let configuration = reader.get_group_configuration(field_rev.clone()).await; - let configuration = C::from_configuration(&configuration.content)?; + let configuration_rev = reader.get_group_configuration(field_rev.clone()).await; + let configuration = C::from_configuration_content(&configuration.content)?; Ok(Self { field_rev, + configuration_rev, reader, writer, configuration, }) } + + pub async fn save_configuration(&self) {} } impl GroupConfigurationReader for Arc @@ -69,7 +74,7 @@ where &self, field_id: &str, field_type: FieldTypeRevision, - configuration: Arc, + configuration: GroupConfigurationRevision, ) -> AFFuture> { (**self).save_group_configuration(field_id, field_type, configuration) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index fca49513c8..d78c055ab6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -19,19 +19,19 @@ pub type CheckboxGroupController = GenericGroupController< pub type CheckboxGroupConfiguration = GenericGroupConfiguration; impl GroupConfigurationAction for CheckboxGroupConfiguration { fn group_records(&self) -> &[GroupRecordRevision] { - todo!() + vec![].as_slice() } - fn save_groups(&self) -> FlowyResult<()> { - todo!() + fn merge_groups(&self, groups: Vec) -> FlowyResult<()> { + Ok(()) } fn hide_group(&self, group_id: &str) -> FlowyResult<()> { - todo!() + Ok(()) } fn show_group(&self, group_id: &str) -> FlowyResult<()> { - todo!() + Ok(()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs index d95a39f60c..a0a4c2f13e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -11,10 +11,11 @@ use flowy_grid_data_model::revision::{ pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; impl GroupConfigurationAction for SelectOptionGroupConfiguration { fn group_records(&self) -> &[GroupRecordRevision] { - todo!() + self.configuration.as_slice() } - fn save_groups(&self) -> FlowyResult<()> { + fn merge_groups(&self, groups: Vec) -> FlowyResult<()> { + // self.writer.save_group_configuration() todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs index fb2c0aaa6e..97755fd0ee 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs @@ -5,11 +5,11 @@ use crate::services::group::configuration::{GenericGroupConfiguration, GroupConf use crate::services::group::entities::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, RowChangeset, RowRevision, - TypeOptionDataDeserializer, + FieldRevision, GroupConfigurationContentSerde, RowChangeset, RowRevision, TypeOptionDataDeserializer, }; use indexmap::IndexMap; -use lib_infra::future::AFFuture; + +use crate::services::group::GroupConfigurationWriter; use std::marker::PhantomData; use std::sync::Arc; @@ -84,7 +84,7 @@ where pub async fn new( field_rev: &Arc, configuration_reader: Arc, - configuration_writer: Arc, + configuration_writer: Arc, ) -> FlowyResult { let configuration = GenericGroupConfiguration::::new(field_rev.clone(), configuration_reader, configuration_writer).await?; 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 42e687445d..0b60b54535 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,3 @@ -use crate::entities::{ - CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupRowsChangesetPB, - NumberGroupConfigurationPB, SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB, -}; use crate::services::group::configuration::GroupConfigurationReader; use crate::services::group::group_controller::GroupController; use crate::services::group::{ @@ -14,6 +10,7 @@ use flowy_grid_data_model::revision::{ TextGroupConfigurationRevision, UrlGroupConfigurationRevision, }; +use crate::entities::{FieldType, GroupRowsChangesetPB}; use std::future::Future; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index 83deeb2735..c4d2287c0c 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -4,7 +4,8 @@ use serde_json::Error; use serde_repr::*; pub trait GroupConfigurationContentSerde: Sized { - fn from_configuration(s: &str) -> Result; + fn from_configuration_content(s: &str) -> Result; + fn to_configuration_content(&self) -> Result; } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] @@ -36,9 +37,12 @@ pub struct TextGroupConfigurationRevision { } impl GroupConfigurationContentSerde for TextGroupConfigurationRevision { - fn from_configuration(s: &str) -> Result { + fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } } #[derive(Default, Serialize, Deserialize)] @@ -47,9 +51,12 @@ pub struct NumberGroupConfigurationRevision { } impl GroupConfigurationContentSerde for NumberGroupConfigurationRevision { - fn from_configuration(s: &str) -> Result { + fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } } #[derive(Default, Serialize, Deserialize)] @@ -58,9 +65,12 @@ pub struct UrlGroupConfigurationRevision { } impl GroupConfigurationContentSerde for UrlGroupConfigurationRevision { - fn from_configuration(s: &str) -> Result { + fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } } #[derive(Default, Serialize, Deserialize)] @@ -69,9 +79,13 @@ pub struct CheckboxGroupConfigurationRevision { } impl GroupConfigurationContentSerde for CheckboxGroupConfigurationRevision { - fn from_configuration(s: &str) -> Result { + fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } } #[derive(Default, Serialize, Deserialize)] @@ -81,9 +95,13 @@ pub struct SelectOptionGroupConfigurationRevision { } impl GroupConfigurationContentSerde for SelectOptionGroupConfigurationRevision { - fn from_configuration(s: &str) -> Result { + fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } } #[derive(Default, Serialize, Deserialize)] @@ -102,9 +120,12 @@ pub struct DateGroupConfigurationRevision { } impl GroupConfigurationContentSerde for DateGroupConfigurationRevision { - fn from_configuration(s: &str) -> Result { + fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } } #[derive(Serialize_repr, Deserialize_repr)] From 3c022d4de5c3b249d35f54f1a77a94fd138bdf22 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 20 Aug 2022 17:10:34 +0800 Subject: [PATCH 05/10] chore: save group configuration --- .../src/services/grid_view_editor.rs | 29 +++++++++++++++++-- .../src/services/group/configuration.rs | 20 +++++++++---- .../controller_impls/checkbox_controller.rs | 2 +- .../select_option_controller/util.rs | 3 +- .../src/client_grid/view_revision_pad.rs | 21 ++++++++++++++ 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 3a04a9946f..9ab6f4801a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -287,9 +287,11 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { &self, field_id: &str, field_type: FieldTypeRevision, - configuration: GroupConfigurationRevision, + group_id: &str, + mut_fn: impl FnOnce(&mut GroupConfigurationRevision), ) -> AFFuture> { let user_id = self.user_id.clone(); + let group_id = group_id.to_owned(); let rev_manager = self.rev_manager.clone(); let view_pad = self.view_pad.clone(); let field_id = field_id.to_owned(); @@ -298,13 +300,36 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { match view_pad .write() .await - .insert_group_configuration(&field_id, &field_type, configuration)? + .get_mut_group(&field_id, &field_type, &group_id, mut_fn)? { None => Ok(()), Some(changeset) => apply_change(&user_id, rev_manager, changeset).await, } }) } + // fn save_group_configuration( + // &self, + // field_id: &str, + // field_type: FieldTypeRevision, + // + // configuration: GroupConfigurationRevision, + // ) -> AFFuture> { + // let user_id = self.user_id.clone(); + // let rev_manager = self.rev_manager.clone(); + // let view_pad = self.view_pad.clone(); + // let field_id = field_id.to_owned(); + // + // wrap_future(async move { + // match view_pad + // .write() + // .await + // .insert_group_configuration(&field_id, &field_type, configuration)? + // { + // None => Ok(()), + // Some(changeset) => apply_change(&user_id, rev_manager, changeset).await, + // } + // }) + // } } pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc]) -> GridSettingPB { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 0c120d477f..4fe59fbaca 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -10,12 +10,13 @@ pub trait GroupConfigurationReader: Send + Sync + 'static { fn get_group_configuration(&self, field_rev: Arc) -> AFFuture>; } -pub trait GroupConfigurationWriter: Send + Sync + 'static { +pub trait GroupConfigurationWriter: Send + Sync + 'static + ?Sized { fn save_group_configuration( &self, field_id: &str, field_type: FieldTypeRevision, - configuration: GroupConfigurationRevision, + group_id: &str, + mut_fn: fn(&mut GroupConfigurationRevision), ) -> AFFuture>; } @@ -44,7 +45,7 @@ where writer: Arc, ) -> FlowyResult { let configuration_rev = reader.get_group_configuration(field_rev.clone()).await; - let configuration = C::from_configuration_content(&configuration.content)?; + let configuration = C::from_configuration_content(&configuration_rev.content)?; Ok(Self { field_rev, configuration_rev, @@ -74,8 +75,17 @@ where &self, field_id: &str, field_type: FieldTypeRevision, - configuration: GroupConfigurationRevision, + group_id: &str, + mut_fn: impl FnOnce(&mut GroupConfigurationRevision), ) -> AFFuture> { - (**self).save_group_configuration(field_id, field_type, configuration) + todo!() } + // fn save_group_configuration( + // &self, + // field_id: &str, + // field_type: FieldTypeRevision, + // configuration: GroupConfigurationRevision, + // ) -> AFFuture> { + // (**self).save_group_configuration(field_id, field_type, configuration) + // } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index d78c055ab6..dc278af7f5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -19,7 +19,7 @@ pub type CheckboxGroupController = GenericGroupController< pub type CheckboxGroupConfiguration = GenericGroupConfiguration; impl GroupConfigurationAction for CheckboxGroupConfiguration { fn group_records(&self) -> &[GroupRecordRevision] { - vec![].as_slice() + &[] } fn merge_groups(&self, groups: Vec) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs index a0a4c2f13e..b6439f1f12 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -11,7 +11,8 @@ use flowy_grid_data_model::revision::{ pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; impl GroupConfigurationAction for SelectOptionGroupConfiguration { fn group_records(&self) -> &[GroupRecordRevision] { - self.configuration.as_slice() + // self.configuration.as_slice() + todo!() } fn merge_groups(&self, groups: Vec) -> FlowyResult<()> { diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index 5ec4a87ef9..3f5f799369 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -66,6 +66,27 @@ impl GridViewRevisionPad { }) } + pub fn get_mut_group( + &mut self, + field_id: &str, + field_type: &FieldTypeRevision, + group_id: &str, + mut_group_fn: F, + ) -> CollaborateResult> { + self.modify(|view| match view.groups.get_mut_objects(field_id, field_type) { + None => Ok(None), + Some(groups) => { + for mut group in groups { + if group.id == group_id { + mut_group_fn(Arc::make_mut(&mut group)); + return Ok(Some(())); + } + } + Ok(None) + } + }) + } + pub fn delete_group( &mut self, field_id: &str, From 6e6a8122434f2ce943761289b11d2a7e6236bfcb Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 20 Aug 2022 23:54:51 +0800 Subject: [PATCH 06/10] chore: save group revision and fix warnings --- .../app_flowy/lib/plugins/board/board.dart | 2 +- .../grid/application/grid_service.dart | 1 - .../flowy-grid/src/services/grid_editor.rs | 12 +- .../src/services/grid_view_editor.rs | 47 +++----- .../src/services/grid_view_manager.rs | 1 + .../src/services/group/configuration.rs | 112 ++++++++++++------ .../{group_controller.rs => controller.rs} | 35 +++--- .../controller_impls/checkbox_controller.rs | 31 +---- .../select_option_controller/mod.rs | 1 + .../multi_select_controller.rs | 4 +- .../single_select_controller.rs | 4 +- .../select_option_controller/util.rs | 25 +--- .../src/services/group/group_service.rs | 26 ++-- .../flowy-grid/src/services/group/mod.rs | 2 +- .../tests/grid/field_test/script.rs | 3 +- .../flowy-grid/tests/grid/field_test/test.rs | 2 +- .../tests/grid/filter_test/script.rs | 3 +- .../flowy-grid/tests/grid/grid_editor.rs | 3 - .../src/revision/group_rev.rs | 56 +++++++-- .../src/client_grid/view_revision_pad.rs | 13 +- 20 files changed, 203 insertions(+), 180 deletions(-) rename frontend/rust-lib/flowy-grid/src/services/group/{group_controller.rs => controller.rs} (88%) diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index c55d7f2e17..213cc8bc3c 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder { class BoardPluginConfig implements PluginConfig { @override - bool get creatable => false; + bool get creatable => true; } class BoardPlugin extends Plugin { diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart index 8c46ce18b2..c8b6873d91 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart @@ -3,7 +3,6 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/board_card.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart'; 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 0559cfa364..dabb77e1de 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -168,10 +168,12 @@ impl GridRevisionEditor { pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { let field_id = params.field_id.clone(); - let field_type: Option = match self.grid_pad.read().await.get_field_rev(params.field_id.as_str()) { - None => None, - Some((_, field_rev)) => Some(field_rev.ty.into()), - }; + let field_type: Option = self + .grid_pad + .read() + .await + .get_field_rev(params.field_id.as_str()) + .map(|(_, field_rev)| field_rev.ty.into()); match field_type { None => Err(ErrorCode::FieldDoesNotExist.into()), @@ -341,7 +343,7 @@ impl GridRevisionEditor { Ok(row_pb) } - pub async fn move_group(&self, params: MoveGroupParams) -> FlowyResult { + pub async fn move_group(&self, _params: MoveGroupParams) -> FlowyResult { // todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 9ab6f4801a..a9ade3f194 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -183,7 +183,7 @@ impl GridViewRevisionEditor { grid_setting } - pub(crate) async fn update_setting(&self, changeset: GridSettingChangesetParams) -> FlowyResult<()> { + pub(crate) async fn update_setting(&self, _changeset: GridSettingChangesetParams) -> FlowyResult<()> { // let _ = self.modify(|pad| Ok(pad.update_setting(changeset)?)).await; // Ok(()) todo!() @@ -207,6 +207,7 @@ impl GridViewRevisionEditor { .send(); } + #[allow(dead_code)] async fn modify(&self, f: F) -> FlowyResult<()> where F: for<'a> FnOnce(&'a mut GridViewRevisionPad) -> FlowyResult>, @@ -230,7 +231,7 @@ async fn apply_change( let GridViewRevisionChangeset { delta, md5 } = change; let (base_rev_id, rev_id) = rev_manager.next_rev_id_pair(); let delta_data = delta.json_bytes(); - let revision = Revision::new(&rev_manager.object_id, base_rev_id, rev_id, delta_data, &user_id, md5); + let revision = Revision::new(&rev_manager.object_id, base_rev_id, rev_id, delta_data, user_id, md5); let _ = rev_manager.add_local_revision(&revision).await?; Ok(()) } @@ -287,49 +288,29 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { &self, field_id: &str, field_type: FieldTypeRevision, - group_id: &str, - mut_fn: impl FnOnce(&mut GroupConfigurationRevision), + configuration_id: &str, + content: String, ) -> AFFuture> { let user_id = self.user_id.clone(); - let group_id = group_id.to_owned(); + let configuration_id = configuration_id.to_owned(); let rev_manager = self.rev_manager.clone(); let view_pad = self.view_pad.clone(); let field_id = field_id.to_owned(); wrap_future(async move { - match view_pad - .write() - .await - .get_mut_group(&field_id, &field_type, &group_id, mut_fn)? - { + match view_pad.write().await.get_mut_group( + &field_id, + &field_type, + &configuration_id, + |group_configuration| { + group_configuration.content = content; + }, + )? { None => Ok(()), Some(changeset) => apply_change(&user_id, rev_manager, changeset).await, } }) } - // fn save_group_configuration( - // &self, - // field_id: &str, - // field_type: FieldTypeRevision, - // - // configuration: GroupConfigurationRevision, - // ) -> AFFuture> { - // let user_id = self.user_id.clone(); - // let rev_manager = self.rev_manager.clone(); - // let view_pad = self.view_pad.clone(); - // let field_id = field_id.to_owned(); - // - // wrap_future(async move { - // match view_pad - // .write() - // .await - // .insert_group_configuration(&field_id, &field_type, configuration)? - // { - // None => Ok(()), - // Some(changeset) => apply_change(&user_id, rev_manager, changeset).await, - // } - // }) - // } } pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc]) -> GridSettingPB { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 42c4ff1c65..5386bdb893 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -131,6 +131,7 @@ impl GridViewManager { } } + #[allow(dead_code)] pub(crate) async fn move_group(&self) {} pub(crate) async fn get_view_editor(&self, view_id: &str) -> FlowyResult> { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 4fe59fbaca..15cbe6c61f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,8 +1,9 @@ use crate::services::group::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRecordRevision, + FieldRevision, FieldTypeRevision, GroupConfigurationContent, GroupConfigurationRevision, GroupRecordRevision, }; + use lib_infra::future::AFFuture; use std::sync::Arc; @@ -10,34 +11,28 @@ pub trait GroupConfigurationReader: Send + Sync + 'static { fn get_group_configuration(&self, field_rev: Arc) -> AFFuture>; } -pub trait GroupConfigurationWriter: Send + Sync + 'static + ?Sized { +pub trait GroupConfigurationWriter: Send + Sync + 'static { fn save_group_configuration( &self, field_id: &str, field_type: FieldTypeRevision, - group_id: &str, - mut_fn: fn(&mut GroupConfigurationRevision), + configuration_id: &str, + content: String, ) -> AFFuture>; } -pub trait GroupConfigurationAction: Send + Sync { - fn group_records(&self) -> &[GroupRecordRevision]; - fn merge_groups(&self, groups: Vec) -> FlowyResult<()>; - fn hide_group(&self, group_id: &str) -> FlowyResult<()>; - fn show_group(&self, group_id: &str) -> FlowyResult<()>; -} - pub struct GenericGroupConfiguration { + pub configuration: C, + // pub groups_map: IndexMap, + configuration_id: String, field_rev: Arc, reader: Arc, - configuration_rev: Arc, writer: Arc, - pub(crate) configuration: C, } impl GenericGroupConfiguration where - C: GroupConfigurationContentSerde, + C: GroupConfigurationContent, { pub async fn new( field_rev: Arc, @@ -45,17 +40,58 @@ where writer: Arc, ) -> FlowyResult { let configuration_rev = reader.get_group_configuration(field_rev.clone()).await; + let configuration_id = configuration_rev.id.clone(); let configuration = C::from_configuration_content(&configuration_rev.content)?; Ok(Self { + configuration_id, field_rev, - configuration_rev, reader, writer, configuration, }) } - pub async fn save_configuration(&self) {} + #[allow(dead_code)] + fn group_records(&self) -> &[GroupRecordRevision] { + todo!() + } + pub(crate) async fn merge_groups(&mut self, groups: &[Group]) -> FlowyResult<()> { + match merge_groups(self.configuration.get_groups(), groups) { + None => Ok(()), + Some(new_groups) => { + self.configuration.set_groups(new_groups); + let _ = self.save_configuration().await?; + Ok(()) + } + } + } + + #[allow(dead_code)] + pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> { + self.configuration.mut_group(group_id, |group_rev| { + group_rev.visible = false; + }); + let _ = self.save_configuration().await?; + Ok(()) + } + + #[allow(dead_code)] + pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> { + self.configuration.mut_group(group_id, |group_rev| { + group_rev.visible = true; + }); + let _ = self.save_configuration().await?; + Ok(()) + } + + pub async fn save_configuration(&self) -> FlowyResult<()> { + let content = self.configuration.to_configuration_content()?; + let _ = self + .writer + .save_group_configuration(&self.field_rev.id, self.field_rev.ty, &self.configuration_id, content) + .await?; + Ok(()) + } } impl GroupConfigurationReader for Arc @@ -67,25 +103,29 @@ where } } -impl GroupConfigurationWriter for Arc -where - T: GroupConfigurationWriter, -{ - fn save_group_configuration( - &self, - field_id: &str, - field_type: FieldTypeRevision, - group_id: &str, - mut_fn: impl FnOnce(&mut GroupConfigurationRevision), - ) -> AFFuture> { - todo!() +fn merge_groups(old_group: &[GroupRecordRevision], groups: &[Group]) -> Option> { + // tracing::trace!("Merge group: old: {}, new: {}", old_group.len(), groups.len()); + if old_group.is_empty() { + let new_groups = groups + .iter() + .map(|group| GroupRecordRevision::new(group.id.clone())) + .collect(); + return Some(new_groups); } - // fn save_group_configuration( - // &self, - // field_id: &str, - // field_type: FieldTypeRevision, - // configuration: GroupConfigurationRevision, - // ) -> AFFuture> { - // (**self).save_group_configuration(field_id, field_type, configuration) - // } + + let new_groups = groups + .iter() + .filter(|group| !old_group.iter().any(|group_rev| group_rev.group_id == group.id)) + .collect::>(); + + if new_groups.is_empty() { + return None; + } + + let mut old_group = old_group.to_vec(); + let new_groups = new_groups + .iter() + .map(|group| GroupRecordRevision::new(group.id.clone())); + old_group.extend(new_groups); + Some(old_group) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs similarity index 88% rename from frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs rename to frontend/rust-lib/flowy-grid/src/services/group/controller.rs index 97755fd0ee..44344fa0a1 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -1,15 +1,14 @@ use crate::entities::{GroupRowsChangesetPB, RowPB}; use crate::services::cell::{decode_any_cell_data, CellBytesParser}; use crate::services::group::action::GroupAction; -use crate::services::group::configuration::{GenericGroupConfiguration, GroupConfigurationReader}; +use crate::services::group::configuration::GenericGroupConfiguration; use crate::services::group::entities::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, GroupConfigurationContentSerde, RowChangeset, RowRevision, TypeOptionDataDeserializer, + FieldRevision, GroupConfigurationContent, RowChangeset, RowRevision, TypeOptionDataDeserializer, }; use indexmap::IndexMap; -use crate::services::group::GroupConfigurationWriter; use std::marker::PhantomData; use std::sync::Arc; @@ -18,7 +17,7 @@ const DEFAULT_GROUP_ID: &str = "default_group"; // Each kind of group must implement this trait to provide custom group // operations. For example, insert cell data to the row_rev when creating // a new row. -pub trait GroupController: GroupControllerSharedAction + Send + Sync { +pub trait GroupController: GroupControllerSharedOperation + Send + Sync { fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); } @@ -34,9 +33,10 @@ pub trait GroupGenerator { } // Defines the shared actions each group controller can perform. -pub trait GroupControllerSharedAction: Send + Sync { +pub trait GroupControllerSharedOperation: Send + Sync { // The field that is used for grouping the rows fn field_id(&self) -> &str; + fn groups(&self) -> &[Group]; fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult>; fn did_update_row( &mut self, @@ -66,32 +66,28 @@ pub trait GroupControllerSharedAction: Send + Sync { pub struct GenericGroupController { pub field_id: String, pub groups_map: IndexMap, - - /// default_group is used to store the rows that don't belong to any groups. - default_group: Group, pub type_option: Option, pub configuration: GenericGroupConfiguration, + /// default_group is used to store the rows that don't belong to any groups. + default_group: Group, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData

, } impl GenericGroupController where - C: GroupConfigurationContentSerde, + C: GroupConfigurationContent, T: TypeOptionDataDeserializer, G: GroupGenerator, TypeOptionType = T>, { pub async fn new( field_rev: &Arc, - configuration_reader: Arc, - configuration_writer: Arc, + mut configuration: GenericGroupConfiguration, ) -> FlowyResult { - let configuration = - GenericGroupConfiguration::::new(field_rev.clone(), configuration_reader, configuration_writer).await?; let field_type_rev = field_rev.ty; let type_option = field_rev.get_type_option_entry::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); - + let _ = configuration.merge_groups(&groups).await?; let default_group = Group::new( DEFAULT_GROUP_ID.to_owned(), field_rev.id.clone(), @@ -111,20 +107,21 @@ where } } -impl GroupControllerSharedAction for GenericGroupController +impl GroupControllerSharedOperation for GenericGroupController where P: CellBytesParser, + C: GroupConfigurationContent, Self: GroupAction, { fn field_id(&self) -> &str { &self.field_id } - fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult> { - // if self.configuration.is_none() { - // return Ok(vec![]); - // } + fn groups(&self) -> &[Group] { + todo!() + } + fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult> { for row_rev in row_revs { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let mut group_rows: Vec = vec![]; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index dc278af7f5..59a53ae72a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -1,13 +1,11 @@ use crate::entities::GroupRowsChangesetPB; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::group::action::GroupAction; -use crate::services::group::configuration::{GenericGroupConfiguration, GroupConfigurationAction}; +use crate::services::group::configuration::GenericGroupConfiguration; +use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; use crate::services::group::entities::Group; -use crate::services::group::group_controller::{GenericGroupController, GroupController, GroupGenerator}; -use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::{ - CheckboxGroupConfigurationRevision, FieldRevision, GroupRecordRevision, RowChangeset, RowRevision, -}; + +use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, RowChangeset, RowRevision}; pub type CheckboxGroupController = GenericGroupController< CheckboxGroupConfigurationRevision, @@ -17,23 +15,6 @@ pub type CheckboxGroupController = GenericGroupController< >; pub type CheckboxGroupConfiguration = GenericGroupConfiguration; -impl GroupConfigurationAction for CheckboxGroupConfiguration { - fn group_records(&self) -> &[GroupRecordRevision] { - &[] - } - - fn merge_groups(&self, groups: Vec) -> FlowyResult<()> { - Ok(()) - } - - fn hide_group(&self, group_id: &str) -> FlowyResult<()> { - Ok(()) - } - - fn show_group(&self, group_id: &str) -> FlowyResult<()> { - Ok(()) - } -} impl GroupAction for CheckboxGroupController { type CellDataType = CheckboxCellData; @@ -82,8 +63,8 @@ impl GroupGenerator for CheckboxGroupGenerator { fn generate_groups( field_id: &str, - configuration: &Self::ConfigurationType, - type_option: &Option, + _configuration: &Self::ConfigurationType, + _type_option: &Option, ) -> Vec { let check_group = Group::new( "true".to_string(), diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs index a2f393d093..0d7b8fa03e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/mod.rs @@ -4,3 +4,4 @@ mod util; pub use multi_select_controller::*; pub use single_select_controller::*; +pub use util::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index 33cd0613cd..e2e7f13ef9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -3,9 +3,9 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser}; use crate::services::group::action::GroupAction; +use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use crate::services::group::group_controller::{GenericGroupController, GroupController, GroupGenerator}; use flowy_grid_data_model::revision::{ FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, }; @@ -88,7 +88,7 @@ impl GroupGenerator for MultiSelectGroupGenerator { type TypeOptionType = MultiSelectTypeOptionPB; fn generate_groups( field_id: &str, - configuration: &Self::ConfigurationType, + _configuration: &Self::ConfigurationType, type_option: &Option, ) -> Vec { match type_option { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index 4c8360f427..44920a0f1f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -3,9 +3,9 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB}; use crate::services::group::action::GroupAction; +use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use crate::services::group::group_controller::{GenericGroupController, GroupController, GroupGenerator}; use flowy_grid_data_model::revision::{ FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, @@ -89,7 +89,7 @@ impl GroupGenerator for SingleSelectGroupGenerator { type TypeOptionType = SingleSelectTypeOptionPB; fn generate_groups( field_id: &str, - configuration: &Self::ConfigurationType, + _configuration: &Self::ConfigurationType, type_option: &Option, ) -> Vec { match type_option { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs index b6439f1f12..6675f26aa4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -1,33 +1,14 @@ use crate::entities::{GroupRowsChangesetPB, InsertedRowPB, RowPB}; use crate::services::cell::insert_select_option_cell; use crate::services::field::SelectOptionCellDataPB; -use crate::services::group::configuration::{GenericGroupConfiguration, GroupConfigurationAction}; +use crate::services::group::configuration::GenericGroupConfiguration; use crate::services::group::Group; -use flowy_error::FlowyResult; + use flowy_grid_data_model::revision::{ - FieldRevision, GroupRecordRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, + FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, }; pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; -impl GroupConfigurationAction for SelectOptionGroupConfiguration { - fn group_records(&self) -> &[GroupRecordRevision] { - // self.configuration.as_slice() - todo!() - } - - fn merge_groups(&self, groups: Vec) -> FlowyResult<()> { - // self.writer.save_group_configuration() - todo!() - } - - fn hide_group(&self, group_id: &str) -> FlowyResult<()> { - todo!() - } - - fn show_group(&self, group_id: &str) -> FlowyResult<()> { - todo!() - } -} pub fn add_row( group: &mut Group, 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 0b60b54535..7cd4e387b9 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,8 @@ use crate::services::group::configuration::GroupConfigurationReader; -use crate::services::group::group_controller::GroupController; +use crate::services::group::controller::GroupController; use crate::services::group::{ - CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController, SingleSelectGroupController, + CheckboxGroupConfiguration, CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController, + SelectOptionGroupConfiguration, SingleSelectGroupController, }; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ @@ -35,8 +36,8 @@ impl GroupService { } pub(crate) async fn groups(&self) -> Vec { - // if let Some(group_action_handler) = self.group_controller.as_ref() { - // group_action_handler.read().await.groups() + // if let Some(group_controller) = self.group_controller.as_ref() { + // group_controller.read().await.groups() // } else { // vec![] // } @@ -182,30 +183,33 @@ impl GroupService { // let generator = GroupGenerator::::from_configuration(configuration); } FieldType::SingleSelect => { - let controller = SingleSelectGroupController::new( - field_rev, + let configuration = SelectOptionGroupConfiguration::new( + field_rev.clone(), self.configuration_reader.clone(), self.configuration_writer.clone(), ) .await?; + let controller = SingleSelectGroupController::new(field_rev, configuration).await?; group_controller = Some(Arc::new(RwLock::new(controller))); } FieldType::MultiSelect => { - let controller = MultiSelectGroupController::new( - field_rev, + let configuration = SelectOptionGroupConfiguration::new( + field_rev.clone(), self.configuration_reader.clone(), self.configuration_writer.clone(), ) .await?; + let controller = MultiSelectGroupController::new(field_rev, configuration).await?; group_controller = Some(Arc::new(RwLock::new(controller))); } FieldType::Checkbox => { - let controller = CheckboxGroupController::new( - field_rev, + let configuration = CheckboxGroupConfiguration::new( + field_rev.clone(), self.configuration_reader.clone(), self.configuration_writer.clone(), ) .await?; + let controller = CheckboxGroupController::new(field_rev, configuration).await?; group_controller = Some(Arc::new(RwLock::new(controller))) } FieldType::URL => { @@ -229,7 +233,7 @@ fn find_group_field(field_revs: &[Arc]) -> Option GroupConfigurationRevision { let field_id = field_rev.id.clone(); - let field_type_rev = field_rev.ty.clone(); + let field_type_rev = field_rev.ty; let field_type: FieldType = field_rev.ty.into(); match field_type { FieldType::RichText => { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs index 19536b8c5b..2bc979c28d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs @@ -1,8 +1,8 @@ mod action; mod configuration; +mod controller; mod controller_impls; mod entities; -mod group_controller; mod group_service; pub(crate) use configuration::*; diff --git a/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs index ebe3d3adf2..c790285fb1 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs @@ -1,7 +1,6 @@ use crate::grid::grid_editor::GridEditorTest; -use flowy_grid::entities::InsertFieldParams; +use flowy_grid::entities::{FieldChangesetParams, InsertFieldParams}; use flowy_grid_data_model::revision::FieldRevision; -use flowy_sync::entities::grid::FieldChangesetParams; pub enum FieldScript { CreateField { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs index 98cb3d0324..3e255d3662 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs @@ -1,10 +1,10 @@ use crate::grid::field_test::script::FieldScript::*; use crate::grid::field_test::script::GridFieldTest; use crate::grid::field_test::util::*; +use flowy_grid::entities::FieldChangesetParams; use flowy_grid::services::field::selection_type_option::SelectOptionPB; use flowy_grid::services::field::SingleSelectTypeOptionPB; use flowy_grid_data_model::revision::TypeOptionDataEntry; -use flowy_sync::entities::grid::FieldChangesetParams; #[tokio::test] async fn grid_create_field() { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index 459cf5f82d..948528589f 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -3,10 +3,9 @@ #![allow(dead_code)] #![allow(unused_imports)] -use flowy_grid::entities::{CreateGridFilterPayloadPB, GridLayout, GridSettingPB}; +use flowy_grid::entities::{CreateFilterParams, CreateGridFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB}; use flowy_grid::services::setting::GridSettingChangesetBuilder; use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision}; -use flowy_sync::entities::grid::{CreateFilterParams, DeleteFilterParams, GridSettingChangesetParams}; use crate::grid::grid_editor::GridEditorTest; pub enum FilterScript { 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 ea8de69056..78cfc17b26 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -12,9 +12,6 @@ use flowy_grid::services::setting::GridSettingChangesetBuilder; use flowy_grid_data_model::revision::*; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::client_grid::GridBuilder; -use flowy_sync::entities::grid::{ - CreateFilterParams, DeleteFilterParams, FieldChangesetParams, GridSettingChangesetParams, -}; use flowy_test::helper::ViewTest; use flowy_test::FlowySDKTest; use std::collections::HashMap; diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index c4d2287c0c..9d7da79e5a 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -3,8 +3,21 @@ use serde::{Deserialize, Serialize}; use serde_json::Error; use serde_repr::*; -pub trait GroupConfigurationContentSerde: Sized { +pub trait GroupConfigurationContent: Sized { fn from_configuration_content(s: &str) -> Result; + + fn get_groups(&self) -> &[GroupRecordRevision] { + &[] + } + + fn mut_group(&mut self, _group_id: &str, _f: F) + where + F: FnOnce(&mut GroupRecordRevision), + { + } + + fn set_groups(&mut self, _new_groups: Vec) {} + fn to_configuration_content(&self) -> Result; } @@ -36,7 +49,7 @@ pub struct TextGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContentSerde for TextGroupConfigurationRevision { +impl GroupConfigurationContent for TextGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -50,7 +63,7 @@ pub struct NumberGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContentSerde for NumberGroupConfigurationRevision { +impl GroupConfigurationContent for NumberGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -64,7 +77,7 @@ pub struct UrlGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContentSerde for UrlGroupConfigurationRevision { +impl GroupConfigurationContent for UrlGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -78,7 +91,7 @@ pub struct CheckboxGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContentSerde for CheckboxGroupConfigurationRevision { +impl GroupConfigurationContent for CheckboxGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -94,17 +107,35 @@ pub struct SelectOptionGroupConfigurationRevision { pub groups: Vec, } -impl GroupConfigurationContentSerde for SelectOptionGroupConfigurationRevision { +impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } + fn get_groups(&self) -> &[GroupRecordRevision] { + &self.groups + } + + fn mut_group(&mut self, group_id: &str, f: F) + where + F: FnOnce(&mut GroupRecordRevision), + { + match self.groups.iter_mut().find(|group| group.group_id == group_id) { + None => {} + Some(group) => f(group), + } + } + + fn set_groups(&mut self, new_groups: Vec) { + self.groups = new_groups; + } + fn to_configuration_content(&self) -> Result { serde_json::to_string(self) } } -#[derive(Default, Serialize, Deserialize)] +#[derive(Clone, Default, Serialize, Deserialize)] pub struct GroupRecordRevision { pub group_id: String, @@ -113,13 +144,22 @@ pub struct GroupRecordRevision { } const DEFAULT_GROUP_RECORD_VISIBILITY: fn() -> bool = || true; +impl GroupRecordRevision { + pub fn new(group_id: String) -> Self { + Self { + group_id, + visible: true, + } + } +} + #[derive(Default, Serialize, Deserialize)] pub struct DateGroupConfigurationRevision { pub hide_empty: bool, pub condition: DateCondition, } -impl GroupConfigurationContentSerde for DateGroupConfigurationRevision { +impl GroupConfigurationContent for DateGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index 3f5f799369..fc5fa4bf67 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -70,15 +70,15 @@ impl GridViewRevisionPad { &mut self, field_id: &str, field_type: &FieldTypeRevision, - group_id: &str, - mut_group_fn: F, + configuration_id: &str, + mut_configuration_fn: F, ) -> CollaborateResult> { self.modify(|view| match view.groups.get_mut_objects(field_id, field_type) { None => Ok(None), - Some(groups) => { - for mut group in groups { - if group.id == group_id { - mut_group_fn(Arc::make_mut(&mut group)); + Some(configurations_revs) => { + for configuration_rev in configurations_revs { + if configuration_rev.id == configuration_id { + mut_configuration_fn(Arc::make_mut(configuration_rev)); return Ok(Some(())); } } @@ -170,6 +170,7 @@ impl GridViewRevisionPad { } } +#[derive(Debug)] pub struct GridViewRevisionChangeset { pub delta: TextDelta, pub md5: String, From 23efbc00c166dd28adda7a77ffa6098318604569 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 21 Aug 2022 13:56:06 +0800 Subject: [PATCH 07/10] ci: fix unit test --- .../flowy-grid/src/dart_notification.rs | 3 +- .../group_entities/group_changeset.rs | 4 +- .../rust-lib/flowy-grid/src/event_handler.rs | 17 +--- frontend/rust-lib/flowy-grid/src/event_map.rs | 4 +- .../flowy-grid/src/services/grid_editor.rs | 15 ++-- .../src/services/grid_view_editor.rs | 62 ++++++++++---- .../src/services/grid_view_manager.rs | 28 ++++--- .../src/services/group/configuration.rs | 84 ++++++++++++------- .../src/services/group/controller.rs | 17 ++-- .../multi_select_controller.rs | 8 +- .../single_select_controller.rs | 8 +- .../src/services/group/group_service.rs | 11 ++- .../tests/grid/filter_test/script.rs | 21 +---- .../tests/grid/group_test/script.rs | 21 ++++- .../src/revision/group_rev.rs | 29 +++---- .../src/client_grid/view_revision_pad.rs | 14 ---- 16 files changed, 193 insertions(+), 153 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 0bba5bbc11..a0030c6773 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -11,7 +11,8 @@ pub enum GridNotification { DidUpdateRow = 30, DidUpdateCell = 40, DidUpdateField = 50, - DidUpdateGroup = 60, + DidUpdateGroupView = 60, + DidUpdateGroup = 61, } impl std::default::Default for GridNotification { diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs index 41d46e3cc7..dbee60dca9 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs @@ -104,7 +104,7 @@ impl TryInto for MoveGroupPayloadPB { } #[derive(Debug, Default, ProtoBuf)] -pub struct GroupsChangesetPB { +pub struct GroupViewChangesetPB { #[pb(index = 1)] pub view_id: String, @@ -115,4 +115,4 @@ pub struct GroupsChangesetPB { pub deleted_groups: Vec, } -impl GroupsChangesetPB {} +impl GroupViewChangesetPB {} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 47df88b976..149f7017a3 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -35,17 +35,6 @@ pub(crate) async fn get_grid_setting_handler( data_result(grid_setting) } -#[tracing::instrument(level = "trace", skip(data, manager), err)] -pub(crate) async fn update_grid_setting_handler( - data: Data, - manager: AppData>, -) -> Result<(), FlowyError> { - let params: GridSettingChangesetParams = data.into_inner().try_into()?; - let editor = manager.open_grid(¶ms.grid_id).await?; - let _ = editor.update_grid_setting(params).await?; - Ok(()) -} - #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_grid_blocks_handler( data: Data, @@ -441,9 +430,9 @@ pub(crate) async fn create_board_card_handler( pub(crate) async fn move_group_handler( data: Data, manager: AppData>, -) -> DataResult { +) -> FlowyResult<()> { let params: MoveGroupParams = data.into_inner().try_into()?; let editor = manager.get_grid_editor(params.view_id.as_ref())?; - let changeset = editor.move_group(params).await?; - data_result(changeset) + let _ = editor.move_group(params).await?; + Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 76087fe64b..844ae7f5c3 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -11,7 +11,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetGrid, get_grid_handler) .event(GridEvent::GetGridBlocks, get_grid_blocks_handler) .event(GridEvent::GetGridSetting, get_grid_setting_handler) - .event(GridEvent::UpdateGridSetting, update_grid_setting_handler) + // .event(GridEvent::UpdateGridSetting, update_grid_setting_handler) // Field .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) @@ -219,6 +219,6 @@ pub enum GridEvent { #[event(input = "CreateBoardCardPayloadPB", output = "RowPB")] CreateBoardCard = 110, - #[event(input = "MoveGroupPayloadPB", output = "GroupsChangesetPB")] + #[event(input = "MoveGroupPayloadPB")] MoveGroup = 111, } 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 dabb77e1de..93c48b0880 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -343,9 +343,9 @@ impl GridRevisionEditor { Ok(row_pb) } - pub async fn move_group(&self, _params: MoveGroupParams) -> FlowyResult { - // - todo!() + pub async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { + let _ = self.view_manager.move_group(params).await?; + Ok(()) } pub async fn insert_rows(&self, row_revs: Vec) -> FlowyResult> { @@ -514,8 +514,13 @@ impl GridRevisionEditor { self.view_manager.get_filters().await } - pub async fn update_grid_setting(&self, params: GridSettingChangesetParams) -> FlowyResult<()> { - let _ = self.view_manager.update_setting(params).await?; + pub async fn update_filter(&self, params: CreateFilterParams) -> FlowyResult<()> { + let _ = self.view_manager.update_filter(params).await?; + Ok(()) + } + + pub async fn delete_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> { + let _ = self.view_manager.delete_filter(params).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index a9ade3f194..ff58585584 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -1,8 +1,8 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::entities::{ - CreateRowParams, GridFilterConfiguration, GridLayout, GridLayoutPB, GridSettingChangesetParams, GridSettingPB, - GroupPB, GroupRowsChangesetPB, InsertedRowPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, - RowPB, + CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridLayout, GridLayoutPB, + GridSettingChangesetParams, GridSettingPB, GroupPB, GroupRowsChangesetPB, GroupViewChangesetPB, InsertedRowPB, + MoveGroupParams, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RowPB, }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; @@ -11,7 +11,8 @@ use crate::services::group::{ }; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ - FieldRevision, FieldTypeRevision, GroupConfigurationRevision, RowChangeset, RowRevision, + gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision, + RowChangeset, RowRevision, }; use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad}; @@ -99,7 +100,7 @@ impl GridViewRevisionEditor { index: None, }; let changeset = GroupRowsChangesetPB::insert(group_id.clone(), vec![inserted_row]); - self.notify_did_update_group(changeset).await; + self.notify_did_update_group_rows(changeset).await; } } } @@ -114,7 +115,7 @@ impl GridViewRevisionEditor { .await { for changeset in changesets { - self.notify_did_update_group(changeset).await; + self.notify_did_update_group_rows(changeset).await; } } } @@ -128,7 +129,7 @@ impl GridViewRevisionEditor { .await { for changeset in changesets { - self.notify_did_update_group(changeset).await; + self.notify_did_update_group_rows(changeset).await; } } } @@ -150,7 +151,7 @@ impl GridViewRevisionEditor { { for changeset in changesets { tracing::trace!("Group: {} changeset: {}", changeset.group_id, changeset); - self.notify_did_update_group(changeset).await; + self.notify_did_update_group_rows(changeset).await; } } } @@ -173,22 +174,19 @@ impl GridViewRevisionEditor { } else { self.group_service.read().await.groups().await }; - Ok(groups.into_iter().map(GroupPB::from).collect()) } + pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { + todo!() + } + pub(crate) async fn get_setting(&self) -> GridSettingPB { let field_revs = self.field_delegate.get_field_revs().await; let grid_setting = make_grid_setting(&*self.pad.read().await, &field_revs); grid_setting } - pub(crate) async fn update_setting(&self, _changeset: GridSettingChangesetParams) -> FlowyResult<()> { - // let _ = self.modify(|pad| Ok(pad.update_setting(changeset)?)).await; - // Ok(()) - todo!() - } - pub(crate) async fn get_filters(&self) -> Vec { let field_revs = self.field_delegate.get_field_revs().await; match self.pad.read().await.get_all_filters(&field_revs) { @@ -201,12 +199,44 @@ impl GridViewRevisionEditor { } } - async fn notify_did_update_group(&self, changeset: GroupRowsChangesetPB) { + pub(crate) async fn insert_filter(&self, insert_filter: CreateFilterParams) -> FlowyResult<()> { + self.modify(|pad| { + let filter_rev = FilterConfigurationRevision { + id: gen_grid_filter_id(), + field_id: insert_filter.field_id.clone(), + condition: insert_filter.condition, + content: insert_filter.content, + }; + let changeset = pad.insert_filter(&insert_filter.field_id, &insert_filter.field_type_rev, filter_rev)?; + Ok(changeset) + }) + .await + } + + pub(crate) async fn delete_filter(&self, delete_filter: DeleteFilterParams) -> FlowyResult<()> { + self.modify(|pad| { + let changeset = pad.delete_filter( + &delete_filter.field_id, + &delete_filter.field_type_rev, + &delete_filter.filter_id, + )?; + Ok(changeset) + }) + .await + } + + async fn notify_did_update_group_rows(&self, changeset: GroupRowsChangesetPB) { send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup) .payload(changeset) .send(); } + async fn notify_did_update_view(&self, changeset: GroupViewChangesetPB) { + send_dart_notification(&self.view_id, GridNotification::DidUpdateGroupView) + .payload(changeset) + .send(); + } + #[allow(dead_code)] async fn modify(&self, f: F) -> FlowyResult<()> where diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 5386bdb893..802560190a 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -1,5 +1,6 @@ use crate::entities::{ - CreateRowParams, GridFilterConfiguration, GridSettingChangesetParams, GridSettingPB, RepeatedGridGroupPB, RowPB, + CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridSettingChangesetParams, + GridSettingPB, MoveGroupParams, RepeatedGridGroupPB, RowPB, }; use crate::manager::GridUser; use crate::services::grid_editor_task::GridServiceTaskScheduler; @@ -98,23 +99,33 @@ impl GridViewManager { Ok(view_editor.get_setting().await) } - pub(crate) async fn update_setting(&self, params: GridSettingChangesetParams) -> FlowyResult<()> { - let view_editor = self.get_default_view_editor().await?; - let _ = view_editor.update_setting(params).await?; - Ok(()) - } - pub(crate) async fn get_filters(&self) -> FlowyResult> { let view_editor = self.get_default_view_editor().await?; Ok(view_editor.get_filters().await) } + pub(crate) async fn update_filter(&self, insert_filter: CreateFilterParams) -> FlowyResult<()> { + let view_editor = self.get_default_view_editor().await?; + view_editor.insert_filter(insert_filter).await + } + + pub(crate) async fn delete_filter(&self, delete_filter: DeleteFilterParams) -> FlowyResult<()> { + let view_editor = self.get_default_view_editor().await?; + view_editor.delete_filter(delete_filter).await + } + pub(crate) async fn load_groups(&self) -> FlowyResult { let view_editor = self.get_default_view_editor().await?; let groups = view_editor.load_groups().await?; Ok(RepeatedGridGroupPB { items: groups }) } + pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { + let view_editor = self.get_default_view_editor().await?; + let _s = view_editor.move_group(params).await?; + Ok(()) + } + /// It may generate a RowChangeset when the Row was moved from one group to another. /// The return value, [RowChangeset], contains the changes made by the groups. /// @@ -131,9 +142,6 @@ impl GridViewManager { } } - #[allow(dead_code)] - pub(crate) async fn move_group(&self) {} - pub(crate) async fn get_view_editor(&self, view_id: &str) -> FlowyResult> { debug_assert!(!view_id.is_empty()); match self.view_editors.get(view_id) { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 15cbe6c61f..9c1562769c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -4,6 +4,7 @@ use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, GroupConfigurationContent, GroupConfigurationRevision, GroupRecordRevision, }; +use indexmap::IndexMap; use lib_infra::future::AFFuture; use std::sync::Arc; @@ -23,10 +24,9 @@ pub trait GroupConfigurationWriter: Send + Sync + 'static { pub struct GenericGroupConfiguration { pub configuration: C, - // pub groups_map: IndexMap, configuration_id: String, field_rev: Arc, - reader: Arc, + groups_map: IndexMap, writer: Arc, } @@ -45,30 +45,33 @@ where Ok(Self { configuration_id, field_rev, - reader, + groups_map: IndexMap::new(), writer, configuration, }) } - #[allow(dead_code)] - fn group_records(&self) -> &[GroupRecordRevision] { - todo!() + pub(crate) fn groups(&self) -> Vec<&Group> { + self.groups_map.values().collect() } - pub(crate) async fn merge_groups(&mut self, groups: &[Group]) -> FlowyResult<()> { - match merge_groups(self.configuration.get_groups(), groups) { - None => Ok(()), - Some(new_groups) => { - self.configuration.set_groups(new_groups); - let _ = self.save_configuration().await?; - Ok(()) - } - } + + pub(crate) fn clone_groups(&self) -> Vec { + self.groups_map.values().cloned().collect() + } + + pub(crate) async fn merge_groups(&mut self, groups: Vec) -> FlowyResult<()> { + let (group_revs, groups) = merge_groups(self.configuration.get_groups(), groups); + self.configuration.set_groups(group_revs); + let _ = self.save_configuration().await?; + groups.into_iter().for_each(|group| { + self.groups_map.insert(group.id.clone(), group); + }); + Ok(()) } #[allow(dead_code)] pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> { - self.configuration.mut_group(group_id, |group_rev| { + self.configuration.with_mut_group(group_id, |group_rev| { group_rev.visible = false; }); let _ = self.save_configuration().await?; @@ -77,13 +80,27 @@ where #[allow(dead_code)] pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> { - self.configuration.mut_group(group_id, |group_rev| { + self.configuration.with_mut_group(group_id, |group_rev| { group_rev.visible = true; }); let _ = self.save_configuration().await?; Ok(()) } + pub(crate) fn with_mut_groups(&mut self, mut mut_groups_fn: impl FnMut(&mut Group)) { + self.groups_map.iter_mut().for_each(|(_, group)| { + mut_groups_fn(group); + }) + } + + pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut Group> { + self.groups_map.get_mut(group_id) + } + + pub(crate) fn get_group(&mut self, group_id: &str) -> Option<&Group> { + self.groups_map.get(group_id) + } + pub async fn save_configuration(&self) -> FlowyResult<()> { let content = self.configuration.to_configuration_content()?; let _ = self @@ -103,29 +120,32 @@ where } } -fn merge_groups(old_group: &[GroupRecordRevision], groups: &[Group]) -> Option> { +fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> (Vec, Vec) { // tracing::trace!("Merge group: old: {}, new: {}", old_group.len(), groups.len()); - if old_group.is_empty() { + if old_group_revs.is_empty() { let new_groups = groups .iter() .map(|group| GroupRecordRevision::new(group.id.clone())) .collect(); - return Some(new_groups); + return (new_groups, groups); } - let new_groups = groups - .iter() - .filter(|group| !old_group.iter().any(|group_rev| group_rev.group_id == group.id)) - .collect::>(); + let mut group_map: IndexMap = IndexMap::new(); + groups.into_iter().for_each(|group| { + group_map.insert(group.id.clone(), group); + }); - if new_groups.is_empty() { - return None; + let mut sorted_groups: Vec = vec![]; + for group_rev in old_group_revs { + if let Some(group) = group_map.remove(&group_rev.group_id) { + sorted_groups.push(group); + } } - - let mut old_group = old_group.to_vec(); - let new_groups = new_groups + sorted_groups.extend(group_map.into_values().collect::>()); + let new_group_revs = sorted_groups .iter() - .map(|group| GroupRecordRevision::new(group.id.clone())); - old_group.extend(new_groups); - Some(old_group) + .map(|group| GroupRecordRevision::new(group.id.clone())) + .collect::>(); + + (new_group_revs, sorted_groups) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index 44344fa0a1..1cba496b51 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -7,7 +7,6 @@ use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ FieldRevision, GroupConfigurationContent, RowChangeset, RowRevision, TypeOptionDataDeserializer, }; -use indexmap::IndexMap; use std::marker::PhantomData; use std::sync::Arc; @@ -36,7 +35,7 @@ pub trait GroupGenerator { pub trait GroupControllerSharedOperation: Send + Sync { // The field that is used for grouping the rows fn field_id(&self) -> &str; - fn groups(&self) -> &[Group]; + fn groups(&self) -> Vec; fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult>; fn did_update_row( &mut self, @@ -65,7 +64,6 @@ pub trait GroupControllerSharedOperation: Send + Sync { /// P: the parser that impl [CellBytesParser] for the CellBytes pub struct GenericGroupController { pub field_id: String, - pub groups_map: IndexMap, pub type_option: Option, pub configuration: GenericGroupConfiguration, /// default_group is used to store the rows that don't belong to any groups. @@ -87,7 +85,7 @@ where let field_type_rev = field_rev.ty; let type_option = field_rev.get_type_option_entry::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); - let _ = configuration.merge_groups(&groups).await?; + let _ = configuration.merge_groups(groups).await?; let default_group = Group::new( DEFAULT_GROUP_ID.to_owned(), field_rev.id.clone(), @@ -97,7 +95,6 @@ where Ok(Self { field_id: field_rev.id.clone(), - groups_map: groups.into_iter().map(|group| (group.id.clone(), group)).collect(), default_group, type_option, configuration, @@ -117,8 +114,8 @@ where &self.field_id } - fn groups(&self) -> &[Group] { - todo!() + fn groups(&self) -> Vec { + self.configuration.clone_groups() } fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult> { @@ -127,7 +124,7 @@ where let mut group_rows: Vec = vec![]; let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_data = cell_bytes.parser::

()?; - for group in self.groups_map.values() { + for group in self.configuration.groups() { if self.can_group(&group.content, &cell_data) { group_rows.push(GroupRow { row: row_rev.into(), @@ -140,7 +137,7 @@ where self.default_group.add_row(row_rev.into()); } else { for group_row in group_rows { - if let Some(group) = self.groups_map.get_mut(&group_row.group_id) { + if let Some(group) = self.configuration.get_mut_group(&group_row.group_id) { group.add_row(group_row.row); } } @@ -151,7 +148,7 @@ where } let default_group = self.default_group.clone(); - let mut groups: Vec = self.groups_map.values().cloned().collect(); + let mut groups: Vec = self.configuration.clone_groups(); if !default_group.number_of_row() == 0 { groups.push(default_group); } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index e2e7f13ef9..47e7dfbce9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -27,7 +27,7 @@ impl GroupAction for MultiSelectGroupController { fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + self.configuration.with_mut_groups(|group| { add_row(group, &mut changesets, cell_data, row_rev); }); changesets @@ -39,7 +39,7 @@ impl GroupAction for MultiSelectGroupController { cell_data: &Self::CellDataType, ) -> Vec { let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + self.configuration.with_mut_groups(|group| { remove_row(group, &mut changesets, cell_data, row_rev); }); changesets @@ -54,7 +54,7 @@ impl GroupAction for MultiSelectGroupController { to_row_id: &str, ) -> Vec { let mut group_changeset = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + self.configuration.with_mut_groups(|group| { move_row( group, &mut group_changeset, @@ -71,7 +71,7 @@ impl GroupAction for MultiSelectGroupController { impl GroupController for MultiSelectGroupController { fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { - let group: Option<&Group> = self.groups_map.get(group_id); + let group: Option<&Group> = self.configuration.get_group(group_id); match group { None => tracing::warn!("Can not find the group: {}", group_id), Some(group) => { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index 44920a0f1f..2eb1e4a60f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -27,7 +27,7 @@ impl GroupAction for SingleSelectGroupController { fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + self.configuration.with_mut_groups(|group| { add_row(group, &mut changesets, cell_data, row_rev); }); changesets @@ -39,7 +39,7 @@ impl GroupAction for SingleSelectGroupController { cell_data: &Self::CellDataType, ) -> Vec { let mut changesets = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + self.configuration.with_mut_groups(|group| { remove_row(group, &mut changesets, cell_data, row_rev); }); changesets @@ -54,7 +54,7 @@ impl GroupAction for SingleSelectGroupController { to_row_id: &str, ) -> Vec { let mut group_changeset = vec![]; - self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| { + self.configuration.with_mut_groups(|group| { move_row( group, &mut group_changeset, @@ -71,7 +71,7 @@ impl GroupAction for SingleSelectGroupController { impl GroupController for SingleSelectGroupController { fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { - let group: Option<&mut Group> = self.groups_map.get_mut(group_id); + let group: Option<&mut Group> = self.configuration.get_mut_group(group_id); match group { None => {} Some(group) => { 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 7cd4e387b9..a1cdd597af 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 @@ -36,12 +36,11 @@ impl GroupService { } pub(crate) async fn groups(&self) -> Vec { - // if let Some(group_controller) = self.group_controller.as_ref() { - // group_controller.read().await.groups() - // } else { - // vec![] - // } - todo!() + if let Some(group_controller) = self.group_controller.as_ref() { + group_controller.read().await.groups() + } else { + vec![] + } } pub(crate) async fn load_groups( diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index 948528589f..a1f0b8a0c6 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -9,10 +9,6 @@ use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision}; use crate::grid::grid_editor::GridEditorTest; pub enum FilterScript { - #[allow(dead_code)] - UpdateGridSetting { - params: GridSettingChangesetParams, - }, InsertGridTableFilter { payload: CreateGridFilterPayloadPB, }, @@ -49,27 +45,18 @@ impl GridFilterTest { pub async fn run_script(&mut self, script: FilterScript) { match script { - FilterScript::UpdateGridSetting { params } => { - let _ = self.editor.update_grid_setting(params).await.unwrap(); - } + FilterScript::InsertGridTableFilter { payload } => { let params: CreateFilterParams = payload.try_into().unwrap(); - let layout_type = GridLayout::Table; - let params = GridSettingChangesetBuilder::new(&self.grid_id, &layout_type) - .insert_filter(params) - .build(); - let _ = self.editor.update_grid_setting(params).await.unwrap(); + let _ = self.editor.update_filter(params).await.unwrap(); } FilterScript::AssertTableFilterCount { count } => { let filters = self.editor.get_grid_filter().await.unwrap(); assert_eq!(count as usize, filters.len()); } FilterScript::DeleteGridTableFilter { filter_id, field_rev} => { - let layout_type = GridLayout::Table; - let params = GridSettingChangesetBuilder::new(&self.grid_id, &layout_type) - .delete_filter(DeleteFilterParams { field_id: field_rev.id, filter_id, field_type_rev: field_rev.ty }) - .build(); - let _ = self.editor.update_grid_setting(params).await.unwrap(); + let params = DeleteFilterParams { field_id: field_rev.id, filter_id, field_type_rev: field_rev.ty }; + let _ = self.editor.delete_filter(params).await.unwrap(); } FilterScript::AssertGridSetting { expected_setting } => { let setting = self.editor.get_grid_setting().await.unwrap(); 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 1900e89bff..118d417c31 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 @@ -1,5 +1,5 @@ use crate::grid::grid_editor::GridEditorTest; -use flowy_grid::entities::{CreateRowParams, FieldType, GridLayout, GroupPB, MoveRowParams, RowPB}; +use flowy_grid::entities::{CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveRowParams, RowPB}; use flowy_grid::services::cell::insert_select_option_cell; use flowy_grid_data_model::revision::RowChangeset; @@ -32,6 +32,10 @@ pub enum GroupScript { row_index: usize, to_group_index: usize, }, + MoveGroup { + from_group_index: usize, + to_group_index: usize, + }, } pub struct GridGroupTest { @@ -84,7 +88,6 @@ impl GridGroupTest { // let group = self.group_at_index(group_index).await; let compare_row = group.rows.get(row_index).unwrap().clone(); - assert_eq!(row.id, compare_row.id); } GroupScript::CreateRow { group_index } => { @@ -125,6 +128,20 @@ impl GridGroupTest { row_changeset.cell_by_field_id.insert(field_id, cell_rev); self.editor.update_row(row_changeset).await.unwrap(); } + GroupScript::MoveGroup { + from_group_index, + to_group_index, + } => { + let from_group = self.group_at_index(from_group_index).await; + let to_group = self.group_at_index(to_group_index).await; + let params = MoveGroupParams { + view_id: self.editor.grid_id.clone(), + from_group_id: from_group.group_id, + to_group_id: to_group.group_id, + }; + self.editor.move_group(params).await.unwrap(); + // + } } } diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index 9d7da79e5a..b8c9567cb4 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -6,19 +6,19 @@ use serde_repr::*; pub trait GroupConfigurationContent: Sized { fn from_configuration_content(s: &str) -> Result; + fn to_configuration_content(&self) -> Result; + fn get_groups(&self) -> &[GroupRecordRevision] { &[] } - fn mut_group(&mut self, _group_id: &str, _f: F) + fn set_groups(&mut self, _new_groups: Vec) {} + + fn with_mut_group(&mut self, _group_id: &str, _f: F) where F: FnOnce(&mut GroupRecordRevision), { } - - fn set_groups(&mut self, _new_groups: Vec) {} - - fn to_configuration_content(&self) -> Result; } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] @@ -112,11 +112,19 @@ impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision { serde_json::from_str(s) } + fn to_configuration_content(&self) -> Result { + serde_json::to_string(self) + } + fn get_groups(&self) -> &[GroupRecordRevision] { &self.groups } - fn mut_group(&mut self, group_id: &str, f: F) + fn set_groups(&mut self, new_groups: Vec) { + self.groups = new_groups; + } + + fn with_mut_group(&mut self, group_id: &str, f: F) where F: FnOnce(&mut GroupRecordRevision), { @@ -125,14 +133,6 @@ impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision { Some(group) => f(group), } } - - fn set_groups(&mut self, new_groups: Vec) { - self.groups = new_groups; - } - - fn to_configuration_content(&self) -> Result { - serde_json::to_string(self) - } } #[derive(Clone, Default, Serialize, Deserialize)] @@ -142,6 +142,7 @@ pub struct GroupRecordRevision { #[serde(default = "DEFAULT_GROUP_RECORD_VISIBILITY")] pub visible: bool, } + const DEFAULT_GROUP_RECORD_VISIBILITY: fn() -> bool = || true; impl GroupRecordRevision { diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index fc5fa4bf67..e63c5d2088 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -52,20 +52,6 @@ impl GridViewRevisionPad { self.groups.get_all_objects(field_revs) } - pub fn insert_group_configuration( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - group_rev: GroupConfigurationRevision, - ) -> CollaborateResult> { - self.modify(|view| { - // only one group can be set - view.groups.remove_all(); - view.groups.insert_object(field_id, field_type, group_rev); - Ok(Some(())) - }) - } - pub fn get_mut_group( &mut self, field_id: &str, From 93f5b5d754b4c621ce4236ab83323c9dde18ac4c Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 21 Aug 2022 22:47:24 +0800 Subject: [PATCH 08/10] fix: save group rev without apply change --- frontend/rust-lib/flowy-error/src/errors.rs | 1 + .../group_entities/group_changeset.rs | 11 +- .../src/services/grid_view_editor.rs | 106 +++++++++++++----- .../src/services/grid_view_manager.rs | 10 +- .../src/services/group/configuration.rs | 67 ++++++++--- .../src/services/group/controller.rs | 11 ++ .../multi_select_controller.rs | 5 +- .../src/services/group/group_service.rs | 21 +++- .../tests/grid/group_test/script.rs | 15 ++- .../flowy-grid/tests/grid/group_test/test.rs | 50 ++++++--- frontend/rust-lib/flowy-sdk/src/lib.rs | 2 +- shared-lib/flowy-error-code/src/code.rs | 3 + .../src/revision/grid_setting_rev.rs | 2 +- .../src/revision/grid_view.rs | 105 +++++------------ .../src/revision/group_rev.rs | 19 ++++ .../src/client_grid/view_revision_pad.rs | 23 +++- 16 files changed, 302 insertions(+), 149 deletions(-) diff --git a/frontend/rust-lib/flowy-error/src/errors.rs b/frontend/rust-lib/flowy-error/src/errors.rs index e19ebb15b2..bc453054aa 100644 --- a/frontend/rust-lib/flowy-error/src/errors.rs +++ b/frontend/rust-lib/flowy-error/src/errors.rs @@ -66,6 +66,7 @@ impl FlowyError { static_flowy_error!(user_not_exist, ErrorCode::UserNotExist); static_flowy_error!(text_too_long, ErrorCode::TextTooLong); static_flowy_error!(invalid_data, ErrorCode::InvalidData); + static_flowy_error!(out_of_bounds, ErrorCode::OutOfBounds); } impl std::convert::From for FlowyError { diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs index dbee60dca9..a3ebee9cb7 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs @@ -109,10 +109,19 @@ pub struct GroupViewChangesetPB { pub view_id: String, #[pb(index = 2)] - pub inserted_groups: Vec, + pub inserted_groups: Vec, #[pb(index = 3)] pub deleted_groups: Vec, } impl GroupViewChangesetPB {} + +#[derive(Debug, Default, ProtoBuf)] +pub struct InsertedGroupPB { + #[pb(index = 1)] + pub group: GroupPB, + + #[pb(index = 2)] + pub index: i32, +} diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index ff58585584..617c9a30d5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -1,14 +1,12 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::entities::{ CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridLayout, GridLayoutPB, - GridSettingChangesetParams, GridSettingPB, GroupPB, GroupRowsChangesetPB, GroupViewChangesetPB, InsertedRowPB, + GridSettingPB, GroupPB, GroupRowsChangesetPB, GroupViewChangesetPB, InsertedGroupPB, InsertedRowPB, MoveGroupParams, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RowPB, }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; -use crate::services::group::{ - default_group_configuration, GroupConfigurationReader, GroupConfigurationWriter, GroupService, -}; +use crate::services::group::{GroupConfigurationReader, GroupConfigurationWriter, GroupService}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision, @@ -19,6 +17,7 @@ use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad}; use flowy_sync::entities::revision::Revision; use lib_infra::future::{wrap_future, AFFuture, FutureResult}; use std::collections::HashMap; + use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; @@ -37,6 +36,7 @@ pub struct GridViewRevisionEditor { } impl GridViewRevisionEditor { + #[tracing::instrument(level = "trace", skip_all, err)] pub(crate) async fn new( user_id: &str, token: &str, @@ -109,7 +109,7 @@ impl GridViewRevisionEditor { // Send the group notification if the current view has groups; if let Some(changesets) = self .group_service - .write() + .read() .await .did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) .await @@ -123,7 +123,7 @@ impl GridViewRevisionEditor { pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) { if let Some(changesets) = self .group_service - .write() + .read() .await .did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) .await @@ -142,7 +142,7 @@ impl GridViewRevisionEditor { ) { if let Some(changesets) = self .group_service - .write() + .read() .await .did_move_row(row_rev, row_changeset, upper_row_id, |field_id| { self.field_delegate.get_field_rev(&field_id) @@ -156,11 +156,13 @@ impl GridViewRevisionEditor { } } + #[tracing::instrument(level = "trace", skip(self))] pub(crate) async fn load_groups(&self) -> FlowyResult> { let groups = if !self.did_load_group.load(Ordering::SeqCst) { self.did_load_group.store(true, Ordering::SeqCst); let field_revs = self.field_delegate.get_field_revs().await; let row_revs = self.row_delegate.gv_row_revs().await; + match self .group_service .write() @@ -174,11 +176,37 @@ impl GridViewRevisionEditor { } else { self.group_service.read().await.groups().await }; + + tracing::trace!("Number of groups: {}", groups.len()); Ok(groups.into_iter().map(GroupPB::from).collect()) } pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { - todo!() + let _ = self + .group_service + .read() + .await + .move_group(¶ms.from_group_id, ¶ms.to_group_id) + .await?; + + match self.group_service.read().await.get_group(¶ms.from_group_id).await { + None => {} + Some((index, group)) => { + let inserted_group = InsertedGroupPB { + group: GroupPB::from(group), + index: index as i32, + }; + + let changeset = GroupViewChangesetPB { + view_id: "".to_string(), + inserted_groups: vec![inserted_group], + deleted_groups: vec![params.from_group_id.clone()], + }; + + self.notify_did_update_view(changeset).await; + } + } + Ok(()) } pub(crate) async fn get_setting(&self) -> GridSettingPB { @@ -291,17 +319,19 @@ impl RevisionObjectBuilder for GridViewRevisionPadBuilder { struct GroupConfigurationReaderImpl(Arc>); impl GroupConfigurationReader for GroupConfigurationReaderImpl { - fn get_group_configuration(&self, field_rev: Arc) -> AFFuture> { + fn get_group_configuration( + &self, + field_rev: Arc, + ) -> AFFuture>> { let view_pad = self.0.clone(); wrap_future(async move { - let view_pad = view_pad.read().await; - let configurations = view_pad.get_groups(&field_rev.id, &field_rev.ty); - match configurations { - None => { - let default_configuration = default_group_configuration(&field_rev); - Arc::new(default_configuration) - } - Some(configuration) => configuration, + let mut groups = view_pad.read().await.groups.get_objects(&field_rev.id, &field_rev.ty)?; + + if groups.is_empty() { + None + } else { + debug_assert_eq!(groups.len(), 1); + Some(groups.pop().unwrap()) } }) } @@ -328,17 +358,25 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { let field_id = field_id.to_owned(); wrap_future(async move { - match view_pad.write().await.get_mut_group( - &field_id, - &field_type, - &configuration_id, - |group_configuration| { - group_configuration.content = content; - }, - )? { - None => Ok(()), - Some(changeset) => apply_change(&user_id, rev_manager, changeset).await, + let is_contained = view_pad.read().await.contains_group(&field_id, &field_type); + let changeset = if is_contained { + view_pad.write().await.with_mut_group( + &field_id, + &field_type, + &configuration_id, + |group_configuration| { + group_configuration.content = content; + }, + )? + } else { + let group_rev = GroupConfigurationRevision::new(field_id.clone(), field_type, content)?; + view_pad.write().await.insert_group(&field_id, &field_type, group_rev)? + }; + + if let Some(changeset) = changeset { + let _ = apply_change(&user_id, rev_manager, changeset).await?; } + Ok(()) }) } } @@ -371,3 +409,17 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc FlowyResult<()> { let view_editor = self.get_default_view_editor().await?; - let _s = view_editor.move_group(params).await?; + let _ = view_editor.move_group(params).await?; Ok(()) } @@ -175,12 +175,11 @@ async fn make_view_editor( row_delegate: Arc, scheduler: Arc, ) -> FlowyResult { - tracing::trace!("Open view:{} editor", view_id); - let rev_manager = make_grid_view_rev_manager(user, view_id).await?; let user_id = user.user_id()?; let token = user.token()?; let view_id = view_id.to_owned(); + GridViewRevisionEditor::new( &user_id, &token, @@ -194,7 +193,6 @@ async fn make_view_editor( } pub async fn make_grid_view_rev_manager(user: &Arc, view_id: &str) -> FlowyResult { - tracing::trace!("Open view:{} editor", view_id); let user_id = user.user_id()?; let pool = user.db_pool()?; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 9c1562769c..f4a25d7304 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,5 +1,5 @@ -use crate::services::group::Group; -use flowy_error::FlowyResult; +use crate::services::group::{default_group_configuration, Group}; +use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, GroupConfigurationContent, GroupConfigurationRevision, GroupRecordRevision, }; @@ -9,7 +9,10 @@ use lib_infra::future::AFFuture; use std::sync::Arc; pub trait GroupConfigurationReader: Send + Sync + 'static { - fn get_group_configuration(&self, field_rev: Arc) -> AFFuture>; + fn get_group_configuration( + &self, + field_rev: Arc, + ) -> AFFuture>>; } pub trait GroupConfigurationWriter: Send + Sync + 'static { @@ -39,7 +42,22 @@ where reader: Arc, writer: Arc, ) -> FlowyResult { - let configuration_rev = reader.get_group_configuration(field_rev.clone()).await; + let configuration_rev = match reader.get_group_configuration(field_rev.clone()).await { + None => { + let default_group_configuration = default_group_configuration(&field_rev); + writer + .save_group_configuration( + &field_rev.id, + field_rev.ty, + &default_group_configuration.id, + default_group_configuration.content.clone(), + ) + .await?; + Arc::new(default_group_configuration) + } + Some(configuration) => configuration, + }; + let configuration_id = configuration_rev.id.clone(); let configuration = C::from_configuration_content(&configuration_rev.content)?; Ok(Self { @@ -63,6 +81,8 @@ where let (group_revs, groups) = merge_groups(self.configuration.get_groups(), groups); self.configuration.set_groups(group_revs); let _ = self.save_configuration().await?; + + tracing::trace!("merge new groups: {}", groups.len()); groups.into_iter().for_each(|group| { self.groups_map.insert(group.id.clone(), group); }); @@ -97,8 +117,25 @@ where self.groups_map.get_mut(group_id) } - pub(crate) fn get_group(&mut self, group_id: &str) -> Option<&Group> { - self.groups_map.get(group_id) + pub(crate) fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { + let from_group_index = self.groups_map.get_index_of(from_group_id); + let to_group_index = self.groups_map.get_index_of(to_group_id); + match (from_group_index, to_group_index) { + (Some(from_index), Some(to_index)) => { + self.groups_map.swap_indices(from_index, to_index); + self.configuration.swap_group(from_group_id, to_group_id); + Ok(()) + } + _ => Err(FlowyError::out_of_bounds()), + } + } + + // Returns the index and group specified by the group_id + pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &Group)> { + match (self.groups_map.get_index_of(group_id), self.groups_map.get(group_id)) { + (Some(index), Some(group)) => Some((index, group)), + _ => None, + } } pub async fn save_configuration(&self) -> FlowyResult<()> { @@ -111,17 +148,17 @@ where } } -impl GroupConfigurationReader for Arc -where - T: GroupConfigurationReader, -{ - fn get_group_configuration(&self, field_rev: Arc) -> AFFuture> { - (**self).get_group_configuration(field_rev) - } -} +// impl GroupConfigurationReader for Arc +// where +// T: GroupConfigurationReader, +// { +// fn get_group_configuration(&self, field_rev: Arc) -> AFFuture> { +// (**self).get_group_configuration(field_rev) +// } +// } fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> (Vec, Vec) { - // tracing::trace!("Merge group: old: {}, new: {}", old_group.len(), groups.len()); + tracing::trace!("Merge group: old: {}, new: {}", old_group_revs.len(), groups.len()); if old_group_revs.is_empty() { let new_groups = groups .iter() diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index 1cba496b51..af4d676b02 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -36,7 +36,9 @@ pub trait GroupControllerSharedOperation: Send + Sync { // The field that is used for grouping the rows fn field_id(&self) -> &str; fn groups(&self) -> Vec; + fn get_group(&self, group_id: &str) -> Option<(usize, Group)>; fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult>; + fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()>; fn did_update_row( &mut self, row_rev: &RowRevision, @@ -118,6 +120,11 @@ where self.configuration.clone_groups() } + fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { + let group = self.configuration.get_group(group_id)?; + Some((group.0, group.1.clone())) + } + fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult> { for row_rev in row_revs { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { @@ -156,6 +163,10 @@ where Ok(groups) } + fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { + self.configuration.move_group(from_group_id, to_group_id) + } + fn did_update_row( &mut self, row_rev: &RowRevision, diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index 47e7dfbce9..7a208a884f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -71,10 +71,9 @@ impl GroupAction for MultiSelectGroupController { impl GroupController for MultiSelectGroupController { fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { - let group: Option<&Group> = self.configuration.get_group(group_id); - match group { + match self.configuration.get_group(group_id) { None => tracing::warn!("Can not find the group: {}", group_id), - Some(group) => { + Some((_, group)) => { let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); row_rev.cells.insert(field_rev.id.clone(), cell_rev); } 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 a1cdd597af..7050c2c087 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 @@ -43,6 +43,14 @@ impl GroupService { } } + pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { + if let Some(group_controller) = self.group_controller.as_ref() { + group_controller.read().await.get_group(group_id) + } else { + None + } + } + pub(crate) async fn load_groups( &mut self, field_revs: &[Arc], @@ -164,9 +172,20 @@ impl GroupService { } } + #[tracing::instrument(level = "trace", skip_all)] + pub(crate) async fn move_group(&self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { + match self.group_controller.as_ref() { + None => Ok(()), + Some(group_controller) => { + let _ = group_controller.write().await.move_group(from_group_id, to_group_id)?; + Ok(()) + } + } + } + #[tracing::instrument(level = "trace", skip_all)] async fn make_group_controller( - &mut self, + &self, field_type: &FieldType, field_rev: &Arc, ) -> FlowyResult>>> { 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 118d417c31..d284e69c76 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,11 +4,15 @@ use flowy_grid::services::cell::insert_select_option_cell; use flowy_grid_data_model::revision::RowChangeset; pub enum GroupScript { - AssertGroup { + AssertGroupRowCount { group_index: usize, row_count: usize, }, AssertGroupCount(usize), + AssertGroup { + group_index: usize, + expected_group: GroupPB, + }, AssertRow { group_index: usize, row_index: usize, @@ -56,7 +60,7 @@ impl GridGroupTest { pub async fn run_script(&mut self, script: GroupScript) { match script { - GroupScript::AssertGroup { group_index, row_count } => { + GroupScript::AssertGroupRowCount { group_index, row_count } => { assert_eq!(row_count, self.group_at_index(group_index).await.rows.len()); } GroupScript::AssertGroupCount(count) => { @@ -142,6 +146,13 @@ impl GridGroupTest { self.editor.move_group(params).await.unwrap(); // } + GroupScript::AssertGroup { + group_index, + expected_group: group_pb, + } => { + let group = self.group_at_index(group_index).await; + assert_eq!(group.group_id, group_pb.group_id); + } } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs index 798f478439..6092e97a5e 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs @@ -6,15 +6,15 @@ async fn board_init_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ AssertGroupCount(3), - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 2, }, - AssertGroup { + AssertGroupRowCount { group_index: 1, row_count: 2, }, - AssertGroup { + AssertGroupRowCount { group_index: 2, row_count: 1, }, @@ -34,7 +34,7 @@ async fn board_move_row_test() { to_group_index: 0, to_row_index: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 2, }, @@ -58,11 +58,11 @@ async fn board_move_row_to_other_group_test() { to_group_index: 1, to_row_index: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 1, row_count: 3, }, @@ -106,13 +106,13 @@ async fn board_create_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ CreateRow { group_index: 0 }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 3, }, CreateRow { group_index: 1 }, CreateRow { group_index: 1 }, - AssertGroup { + AssertGroupRowCount { group_index: 1, row_count: 4, }, @@ -128,7 +128,7 @@ async fn board_delete_row_test() { group_index: 0, row_index: 0, }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 1, }, @@ -148,7 +148,7 @@ async fn board_delete_all_row_test() { group_index: 0, row_index: 0, }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 0, }, @@ -166,11 +166,11 @@ async fn board_update_row_test() { row_index: 0, to_group_index: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 1, row_count: 3, }, @@ -188,14 +188,36 @@ async fn board_reorder_group_test() { row_index: 0, to_group_index: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 0, row_count: 1, }, - AssertGroup { + AssertGroupRowCount { group_index: 1, row_count: 3, }, ]; test.run_scripts(scripts).await; } + +#[tokio::test] +async fn board_move_group_test() { + let mut test = GridGroupTest::new().await; + let group_0 = test.group_at_index(0).await; + let group_1 = test.group_at_index(1).await; + let scripts = vec![ + MoveGroup { + from_group_index: 0, + to_group_index: 1, + }, + AssertGroup { + group_index: 0, + expected_group: group_1, + }, + AssertGroup { + group_index: 1, + expected_group: group_0, + }, + ]; + test.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index ce5920e532..e0bd601987 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -74,7 +74,7 @@ fn crate_log_filter(level: String) -> String { filters.push(format!("lib_ot={}", level)); filters.push(format!("lib_ws={}", level)); filters.push(format!("lib_infra={}", level)); - // filters.push(format!("flowy_sync={}", level)); + filters.push(format!("flowy_sync={}", level)); // filters.push(format!("flowy_revision={}", level)); // filters.push(format!("lib_dispatch={}", level)); diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index 63f7ac7749..c5e89a99f3 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -125,6 +125,9 @@ pub enum ErrorCode { #[display(fmt = "Invalid data")] InvalidData = 1000, + + #[display(fmt = "Out of bounds")] + OutOfBounds = 10001, } impl ErrorCode { 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 01ca80a380..829ebe4c07 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 @@ -49,7 +49,7 @@ where .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::()); + tracing::warn!("[Configuration] Can't find the {:?} with", std::any::type_name::()); } value } diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs index 9d4df3067e..74c3c72511 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_view.rs @@ -1,11 +1,7 @@ -use crate::revision::{ - FieldRevision, FieldTypeRevision, FilterConfiguration, FilterConfigurationRevision, FilterConfigurationsByFieldId, - GroupConfiguration, GroupConfigurationRevision, GroupConfigurationsByFieldId, -}; +use crate::revision::{FilterConfiguration, GroupConfiguration}; use nanoid::nanoid; use serde::{Deserialize, Serialize}; use serde_repr::*; -use std::sync::Arc; #[allow(dead_code)] pub fn gen_grid_view_id() -> String { @@ -40,15 +36,15 @@ pub struct GridViewRevision { pub layout: LayoutRevision, + #[serde(default)] pub filters: FilterConfiguration, #[serde(default)] pub groups: GroupConfiguration, - - // For the moment, we just use the order returned from the GridRevision - #[allow(dead_code)] - #[serde(skip, rename = "row")] - pub row_orders: Vec, + // // For the moment, we just use the order returned from the GridRevision + // #[allow(dead_code)] + // #[serde(skip, rename = "rows")] + // pub row_orders: Vec, } impl GridViewRevision { @@ -59,78 +55,33 @@ impl GridViewRevision { layout: Default::default(), filters: Default::default(), groups: Default::default(), - row_orders: vec![], + // row_orders: vec![], } } - - pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { - self.groups.get_all_objects(field_revs) - } - - pub fn get_groups( - &self, - field_id: &str, - field_type_rev: &FieldTypeRevision, - ) -> Option> { - let mut groups = self.groups.get_objects(field_id, field_type_rev)?; - if groups.is_empty() { - debug_assert_eq!(groups.len(), 1); - Some(groups.pop().unwrap()) - } else { - None - } - } - - pub fn get_mut_groups( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - ) -> Option<&mut Vec>> { - self.groups.get_mut_objects(field_id, field_type) - } - - pub fn insert_group( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - group_rev: GroupConfigurationRevision, - ) { - // only one group can be set - self.groups.remove_all(); - self.groups.insert_object(field_id, field_type, group_rev); - } - - pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { - self.filters.get_all_objects(field_revs) - } - - pub fn get_filters( - &self, - field_id: &str, - field_type_rev: &FieldTypeRevision, - ) -> Option>> { - self.filters.get_objects(field_id, field_type_rev) - } - - pub fn get_mut_filters( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - ) -> Option<&mut Vec>> { - self.filters.get_mut_objects(field_id, field_type) - } - - pub fn insert_filter( - &mut self, - field_id: &str, - field_type: &FieldTypeRevision, - filter_rev: FilterConfigurationRevision, - ) { - self.filters.insert_object(field_id, field_type, filter_rev); - } } #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct RowOrderRevision { pub row_id: String, } + +#[cfg(test)] +mod tests { + use crate::revision::GridViewRevision; + + #[test] + fn grid_view_revision_serde_test() { + let grid_view_revision = GridViewRevision { + view_id: "1".to_string(), + grid_id: "1".to_string(), + layout: Default::default(), + filters: Default::default(), + groups: Default::default(), + }; + let s = serde_json::to_string(&grid_view_revision).unwrap(); + assert_eq!( + s, + r#"{"view_id":"1","grid_id":"1","layout":0,"filters":[],"groups":[]}"# + ); + } +} diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index b8c9567cb4..caaa1b43a9 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -12,8 +12,23 @@ pub trait GroupConfigurationContent: Sized { &[] } + fn mut_groups(&mut self) -> &mut Vec { + todo!() + } + fn set_groups(&mut self, _new_groups: Vec) {} + fn swap_group(&mut self, from_group_id: &str, to_group_id: &str) { + let from_index = self + .get_groups() + .iter() + .position(|group| group.group_id == from_group_id); + let to_index = self.get_groups().iter().position(|group| group.group_id == to_group_id); + if let (Some(from), Some(to)) = (from_index, to_index) { + self.mut_groups().swap(from, to); + } + } + fn with_mut_group(&mut self, _group_id: &str, _f: F) where F: FnOnce(&mut GroupRecordRevision), @@ -120,6 +135,10 @@ impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision { &self.groups } + fn mut_groups(&mut self) -> &mut Vec { + &mut self.groups + } + fn set_groups(&mut self, new_groups: Vec) { self.groups = new_groups; } diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index e63c5d2088..57bd783d75 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -52,7 +52,26 @@ impl GridViewRevisionPad { self.groups.get_all_objects(field_revs) } - pub fn get_mut_group( + #[tracing::instrument(level = "trace", skip_all, err)] + pub fn insert_group( + &mut self, + field_id: &str, + field_type: &FieldTypeRevision, + group_rev: GroupConfigurationRevision, + ) -> CollaborateResult> { + self.modify(|view| { + view.groups.insert_object(field_id, field_type, group_rev); + Ok(Some(())) + }) + } + + #[tracing::instrument(level = "trace", skip_all)] + pub fn contains_group(&self, field_id: &str, field_type: &FieldTypeRevision) -> bool { + self.view.groups.get_objects(field_id, field_type).is_some() + } + + #[tracing::instrument(level = "trace", skip_all, err)] + pub fn with_mut_group( &mut self, field_id: &str, field_type: &FieldTypeRevision, @@ -147,6 +166,8 @@ impl GridViewRevisionPad { None => Ok(None), Some(delta) => { self.delta = self.delta.compose(&delta)?; + tracing::info!("GridView: {:?}", delta); + let md5 = md5(&self.delta.json_bytes()); Ok(Some(GridViewRevisionChangeset { delta, md5 })) } From ffc6f141fad8de46630630297e7ba765a559a2e8 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 22 Aug 2022 08:53:02 +0800 Subject: [PATCH 09/10] chore: fix GroupConfigurationRevision deserialize error --- .../entities/group_entities/configuration.rs | 4 - frontend/rust-lib/flowy-grid/src/manager.rs | 1 - .../src/services/grid_view_editor.rs | 22 +--- .../src/services/group/configuration.rs | 124 ++++++++++++------ .../src/services/group/controller.rs | 6 +- .../src/services/group/group_service.rs | 8 +- .../src/revision/grid_setting_rev.rs | 16 +-- .../src/revision/group_rev.rs | 74 ++--------- 8 files changed, 116 insertions(+), 139 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs index 5797da3517..cb5503727b 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/configuration.rs @@ -17,16 +17,12 @@ pub struct TextGroupConfigurationPB { pub struct SelectOptionGroupConfigurationPB { #[pb(index = 1)] hide_empty: bool, - - #[pb(index = 2)] - groups: Vec, } impl std::convert::From for SelectOptionGroupConfigurationPB { fn from(rev: SelectOptionGroupConfigurationRevision) -> Self { Self { hide_empty: rev.hide_empty, - groups: rev.groups.into_iter().map(GroupRecordPB::from).collect(), } } } diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 9e4556b793..12b94ff8db 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -131,7 +131,6 @@ impl GridManager { async fn get_or_create_grid_editor(&self, grid_id: &str) -> FlowyResult> { match self.grid_editors.get(grid_id) { None => { - tracing::trace!("Create grid editor with id: {}", grid_id); let db_pool = self.grid_user.db_pool()?; let editor = self.make_grid_rev_editor(grid_id, db_pool).await?; diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index 617c9a30d5..fb8706b175 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -348,30 +348,18 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { &self, field_id: &str, field_type: FieldTypeRevision, - configuration_id: &str, - content: String, + group_configuration: GroupConfigurationRevision, ) -> AFFuture> { let user_id = self.user_id.clone(); - let configuration_id = configuration_id.to_owned(); let rev_manager = self.rev_manager.clone(); let view_pad = self.view_pad.clone(); let field_id = field_id.to_owned(); wrap_future(async move { - let is_contained = view_pad.read().await.contains_group(&field_id, &field_type); - let changeset = if is_contained { - view_pad.write().await.with_mut_group( - &field_id, - &field_type, - &configuration_id, - |group_configuration| { - group_configuration.content = content; - }, - )? - } else { - let group_rev = GroupConfigurationRevision::new(field_id.clone(), field_type, content)?; - view_pad.write().await.insert_group(&field_id, &field_type, group_rev)? - }; + let changeset = view_pad + .write() + .await + .insert_group(&field_id, &field_type, group_configuration)?; if let Some(changeset) = changeset { let _ = apply_change(&user_id, rev_manager, changeset).await?; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index f4a25d7304..36d49a10e1 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,8 +1,9 @@ use crate::services::group::{default_group_configuration, Group}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ - FieldRevision, FieldTypeRevision, GroupConfigurationContent, GroupConfigurationRevision, GroupRecordRevision, + FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRecordRevision, }; +use std::marker::PhantomData; use indexmap::IndexMap; use lib_infra::future::AFFuture; @@ -20,14 +21,13 @@ pub trait GroupConfigurationWriter: Send + Sync + 'static { &self, field_id: &str, field_type: FieldTypeRevision, - configuration_id: &str, - content: String, + group_configuration: GroupConfigurationRevision, ) -> AFFuture>; } pub struct GenericGroupConfiguration { - pub configuration: C, - configuration_id: String, + pub configuration: Arc, + configuration_content: PhantomData, field_rev: Arc, groups_map: IndexMap, writer: Arc, @@ -35,37 +35,32 @@ pub struct GenericGroupConfiguration { impl GenericGroupConfiguration where - C: GroupConfigurationContent, + C: GroupConfigurationContentSerde, { + #[tracing::instrument(level = "trace", skip_all, err)] pub async fn new( field_rev: Arc, reader: Arc, writer: Arc, ) -> FlowyResult { - let configuration_rev = match reader.get_group_configuration(field_rev.clone()).await { + let configuration = match reader.get_group_configuration(field_rev.clone()).await { None => { let default_group_configuration = default_group_configuration(&field_rev); writer - .save_group_configuration( - &field_rev.id, - field_rev.ty, - &default_group_configuration.id, - default_group_configuration.content.clone(), - ) + .save_group_configuration(&field_rev.id, field_rev.ty, default_group_configuration.clone()) .await?; Arc::new(default_group_configuration) } Some(configuration) => configuration, }; - let configuration_id = configuration_rev.id.clone(); - let configuration = C::from_configuration_content(&configuration_rev.content)?; + // let configuration = C::from_configuration_content(&configuration_rev.content)?; Ok(Self { - configuration_id, field_rev, groups_map: IndexMap::new(), writer, configuration, + configuration_content: PhantomData, }) } @@ -78,11 +73,12 @@ where } pub(crate) async fn merge_groups(&mut self, groups: Vec) -> FlowyResult<()> { - let (group_revs, groups) = merge_groups(self.configuration.get_groups(), groups); - self.configuration.set_groups(group_revs); - let _ = self.save_configuration().await?; + let (group_revs, groups) = merge_groups(&self.configuration.groups, groups); + self.mut_configuration(move |configuration| { + configuration.groups = group_revs; + true + })?; - tracing::trace!("merge new groups: {}", groups.len()); groups.into_iter().for_each(|group| { self.groups_map.insert(group.id.clone(), group); }); @@ -91,19 +87,17 @@ where #[allow(dead_code)] pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> { - self.configuration.with_mut_group(group_id, |group_rev| { + self.mut_configuration_group(group_id, |group_rev| { group_rev.visible = false; - }); - let _ = self.save_configuration().await?; + })?; Ok(()) } #[allow(dead_code)] pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> { - self.configuration.with_mut_group(group_id, |group_rev| { + self.mut_configuration_group(group_id, |group_rev| { group_rev.visible = true; - }); - let _ = self.save_configuration().await?; + })?; Ok(()) } @@ -123,7 +117,21 @@ where match (from_group_index, to_group_index) { (Some(from_index), Some(to_index)) => { self.groups_map.swap_indices(from_index, to_index); - self.configuration.swap_group(from_group_id, to_group_id); + + self.mut_configuration(|configuration| { + let from_index = configuration + .groups + .iter() + .position(|group| group.group_id == from_group_id); + let to_index = configuration + .groups + .iter() + .position(|group| group.group_id == to_group_id); + if let (Some(from), Some(to)) = (from_index, to_index) { + configuration.groups.swap(from, to); + } + true + })?; Ok(()) } _ => Err(FlowyError::out_of_bounds()), @@ -138,25 +146,55 @@ where } } - pub async fn save_configuration(&self) -> FlowyResult<()> { - let content = self.configuration.to_configuration_content()?; - let _ = self - .writer - .save_group_configuration(&self.field_rev.id, self.field_rev.ty, &self.configuration_id, content) - .await?; + pub fn save_configuration(&self) -> FlowyResult<()> { + let configuration = (&*self.configuration).clone(); + let writer = self.writer.clone(); + let field_id = self.field_rev.id.clone(); + let field_type = self.field_rev.ty.clone(); + tokio::spawn(async move { + match writer + .save_group_configuration(&field_id, field_type, configuration) + .await + { + Ok(_) => {} + Err(e) => { + tracing::error!("Save group configuration failed: {}", e); + } + } + }); + + Ok(()) + } + + fn mut_configuration_group( + &mut self, + group_id: &str, + mut_groups_fn: impl Fn(&mut GroupRecordRevision), + ) -> FlowyResult<()> { + self.mut_configuration(|configuration| { + match configuration.groups.iter_mut().find(|group| group.group_id == group_id) { + None => false, + Some(group_rev) => { + mut_groups_fn(group_rev); + true + } + } + }) + } + + fn mut_configuration( + &mut self, + mut_configuration_fn: impl FnOnce(&mut GroupConfigurationRevision) -> bool, + ) -> FlowyResult<()> { + let configuration = Arc::make_mut(&mut self.configuration); + let is_changed = mut_configuration_fn(configuration); + if is_changed { + let _ = self.save_configuration()?; + } Ok(()) } } -// impl GroupConfigurationReader for Arc -// where -// T: GroupConfigurationReader, -// { -// fn get_group_configuration(&self, field_rev: Arc) -> AFFuture> { -// (**self).get_group_configuration(field_rev) -// } -// } - fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> (Vec, Vec) { tracing::trace!("Merge group: old: {}, new: {}", old_group_revs.len(), groups.len()); if old_group_revs.is_empty() { @@ -172,6 +210,7 @@ fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> ( group_map.insert(group.id.clone(), group); }); + // Inert let mut sorted_groups: Vec = vec![]; for group_rev in old_group_revs { if let Some(group) = group_map.remove(&group_rev.group_id) { @@ -184,5 +223,6 @@ fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> ( .map(|group| GroupRecordRevision::new(group.id.clone())) .collect::>(); + tracing::trace!("group revs: {}, groups: {}", new_group_revs.len(), sorted_groups.len()); (new_group_revs, sorted_groups) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index af4d676b02..13b4ccce63 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -5,7 +5,7 @@ use crate::services::group::configuration::GenericGroupConfiguration; use crate::services::group::entities::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, GroupConfigurationContent, RowChangeset, RowRevision, TypeOptionDataDeserializer, + FieldRevision, GroupConfigurationContentSerde, RowChangeset, RowRevision, TypeOptionDataDeserializer, }; use std::marker::PhantomData; @@ -76,7 +76,7 @@ pub struct GenericGroupController { impl GenericGroupController where - C: GroupConfigurationContent, + C: GroupConfigurationContentSerde, T: TypeOptionDataDeserializer, G: GroupGenerator, TypeOptionType = T>, { @@ -109,7 +109,7 @@ where impl GroupControllerSharedOperation for GenericGroupController where P: CellBytesParser, - C: GroupConfigurationContent, + C: GroupConfigurationContentSerde, Self: GroupAction, { fn field_id(&self) -> &str { 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 7050c2c087..63a3b4b67b 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 @@ -71,12 +71,14 @@ impl GroupService { vec![] } }; - drop(write_guard); } Some(groups) } - Err(_) => Some(vec![]), + Err(err) => { + tracing::error!("Load group failed: {}", err); + Some(vec![]) + } } } @@ -183,7 +185,7 @@ impl GroupService { } } - #[tracing::instrument(level = "trace", skip_all)] + #[tracing::instrument(level = "trace", skip(self, field_rev), err)] async fn make_group_controller( &self, field_type: &FieldType, 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 829ebe4c07..61a8a386d5 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 @@ -25,11 +25,11 @@ pub type FilterConfigurationsByFieldId = HashMap; pub type GroupConfigurationsByFieldId = HashMap>>; -#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(transparent)] pub struct Configuration where - T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, + T: Debug + Clone + Default + serde::Serialize + serde::de::DeserializeOwned + 'static, { /// Key: field_id /// Value: this value contains key/value. @@ -41,7 +41,7 @@ where impl Configuration where - T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, + T: Debug + Clone + Default + serde::Serialize + serde::de::DeserializeOwned + 'static, { pub fn get_mut_objects(&mut self, field_id: &str, field_type: &FieldTypeRevision) -> Option<&mut Vec>> { let value = self @@ -93,11 +93,11 @@ where } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(transparent)] pub struct ObjectIndexMap where - T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, + T: Debug + Clone + Default + serde::Serialize + serde::de::DeserializeOwned + 'static, { #[serde(with = "indexmap::serde_seq")] pub object_by_field_type: IndexMap>>, @@ -105,7 +105,7 @@ where impl ObjectIndexMap where - T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, + T: Debug + Clone + Default + serde::Serialize + serde::de::DeserializeOwned + 'static, { pub fn new() -> Self { ObjectIndexMap::default() @@ -114,7 +114,7 @@ where impl std::ops::Deref for ObjectIndexMap where - T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, + T: Debug + Clone + Default + serde::Serialize + serde::de::DeserializeOwned + 'static, { type Target = IndexMap>>; @@ -125,7 +125,7 @@ where impl std::ops::DerefMut for ObjectIndexMap where - T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, + T: Debug + Clone + Default + serde::Serialize + serde::de::DeserializeOwned + 'static, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.object_by_field_type diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index caaa1b43a9..204bdf273f 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -3,57 +3,32 @@ use serde::{Deserialize, Serialize}; use serde_json::Error; use serde_repr::*; -pub trait GroupConfigurationContent: Sized { +pub trait GroupConfigurationContentSerde: Sized + Send + Sync { fn from_configuration_content(s: &str) -> Result; fn to_configuration_content(&self) -> Result; - - fn get_groups(&self) -> &[GroupRecordRevision] { - &[] - } - - fn mut_groups(&mut self) -> &mut Vec { - todo!() - } - - fn set_groups(&mut self, _new_groups: Vec) {} - - fn swap_group(&mut self, from_group_id: &str, to_group_id: &str) { - let from_index = self - .get_groups() - .iter() - .position(|group| group.group_id == from_group_id); - let to_index = self.get_groups().iter().position(|group| group.group_id == to_group_id); - if let (Some(from), Some(to)) = (from_index, to_index) { - self.mut_groups().swap(from, to); - } - } - - fn with_mut_group(&mut self, _group_id: &str, _f: F) - where - F: FnOnce(&mut GroupRecordRevision), - { - } } -#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct GroupConfigurationRevision { pub id: String, pub field_id: String, pub field_type_rev: FieldTypeRevision, + pub groups: Vec, pub content: String, } impl GroupConfigurationRevision { pub fn new(field_id: String, field_type: FieldTypeRevision, content: T) -> Result where - T: serde::Serialize, + T: GroupConfigurationContentSerde, { - let content = serde_json::to_string(&content)?; + let content = content.to_configuration_content()?; Ok(Self { id: gen_grid_group_id(), field_id, field_type_rev: field_type, + groups: vec![], content, }) } @@ -64,7 +39,7 @@ pub struct TextGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContent for TextGroupConfigurationRevision { +impl GroupConfigurationContentSerde for TextGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -78,7 +53,7 @@ pub struct NumberGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContent for NumberGroupConfigurationRevision { +impl GroupConfigurationContentSerde for NumberGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -92,7 +67,7 @@ pub struct UrlGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContent for UrlGroupConfigurationRevision { +impl GroupConfigurationContentSerde for UrlGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -106,7 +81,7 @@ pub struct CheckboxGroupConfigurationRevision { pub hide_empty: bool, } -impl GroupConfigurationContent for CheckboxGroupConfigurationRevision { +impl GroupConfigurationContentSerde for CheckboxGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -119,10 +94,9 @@ impl GroupConfigurationContent for CheckboxGroupConfigurationRevision { #[derive(Default, Serialize, Deserialize)] pub struct SelectOptionGroupConfigurationRevision { pub hide_empty: bool, - pub groups: Vec, } -impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision { +impl GroupConfigurationContentSerde for SelectOptionGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } @@ -130,31 +104,9 @@ impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision { fn to_configuration_content(&self) -> Result { serde_json::to_string(self) } - - fn get_groups(&self) -> &[GroupRecordRevision] { - &self.groups - } - - fn mut_groups(&mut self) -> &mut Vec { - &mut self.groups - } - - fn set_groups(&mut self, new_groups: Vec) { - self.groups = new_groups; - } - - fn with_mut_group(&mut self, group_id: &str, f: F) - where - F: FnOnce(&mut GroupRecordRevision), - { - match self.groups.iter_mut().find(|group| group.group_id == group_id) { - None => {} - Some(group) => f(group), - } - } } -#[derive(Clone, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct GroupRecordRevision { pub group_id: String, @@ -179,7 +131,7 @@ pub struct DateGroupConfigurationRevision { pub condition: DateCondition, } -impl GroupConfigurationContent for DateGroupConfigurationRevision { +impl GroupConfigurationContentSerde for DateGroupConfigurationRevision { fn from_configuration_content(s: &str) -> Result { serde_json::from_str(s) } From 074c497d576c2184ad23e31dc52746623d2523f3 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 22 Aug 2022 16:16:15 +0800 Subject: [PATCH 10/10] fix: fix some bugs --- frontend/.vscode/launch.json | 2 +- .../plugins/board/application/board_bloc.dart | 32 +++-- .../board/application/group_controller.dart | 17 +++ .../app_flowy/lib/plugins/board/board.dart | 2 +- .../grid/application/row/row_service.dart | 30 +++++ .../example/lib/multi_board_list_example.dart | 2 +- .../board_column/board_column_data.dart | 3 +- .../lib/src/widgets/board_data.dart | 15 ++- .../flowy-grid/src/entities/grid_entities.rs | 43 ++++++ .../rust-lib/flowy-grid/src/event_handler.rs | 11 ++ frontend/rust-lib/flowy-grid/src/event_map.rs | 4 + .../flowy-grid/src/services/grid_editor.rs | 39 ++++-- .../src/services/grid_view_editor.rs | 19 ++- .../src/services/grid_view_manager.rs | 11 +- .../flowy-grid/src/services/group/action.rs | 12 +- .../src/services/group/configuration.rs | 25 ++-- .../src/services/group/controller.rs | 31 ++--- .../controller_impls/checkbox_controller.rs | 13 +- .../multi_select_controller.rs | 25 +--- .../single_select_controller.rs | 25 +--- .../select_option_controller/util.rs | 78 ++++++----- .../src/services/group/group_service.rs | 123 ++++++++--------- .../tests/grid/group_test/script.rs | 14 +- .../flowy-grid/tests/grid/group_test/test.rs | 125 +++++++++++++++--- .../src/revision/grid_setting_rev.rs | 5 +- .../src/revision/group_rev.rs | 24 ++++ .../src/client_grid/view_revision_pad.rs | 8 +- 27 files changed, 486 insertions(+), 252 deletions(-) diff --git a/frontend/.vscode/launch.json b/frontend/.vscode/launch.json index e70b9ffb97..0efc79b00e 100644 --- a/frontend/.vscode/launch.json +++ b/frontend/.vscode/launch.json @@ -29,7 +29,7 @@ "program": "./lib/main.dart", "type": "dart", "env": { - "RUST_LOG": "trace" + "RUST_LOG": "debug" }, "cwd": "${workspaceRoot}/app_flowy" }, diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index ac72b6e24e..f84c2a2bd1 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -23,7 +23,7 @@ class BoardBloc extends Bloc { final BoardDataController _dataController; late final AFBoardDataController afBoardDataController; final MoveRowFFIService _rowService; - Map groupControllers = {}; + LinkedHashMap groupControllers = LinkedHashMap.new(); GridFieldCache get fieldCache => _dataController.fieldCache; String get gridId => _dataController.gridId; @@ -34,9 +34,13 @@ class BoardBloc extends Bloc { super(BoardState.initial(view.id)) { afBoardDataController = AFBoardDataController( onMoveColumn: ( + fromColumnId, fromIndex, + toColumnId, toIndex, - ) {}, + ) { + _moveGroup(fromColumnId, toColumnId); + }, onMoveColumnItem: ( columnId, fromIndex, @@ -44,7 +48,7 @@ class BoardBloc extends Bloc { ) { final fromRow = groupControllers[columnId]?.rowAtIndex(fromIndex); final toRow = groupControllers[columnId]?.rowAtIndex(toIndex); - _moveRow(fromRow, toRow); + _moveRow(fromRow, columnId, toRow); }, onMoveColumnItemToColumn: ( fromColumnId, @@ -54,7 +58,7 @@ class BoardBloc extends Bloc { ) { final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex); final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex); - _moveRow(fromRow, toRow); + _moveRow(fromRow, toColumnId, toRow); }, ); @@ -95,12 +99,13 @@ class BoardBloc extends Bloc { ); } - void _moveRow(RowPB? fromRow, RowPB? toRow) { - if (fromRow != null && toRow != null) { + void _moveRow(RowPB? fromRow, String columnId, RowPB? toRow) { + if (fromRow != null) { _rowService - .moveRow( + .moveGroupRow( fromRowId: fromRow.id, - toRowId: toRow.id, + toGroupId: columnId, + toRowId: toRow?.id, ) .then((result) { result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r))); @@ -108,6 +113,17 @@ class BoardBloc extends Bloc { } } + void _moveGroup(String fromColumnId, String toColumnId) { + _rowService + .moveGroup( + fromGroupId: fromColumnId, + toGroupId: toColumnId, + ) + .then((result) { + result.fold((l) => null, (r) => add(BoardEvent.didReceiveError(r))); + }); + } + @override Future close() async { await _dataController.dispose(); diff --git a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart index 3f545dae3b..6fd68b1df8 100644 --- a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart @@ -37,6 +37,14 @@ class GroupController { (GroupRowsChangesetPB changeset) { for (final insertedRow in changeset.insertedRows) { final index = insertedRow.hasIndex() ? insertedRow.index : null; + + if (insertedRow.hasIndex() && + group.rows.length > insertedRow.index) { + group.rows.insert(insertedRow.index, insertedRow.row); + } else { + group.rows.add(insertedRow.row); + } + delegate.insertRow( group.groupId, insertedRow.row, @@ -45,10 +53,19 @@ class GroupController { } for (final deletedRow in changeset.deletedRows) { + group.rows.removeWhere((rowPB) => rowPB.id == deletedRow); delegate.removeRow(group.groupId, deletedRow); } for (final updatedRow in changeset.updatedRows) { + final index = group.rows.indexWhere( + (rowPB) => rowPB.id == updatedRow.id, + ); + + if (index != -1) { + group.rows[index] = updatedRow; + } + delegate.updateRow(group.groupId, updatedRow); } }, diff --git a/frontend/app_flowy/lib/plugins/board/board.dart b/frontend/app_flowy/lib/plugins/board/board.dart index 213cc8bc3c..c55d7f2e17 100644 --- a/frontend/app_flowy/lib/plugins/board/board.dart +++ b/frontend/app_flowy/lib/plugins/board/board.dart @@ -31,7 +31,7 @@ class BoardPluginBuilder implements PluginBuilder { class BoardPluginConfig implements PluginConfig { @override - bool get creatable => true; + bool get creatable => false; } class BoardPlugin extends Plugin { diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart index a18c0c8e75..2612f5975c 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart @@ -3,6 +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/block_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; class RowFFIService { @@ -68,4 +69,33 @@ class MoveRowFFIService { return GridEventMoveRow(payload).send(); } + + Future> moveGroupRow({ + required String fromRowId, + required String toGroupId, + required String? toRowId, + }) { + var payload = MoveGroupRowPayloadPB.create() + ..viewId = gridId + ..fromRowId = fromRowId + ..toGroupId = toGroupId; + + if (toRowId != null) { + payload.toRowId = toRowId; + } + + return GridEventMoveGroupRow(payload).send(); + } + + Future> moveGroup({ + required String fromGroupId, + required String toGroupId, + }) { + final payload = MoveGroupPayloadPB.create() + ..viewId = gridId + ..fromGroupId = fromGroupId + ..toGroupId = toGroupId; + + return GridEventMoveGroup(payload).send(); + } } diff --git a/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart b/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart index 83f75d2a0e..01aba725a5 100644 --- a/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart +++ b/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart @@ -10,7 +10,7 @@ class MultiBoardListExample extends StatefulWidget { class _MultiBoardListExampleState extends State { final AFBoardDataController boardDataController = AFBoardDataController( - onMoveColumn: (fromIndex, toIndex) { + onMoveColumn: (fromColumnId, fromIndex, toColumnId, toIndex) { debugPrint('Move column from $fromIndex to $toIndex'); }, onMoveColumnItem: (columnId, fromIndex, toIndex) { diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart index 6e184761c5..f26bd16c50 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart @@ -145,7 +145,8 @@ class AFBoardColumnData extends ReoderFlexItem with EquatableMixin { }) : _items = items; /// Returns the readonly List - UnmodifiableListView get items => UnmodifiableListView(_items); + UnmodifiableListView get items => + UnmodifiableListView([..._items]); @override List get props => [id, ..._items]; diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart index 6208dbd0f0..e8d5471939 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart @@ -8,7 +8,12 @@ import 'reorder_flex/reorder_flex.dart'; import 'package:flutter/material.dart'; import 'reorder_phantom/phantom_controller.dart'; -typedef OnMoveColumn = void Function(int fromIndex, int toIndex); +typedef OnMoveColumn = void Function( + String fromColumnId, + int fromIndex, + String toColumnId, + int toIndex, +); typedef OnMoveColumnItem = void Function( String columnId, @@ -98,9 +103,11 @@ class AFBoardDataController extends ChangeNotifier } void moveColumn(int fromIndex, int toIndex, {bool notify = true}) { - final columnData = _columnDatas.removeAt(fromIndex); - _columnDatas.insert(toIndex, columnData); - onMoveColumn?.call(fromIndex, toIndex); + final toColumnData = _columnDatas[toIndex]; + final fromColumnData = _columnDatas.removeAt(fromIndex); + + _columnDatas.insert(toIndex, fromColumnData); + onMoveColumn?.call(fromColumnData.id, fromIndex, toColumnData.id, toIndex); if (notify) notifyListeners(); } diff --git a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs index be8cfdeae1..c012376f55 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/grid_entities.rs @@ -123,3 +123,46 @@ impl TryInto for MoveRowPayloadPB { }) } } +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct MoveGroupRowPayloadPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2)] + pub from_row_id: String, + + #[pb(index = 3)] + pub to_group_id: String, + + #[pb(index = 4, one_of)] + pub to_row_id: Option, +} + +pub struct MoveGroupRowParams { + pub view_id: String, + pub from_row_id: String, + pub to_group_id: String, + pub to_row_id: Option, +} + +impl TryInto for MoveGroupRowPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::GridViewIdIsEmpty)?; + let from_row_id = NotEmptyStr::parse(self.from_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?; + let to_group_id = NotEmptyStr::parse(self.to_group_id).map_err(|_| ErrorCode::GroupIdIsEmpty)?; + + let to_row_id = match self.to_row_id { + None => None, + Some(to_row_id) => Some(NotEmptyStr::parse(to_row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?.0), + }; + + Ok(MoveGroupRowParams { + view_id: view_id.0, + from_row_id: from_row_id.0, + to_group_id: to_group_id.0, + to_row_id, + }) + } +} diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 149f7017a3..a9060aa87e 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -436,3 +436,14 @@ pub(crate) async fn move_group_handler( let _ = editor.move_group(params).await?; Ok(()) } + +#[tracing::instrument(level = "debug", skip(data, manager), err)] +pub(crate) async fn move_group_row_handler( + data: Data, + manager: AppData>, +) -> FlowyResult<()> { + let params: MoveGroupRowParams = data.into_inner().try_into()?; + let editor = manager.get_grid_editor(params.view_id.as_ref())?; + let _ = editor.move_group_row(params).await?; + Ok(()) +} diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 844ae7f5c3..a78bcb5ed3 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -42,6 +42,7 @@ pub fn create(grid_manager: Arc) -> Module { // Group .event(GridEvent::CreateBoardCard, create_board_card_handler) .event(GridEvent::MoveGroup, move_group_handler) + .event(GridEvent::MoveGroupRow, move_group_row_handler) .event(GridEvent::GetGroup, get_groups_handler); module @@ -221,4 +222,7 @@ pub enum GridEvent { #[event(input = "MoveGroupPayloadPB")] MoveGroup = 111, + + #[event(input = "MoveGroupRowPayloadPB")] + MoveGroupRow = 112, } 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 93c48b0880..485bf6930c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -560,16 +560,6 @@ impl GridRevisionEditor { .block_manager .move_row(row_rev.clone(), from_index, to_index) .await?; - - if let Some(row_changeset) = self.view_manager.move_row(row_rev, to_row_id.clone()).await { - tracing::trace!("Receive row changeset after moving the row"); - match self.block_manager.update_row(row_changeset).await { - Ok(_) => {} - Err(e) => { - tracing::error!("Apply row changeset error:{:?}", e); - } - } - } } (_, None) => tracing::warn!("Can not find the from row id: {}", from_row_id), (None, _) => tracing::warn!("Can not find the to row id: {}", to_row_id), @@ -579,6 +569,35 @@ impl GridRevisionEditor { Ok(()) } + pub async fn move_group_row(&self, params: MoveGroupRowParams) -> FlowyResult<()> { + let MoveGroupRowParams { + view_id: _, + from_row_id, + to_group_id, + to_row_id, + } = params; + + match self.block_manager.get_row_rev(&from_row_id).await? { + None => tracing::warn!("Move row failed, can not find the row:{}", from_row_id), + Some(row_rev) => { + if let Some(row_changeset) = self + .view_manager + .move_group_row(row_rev, to_group_id, to_row_id.clone()) + .await + { + match self.block_manager.update_row(row_changeset).await { + Ok(_) => {} + Err(e) => { + tracing::error!("Apply row changeset error:{:?}", e); + } + } + } + } + } + + Ok(()) + } + pub async fn move_field(&self, params: MoveFieldParams) -> FlowyResult<()> { let MoveFieldParams { grid_id: _, diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index fb8706b175..4e23d9be19 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -80,7 +80,7 @@ impl GridViewRevisionEditor { None => {} Some(group_id) => { self.group_service - .read() + .write() .await .will_create_row(row_rev, group_id, |field_id| { self.field_delegate.get_field_rev(&field_id) @@ -109,7 +109,7 @@ impl GridViewRevisionEditor { // Send the group notification if the current view has groups; if let Some(changesets) = self .group_service - .read() + .write() .await .did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) .await @@ -123,7 +123,7 @@ impl GridViewRevisionEditor { pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) { if let Some(changesets) = self .group_service - .read() + .write() .await .did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) .await @@ -134,23 +134,23 @@ impl GridViewRevisionEditor { } } - pub(crate) async fn did_move_row( + pub(crate) async fn move_group_row( &self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, - upper_row_id: &str, + to_group_id: &str, + to_row_id: Option, ) { if let Some(changesets) = self .group_service - .read() + .write() .await - .did_move_row(row_rev, row_changeset, upper_row_id, |field_id| { + .move_group_row(row_rev, row_changeset, to_group_id, to_row_id, |field_id| { self.field_delegate.get_field_rev(&field_id) }) .await { for changeset in changesets { - tracing::trace!("Group: {} changeset: {}", changeset.group_id, changeset); self.notify_did_update_group_rows(changeset).await; } } @@ -184,7 +184,7 @@ impl GridViewRevisionEditor { pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { let _ = self .group_service - .read() + .write() .await .move_group(¶ms.from_group_id, ¶ms.to_group_id) .await?; @@ -326,7 +326,6 @@ impl GroupConfigurationReader for GroupConfigurationReaderImpl { let view_pad = self.0.clone(); wrap_future(async move { let mut groups = view_pad.read().await.groups.get_objects(&field_rev.id, &field_rev.ty)?; - if groups.is_empty() { None } else { diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index a1265d0e25..b0e578f804 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -129,10 +129,17 @@ impl GridViewManager { /// It may generate a RowChangeset when the Row was moved from one group to another. /// The return value, [RowChangeset], contains the changes made by the groups. /// - pub(crate) async fn move_row(&self, row_rev: Arc, to_row_id: String) -> Option { + pub(crate) async fn move_group_row( + &self, + row_rev: Arc, + to_group_id: String, + to_row_id: Option, + ) -> Option { let mut row_changeset = RowChangeset::new(row_rev.id.clone()); for view_editor in self.view_editors.iter() { - view_editor.did_move_row(&row_rev, &mut row_changeset, &to_row_id).await; + view_editor + .move_group_row(&row_rev, &mut row_changeset, &to_group_id, to_row_id.clone()) + .await; } if row_changeset.has_changed() { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/action.rs b/frontend/rust-lib/flowy-grid/src/services/group/action.rs index a495fe0a1f..29dc51cc37 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/action.rs @@ -1,6 +1,7 @@ use crate::entities::GroupRowsChangesetPB; -use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; +use crate::services::group::controller::MoveGroupRowContext; +use flowy_grid_data_model::revision::RowRevision; pub trait GroupAction: Send + Sync { type CellDataType; @@ -12,12 +13,5 @@ pub trait GroupAction: Send + Sync { cell_data: &Self::CellDataType, ) -> Vec; - fn move_row_if_match( - &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &Self::CellDataType, - to_row_id: &str, - ) -> Vec; + fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec; } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 36d49a10e1..a462278d2b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -101,9 +101,9 @@ where Ok(()) } - pub(crate) fn with_mut_groups(&mut self, mut mut_groups_fn: impl FnMut(&mut Group)) { + pub(crate) fn with_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) { self.groups_map.iter_mut().for_each(|(_, group)| { - mut_groups_fn(group); + each(group); }) } @@ -111,22 +111,16 @@ where self.groups_map.get_mut(group_id) } - pub(crate) fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { - let from_group_index = self.groups_map.get_index_of(from_group_id); - let to_group_index = self.groups_map.get_index_of(to_group_id); - match (from_group_index, to_group_index) { + pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> { + let from_index = self.groups_map.get_index_of(from_id); + let to_index = self.groups_map.get_index_of(to_id); + match (from_index, to_index) { (Some(from_index), Some(to_index)) => { self.groups_map.swap_indices(from_index, to_index); self.mut_configuration(|configuration| { - let from_index = configuration - .groups - .iter() - .position(|group| group.group_id == from_group_id); - let to_index = configuration - .groups - .iter() - .position(|group| group.group_id == to_group_id); + let from_index = configuration.groups.iter().position(|group| group.group_id == from_id); + let to_index = configuration.groups.iter().position(|group| group.group_id == to_id); if let (Some(from), Some(to)) = (from_index, to_index) { configuration.groups.swap(from, to); } @@ -150,7 +144,7 @@ where let configuration = (&*self.configuration).clone(); let writer = self.writer.clone(); let field_id = self.field_rev.id.clone(); - let field_type = self.field_rev.ty.clone(); + let field_type = self.field_rev.ty; tokio::spawn(async move { match writer .save_group_configuration(&field_id, field_type, configuration) @@ -196,7 +190,6 @@ where } fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec) -> (Vec, Vec) { - tracing::trace!("Merge group: old: {}, new: {}", old_group_revs.len(), groups.len()); if old_group_revs.is_empty() { let new_groups = groups .iter() diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index 13b4ccce63..1a5ee23694 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -31,6 +31,14 @@ pub trait GroupGenerator { ) -> Vec; } +pub struct MoveGroupRowContext<'a> { + pub row_rev: &'a RowRevision, + pub row_changeset: &'a mut RowChangeset, + pub field_rev: &'a FieldRevision, + pub to_group_id: &'a str, + pub to_row_id: Option, +} + // Defines the shared actions each group controller can perform. pub trait GroupControllerSharedOperation: Send + Sync { // The field that is used for grouping the rows @@ -51,13 +59,7 @@ pub trait GroupControllerSharedOperation: Send + Sync { field_rev: &FieldRevision, ) -> FlowyResult>; - fn did_move_row( - &mut self, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - field_rev: &FieldRevision, - to_row_id: &str, - ) -> FlowyResult>; + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult>; } /// C: represents the group configuration that impl [GroupConfigurationSerde] @@ -195,18 +197,11 @@ where } } - fn did_move_row( - &mut self, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - field_rev: &FieldRevision, - to_row_id: &str, - ) -> FlowyResult> { - if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { - let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult> { + if let Some(cell_rev) = context.row_rev.cells.get(&self.field_id) { + let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), context.field_rev); let cell_data = cell_bytes.parser::

()?; - tracing::trace!("Move row:{} to row:{}", row_rev.id, to_row_id); - Ok(self.move_row_if_match(field_rev, row_rev, row_changeset, &cell_data, to_row_id)) + Ok(self.move_row(&cell_data, context)) } else { Ok(vec![]) } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index 59a53ae72a..ffcbf117fe 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -2,10 +2,12 @@ use crate::entities::GroupRowsChangesetPB; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::group::action::GroupAction; use crate::services::group::configuration::GenericGroupConfiguration; -use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; +use crate::services::group::controller::{ + GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, +}; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, RowChangeset, RowRevision}; +use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, RowRevision}; pub type CheckboxGroupController = GenericGroupController< CheckboxGroupConfigurationRevision, @@ -38,13 +40,10 @@ impl GroupAction for CheckboxGroupController { todo!() } - fn move_row_if_match( + fn move_row( &mut self, - _field_rev: &FieldRevision, - _row_rev: &RowRevision, - _row_changeset: &mut RowChangeset, _cell_data: &Self::CellDataType, - _to_row_id: &str, + _context: MoveGroupRowContext, ) -> Vec { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index 7a208a884f..cce2698158 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -3,12 +3,12 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser}; use crate::services::group::action::GroupAction; -use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; +use crate::services::group::controller::{ + GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, +}; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{ - FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // MultiSelect pub type MultiSelectGroupController = GenericGroupController< @@ -45,25 +45,14 @@ impl GroupAction for MultiSelectGroupController { changesets } - fn move_row_if_match( + fn move_row( &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, - to_row_id: &str, + mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; self.configuration.with_mut_groups(|group| { - move_row( - group, - &mut group_changeset, - field_rev, - row_rev, - row_changeset, - cell_data, - to_row_id, - ); + move_select_option_row(group, &mut group_changeset, cell_data, &mut context); }); group_changeset } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index 2eb1e4a60f..d48cdd8ee7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -3,13 +3,13 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB}; use crate::services::group::action::GroupAction; -use crate::services::group::controller::{GenericGroupController, GroupController, GroupGenerator}; +use crate::services::group::controller::{ + GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, +}; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{ - FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // SingleSelect pub type SingleSelectGroupController = GenericGroupController< @@ -45,25 +45,14 @@ impl GroupAction for SingleSelectGroupController { changesets } - fn move_row_if_match( + fn move_row( &mut self, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, cell_data: &Self::CellDataType, - to_row_id: &str, + mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; self.configuration.with_mut_groups(|group| { - move_row( - group, - &mut group_changeset, - field_rev, - row_rev, - row_changeset, - cell_data, - to_row_id, - ); + move_select_option_row(group, &mut group_changeset, cell_data, &mut context); }); group_changeset } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs index 6675f26aa4..bdca688531 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -4,9 +4,8 @@ use crate::services::field::SelectOptionCellDataPB; use crate::services::group::configuration::GenericGroupConfiguration; use crate::services::group::Group; -use flowy_grid_data_model::revision::{ - FieldRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use crate::services::group::controller::MoveGroupRowContext; +use flowy_grid_data_model::revision::{RowRevision, SelectOptionGroupConfigurationRevision}; pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; @@ -47,45 +46,60 @@ pub fn remove_row( }); } -pub fn move_row( +pub fn move_select_option_row( group: &mut Group, group_changeset: &mut Vec, - field_rev: &FieldRevision, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - cell_data: &SelectOptionCellDataPB, - to_row_id: &str, + _cell_data: &SelectOptionCellDataPB, + context: &mut MoveGroupRowContext, ) { - cell_data.select_options.iter().for_each(|option| { - // Remove the row in which group contains the row - let is_group_contains = group.contains_row(&row_rev.id); - let to_index = group.index_of_row(to_row_id); + let MoveGroupRowContext { + row_rev, + row_changeset, + field_rev, + to_group_id, + to_row_id, + } = context; - if option.id == group.id && is_group_contains { - group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); - group.remove_row(&row_rev.id); - } + let from_index = group.index_of_row(&row_rev.id); + let to_index = match to_row_id { + None => None, + Some(to_row_id) => group.index_of_row(to_row_id), + }; - // Find the inserted group - if let Some(to_index) = to_index { - let row_pb = RowPB::from(row_rev); - let inserted_row = InsertedRowPB { - row: row_pb.clone(), - index: Some(to_index as i32), - }; - group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); - if group.number_of_row() == to_index { + // Remove the row in which group contains it + if from_index.is_some() { + group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()])); + tracing::debug!("Group:{} remove row:{}", group.id, row_rev.id); + group.remove_row(&row_rev.id); + } + + if group.id == *to_group_id { + let row_pb = RowPB::from(*row_rev); + let mut inserted_row = InsertedRowPB::new(row_pb.clone()); + match to_index { + None => { + group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); + tracing::debug!("Group:{} append row:{}", group.id, row_rev.id); group.add_row(row_pb); - } else { - group.insert_row(to_index, row_pb); + } + Some(to_index) => { + if to_index < group.number_of_row() { + tracing::debug!("Group:{} insert row:{} at {} ", group.id, row_rev.id, to_index); + inserted_row.index = Some(to_index as i32); + group.insert_row(to_index, row_pb); + } else { + tracing::debug!("Group:{} append row:{}", group.id, row_rev.id); + group.add_row(row_pb); + } + group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row])); } } - // If the inserted row comes from other group, it needs to update the corresponding cell content. - if to_index.is_some() && option.id != group.id { - // Update the corresponding row's cell content. + // Update the corresponding row's cell content. + if from_index.is_none() { + tracing::debug!("Mark row:{} belong to group:{}", row_rev.id, group.id); let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev); } - }); + } } 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 63a3b4b67b..6afec9dd82 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,5 +1,6 @@ +use crate::entities::{FieldType, GroupRowsChangesetPB}; use crate::services::group::configuration::GroupConfigurationReader; -use crate::services::group::controller::GroupController; +use crate::services::group::controller::{GroupController, MoveGroupRowContext}; use crate::services::group::{ CheckboxGroupConfiguration, CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController, SelectOptionGroupConfiguration, SingleSelectGroupController, @@ -10,16 +11,13 @@ use flowy_grid_data_model::revision::{ NumberGroupConfigurationRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, TextGroupConfigurationRevision, UrlGroupConfigurationRevision, }; - -use crate::entities::{FieldType, GroupRowsChangesetPB}; use std::future::Future; use std::sync::Arc; -use tokio::sync::RwLock; pub(crate) struct GroupService { configuration_reader: Arc, configuration_writer: Arc, - group_controller: Option>>, + group_controller: Option>, } impl GroupService { @@ -36,19 +34,16 @@ impl GroupService { } pub(crate) async fn groups(&self) -> Vec { - if let Some(group_controller) = self.group_controller.as_ref() { - group_controller.read().await.groups() - } else { - vec![] - } + self.group_controller + .as_ref() + .and_then(|group_controller| Some(group_controller.groups())) + .unwrap_or(vec![]) } pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { - if let Some(group_controller) = self.group_controller.as_ref() { - group_controller.read().await.get_group(group_id) - } else { - None - } + self.group_controller + .as_ref() + .and_then(|group_controller| group_controller.get_group(group_id)) } pub(crate) async fn load_groups( @@ -58,51 +53,37 @@ impl GroupService { ) -> Option> { let field_rev = find_group_field(field_revs)?; let field_type: FieldType = field_rev.ty.into(); - match self.make_group_controller(&field_type, &field_rev).await { - Ok(group_controller) => { - self.group_controller = group_controller; - let mut groups = vec![]; - if let Some(group_action_handler) = self.group_controller.as_ref() { - let mut write_guard = group_action_handler.write().await; - groups = match write_guard.fill_groups(&row_revs, &field_rev) { - Ok(groups) => groups, - Err(e) => { - tracing::error!("Fill groups failed:{:?}", e); - vec![] - } - }; - drop(write_guard); - } - Some(groups) + + let mut group_controller = self.make_group_controller(&field_type, &field_rev).await.ok()??; + let groups = match group_controller.fill_groups(&row_revs, &field_rev) { + Ok(groups) => groups, + Err(e) => { + tracing::error!("Fill groups failed:{:?}", e); + vec![] } - Err(err) => { - tracing::error!("Load group failed: {}", err); - Some(vec![]) - } - } + }; + self.group_controller = Some(group_controller); + Some(groups) } - pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F) + pub(crate) async fn will_create_row(&mut self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F) where F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - if let Some(group_controller) = self.group_controller.as_ref() { - let field_id = group_controller.read().await.field_id().to_owned(); + if let Some(group_controller) = self.group_controller.as_mut() { + let field_id = group_controller.field_id().to_owned(); match get_field_fn(field_id).await { None => {} Some(field_rev) => { - group_controller - .write() - .await - .will_create_row(row_rev, &field_rev, group_id); + group_controller.will_create_row(row_rev, &field_rev, group_id); } } } } pub(crate) async fn did_delete_row( - &self, + &mut self, row_rev: &RowRevision, get_field_fn: F, ) -> Option> @@ -110,11 +91,11 @@ impl GroupService { F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - let group_controller = self.group_controller.as_ref()?; - let field_id = group_controller.read().await.field_id().to_owned(); + let group_controller = self.group_controller.as_mut()?; + let field_id = group_controller.field_id().to_owned(); let field_rev = get_field_fn(field_id).await?; - match group_controller.write().await.did_delete_row(row_rev, &field_rev) { + match group_controller.did_delete_row(row_rev, &field_rev) { Ok(changesets) => Some(changesets), Err(e) => { tracing::error!("Delete group data failed, {:?}", e); @@ -123,26 +104,30 @@ impl GroupService { } } - pub(crate) async fn did_move_row( - &self, + pub(crate) async fn move_group_row( + &mut self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, - upper_row_id: &str, + to_group_id: &str, + to_row_id: Option, get_field_fn: F, ) -> Option> where F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - let group_controller = self.group_controller.as_ref()?; - let field_id = group_controller.read().await.field_id().to_owned(); + let group_controller = self.group_controller.as_mut()?; + let field_id = group_controller.field_id().to_owned(); let field_rev = get_field_fn(field_id).await?; + let move_row_context = MoveGroupRowContext { + row_rev, + row_changeset, + field_rev: field_rev.as_ref(), + to_group_id, + to_row_id, + }; - match group_controller - .write() - .await - .did_move_row(row_rev, row_changeset, &field_rev, upper_row_id) - { + match group_controller.move_group_row(move_row_context) { Ok(changesets) => Some(changesets), Err(e) => { tracing::error!("Move group data failed, {:?}", e); @@ -153,7 +138,7 @@ impl GroupService { #[tracing::instrument(level = "trace", skip_all)] pub(crate) async fn did_update_row( - &self, + &mut self, row_rev: &RowRevision, get_field_fn: F, ) -> Option> @@ -161,11 +146,11 @@ impl GroupService { F: FnOnce(String) -> O, O: Future>> + Send + Sync + 'static, { - let group_controller = self.group_controller.as_ref()?; - let field_id = group_controller.read().await.field_id().to_owned(); + let group_controller = self.group_controller.as_mut()?; + let field_id = group_controller.field_id().to_owned(); let field_rev = get_field_fn(field_id).await?; - match group_controller.write().await.did_update_row(row_rev, &field_rev) { + match group_controller.did_update_row(row_rev, &field_rev) { Ok(changeset) => Some(changeset), Err(e) => { tracing::error!("Update group data failed, {:?}", e); @@ -175,11 +160,11 @@ impl GroupService { } #[tracing::instrument(level = "trace", skip_all)] - pub(crate) async fn move_group(&self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { - match self.group_controller.as_ref() { + pub(crate) async fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { + match self.group_controller.as_mut() { None => Ok(()), Some(group_controller) => { - let _ = group_controller.write().await.move_group(from_group_id, to_group_id)?; + let _ = group_controller.move_group(from_group_id, to_group_id)?; Ok(()) } } @@ -190,8 +175,8 @@ impl GroupService { &self, field_type: &FieldType, field_rev: &Arc, - ) -> FlowyResult>>> { - let mut group_controller: Option>> = None; + ) -> FlowyResult>> { + let mut group_controller: Option> = None; match field_type { FieldType::RichText => { // let generator = GroupGenerator::::from_configuration(configuration); @@ -210,7 +195,7 @@ impl GroupService { ) .await?; let controller = SingleSelectGroupController::new(field_rev, configuration).await?; - group_controller = Some(Arc::new(RwLock::new(controller))); + group_controller = Some(Box::new(controller)); } FieldType::MultiSelect => { let configuration = SelectOptionGroupConfiguration::new( @@ -220,7 +205,7 @@ impl GroupService { ) .await?; let controller = MultiSelectGroupController::new(field_rev, configuration).await?; - group_controller = Some(Arc::new(RwLock::new(controller))); + group_controller = Some(Box::new(controller)); } FieldType::Checkbox => { let configuration = CheckboxGroupConfiguration::new( @@ -230,7 +215,7 @@ impl GroupService { ) .await?; let controller = CheckboxGroupController::new(field_rev, configuration).await?; - group_controller = Some(Arc::new(RwLock::new(controller))) + group_controller = Some(Box::new(controller)); } FieldType::URL => { // let generator = GroupGenerator::::from_configuration(configuration); 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 d284e69c76..94ef4dff1b 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 @@ -1,5 +1,7 @@ use crate::grid::grid_editor::GridEditorTest; -use flowy_grid::entities::{CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveRowParams, RowPB}; +use flowy_grid::entities::{ + CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB, +}; use flowy_grid::services::cell::insert_select_option_cell; use flowy_grid_data_model::revision::RowChangeset; @@ -75,14 +77,16 @@ impl GridGroupTest { } => { let groups: Vec = self.editor.load_groups().await.unwrap().items; let from_row = groups.get(from_group_index).unwrap().rows.get(from_row_index).unwrap(); - let to_row = groups.get(to_group_index).unwrap().rows.get(to_row_index).unwrap(); - let params = MoveRowParams { + let to_group = groups.get(to_group_index).unwrap(); + let to_row = to_group.rows.get(to_row_index).unwrap(); + let params = MoveGroupRowParams { view_id: self.inner.grid_id.clone(), from_row_id: from_row.id.clone(), - to_row_id: to_row.id.clone(), + to_group_id: to_group.group_id.clone(), + to_row_id: Some(to_row.id.clone()), }; - self.editor.move_row(params).await.unwrap(); + self.editor.move_group_row(params).await.unwrap(); } GroupScript::AssertRow { group_index, diff --git a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs index 6092e97a5e..bebf499773 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/group_test/test.rs @@ -2,7 +2,7 @@ use crate::grid::group_test::script::GridGroupTest; use crate::grid::group_test::script::GroupScript::*; #[tokio::test] -async fn board_init_test() { +async fn group_init_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ AssertGroupCount(3), @@ -23,7 +23,7 @@ async fn board_init_test() { } #[tokio::test] -async fn board_move_row_test() { +async fn group_move_row_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -48,7 +48,7 @@ async fn board_move_row_test() { } #[tokio::test] -async fn board_move_row_to_other_group_test() { +async fn group_move_row_to_other_group_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -76,7 +76,7 @@ async fn board_move_row_to_other_group_test() { } #[tokio::test] -async fn board_move_row_to_other_group_and_reorder_test() { +async fn group_move_two_row_to_other_group_test() { let mut test = GridGroupTest::new().await; let group = test.group_at_index(0).await; let scripts = vec![ @@ -86,15 +86,41 @@ async fn board_move_row_to_other_group_and_reorder_test() { to_group_index: 1, to_row_index: 1, }, - MoveRow { - from_group_index: 1, - from_row_index: 1, - to_group_index: 1, - to_row_index: 2, + AssertGroupRowCount { + group_index: 0, + row_count: 1, + }, + AssertGroupRowCount { + group_index: 1, + row_count: 3, }, AssertRow { group_index: 1, - row_index: 2, + row_index: 1, + row: group.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; + + let group = test.group_at_index(0).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }, + AssertGroupRowCount { + group_index: 0, + row_count: 0, + }, + AssertGroupRowCount { + group_index: 1, + row_count: 4, + }, + AssertRow { + group_index: 1, + row_index: 1, row: group.rows.get(0).unwrap().clone(), }, ]; @@ -102,7 +128,74 @@ async fn board_move_row_to_other_group_and_reorder_test() { } #[tokio::test] -async fn board_create_row_test() { +async fn group_move_row_to_other_group_and_reorder_from_up_to_down_test() { + let mut test = GridGroupTest::new().await; + let group_0 = test.group_at_index(0).await; + let group_1 = test.group_at_index(1).await; + let scripts = vec![ + MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }, + AssertRow { + group_index: 1, + row_index: 1, + row: group_0.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; + + let scripts = vec![ + MoveRow { + from_group_index: 1, + from_row_index: 0, + to_group_index: 1, + to_row_index: 2, + }, + AssertRow { + group_index: 1, + row_index: 2, + row: group_1.rows.get(0).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} + +#[tokio::test] +async fn group_move_row_to_other_group_and_reorder_from_bottom_to_up_test() { + let mut test = GridGroupTest::new().await; + let scripts = vec![MoveRow { + from_group_index: 0, + from_row_index: 0, + to_group_index: 1, + to_row_index: 1, + }]; + test.run_scripts(scripts).await; + + let group = test.group_at_index(1).await; + let scripts = vec![ + AssertGroupRowCount { + group_index: 1, + row_count: 3, + }, + MoveRow { + from_group_index: 1, + from_row_index: 2, + to_group_index: 1, + to_row_index: 0, + }, + AssertRow { + group_index: 1, + row_index: 0, + row: group.rows.get(2).unwrap().clone(), + }, + ]; + test.run_scripts(scripts).await; +} +#[tokio::test] +async fn group_create_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ CreateRow { group_index: 0 }, @@ -121,7 +214,7 @@ async fn board_create_row_test() { } #[tokio::test] -async fn board_delete_row_test() { +async fn group_delete_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ DeleteRow { @@ -137,7 +230,7 @@ async fn board_delete_row_test() { } #[tokio::test] -async fn board_delete_all_row_test() { +async fn group_delete_all_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ DeleteRow { @@ -157,7 +250,7 @@ async fn board_delete_all_row_test() { } #[tokio::test] -async fn board_update_row_test() { +async fn group_update_row_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ // Update the row at 0 in group0 by setting the row's group field data @@ -179,7 +272,7 @@ async fn board_update_row_test() { } #[tokio::test] -async fn board_reorder_group_test() { +async fn group_reorder_group_test() { let mut test = GridGroupTest::new().await; let scripts = vec![ // Update the row at 0 in group0 by setting the row's group field data @@ -201,7 +294,7 @@ async fn board_reorder_group_test() { } #[tokio::test] -async fn board_move_group_test() { +async fn group_move_group_test() { let mut test = GridGroupTest::new().await; let group_0 = test.group_at_index(0).await; let group_1 = test.group_at_index(1).await; 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 61a8a386d5..1f52ae93e2 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 @@ -76,7 +76,8 @@ where Some(objects_by_field_id) } - pub fn insert_object(&mut self, field_id: &str, field_type: &FieldTypeRevision, object: T) { + /// add object to the end of the list + pub fn add_object(&mut self, field_id: &str, field_type: &FieldTypeRevision, object: T) { let object_rev_map = self .inner .entry(field_id.to_string()) @@ -88,7 +89,7 @@ where .push(Arc::new(object)) } - pub fn remove_all(&mut self) { + pub fn clear(&mut self) { self.inner.clear() } } diff --git a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs index 204bdf273f..97d45295fe 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/group_rev.rs @@ -155,3 +155,27 @@ impl std::default::Default for DateCondition { DateCondition::Relative } } + +#[cfg(test)] +mod tests { + use crate::revision::{GroupConfigurationRevision, SelectOptionGroupConfigurationRevision}; + + #[test] + fn group_configuration_serde_test() { + let content = SelectOptionGroupConfigurationRevision { hide_empty: false }; + let rev = GroupConfigurationRevision::new("1".to_owned(), 2, content).unwrap(); + let json = serde_json::to_string(&rev).unwrap(); + + let rev: GroupConfigurationRevision = serde_json::from_str(&json).unwrap(); + let _content: SelectOptionGroupConfigurationRevision = serde_json::from_str(&rev.content).unwrap(); + } + + #[test] + fn group_configuration_serde_test2() { + let content = SelectOptionGroupConfigurationRevision { hide_empty: false }; + let content_json = serde_json::to_string(&content).unwrap(); + let rev = GroupConfigurationRevision::new("1".to_owned(), 2, content).unwrap(); + + assert_eq!(rev.content, content_json); + } +} diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index 57bd783d75..ddc9c6e05a 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -60,7 +60,9 @@ impl GridViewRevisionPad { group_rev: GroupConfigurationRevision, ) -> CollaborateResult> { self.modify(|view| { - view.groups.insert_object(field_id, field_type, group_rev); + // Only save one group + view.groups.clear(); + view.groups.add_object(field_id, field_type, group_rev); Ok(Some(())) }) } @@ -127,7 +129,7 @@ impl GridViewRevisionPad { filter_rev: FilterConfigurationRevision, ) -> CollaborateResult> { self.modify(|view| { - view.filters.insert_object(field_id, field_type, filter_rev); + view.filters.add_object(field_id, field_type, filter_rev); Ok(Some(())) }) } @@ -166,8 +168,6 @@ impl GridViewRevisionPad { None => Ok(None), Some(delta) => { self.delta = self.delta.compose(&delta)?; - tracing::info!("GridView: {:?}", delta); - let md5 = md5(&self.delta.json_bytes()); Ok(Some(GridViewRevisionChangeset { delta, md5 })) }