From f192f89ebb098822089b4e0dc350ee180533d2d1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 1 Sep 2022 20:41:15 +0800 Subject: [PATCH] chore: refactor group gen process --- .../assets/images/grid/setting/group.svg | 7 + .../app_flowy/assets/translations/en.json | 3 +- .../toolbar/board_setting_bloc.dart | 1 + .../presentation/toolbar/board_setting.dart | 10 + .../widgets/toolbar/grid_group.dart | 27 ++ .../src/entities/group_entities/group.rs | 4 + .../group_entities/group_changeset.rs | 3 + .../src/services/grid_view_editor.rs | 171 ++++----- .../src/services/group/configuration.rs | 208 +++++----- .../src/services/group/controller.rs | 38 +- .../controller_impls/checkbox_controller.rs | 36 +- .../controller_impls/default_controller.rs | 80 ++++ .../services/group/controller_impls/mod.rs | 2 + .../multi_select_controller.rs | 28 +- .../single_select_controller.rs | 28 +- .../select_option_controller/util.rs | 30 +- .../flowy-grid/src/services/group/entities.rs | 8 +- .../src/services/group/group_service.rs | 361 ------------------ .../src/services/group/group_util.rs | 113 ++++++ .../flowy-grid/src/services/group/mod.rs | 4 +- .../flowy-grid/tests/grid/group_test/test.rs | 16 +- .../src/revision/group_rev.rs | 38 +- 22 files changed, 554 insertions(+), 662 deletions(-) create mode 100644 frontend/app_flowy/assets/images/grid/setting/group.svg create mode 100644 frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs delete mode 100644 frontend/rust-lib/flowy-grid/src/services/group/group_service.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/group/group_util.rs diff --git a/frontend/app_flowy/assets/images/grid/setting/group.svg b/frontend/app_flowy/assets/images/grid/setting/group.svg new file mode 100644 index 0000000000..f0a6dff4f9 --- /dev/null +++ b/frontend/app_flowy/assets/images/grid/setting/group.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 953e5b02bb..3990a5acc4 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -160,7 +160,8 @@ "settings": { "filter": "Filter", "sortBy": "Sort by", - "Properties": "Properties" + "Properties": "Properties", + "group": "Group" }, "field": { "hide": "Hide", diff --git a/frontend/app_flowy/lib/plugins/board/application/toolbar/board_setting_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/toolbar/board_setting_bloc.dart index 480b3a4768..97185c5efe 100644 --- a/frontend/app_flowy/lib/plugins/board/application/toolbar/board_setting_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/toolbar/board_setting_bloc.dart @@ -43,4 +43,5 @@ class BoardSettingState with _$BoardSettingState { enum BoardSettingAction { properties, + groups, } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart index 76ab265a90..962ea28e15 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart @@ -95,6 +95,12 @@ class BoardSettingList extends StatelessWidget { fieldCache: settingContext.fieldCache) .show(context); break; + case BoardSettingAction.groups: + GridPropertyList( + gridId: settingContext.viewId, + fieldCache: settingContext.fieldCache) + .show(context); + break; } }, ); @@ -156,6 +162,8 @@ extension _GridSettingExtension on BoardSettingAction { switch (this) { case BoardSettingAction.properties: return 'grid/setting/properties'; + case BoardSettingAction.groups: + return 'grid/setting/group'; } } @@ -163,6 +171,8 @@ extension _GridSettingExtension on BoardSettingAction { switch (this) { case BoardSettingAction.properties: return LocaleKeys.grid_settings_Properties.tr(); + case BoardSettingAction.groups: + return LocaleKeys.grid_settings_group.tr(); } } } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart new file mode 100644 index 0000000000..5ef4ed7f11 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart @@ -0,0 +1,27 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class GridGroupList extends StatelessWidget { + const GridGroupList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(); + } +} + +class _GridGroupCell extends StatelessWidget { + const _GridGroupCell({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + + // final checkmark = field.visibility + // ? svgWidget('home/show', color: theme.iconColor) + // : svgWidget('home/hide', color: theme.iconColor); + + return Container(); + } +} 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 002cb73c6d..3ed53080ef 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 @@ -91,6 +91,9 @@ pub struct GroupPB { #[pb(index = 5)] pub is_default: bool, + + #[pb(index = 6)] + pub is_visible: bool, } impl std::convert::From for GroupPB { @@ -101,6 +104,7 @@ impl std::convert::From for GroupPB { desc: group.name, rows: group.rows, is_default: group.is_default, + is_visible: group.is_visible, } } } 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 21f39775f6..3d37a6ffa4 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 @@ -133,6 +133,9 @@ pub struct GroupViewChangesetPB { #[pb(index = 2)] pub inserted_groups: Vec, + #[pb(index = 2)] + pub new_groups: Vec, + #[pb(index = 3)] pub deleted_groups: Vec, 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 f598f5bb0b..bfe752ec12 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 @@ -7,7 +7,7 @@ use crate::entities::{ use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; use crate::services::group::{ - make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController, GroupService, + make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController, MoveGroupRowContext, }; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ @@ -20,8 +20,6 @@ use flowy_sync::entities::revision::Revision; use lib_infra::future::{wrap_future, AFFuture, FutureResult}; use std::collections::HashMap; use std::future::Future; - -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; @@ -87,18 +85,16 @@ impl GridViewRevisionEditor { } pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) { - match params.group_id.as_ref() { - None => {} - Some(group_id) => { - self.group_service - .write() - .await - .will_create_row(row_rev, group_id, |field_id| { - self.field_delegate.get_field_rev(&field_id) - }) - .await; - } + if params.group_id.is_none() { + return; } + let group_id = params.group_id.as_ref().unwrap(); + let _ = self + .mut_group_controller(|group_controller, field_rev| { + group_controller.will_create_row(row_rev, &field_rev, group_id); + Ok(()) + }) + .await; } pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) { @@ -123,58 +119,29 @@ impl GridViewRevisionEditor { pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) { // Send the group notification if the current view has groups; - let group_field_id = self.group_controller.read().await.field_id().to_owned(); - let field_rev = self.field_delegate.get_field_rev(&group_field_id).await; - field_rev.and_then(|field_rev| { - if let Some(changesets) = self - .group_controller - .write() - .await - .did_delete_row(row_rev, &field_rev) - .await - { - for changeset in changesets { - self.notify_did_update_group(changeset).await; - } - } - None - }); - } + let changesets = self + .mut_group_controller(|group_controller, field_rev| group_controller.did_delete_row(row_rev, &field_rev)) + .await; - pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) { - let changeset = self - .mut_group_controller(|group_controller, field_rev| async { - group_controller.did_update_row(row_rev, &field_rev).await - }) - .await?; - - if let Some(changeset) = changeset { + if let Some(changesets) = changesets { for changeset in changesets { self.notify_did_update_group(changeset).await; } } } - async fn mut_group_controller(&self, f: F) -> Option - where - F: FnOnce(&mut Box, Arc) -> O, - O: Future> + Send + Sync + 'static, - { - let group_field_id = self.group_controller.read().await.field_id().to_owned(); - match self.field_delegate.get_field_rev(&group_field_id).await { - None => None, - Some(field_rev) => { - let mut write_guard = self.group_controller.write().await; - Some(f(&mut write_guard, field_rev).await) + pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) { + let changesets = self + .mut_group_controller(|group_controller, field_rev| group_controller.did_update_row(row_rev, &field_rev)) + .await; + + if let Some(changesets) = changesets { + for changeset in changesets { + self.notify_did_update_group(changeset).await; } } } - async fn get_group_field_rev(&self) -> Option> { - let group_field_id = self.group_controller.read().await.field_id().to_owned(); - self.field_delegate.get_field_rev(&group_field_id).await - } - pub(crate) async fn move_group_row( &self, row_rev: &RowRevision, @@ -182,54 +149,38 @@ impl GridViewRevisionEditor { to_group_id: &str, to_row_id: Option, ) -> Vec { - match self - .group_service - .write() - .await - .move_group_row(row_rev, row_changeset, to_group_id, to_row_id, |field_id| { - self.field_delegate.get_field_rev(&field_id) + let changesets = self + .mut_group_controller(|group_controller, field_rev| { + let move_row_context = MoveGroupRowContext { + row_rev, + row_changeset, + field_rev: field_rev.as_ref(), + to_group_id, + to_row_id, + }; + + let changesets = group_controller.move_group_row(move_row_context)?; + Ok(changesets) }) - .await - { - None => vec![], - Some(changesets) => changesets, - } + .await; + + changesets.unwrap_or_default() } /// Only call once after grid view editor initialized #[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() - .await - .load_groups(&field_revs, row_revs) - .await - { - None => vec![], - Some(groups) => groups, - } - } else { - self.group_service.read().await.groups().await - }; - + let groups = self.group_controller.read().await.groups(); 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<()> { let _ = self - .group_service + .group_controller .write() .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 { + .move_group(¶ms.from_group_id, ¶ms.to_group_id)?; + match self.group_controller.read().await.get_group(¶ms.from_group_id) { None => {} Some((index, group)) => { let inserted_group = InsertedGroupPB { @@ -242,6 +193,7 @@ impl GridViewRevisionEditor { inserted_groups: vec![inserted_group], deleted_groups: vec![params.from_group_id.clone()], update_groups: vec![], + new_groups: vec![], }; self.notify_did_update_view(changeset).await; @@ -296,7 +248,7 @@ impl GridViewRevisionEditor { #[tracing::instrument(level = "trace", skip_all, err)] pub(crate) async fn did_update_field(&self, field_id: &str) -> FlowyResult<()> { if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await { - match self.group_service.write().await.did_update_field(&field_rev).await? { + match self.group_controller.write().await.did_update_field(&field_rev)? { None => {} Some(changeset) => { self.notify_did_update_view(changeset).await; @@ -331,6 +283,36 @@ impl GridViewRevisionEditor { } Ok(()) } + + async fn mut_group_controller(&self, f: F) -> Option + where + F: FnOnce(&mut Box, Arc) -> FlowyResult, + { + let group_field_id = self.group_controller.read().await.field_id().to_owned(); + match self.field_delegate.get_field_rev(&group_field_id).await { + None => None, + Some(field_rev) => { + let mut write_guard = self.group_controller.write().await; + f(&mut write_guard, field_rev).ok() + } + } + } + + #[allow(dead_code)] + async fn async_mut_group_controller(&self, f: F) -> Option + where + F: FnOnce(Arc>>, Arc) -> O, + O: Future> + Sync + 'static, + { + let group_field_id = self.group_controller.read().await.field_id().to_owned(); + match self.field_delegate.get_field_rev(&group_field_id).await { + None => None, + Some(field_rev) => { + let _write_guard = self.group_controller.write().await; + f(self.group_controller.clone(), field_rev).await.ok() + } + } + } } async fn apply_change( @@ -371,10 +353,7 @@ impl RevisionObjectBuilder for GridViewRevisionPadBuilder { struct GroupConfigurationReaderImpl(Arc>); impl GroupConfigurationReader for GroupConfigurationReaderImpl { - fn get_group_configuration( - &self, - field_rev: Arc, - ) -> AFFuture>> { + fn get_configuration(&self, field_rev: Arc) -> AFFuture>> { 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)?; @@ -395,7 +374,7 @@ struct GroupConfigurationWriterImpl { } impl GroupConfigurationWriter for GroupConfigurationWriterImpl { - fn save_group_configuration( + fn save_configuration( &self, field_id: &str, field_type: FieldTypeRevision, 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 3fb5cefaa3..fba6adf7df 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,24 +1,22 @@ use crate::entities::{GroupPB, GroupViewChangesetPB, InsertedGroupPB}; -use crate::services::group::{default_group_configuration, Group}; +use crate::services::group::{default_group_configuration, GeneratedGroup, Group}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision, }; use indexmap::IndexMap; use lib_infra::future::AFFuture; +use std::collections::HashMap; use std::fmt::Formatter; use std::marker::PhantomData; use std::sync::Arc; pub trait GroupConfigurationReader: Send + Sync + 'static { - fn get_group_configuration( - &self, - field_rev: Arc, - ) -> AFFuture>>; + fn get_configuration(&self, field_rev: Arc) -> AFFuture>>; } pub trait GroupConfigurationWriter: Send + Sync + 'static { - fn save_group_configuration( + fn save_configuration( &self, field_id: &str, field_type: FieldTypeRevision, @@ -26,7 +24,7 @@ pub trait GroupConfigurationWriter: Send + Sync + 'static { ) -> AFFuture>; } -impl std::fmt::Display for GenericGroupConfiguration { +impl std::fmt::Display for GroupContext { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.groups_map.iter().for_each(|(_, group)| { let _ = f.write_fmt(format_args!("Group:{} has {} rows \n", group.id, group.rows.len())); @@ -39,7 +37,7 @@ impl std::fmt::Display for GenericGroupConfiguration { } } -pub struct GenericGroupConfiguration { +pub struct GroupContext { view_id: String, pub configuration: Arc, configuration_content: PhantomData, @@ -50,7 +48,7 @@ pub struct GenericGroupConfiguration { writer: Arc, } -impl GenericGroupConfiguration +impl GroupContext where C: GroupConfigurationContentSerde, { @@ -67,16 +65,17 @@ where field_id: field_rev.id.clone(), name: format!("No {}", field_rev.name), is_default: true, + is_visible: true, rows: vec![], - content: "".to_string(), + filter_content: "".to_string(), }; - let configuration = match reader.get_group_configuration(field_rev.clone()).await { + let configuration = match reader.get_configuration(field_rev.clone()).await { None => { - let default_group_configuration = default_group_configuration(&field_rev); + let default_configuration = default_group_configuration(&field_rev); writer - .save_group_configuration(&field_rev.id, field_rev.ty, default_group_configuration.clone()) + .save_configuration(&field_rev.id, field_rev.ty, default_configuration.clone()) .await?; - Arc::new(default_group_configuration) + Arc::new(default_configuration) } Some(configuration) => configuration, }; @@ -134,47 +133,100 @@ where } } - pub(crate) fn merge_groups(&mut self, groups: Vec) -> FlowyResult> { + pub(crate) fn init_group_revs( + &mut self, + generated_groups: Vec, + ) -> FlowyResult> { + let mut new_groups = vec![]; + let mut filter_content_map = HashMap::new(); + generated_groups.into_iter().for_each(|generate_group| { + filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content); + new_groups.push(generate_group.group_rev); + }); + let MergeGroupResult { - groups, - inserted_groups, - updated_groups, - } = merge_groups(&self.configuration.groups, groups); + mut all_group_revs, + new_group_revs, + updated_group_revs: _, + deleted_group_revs, + } = merge_groups(&self.configuration.groups, new_groups); - let group_revs = groups + let deleted_group_ids = deleted_group_revs .iter() - .map(|group| GroupRevision::new(group.id.clone(), group.name.clone())) - .collect::>(); + .map(|group_rev| group_rev.id) + .collect::>(); - self.mut_configuration(move |configuration| { + self.mut_configuration(|configuration| { let mut is_changed = false; - for new_group_rev in group_revs { + if !deleted_group_ids.is_empty() { + configuration + .groups + .retain(|group| !deleted_group_ids.contains(&group.id)); + is_changed = true; + } + + for mut group_rev in &mut all_group_revs { match configuration .groups .iter() - .position(|group_rev| group_rev.id == new_group_rev.id) + .position(|old_group_rev| old_group_rev.id == group_rev.id) { None => { - configuration.groups.push(new_group_rev); + configuration.groups.push(group_rev.clone()); is_changed = true; } Some(pos) => { - let removed_group = configuration.groups.remove(pos); - if removed_group != new_group_rev { + let mut old_group = configuration.groups.remove(pos); + // Update the group configuration base on the GroupRevision + group_rev.visible = old_group.visible; + + // Take the GroupRevision if the name has changed + if is_group_changed(&group_rev, &old_group) { + old_group.name = group_rev.name.clone(); is_changed = true; + configuration.groups.insert(pos, old_group); } - configuration.groups.insert(pos, new_group_rev); } } } is_changed })?; - groups.into_iter().for_each(|group| { - self.groups_map.insert(group.id.clone(), group); + debug_assert_eq!(filter_content_map.len(), all_group_revs.len()); + all_group_revs.into_iter().for_each(|group_rev| { + if let Some(filter_content) = filter_content_map.get(&group_rev.id) { + let group = Group::new( + group_rev.id, + self.field_rev.id.clone(), + group_rev.name, + filter_content.clone(), + ); + self.groups_map.insert(group.id.clone(), group); + } }); - let changeset = make_group_view_changeset(self.view_id.clone(), inserted_groups, updated_groups); + let new_groups = new_group_revs + .into_iter() + .map(|group_rev| { + if let Some(filter_content) = filter_content_map.get(&group_rev.id) { + let group = Group::new( + group_rev.id, + self.field_rev.id.clone(), + group_rev.name, + filter_content.clone(), + ); + GroupPB::from(group) + } + }) + .collect(); + + let changeset = GroupViewChangesetPB { + view_id, + new_groups, + deleted_groups: deleted_group_ids, + update_groups: vec![], + inserted_groups: vec![], + }; tracing::trace!("Group changeset: {:?}", changeset); if changeset.is_empty() { Ok(None) @@ -221,10 +273,7 @@ where let field_id = self.field_rev.id.clone(); let field_type = self.field_rev.ty; tokio::spawn(async move { - match writer - .save_group_configuration(&field_id, field_type, configuration) - .await - { + match writer.save_configuration(&field_id, field_type, configuration).await { Ok(_) => {} Err(e) => { tracing::error!("Save group configuration failed: {}", e); @@ -260,82 +309,63 @@ where } } -fn merge_groups(old_groups: &[GroupRevision], groups: Vec) -> MergeGroupResult { +fn merge_groups(old_groups: &[GroupRevision], new_groups: Vec) -> MergeGroupResult { let mut merge_result = MergeGroupResult::new(); if old_groups.is_empty() { - merge_result.groups = groups; + merge_result.all_group_revs = new_groups; return merge_result; } // group_map is a helper map is used to filter out the new groups. - let mut group_map: IndexMap = IndexMap::new(); - groups.into_iter().for_each(|group| { - group_map.insert(group.id.clone(), group); + let mut new_group_map: IndexMap = IndexMap::new(); + new_groups.into_iter().for_each(|group_rev| { + new_group_map.insert(group_rev.id.clone(), group_rev); }); // The group is ordered in old groups. Add them before adding the new groups - for group_rev in old_groups { - if let Some(group) = group_map.remove(&group_rev.id) { - if group.name == group_rev.name { - merge_result.add_group(group); - } else { - merge_result.add_updated_group(group); + for old in old_groups { + if let Some(new) = new_group_map.remove(&old.id) { + merge_result.all_group_revs.push(new.clone()); + if is_group_changed(&new, old) { + merge_result.updated_group_revs.push(new); } + } else { + merge_result.deleted_group_revs.push(old.clone()); } } // Find out the new groups - group_map - .into_values() - .enumerate() - .for_each(|(index, group)| merge_result.add_insert_group(index, group)); - + let new_groups = new_group_map.into_values(); + for (_, group) in new_groups.into_iter().enumerate() { + merge_result.all_group_revs.push(group.clone()); + merge_result.new_group_revs.push(group); + } merge_result } +fn is_group_changed(new: &GroupRevision, old: &GroupRevision) -> bool { + if new.name != old.name { + return true; + } + + false +} + struct MergeGroupResult { - groups: Vec, - inserted_groups: Vec, - updated_groups: Vec, + // Contains the new groups and the updated groups + all_group_revs: Vec, + new_group_revs: Vec, + updated_group_revs: Vec, + deleted_group_revs: Vec, } impl MergeGroupResult { fn new() -> Self { Self { - groups: vec![], - inserted_groups: vec![], - updated_groups: vec![], + all_group_revs: vec![], + new_group_revs: vec![], + updated_group_revs: vec![], + deleted_group_revs: vec![], } } - - fn add_updated_group(&mut self, group: Group) { - self.groups.push(group.clone()); - self.updated_groups.push(group); - } - - fn add_group(&mut self, group: Group) { - self.groups.push(group); - } - - fn add_insert_group(&mut self, index: usize, group: Group) { - self.groups.push(group.clone()); - let inserted_group = InsertedGroupPB { - group: GroupPB::from(group), - index: index as i32, - }; - self.inserted_groups.push(inserted_group); - } -} - -fn make_group_view_changeset( - view_id: String, - inserted_groups: Vec, - updated_group: Vec, -) -> GroupViewChangesetPB { - GroupViewChangesetPB { - view_id, - inserted_groups, - deleted_groups: vec![], - update_groups: updated_group.into_iter().map(GroupPB::from).collect(), - } } 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 62647d44b8..5bcff652a4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -1,11 +1,11 @@ use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB}; use crate::services::cell::{decode_any_cell_data, CellBytesParser}; use crate::services::group::action::GroupAction; -use crate::services::group::configuration::GenericGroupConfiguration; +use crate::services::group::configuration::GroupContext; use crate::services::group::entities::Group; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{ - FieldRevision, GroupConfigurationContentSerde, RowChangeset, RowRevision, TypeOptionDataDeserializer, + FieldRevision, GroupConfigurationContentSerde, GroupRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer, }; use std::marker::PhantomData; @@ -19,14 +19,19 @@ pub trait GroupController: GroupControllerSharedOperation + Send + Sync { } pub trait GroupGenerator { - type ConfigurationType; + type Context; type TypeOptionType; fn generate_groups( field_id: &str, - configuration: &Self::ConfigurationType, + group_ctx: &Self::Context, type_option: &Option, - ) -> Vec; + ) -> Vec; +} + +pub struct GeneratedGroup { + pub group_rev: GroupRevision, + pub filter_content: String, } pub struct MoveGroupRowContext<'a> { @@ -43,7 +48,7 @@ pub trait GroupControllerSharedOperation: Send + Sync { 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 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, @@ -69,7 +74,7 @@ pub trait GroupControllerSharedOperation: Send + Sync { pub struct GenericGroupController { pub field_id: String, pub type_option: Option, - pub configuration: GenericGroupConfiguration, + pub configuration: GroupContext, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData

, } @@ -78,16 +83,13 @@ impl GenericGroupController where C: GroupConfigurationContentSerde, T: TypeOptionDataDeserializer, - G: GroupGenerator, TypeOptionType = T>, + G: GroupGenerator, TypeOptionType = T>, { - pub async fn new( - field_rev: &Arc, - mut configuration: GenericGroupConfiguration, - ) -> FlowyResult { + pub async fn new(field_rev: &Arc, mut configuration: GroupContext) -> FlowyResult { 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)?; + let _ = configuration.init_group_revs(groups)?; Ok(Self { field_id: field_rev.id.clone(), @@ -171,7 +173,7 @@ where P: CellBytesParser, C: GroupConfigurationContentSerde, T: TypeOptionDataDeserializer, - G: GroupGenerator, TypeOptionType = T>, + G: GroupGenerator, TypeOptionType = T>, Self: GroupAction, { @@ -189,14 +191,14 @@ where } #[tracing::instrument(level = "trace", skip_all, fields(row_count=%row_revs.len(), group_result))] - fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult> { + 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 grouped_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.configuration.concrete_groups() { - if self.can_group(&group.content, &cell_data) { + if self.can_group(&group.filter_content, &cell_data) { grouped_rows.push(GroupedRow { row: row_rev.into(), group_id: group.id.clone(), @@ -219,7 +221,7 @@ where } tracing::Span::current().record("group_result", &format!("{},", self.configuration,).as_str()); - Ok(self.groups()) + Ok(()) } fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { @@ -274,7 +276,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, &self.configuration, &type_option); - let changeset = self.configuration.merge_groups(groups)?; + let changeset = self.configuration.init_group_revs(groups)?; Ok(changeset) } } 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 4c06ba63ce..cfae74ecc3 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,14 @@ use crate::entities::GroupChangesetPB; 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::configuration::GroupContext; use crate::services::group::controller::{ GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, }; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, RowRevision}; +use crate::services::group::GeneratedGroup; +use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision}; pub type CheckboxGroupController = GenericGroupController< CheckboxGroupConfigurationRevision, @@ -16,7 +17,7 @@ pub type CheckboxGroupController = GenericGroupController< CheckboxCellDataParser, >; -pub type CheckboxGroupConfiguration = GenericGroupConfiguration; +pub type CheckboxGroupContext = GroupContext; impl GroupAction for CheckboxGroupController { type CellDataType = CheckboxCellData; @@ -49,26 +50,23 @@ impl GroupController for CheckboxGroupController { pub struct CheckboxGroupGenerator(); impl GroupGenerator for CheckboxGroupGenerator { - type ConfigurationType = CheckboxGroupConfiguration; + type Context = CheckboxGroupContext; type TypeOptionType = CheckboxTypeOptionPB; fn generate_groups( field_id: &str, - _configuration: &Self::ConfigurationType, - _type_option: &Option, - ) -> Vec { - let check_group = Group::new( - "true".to_string(), - field_id.to_owned(), - "".to_string(), - CHECK.to_string(), - ); - let uncheck_group = Group::new( - "false".to_string(), - field_id.to_owned(), - "".to_string(), - UNCHECK.to_string(), - ); + group_ctx: &Self::Context, + type_option: &Option, + ) -> Vec { + let check_group = GeneratedGroup { + group_rev: GroupRevision::new("true".to_string(), CHECK.to_string()), + filter_content: "".to_string(), + }; + + let uncheck_group = GeneratedGroup { + group_rev: GroupRevision::new("false".to_string(), UNCHECK.to_string()), + filter_content: "".to_string(), + }; vec![check_group, uncheck_group] } } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs new file mode 100644 index 0000000000..ff934118ca --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs @@ -0,0 +1,80 @@ +use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB}; +use crate::services::group::{Group, GroupController, GroupControllerSharedOperation, MoveGroupRowContext}; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; +use std::sync::Arc; + +pub struct DefaultGroupController { + pub field_id: String, + pub group: Group, +} + +const DEFAULT_GROUP_CONTROLLER: &str = "DefaultGroupController"; + +impl DefaultGroupController { + pub fn new(field_rev: &Arc) -> Self { + let group = Group::new( + DEFAULT_GROUP_CONTROLLER.to_owned(), + field_rev.id.clone(), + "Oops".to_owned(), + "".to_owned(), + ); + Self { + field_id: field_rev.id.clone(), + group, + } + } +} + +impl GroupControllerSharedOperation for DefaultGroupController { + fn field_id(&self) -> &str { + &self.field_id + } + + fn groups(&self) -> Vec { + vec![self.group.clone()] + } + + fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { + Some((0, self.group.clone())) + } + + fn fill_groups(&mut self, row_revs: &[Arc], field_rev: &FieldRevision) -> FlowyResult<()> { + row_revs.iter().for_each(|row_rev| { + self.group.add_row(RowPB::from(row_rev)); + }); + Ok(()) + } + + fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { + Ok(()) + } + + fn did_update_row( + &mut self, + row_rev: &RowRevision, + field_rev: &FieldRevision, + ) -> FlowyResult> { + todo!() + } + + fn did_delete_row( + &mut self, + row_rev: &RowRevision, + field_rev: &FieldRevision, + ) -> FlowyResult> { + todo!() + } + + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult> { + todo!() + } + + fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult> { + Ok(None) + } +} + +impl GroupController for DefaultGroupController { + fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {} +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs index 974f311a48..512be761e9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/mod.rs @@ -1,5 +1,7 @@ mod checkbox_controller; +mod default_controller; mod select_option_controller; pub use checkbox_controller::*; +pub use default_controller::*; pub use select_option_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 index fe90e1b462..678c53b28d 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 @@ -8,7 +8,10 @@ use crate::services::group::controller::{ }; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; +use crate::services::group::GeneratedGroup; +use flowy_grid_data_model::revision::{ + FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision, +}; // MultiSelect pub type MultiSelectGroupController = GenericGroupController< @@ -28,7 +31,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.configuration.iter_mut_groups(|group| { - if let Some(changeset) = add_row(group, cell_data, row_rev) { + if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } }); @@ -38,7 +41,7 @@ impl GroupAction for MultiSelectGroupController { fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.configuration.iter_mut_groups(|group| { - if let Some(changeset) = remove_row(group, cell_data, row_rev) { + if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } }); @@ -70,27 +73,16 @@ impl GroupController for MultiSelectGroupController { pub struct MultiSelectGroupGenerator(); impl GroupGenerator for MultiSelectGroupGenerator { - type ConfigurationType = SelectOptionGroupConfiguration; + type Context = SelectOptionGroupContext; type TypeOptionType = MultiSelectTypeOptionPB; fn generate_groups( field_id: &str, - _configuration: &Self::ConfigurationType, + group_ctx: &Self::Context, type_option: &Option, - ) -> Vec { + ) -> 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(), + Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options), } } } 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 d774ab083f..b2bffed4ec 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 @@ -9,7 +9,10 @@ use crate::services::group::controller::{ use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; +use crate::services::group::GeneratedGroup; +use flowy_grid_data_model::revision::{ + FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision, +}; // SingleSelect pub type SingleSelectGroupController = GenericGroupController< @@ -28,7 +31,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.configuration.iter_mut_groups(|group| { - if let Some(changeset) = add_row(group, cell_data, row_rev) { + if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } }); @@ -38,7 +41,7 @@ impl GroupAction for SingleSelectGroupController { fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.configuration.iter_mut_groups(|group| { - if let Some(changeset) = remove_row(group, cell_data, row_rev) { + if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } }); @@ -72,27 +75,16 @@ impl GroupController for SingleSelectGroupController { pub struct SingleSelectGroupGenerator(); impl GroupGenerator for SingleSelectGroupGenerator { - type ConfigurationType = SelectOptionGroupConfiguration; + type Context = SelectOptionGroupContext; type TypeOptionType = SingleSelectTypeOptionPB; fn generate_groups( field_id: &str, - _configuration: &Self::ConfigurationType, + group_ctx: &Self::Context, type_option: &Option, - ) -> Vec { + ) -> 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(), + Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options), } } } 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 39f581d97d..c60eec49a5 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,15 +1,15 @@ use crate::entities::{GroupChangesetPB, InsertedRowPB, RowPB}; use crate::services::cell::insert_select_option_cell; -use crate::services::field::SelectOptionCellDataPB; -use crate::services::group::configuration::GenericGroupConfiguration; -use crate::services::group::Group; +use crate::services::field::{SelectOptionCellDataPB, SelectOptionPB}; +use crate::services::group::configuration::GroupContext; +use crate::services::group::{GeneratedGroup, Group}; use crate::services::group::controller::MoveGroupRowContext; -use flowy_grid_data_model::revision::{RowRevision, SelectOptionGroupConfigurationRevision}; +use flowy_grid_data_model::revision::{GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision}; -pub type SelectOptionGroupConfiguration = GenericGroupConfiguration; +pub type SelectOptionGroupContext = GroupContext; -pub fn add_row( +pub fn add_select_option_row( group: &mut Group, cell_data: &SelectOptionCellDataPB, row_rev: &RowRevision, @@ -42,7 +42,7 @@ pub fn add_row( } } -pub fn remove_row( +pub fn remove_select_option_row( group: &mut Group, cell_data: &SelectOptionCellDataPB, row_rev: &RowRevision, @@ -125,3 +125,19 @@ pub fn move_select_option_row( Some(changeset) } } + +pub fn generate_select_option_groups( + field_id: &str, + group_ctx: &SelectOptionGroupContext, + options: &[SelectOptionPB], +) -> Vec { + let groups = options + .iter() + .map(|option| GeneratedGroup { + group_rev: GroupRevision::new(option.id.clone(), option.name.clone()), + filter_content: option.id.clone(), + }) + .collect(); + + groups +} diff --git a/frontend/rust-lib/flowy-grid/src/services/group/entities.rs b/frontend/rust-lib/flowy-grid/src/services/group/entities.rs index 9afe7f54e9..c4687859f3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/entities.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/entities.rs @@ -6,21 +6,23 @@ pub struct Group { pub field_id: String, pub name: String, pub is_default: bool, + pub is_visible: bool, pub(crate) rows: Vec, /// [content] is used to determine which group the cell belongs to. - pub content: String, + pub filter_content: String, } impl Group { - pub fn new(id: String, field_id: String, name: String, content: String) -> Self { + pub fn new(id: String, field_id: String, name: String, filter_content: String) -> Self { Self { id, field_id, is_default: false, + is_visible: true, name, rows: vec![], - content, + filter_content, } } 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 deleted file mode 100644 index 8cdae4c359..0000000000 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_service.rs +++ /dev/null @@ -1,361 +0,0 @@ -use crate::entities::{FieldType, GroupChangesetPB, GroupViewChangesetPB}; -use crate::services::group::configuration::GroupConfigurationReader; -use crate::services::group::controller::{GroupController, MoveGroupRowContext}; -use crate::services::group::{ - CheckboxGroupConfiguration, CheckboxGroupController, Group, GroupConfigurationWriter, MultiSelectGroupController, - SelectOptionGroupConfiguration, SingleSelectGroupController, -}; -use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::{ - CheckboxGroupConfigurationRevision, DateGroupConfigurationRevision, FieldRevision, GroupConfigurationRevision, - NumberGroupConfigurationRevision, RowChangeset, RowRevision, SelectOptionGroupConfigurationRevision, - TextGroupConfigurationRevision, UrlGroupConfigurationRevision, -}; -use std::future::Future; -use std::sync::Arc; - -pub(crate) struct GroupService { - view_id: String, - configuration_reader: Arc, - configuration_writer: Arc, - group_controller: Option>, -} - -impl GroupService { - pub(crate) async fn new(view_id: String, configuration_reader: R, configuration_writer: W) -> Self - where - R: GroupConfigurationReader, - W: GroupConfigurationWriter, - { - Self { - view_id, - configuration_reader: Arc::new(configuration_reader), - configuration_writer: Arc::new(configuration_writer), - group_controller: None, - } - } - - pub(crate) async fn groups(&self) -> Vec { - self.group_controller - .as_ref() - .map(|group_controller| group_controller.groups()) - .unwrap_or_default() - } - - pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { - self.group_controller - .as_ref() - .and_then(|group_controller| group_controller.get_group(group_id)) - } - - pub(crate) async fn load_groups( - &mut self, - field_revs: &[Arc], - row_revs: Vec>, - ) -> Option> { - let field_rev = find_group_field(field_revs)?; - let field_type: FieldType = field_rev.ty.into(); - - 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![] - } - }; - self.group_controller = Some(group_controller); - Some(groups) - } - - 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_mut() { - let field_id = group_controller.field_id().to_owned(); - match get_field_fn(field_id).await { - None => {} - Some(field_rev) => { - group_controller.will_create_row(row_rev, &field_rev, group_id); - } - } - } - } - - pub(crate) async fn did_delete_row( - &mut self, - row_rev: &RowRevision, - get_field_fn: F, - ) -> Option> - where - F: FnOnce(String) -> O, - O: Future>> + Send + Sync + 'static, - { - 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.did_delete_row(row_rev, &field_rev) { - Ok(changesets) => Some(changesets), - Err(e) => { - tracing::error!("Delete group data failed, {:?}", e); - None - } - } - } - - pub(crate) async fn move_group_row( - &mut self, - row_rev: &RowRevision, - row_changeset: &mut RowChangeset, - 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_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.move_group_row(move_row_context) { - Ok(changesets) => Some(changesets), - Err(e) => { - tracing::error!("Move group data failed, {:?}", e); - None - } - } - } - - #[tracing::instrument(level = "trace", skip_all)] - pub(crate) async fn did_update_row( - &mut self, - row_rev: &RowRevision, - get_field_fn: F, - ) -> Option> - where - F: FnOnce(String) -> O, - O: Future>> + Send + Sync + 'static, - { - 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.did_update_row(row_rev, &field_rev) { - Ok(changeset) => Some(changeset), - Err(e) => { - tracing::error!("Update group data failed, {:?}", e); - None - } - } - } - - #[tracing::instrument(level = "trace", skip_all)] - 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.move_group(from_group_id, to_group_id)?; - Ok(()) - } - } - } - - #[tracing::instrument(level = "trace", name = "group_did_update_field", skip(self, field_rev), err)] - pub(crate) async fn did_update_field( - &mut self, - field_rev: &FieldRevision, - ) -> FlowyResult> { - match self.group_controller.as_mut() { - None => Ok(None), - Some(group_controller) => group_controller.did_update_field(field_rev), - } - } - - #[tracing::instrument(level = "trace", skip(self, field_rev), err)] - async fn make_group_controller( - &self, - field_type: &FieldType, - field_rev: &Arc, - ) -> FlowyResult>> { - let mut group_controller: Option> = None; - match field_type { - FieldType::RichText => { - // let generator = GroupGenerator::::from_configuration(configuration); - } - FieldType::Number => { - // let generator = GroupGenerator::::from_configuration(configuration); - } - FieldType::DateTime => { - // let generator = GroupGenerator::::from_configuration(configuration); - } - FieldType::SingleSelect => { - let configuration = SelectOptionGroupConfiguration::new( - self.view_id.clone(), - field_rev.clone(), - self.configuration_reader.clone(), - self.configuration_writer.clone(), - ) - .await?; - let controller = SingleSelectGroupController::new(field_rev, configuration).await?; - group_controller = Some(Box::new(controller)); - } - FieldType::MultiSelect => { - let configuration = SelectOptionGroupConfiguration::new( - self.view_id.clone(), - field_rev.clone(), - self.configuration_reader.clone(), - self.configuration_writer.clone(), - ) - .await?; - let controller = MultiSelectGroupController::new(field_rev, configuration).await?; - group_controller = Some(Box::new(controller)); - } - FieldType::Checkbox => { - let configuration = CheckboxGroupConfiguration::new( - self.view_id.clone(), - field_rev.clone(), - self.configuration_reader.clone(), - self.configuration_writer.clone(), - ) - .await?; - let controller = CheckboxGroupController::new(field_rev, configuration).await?; - group_controller = Some(Box::new(controller)); - } - FieldType::URL => { - // let generator = GroupGenerator::::from_configuration(configuration); - } - } - Ok(group_controller) - } -} - -#[tracing::instrument(level = "trace", skip_all, err)] -pub async fn make_group_controller( - view_id: String, - field_revs: Vec>, - row_revs: Vec>, - configuration_reader: R, - configuration_writer: W, -) -> FlowyResult> -where - R: GroupConfigurationReader, - W: GroupConfigurationWriter, -{ - let field_rev = find_group_field(&field_revs)?; - let field_type: FieldType = field_rev.ty.into(); - let mut group_controller: Box; - match field_type { - FieldType::RichText => { - // let generator = GroupGenerator::::from_configuration(configuration); - panic!() - } - FieldType::Number => { - // let generator = GroupGenerator::::from_configuration(configuration); - panic!() - } - FieldType::DateTime => { - // let generator = GroupGenerator::::from_configuration(configuration); - panic!() - } - FieldType::SingleSelect => { - let configuration = SelectOptionGroupConfiguration::new( - view_id, - field_rev.clone(), - configuration_reader, - configuration_writer, - ) - .await?; - let controller = SingleSelectGroupController::new(&field_rev, configuration).await?; - group_controller = Box::new(controller); - } - FieldType::MultiSelect => { - let configuration = SelectOptionGroupConfiguration::new( - view_id, - field_rev.clone(), - configuration_reader, - configuration_writer, - ) - .await?; - let controller = MultiSelectGroupController::new(&field_rev, configuration).await?; - group_controller = Box::new(controller); - } - FieldType::Checkbox => { - let configuration = - CheckboxGroupConfiguration::new(view_id, field_rev.clone(), configuration_reader, configuration_writer) - .await?; - let controller = CheckboxGroupController::new(&field_rev, configuration).await?; - group_controller = Box::new(controller); - } - FieldType::URL => { - // let generator = GroupGenerator::::from_configuration(configuration); - panic!() - } - } - - let _ = group_controller.fill_groups(&row_revs, &field_rev)?; - - Ok(group_controller) -} - -fn find_group_field(field_revs: &[Arc]) -> Option> { - let field_rev = field_revs - .iter() - .find(|field_rev| { - let field_type: FieldType = field_rev.ty.into(); - field_type.can_be_group() - }) - .cloned(); - field_rev -} - -pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision { - let field_id = field_rev.id.clone(); - let field_type_rev = field_rev.ty; - let field_type: FieldType = field_rev.ty.into(); - 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/group/group_util.rs b/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs new file mode 100644 index 0000000000..1e2ea0f9d6 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs @@ -0,0 +1,113 @@ +use crate::entities::FieldType; +use crate::services::group::configuration::GroupConfigurationReader; +use crate::services::group::controller::GroupController; +use crate::services::group::{ + CheckboxGroupContext, CheckboxGroupController, DefaultGroupController, GroupConfigurationWriter, + MultiSelectGroupController, SelectOptionGroupContext, SingleSelectGroupController, +}; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::{ + CheckboxGroupConfigurationRevision, DateGroupConfigurationRevision, FieldRevision, GroupConfigurationRevision, + NumberGroupConfigurationRevision, RowRevision, SelectOptionGroupConfigurationRevision, + TextGroupConfigurationRevision, UrlGroupConfigurationRevision, +}; +use std::sync::Arc; + +#[tracing::instrument(level = "trace", skip_all, err)] +pub async fn make_group_controller( + view_id: String, + field_revs: Vec>, + row_revs: Vec>, + configuration_reader: R, + configuration_writer: W, +) -> FlowyResult> +where + R: GroupConfigurationReader, + W: GroupConfigurationWriter, +{ + let field_rev = find_group_field(&field_revs).unwrap(); + let field_type: FieldType = field_rev.ty.into(); + let mut group_controller: Box; + let configuration_reader = Arc::new(configuration_reader); + let configuration_writer = Arc::new(configuration_writer); + match field_type { + FieldType::SingleSelect => { + let configuration = + SelectOptionGroupContext::new(view_id, field_rev.clone(), configuration_reader, configuration_writer) + .await?; + let controller = SingleSelectGroupController::new(&field_rev, configuration).await?; + group_controller = Box::new(controller); + } + FieldType::MultiSelect => { + let configuration = + SelectOptionGroupContext::new(view_id, field_rev.clone(), configuration_reader, configuration_writer) + .await?; + let controller = MultiSelectGroupController::new(&field_rev, configuration).await?; + group_controller = Box::new(controller); + } + FieldType::Checkbox => { + let configuration = + CheckboxGroupContext::new(view_id, field_rev.clone(), configuration_reader, configuration_writer) + .await?; + let controller = CheckboxGroupController::new(&field_rev, configuration).await?; + group_controller = Box::new(controller); + } + _ => { + group_controller = Box::new(DefaultGroupController::new(&field_rev)); + } + } + + let _ = group_controller.fill_groups(&row_revs, &field_rev)?; + Ok(group_controller) +} + +fn find_group_field(field_revs: &[Arc]) -> Option> { + let field_rev = field_revs + .iter() + .find(|field_rev| { + let field_type: FieldType = field_rev.ty.into(); + field_type.can_be_group() + }) + .cloned(); + field_rev +} + +pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision { + let field_id = field_rev.id.clone(); + let field_type_rev = field_rev.ty; + let field_type: FieldType = field_rev.ty.into(); + 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/group/mod.rs b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs index 35c443f06b..b73ac511b6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs @@ -3,10 +3,10 @@ mod configuration; mod controller; mod controller_impls; mod entities; -mod group_service; +mod group_util; pub(crate) use configuration::*; pub(crate) use controller::*; pub(crate) use controller_impls::*; pub(crate) use entities::*; -pub(crate) use group_service::*; +pub(crate) use group_util::*; 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 297527b905..760f39b2ac 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 @@ -391,11 +391,11 @@ async fn group_update_field_test() { test.run_scripts(scripts).await; } -#[tokio::test] -async fn group_multi_select_field_test() { - let mut test = GridGroupTest::new().await; - let multi_select_field = test.get_multi_select_field().await; - - let scripts = vec![]; - test.run_scripts(scripts).await; -} +// #[tokio::test] +// async fn group_multi_select_field_test() { +// let mut test = GridGroupTest::new().await; +// let multi_select_field = test.get_multi_select_field().await; +// +// let scripts = vec![]; +// test.run_scripts(scripts).await; +// } 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 04b571fd76..e942de59c9 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,9 +4,8 @@ use serde_json::Error; use serde_repr::*; pub trait GroupConfigurationContentSerde: Sized + Send + Sync { - fn from_configuration_content(s: &str) -> Result; - - fn to_configuration_content(&self) -> Result; + fn from_json(s: &str) -> Result; + fn to_json(&self) -> Result; } #[derive(Debug, Clone, Serialize, Deserialize, Default)] @@ -15,6 +14,7 @@ pub struct GroupConfigurationRevision { pub field_id: String, pub field_type_rev: FieldTypeRevision, pub groups: Vec, + // This content is serde in Json format pub content: String, } @@ -23,7 +23,7 @@ impl GroupConfigurationRevision { where T: GroupConfigurationContentSerde, { - let content = content.to_configuration_content()?; + let content = content.to_json()?; Ok(Self { id: gen_grid_group_id(), field_id, @@ -40,10 +40,10 @@ pub struct TextGroupConfigurationRevision { } impl GroupConfigurationContentSerde for TextGroupConfigurationRevision { - fn from_configuration_content(s: &str) -> Result { + fn from_json(s: &str) -> Result { serde_json::from_str(s) } - fn to_configuration_content(&self) -> Result { + fn to_json(&self) -> Result { serde_json::to_string(self) } } @@ -54,10 +54,10 @@ pub struct NumberGroupConfigurationRevision { } impl GroupConfigurationContentSerde for NumberGroupConfigurationRevision { - fn from_configuration_content(s: &str) -> Result { + fn from_json(s: &str) -> Result { serde_json::from_str(s) } - fn to_configuration_content(&self) -> Result { + fn to_json(&self) -> Result { serde_json::to_string(self) } } @@ -68,10 +68,10 @@ pub struct UrlGroupConfigurationRevision { } impl GroupConfigurationContentSerde for UrlGroupConfigurationRevision { - fn from_configuration_content(s: &str) -> Result { + fn from_json(s: &str) -> Result { serde_json::from_str(s) } - fn to_configuration_content(&self) -> Result { + fn to_json(&self) -> Result { serde_json::to_string(self) } } @@ -82,11 +82,11 @@ pub struct CheckboxGroupConfigurationRevision { } impl GroupConfigurationContentSerde for CheckboxGroupConfigurationRevision { - fn from_configuration_content(s: &str) -> Result { + fn from_json(s: &str) -> Result { serde_json::from_str(s) } - fn to_configuration_content(&self) -> Result { + fn to_json(&self) -> Result { serde_json::to_string(self) } } @@ -97,11 +97,11 @@ pub struct SelectOptionGroupConfigurationRevision { } impl GroupConfigurationContentSerde for SelectOptionGroupConfigurationRevision { - fn from_configuration_content(s: &str) -> Result { + fn from_json(s: &str) -> Result { serde_json::from_str(s) } - fn to_configuration_content(&self) -> Result { + fn to_json(&self) -> Result { serde_json::to_string(self) } } @@ -113,22 +113,17 @@ pub struct GroupRevision { #[serde(default)] pub name: String, - #[serde(skip, default = "IS_DEFAULT_GROUP")] - pub is_default: bool, - #[serde(default = "GROUP_REV_VISIBILITY")] pub visible: bool, } const GROUP_REV_VISIBILITY: fn() -> bool = || true; -const IS_DEFAULT_GROUP: fn() -> bool = || false; impl GroupRevision { pub fn new(id: String, group_name: String) -> Self { Self { id, name: group_name, - is_default: false, visible: true, } } @@ -137,7 +132,6 @@ impl GroupRevision { Self { id, name: group_name, - is_default: true, visible: true, } } @@ -150,10 +144,10 @@ pub struct DateGroupConfigurationRevision { } impl GroupConfigurationContentSerde for DateGroupConfigurationRevision { - fn from_configuration_content(s: &str) -> Result { + fn from_json(s: &str) -> Result { serde_json::from_str(s) } - fn to_configuration_content(&self) -> Result { + fn to_json(&self) -> Result { serde_json::to_string(self) } }