From 1931cdd4c086b5936590779bae201f68a668f65b Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 1 Sep 2022 09:03:33 +0800 Subject: [PATCH 1/9] chore: support switch to multi select field --- .../flowy-grid/src/services/grid_editor.rs | 4 + .../src/services/grid_view_editor.rs | 84 +++++++++++++------ .../src/services/group/group_service.rs | 68 +++++++++++++++ .../flowy-grid/src/services/group/mod.rs | 1 + .../tests/grid/group_test/script.rs | 23 ++++- .../flowy-grid/tests/grid/group_test/test.rs | 9 ++ 6 files changed, 164 insertions(+), 25 deletions(-) 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 9ae7918955..176915fe1c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -207,6 +207,10 @@ impl GridRevisionEditor { Ok(()) } + pub async fn group_field(&self, field_id: &str) -> FlowyResult<()> { + todo!() + } + pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> { // let block_ids = self // .get_block_metas() 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 688a844707..f598f5bb0b 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 @@ -6,7 +6,9 @@ use crate::entities::{ }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; -use crate::services::group::{GroupConfigurationReader, GroupConfigurationWriter, GroupService}; +use crate::services::group::{ + make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController, GroupService, +}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision, @@ -17,6 +19,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::future::Future; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -30,9 +33,8 @@ pub struct GridViewRevisionEditor { rev_manager: Arc, field_delegate: Arc, row_delegate: Arc, - group_service: Arc>, + group_controller: Arc>>, scheduler: Arc, - did_load_group: AtomicBool, } impl GridViewRevisionEditor { @@ -53,15 +55,25 @@ impl GridViewRevisionEditor { let pad = Arc::new(RwLock::new(view_revision_pad)); let rev_manager = Arc::new(rev_manager); + // Load group 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(view_id.clone(), configuration_reader, configuration_writer).await; + let field_revs = field_delegate.get_field_revs().await; + let row_revs = row_delegate.gv_row_revs().await; + let group_controller = make_group_controller( + view_id.clone(), + field_revs, + row_revs, + configuration_reader, + configuration_writer, + ) + .await?; + let user_id = user_id.to_owned(); - let did_load_group = AtomicBool::new(false); Ok(Self { pad, user_id, @@ -70,8 +82,7 @@ impl GridViewRevisionEditor { scheduler, field_delegate, row_delegate, - group_service: Arc::new(RwLock::new(group_service)), - did_load_group, + group_controller: Arc::new(RwLock::new(group_controller)), }) } @@ -112,33 +123,58 @@ impl GridViewRevisionEditor { pub(crate) async fn did_delete_row(&self, row_rev: &RowRevision) { // Send the group notification if the current view has groups; - if let Some(changesets) = self - .group_service - .write() - .await - .did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) - .await - { + 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 + }); + } + + 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 { for changeset in changesets { self.notify_did_update_group(changeset).await; } } } - pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) { - if let Some(changesets) = self - .group_service - .write() - .await - .did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id)) - .await - { - 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) } } } + 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, 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 c7d67f65d6..8cdae4c359 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 @@ -241,6 +241,74 @@ impl GroupService { } } +#[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() 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 2bc979c28d..35c443f06b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/mod.rs @@ -6,6 +6,7 @@ mod entities; mod group_service; pub(crate) use configuration::*; +pub(crate) use controller::*; pub(crate) use controller_impls::*; pub(crate) use entities::*; pub(crate) use group_service::*; 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 6afeda6d4b..e779844d46 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 @@ -3,7 +3,8 @@ use flowy_grid::entities::{ CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB, }; use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell}; -use flowy_grid_data_model::revision::RowChangeset; +use flowy_grid_data_model::revision::{FieldRevision, RowChangeset}; +use std::sync::Arc; use std::time::Duration; use tokio::time::interval; @@ -47,6 +48,9 @@ pub enum GroupScript { UpdateField { changeset: FieldChangesetParams, }, + GroupField { + field_id: String, + }, } pub struct GridGroupTest { @@ -179,6 +183,9 @@ impl GridGroupTest { let mut interval = interval(Duration::from_millis(130)); interval.tick().await; } + GroupScript::GroupField { field_id } => { + self.editor.group_field(&field_id).await.unwrap(); + } } } @@ -191,6 +198,20 @@ impl GridGroupTest { let groups = self.group_at_index(group_index).await; groups.rows.get(row_index).unwrap().clone() } + + pub async fn get_multi_select_field(&self) -> Arc { + let field = self + .inner + .field_revs + .iter() + .find(|field_rev| { + let field_type: FieldType = field_rev.ty.into(); + field_type.is_multi_select() + }) + .unwrap() + .clone(); + return field; + } } impl std::ops::Deref for GridGroupTest { 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 a52a088f51..297527b905 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 @@ -390,3 +390,12 @@ 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; +} From f192f89ebb098822089b4e0dc350ee180533d2d1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 1 Sep 2022 20:41:15 +0800 Subject: [PATCH 2/9] 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) } } From e75d8f22c8e9cb179ece02a1e20b89d4eee065e7 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 2 Sep 2022 09:49:26 +0800 Subject: [PATCH 3/9] chore: add edit field type option helper --- .../group_entities/group_changeset.rs | 6 +-- .../rust-lib/flowy-grid/src/event_handler.rs | 12 +++-- frontend/rust-lib/flowy-grid/src/macros.rs | 6 +-- .../src/services/cell/cell_operation.rs | 14 +++--- .../src/services/field/field_builder.rs | 6 +-- .../src/services/field/field_operation.rs | 47 +++++++++++++++++++ .../flowy-grid/src/services/field/mod.rs | 2 + .../checkbox_type_option.rs | 4 +- .../date_type_option/date_type_option.rs | 4 +- .../number_type_option/number_type_option.rs | 4 +- .../multi_select_type_option.rs | 4 +- .../selection_type_option/select_option.rs | 4 +- .../single_select_type_option.rs | 4 +- .../text_type_option/text_type_option.rs | 4 +- .../url_type_option/url_type_option.rs | 4 +- .../src/services/filter/filter_service.rs | 14 +++--- .../flowy-grid/src/services/grid_editor.rs | 10 +++- .../src/services/group/configuration.rs | 29 ++++++------ .../src/services/group/controller.rs | 4 +- .../tests/grid/block_test/script.rs | 2 +- .../flowy-grid/tests/grid/field_test/test.rs | 4 +- .../flowy-grid/tests/grid/field_test/util.rs | 4 +- .../flowy-grid/tests/grid/grid_test.rs | 2 +- .../tests/grid/group_test/script.rs | 23 +++++++++ .../rust-lib/flowy-grid/tests/grid/script.rs | 2 +- .../src/revision/grid_rev.rs | 10 ++-- .../src/revision/group_rev.rs | 4 ++ 27 files changed, 158 insertions(+), 75 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs 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 3d37a6ffa4..fd49709cf3 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,13 +133,13 @@ pub struct GroupViewChangesetPB { #[pb(index = 2)] pub inserted_groups: Vec, - #[pb(index = 2)] + #[pb(index = 3)] pub new_groups: Vec, - #[pb(index = 3)] + #[pb(index = 4)] pub deleted_groups: Vec, - #[pb(index = 4)] + #[pb(index = 5)] pub update_groups: Vec, } diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 4b525c233f..8a04b2ea30 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -203,12 +203,14 @@ pub(crate) async fn move_field_handler( /// The FieldMeta contains multiple data, each of them belongs to a specific FieldType. async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType) -> FlowyResult> { - let s = field_rev - .get_type_option_str(field_type) - .unwrap_or_else(|| default_type_option_builder_from_type(field_type).entry().json_str()); + let s = field_rev.get_type_option_str(field_type).unwrap_or_else(|| { + default_type_option_builder_from_type(field_type) + .data_format() + .json_str() + }); let field_type: FieldType = field_rev.ty.into(); let builder = type_option_builder_from_json_str(&s, &field_type); - let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let type_option_data = builder.data_format().protobuf_bytes().to_vec(); Ok(type_option_data) } @@ -337,7 +339,7 @@ pub(crate) async fn update_select_option_handler( type_option.delete_option(option); } - mut_field_rev.insert_type_option_entry(&*type_option); + mut_field_rev.insert_type_option(&*type_option); let _ = editor.replace_field(field_rev).await?; if let Some(cell_content_changeset) = cell_content_changeset { diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index aee8ca2b68..bee2e95e21 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -30,7 +30,7 @@ macro_rules! impl_type_option { ($target: ident, $field_type:expr) => { impl std::convert::From<&FieldRevision> for $target { fn from(field_rev: &FieldRevision) -> $target { - match field_rev.get_type_option_entry::<$target>($field_type.into()) { + match field_rev.get_type_option::<$target>($field_type.into()) { None => $target::default(), Some(target) => target, } @@ -39,7 +39,7 @@ macro_rules! impl_type_option { impl std::convert::From<&std::sync::Arc> for $target { fn from(field_rev: &std::sync::Arc) -> $target { - match field_rev.get_type_option_entry::<$target>($field_type.into()) { + match field_rev.get_type_option::<$target>($field_type.into()) { None => $target::default(), Some(target) => target, } @@ -52,7 +52,7 @@ macro_rules! impl_type_option { } } - impl TypeOptionDataEntry for $target { + impl TypeOptionDataFormat for $target { fn json_str(&self) -> String { match serde_json::to_string(&self) { Ok(s) => s, diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs b/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs index ecff3b951b..17c52dd3a2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs @@ -101,25 +101,25 @@ pub fn try_decode_cell_data( let field_type: FieldTypeRevision = t_field_type.into(); let data = match t_field_type { FieldType::RichText => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::Number => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::DateTime => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::SingleSelect => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::MultiSelect => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::Checkbox => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), FieldType::URL => field_rev - .get_type_option_entry::(field_type)? + .get_type_option::(field_type)? .decode_cell_data(cell_data.into(), s_field_type, field_rev), }; Some(data) diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index 0242a5ca43..4a1d57c28f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -1,7 +1,7 @@ use crate::entities::{FieldPB, FieldType}; use crate::services::field::type_options::*; use bytes::Bytes; -use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataFormat}; use indexmap::IndexMap; pub struct FieldBuilder { @@ -78,14 +78,14 @@ impl FieldBuilder { pub fn build(self) -> FieldRevision { let mut field_rev = self.field_rev; - field_rev.insert_type_option_entry(self.type_option_builder.entry()); + field_rev.insert_type_option(self.type_option_builder.data_format()); field_rev } } pub trait TypeOptionBuilder { fn field_type(&self) -> FieldType; - fn entry(&self) -> &dyn TypeOptionDataEntry; + fn data_format(&self) -> &dyn TypeOptionDataFormat; } pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs new file mode 100644 index 0000000000..7ee127b382 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs @@ -0,0 +1,47 @@ +use crate::entities::{FieldChangesetParams, FieldType}; +use crate::services::field::{select_option_operation, SelectOptionPB}; +use crate::services::grid_editor::GridRevisionEditor; +use flowy_error::FlowyResult; +use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; +use std::sync::Arc; + +pub async fn edit_field( + field_id: &str, + editor: Arc, + action: impl FnOnce(&mut T) -> bool, +) -> FlowyResult<()> +where + T: TypeOptionDataDeserializer + TypeOptionDataFormat, +{ + let get_type_option = async { + let field_rev = editor.get_field_rev(field_id).await?; + field_rev.get_type_option::(field_rev.ty) + }; + + if let Some(mut type_option) = get_type_option.await { + if action(&mut type_option) { + let changeset = FieldChangesetParams { ..Default::default() }; + let _ = editor.update_field(changeset).await?; + } + } + + Ok(()) +} + +pub fn insert_single_select_option(field_rev: &mut FieldRevision, options: Vec) -> FlowyResult<()> { + if options.is_empty() { + return Ok(()); + } + let mut type_option = select_option_operation(field_rev)?; + options.into_iter().for_each(|option| type_option.insert_option(option)); + Ok(()) +} + +pub fn insert_multi_select_option(field_rev: &mut FieldRevision, options: Vec) -> FlowyResult<()> { + if options.is_empty() { + return Ok(()); + } + let mut type_option = select_option_operation(field_rev)?; + options.into_iter().for_each(|option| type_option.insert_option(option)); + Ok(()) +} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs index c1b689fbf4..5e8a461541 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs @@ -1,5 +1,7 @@ mod field_builder; +mod field_operation; pub(crate) mod type_options; pub use field_builder::*; +pub use field_operation::*; pub use type_options::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs index cf668fcc1e..fbb1ba64e8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs @@ -5,7 +5,7 @@ use crate::services::field::{BoxTypeOptionBuilder, CheckboxCellData, TypeOptionB use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -26,7 +26,7 @@ impl TypeOptionBuilder for CheckboxTypeOptionBuilder { FieldType::Checkbox } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs index 729ae1958a..e4ac22f299 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs @@ -9,7 +9,7 @@ use chrono::format::strftime::StrftimeItems; use chrono::{NaiveDateTime, Timelike}; use flowy_derive::ProtoBuf; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use serde::{Deserialize, Serialize}; // Date @@ -189,7 +189,7 @@ impl TypeOptionBuilder for DateTypeOptionBuilder { FieldType::DateTime } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs index cdb1118385..fe4ddcf5fa 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs @@ -6,7 +6,7 @@ use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBui use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use rust_decimal::Decimal; @@ -45,7 +45,7 @@ impl TypeOptionBuilder for NumberTypeOptionBuilder { FieldType::Number } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs index 75f654507d..967a65e60e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs @@ -9,7 +9,7 @@ use crate::services::field::{ use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use serde::{Deserialize, Serialize}; // Multiple select @@ -108,7 +108,7 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { FieldType::MultiSelect } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs index dcec7772a7..ff579f8172 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs @@ -5,7 +5,7 @@ use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{internal_error, ErrorCode, FlowyResult}; use flowy_grid_data_model::parser::NotEmptyStr; -use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataFormat}; use nanoid::nanoid; use serde::{Deserialize, Serialize}; @@ -75,7 +75,7 @@ pub fn make_selected_select_options( } } -pub trait SelectOptionOperation: TypeOptionDataEntry + Send + Sync { +pub trait SelectOptionOperation: TypeOptionDataFormat + Send + Sync { fn insert_option(&mut self, new_option: SelectOptionPB) { let options = self.mut_options(); if let Some(index) = options diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs index 287d0c3217..23d3c02b69 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs @@ -9,7 +9,7 @@ use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use serde::{Deserialize, Serialize}; // Single select @@ -91,7 +91,7 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder { FieldType::SingleSelect } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs index 6c50ce8da3..33c1f7eb9e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs @@ -8,7 +8,7 @@ use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use serde::{Deserialize, Serialize}; #[derive(Default)] @@ -21,7 +21,7 @@ impl TypeOptionBuilder for RichTextTypeOptionBuilder { FieldType::RichText } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs index adbc91b4f0..d34dfc12d3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs @@ -6,7 +6,7 @@ use bytes::Bytes; use fancy_regex::Regex; use flowy_derive::ProtoBuf; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataEntry}; +use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; @@ -20,7 +20,7 @@ impl TypeOptionBuilder for URLTypeOptionBuilder { FieldType::URL } - fn entry(&self) -> &dyn TypeOptionDataEntry { + fn data_format(&self) -> &dyn TypeOptionDataFormat { &self.0 } } 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 8335a36fb2..173dc8ffea 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 @@ -188,7 +188,7 @@ fn filter_cell( FieldType::RichText => filter_cache.text_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) @@ -196,7 +196,7 @@ fn filter_cell( FieldType::Number => filter_cache.number_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) @@ -204,7 +204,7 @@ fn filter_cell( FieldType::DateTime => filter_cache.date_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) @@ -212,7 +212,7 @@ fn filter_cell( FieldType::SingleSelect => filter_cache.select_option_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) @@ -220,7 +220,7 @@ fn filter_cell( FieldType::MultiSelect => filter_cache.select_option_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) @@ -228,7 +228,7 @@ fn filter_cell( FieldType::Checkbox => filter_cache.checkbox_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) @@ -236,7 +236,7 @@ fn filter_cell( FieldType::URL => filter_cache.url_filter.get(&filter_id).and_then(|filter| { Some( field_rev - .get_type_option_entry::(field_type_rev)? + .get_type_option::(field_type_rev)? .apply_filter(any_cell_data, filter.value()) .ok(), ) 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 176915fe1c..11e8cb139f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -179,6 +179,10 @@ impl GridRevisionEditor { None => Err(ErrorCode::FieldDoesNotExist.into()), Some(field_type) => { let _ = self.update_field_rev(params, field_type).await?; + match self.view_manager.did_update_field(&field_id).await { + Ok(_) => {} + Err(e) => tracing::error!("View manager update field failed: {:?}", e), + } let _ = self.notify_did_update_grid_field(&field_id).await?; Ok(()) } @@ -225,7 +229,9 @@ impl GridRevisionEditor { let type_option_json_builder = |field_type: &FieldTypeRevision| -> String { let field_type: FieldType = field_type.into(); - return default_type_option_builder_from_type(&field_type).entry().json_str(); + return default_type_option_builder_from_type(&field_type) + .data_format() + .json_str(); }; let _ = self @@ -828,7 +834,7 @@ impl JsonDeserializer for TypeOptionJsonDeserializer { fn deserialize(&self, type_option_data: Vec) -> CollaborateResult { // The type_option_data sent from Dart is serialized by protobuf. let builder = type_option_builder_from_bytes(type_option_data, &self.0); - let json = builder.entry().json_str(); + let json = builder.data_format().json_str(); tracing::trace!("Deserialize type option data to: {}", json); Ok(json) } 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 fba6adf7df..da849103a6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -152,7 +152,7 @@ where } = merge_groups(&self.configuration.groups, new_groups); let deleted_group_ids = deleted_group_revs - .iter() + .into_iter() .map(|group_rev| group_rev.id) .collect::>(); @@ -165,7 +165,7 @@ where is_changed = true; } - for mut group_rev in &mut all_group_revs { + for group_rev in &mut all_group_revs { match configuration .groups .iter() @@ -177,8 +177,7 @@ where } Some(pos) => { let mut old_group = configuration.groups.remove(pos); - // Update the group configuration base on the GroupRevision - group_rev.visible = old_group.visible; + group_rev.update_with_other(&old_group); // Take the GroupRevision if the name has changed if is_group_changed(&group_rev, &old_group) { @@ -192,6 +191,7 @@ where is_changed })?; + // The len of the filter_content_map should equal to the len of the all_group_revs 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) { @@ -207,21 +207,20 @@ where 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) - } + .flat_map(|group_rev| { + let 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(), + ); + Some(GroupPB::from(group)) }) .collect(); let changeset = GroupViewChangesetPB { - view_id, + view_id: self.view_id.clone(), new_groups, deleted_groups: deleted_group_ids, update_groups: vec![], 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 5bcff652a4..f0504c23ef 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -87,7 +87,7 @@ where { 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 type_option = field_rev.get_type_option::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); let _ = configuration.init_group_revs(groups)?; @@ -274,7 +274,7 @@ where fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult> { let field_type_rev = field_rev.ty; - let type_option = field_rev.get_type_option_entry::(field_type_rev); + let type_option = field_rev.get_type_option::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &self.configuration, &type_option); let changeset = self.configuration.init_group_revs(groups)?; Ok(changeset) diff --git a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs index 3aa22cc488..df0c105e39 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs @@ -176,7 +176,7 @@ impl GridRowTest { FieldType::Number => { let field_rev = self.editor.get_field_rev(&cell_id.field_id).await.unwrap(); let number_type_option = field_rev - .get_type_option_entry::(FieldType::Number.into()) + .get_type_option::(FieldType::Number.into()) .unwrap(); let cell_data = self .editor 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 3e255d3662..7dfd76a1a4 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 @@ -4,7 +4,7 @@ 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_grid_data_model::revision::TypeOptionDataFormat; #[tokio::test] async fn grid_create_field() { @@ -86,7 +86,7 @@ async fn grid_update_field() { let mut expected_field_rev = single_select_field.clone(); expected_field_rev.frozen = true; expected_field_rev.width = 1000; - expected_field_rev.insert_type_option_entry(&single_select_type_option); + expected_field_rev.insert_type_option(&single_select_type_option); let scripts = vec![ CreateField { params }, diff --git a/frontend/rust-lib/flowy-grid/tests/grid/field_test/util.rs b/frontend/rust-lib/flowy-grid/tests/grid/field_test/util.rs index fa2f003baa..e8cbf2b813 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/field_test/util.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/field_test/util.rs @@ -12,7 +12,7 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) { let cloned_field_rev = field_rev.clone(); let type_option_data = field_rev - .get_type_option_entry::(field_rev.ty) + .get_type_option::(field_rev.ty) .unwrap() .protobuf_bytes() .to_vec(); @@ -45,7 +45,7 @@ pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldRev let field_rev = FieldBuilder::new(single_select).name("Name").visibility(true).build(); let cloned_field_rev = field_rev.clone(); let type_option_data = field_rev - .get_type_option_entry::(field_rev.ty) + .get_type_option::(field_rev.ty) .unwrap() .protobuf_bytes() .to_vec(); diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 11866b7d1c..42e4e860e0 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -8,7 +8,7 @@ use flowy_grid::services::field::{ use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowMetaBuilder}; use flowy_grid_data_model::entities::{ CellChangeset, FieldChangesetParams, FieldType, GridBlockInfoChangeset, GridBlockMetaSnapshot, RowMetaChangeset, - TypeOptionDataEntry, + TypeOptionDataFormat, }; #[tokio::test] 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 e779844d46..c2f3388c3d 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 @@ -3,6 +3,7 @@ use flowy_grid::entities::{ CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB, }; use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell}; +use flowy_grid::services::field::{select_option_operation, SelectOptionOperation}; use flowy_grid_data_model::revision::{FieldRevision, RowChangeset}; use std::sync::Arc; use std::time::Duration; @@ -212,6 +213,28 @@ impl GridGroupTest { .clone(); return field; } + + pub async fn get_single_select_field(&self) -> Arc { + self.inner + .field_revs + .iter() + .find(|field_rev| { + let field_type: FieldType = field_rev.ty.into(); + field_type.is_single_select() + }) + .unwrap() + .clone() + } + + pub async fn edit_single_select_type_option(&self, f: impl FnOnce(Box)) { + let single_select = self.get_single_select_field().await; + let mut field_rev = self.editor.get_field_rev(&single_select.id).await.unwrap(); + let mut_field_rev = Arc::make_mut(&mut field_rev); + let mut type_option = select_option_operation(mut_field_rev)?; + f(type_option); + mut_field_rev.insert_type_option(&*type_option); + let _ = self.editor.replace_field(field_rev).await?; + } } impl std::ops::Deref for GridGroupTest { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index c9ea583a14..eb65e2a7c8 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -5,7 +5,7 @@ use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ BuildGridContext, CellChangeset, Field, FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockInfoChangeset, GridBlockMetaSnapshot, InsertFieldParams, RowMeta, RowMetaChangeset, RowOrder, - TypeOptionDataEntry, + TypeOptionDataFormat, }; use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::client_grid::GridBuilder; diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs index fedac5c591..90187d9b7b 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs @@ -143,15 +143,15 @@ impl FieldRevision { } } - pub fn insert_type_option_entry(&mut self, entry: &T) + pub fn insert_type_option(&mut self, type_option: &T) where - T: TypeOptionDataEntry + ?Sized, + T: TypeOptionDataFormat + ?Sized, { let id = self.ty.to_string(); - self.type_options.insert(id, entry.json_str()); + self.type_options.insert(id, type_option.json_str()); } - pub fn get_type_option_entry(&self, field_type_rev: FieldTypeRevision) -> Option { + pub fn get_type_option(&self, field_type_rev: FieldTypeRevision) -> Option { let id = field_type_rev.to_string(); // TODO: cache the deserialized type option self.type_options.get(&id).map(|s| T::from_json_str(s)) @@ -171,7 +171,7 @@ impl FieldRevision { /// The macro [impl_type_option] will implement the [TypeOptionDataEntry] for the type that /// supports the serde trait and the TryInto trait. -pub trait TypeOptionDataEntry { +pub trait TypeOptionDataFormat { fn json_str(&self) -> String; fn protobuf_bytes(&self) -> Bytes; } 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 e942de59c9..0aded0d3c7 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 @@ -135,6 +135,10 @@ impl GroupRevision { visible: true, } } + + pub fn update_with_other(&mut self, other: &GroupRevision) { + self.visible = other.visible + } } #[derive(Default, Serialize, Deserialize)] From bb7cddc7f7b07a6b9ac3affb06b6ef4e125fa7c0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 2 Sep 2022 21:34:00 +0800 Subject: [PATCH 4/9] chore: reload group when group by new field --- .../plugins/board/application/board_bloc.dart | 44 +++++--- .../application/board_data_controller.dart | 42 ++++--- .../board/application/board_listener.dart | 32 ++++-- .../lib/src/widgets/board_data.dart | 5 + .../flowy-grid/src/dart_notification.rs | 1 + .../group_entities/group_changeset.rs | 5 +- .../src/services/field/field_operation.rs | 44 ++++---- .../flowy-grid/src/services/grid_editor.rs | 3 +- .../src/services/grid_view_editor.rs | 105 ++++++++++++++---- .../src/services/grid_view_manager.rs | 6 + .../src/services/group/configuration.rs | 21 ++-- .../src/services/group/controller.rs | 31 +++--- .../controller_impls/checkbox_controller.rs | 7 +- .../controller_impls/default_controller.rs | 20 ++-- .../multi_select_controller.rs | 14 +-- .../single_select_controller.rs | 12 +- .../select_option_controller/util.rs | 4 +- .../src/services/group/group_util.rs | 7 +- .../flowy-grid/tests/grid/grid_editor.rs | 7 ++ .../tests/grid/group_test/script.rs | 41 +++---- .../flowy-grid/tests/grid/group_test/test.rs | 58 ++++++---- .../src/revision/grid_setting_rev.rs | 10 +- .../src/client_grid/view_revision_pad.rs | 10 +- .../src/core/document/document_operation.rs | 2 +- shared-lib/lib-ot/src/core/document/mod.rs | 1 + shared-lib/lib-ot/tests/main.rs | 30 ++--- 26 files changed, 353 insertions(+), 209 deletions(-) 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 6913b07023..d4ffebd117 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -110,9 +110,11 @@ class BoardBloc extends Bloc { emit(state.copyWith(noneOrError: some(error))); }, didReceiveGroups: (List groups) { - emit(state.copyWith( - groupIds: groups.map((group) => group.groupId).toList(), - )); + emit( + state.copyWith( + groupIds: groups.map((group) => group.groupId).toList(), + ), + ); }, ); }, @@ -154,6 +156,23 @@ class BoardBloc extends Bloc { } void initializeGroups(List groups) { + for (var controller in groupControllers.values) { + controller.dispose(); + } + groupControllers.clear(); + boardController.clear(); + + // + List columns = groups.map((group) { + return AFBoardColumnData( + id: group.groupId, + name: group.desc, + items: _buildRows(group), + customData: group, + ); + }).toList(); + boardController.addColumns(columns); + for (final group in groups) { final delegate = GroupControllerDelegateImpl( controller: boardController, @@ -184,16 +203,6 @@ class BoardBloc extends Bloc { } }, didLoadGroups: (groups) { - List columns = groups.map((group) { - return AFBoardColumnData( - id: group.groupId, - name: group.desc, - items: _buildRows(group), - customData: group, - ); - }).toList(); - - boardController.addColumns(columns); initializeGroups(groups); add(BoardEvent.didReceiveGroups(groups)); }, @@ -204,18 +213,19 @@ class BoardBloc extends Bloc { // }, onUpdatedGroup: (updatedGroups) { - // for (final group in updatedGroups) { final columnController = boardController.getColumnController(group.groupId); - if (columnController != null) { - columnController.updateColumnName(group.desc); - } + columnController?.updateColumnName(group.desc); } }, onError: (err) { Log.error(err); }, + onResetGroups: (groups) { + initializeGroups(groups); + add(BoardEvent.didReceiveGroups(groups)); + }, ); } diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index 4ab45c64b7..c78621b0a3 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -18,6 +18,7 @@ typedef DidLoadGroups = void Function(List); typedef OnUpdatedGroup = void Function(List); typedef OnDeletedGroup = void Function(List); typedef OnInsertedGroup = void Function(List); +typedef OnResetGroups = void Function(List); typedef OnRowsChanged = void Function( List, @@ -65,6 +66,7 @@ class BoardDataController { required OnUpdatedGroup onUpdatedGroup, required OnDeletedGroup onDeletedGroup, required OnInsertedGroup onInsertedGroup, + required OnResetGroups onResetGroups, required OnError? onError, }) { _onGridChanged = onGridChanged; @@ -77,24 +79,32 @@ class BoardDataController { _onFieldsChanged?.call(UnmodifiableListView(fields)); }); - _listener.start(onBoardChanged: (result) { - result.fold( - (changeset) { - if (changeset.updateGroups.isNotEmpty) { - onUpdatedGroup.call(changeset.updateGroups); - } + _listener.start( + onBoardChanged: (result) { + result.fold( + (changeset) { + if (changeset.updateGroups.isNotEmpty) { + onUpdatedGroup.call(changeset.updateGroups); + } - if (changeset.insertedGroups.isNotEmpty) { - onInsertedGroup.call(changeset.insertedGroups); - } + if (changeset.insertedGroups.isNotEmpty) { + onInsertedGroup.call(changeset.insertedGroups); + } - if (changeset.deletedGroups.isNotEmpty) { - onDeletedGroup.call(changeset.deletedGroups); - } - }, - (e) => _onError?.call(e), - ); - }); + if (changeset.deletedGroups.isNotEmpty) { + onDeletedGroup.call(changeset.deletedGroups); + } + }, + (e) => _onError?.call(e), + ); + }, + onGroupByNewField: (result) { + result.fold( + (groups) => onResetGroups(groups), + (e) => _onError?.call(e), + ); + }, + ); } Future> loadData() async { diff --git a/frontend/app_flowy/lib/plugins/board/application/board_listener.dart b/frontend/app_flowy/lib/plugins/board/application/board_listener.dart index a953a993cc..9f8662fc5b 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_listener.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_listener.dart @@ -5,20 +5,26 @@ import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart'; -typedef UpdateBoardNotifiedValue = Either; +typedef GroupUpdateValue = Either; +typedef GroupByNewFieldValue = Either, FlowyError>; class BoardListener { final String viewId; - PublishNotifier? _groupNotifier = PublishNotifier(); + PublishNotifier? _groupUpdateNotifier = PublishNotifier(); + PublishNotifier? _groupByNewFieldNotifier = + PublishNotifier(); GridNotificationListener? _listener; BoardListener(this.viewId); void start({ - required void Function(UpdateBoardNotifiedValue) onBoardChanged, + required void Function(GroupUpdateValue) onBoardChanged, + required void Function(GroupByNewFieldValue) onGroupByNewField, }) { - _groupNotifier?.addPublishListener(onBoardChanged); + _groupUpdateNotifier?.addPublishListener(onBoardChanged); + _groupByNewFieldNotifier?.addPublishListener(onGroupByNewField); _listener = GridNotificationListener( objectId: viewId, handler: _handler, @@ -32,9 +38,16 @@ class BoardListener { switch (ty) { case GridNotification.DidUpdateGroupView: result.fold( - (payload) => _groupNotifier?.value = + (payload) => _groupUpdateNotifier?.value = left(GroupViewChangesetPB.fromBuffer(payload)), - (error) => _groupNotifier?.value = right(error), + (error) => _groupUpdateNotifier?.value = right(error), + ); + break; + case GridNotification.DidGroupByNewField: + result.fold( + (payload) => _groupByNewFieldNotifier?.value = + left(GroupViewChangesetPB.fromBuffer(payload).newGroups), + (error) => _groupByNewFieldNotifier?.value = right(error), ); break; default: @@ -44,7 +57,10 @@ class BoardListener { Future stop() async { await _listener?.stop(); - _groupNotifier?.dispose(); - _groupNotifier = null; + _groupUpdateNotifier?.dispose(); + _groupUpdateNotifier = null; + + _groupByNewFieldNotifier?.dispose(); + _groupByNewFieldNotifier = null; } } 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 75282d183c..4c20161691 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 @@ -89,6 +89,11 @@ class AFBoardDataController extends ChangeNotifier if (columnIds.isNotEmpty && notify) notifyListeners(); } + void clear() { + _columnDatas.clear(); + notifyListeners(); + } + AFBoardColumnDataController? getColumnController(String columnId) { final columnController = _columnControllers[columnId]; if (columnController == null) { diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index a0030c6773..ca0f0aa681 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -13,6 +13,7 @@ pub enum GridNotification { DidUpdateField = 50, DidUpdateGroupView = 60, DidUpdateGroup = 61, + DidGroupByNewField = 62, } 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 fd49709cf3..63b883d570 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 @@ -145,7 +145,10 @@ pub struct GroupViewChangesetPB { impl GroupViewChangesetPB { pub fn is_empty(&self) -> bool { - self.inserted_groups.is_empty() && self.deleted_groups.is_empty() && self.update_groups.is_empty() + self.new_groups.is_empty() + && self.inserted_groups.is_empty() + && self.deleted_groups.is_empty() + && self.update_groups.is_empty() } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs index 7ee127b382..3a2ce89c21 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_operation.rs @@ -1,14 +1,13 @@ -use crate::entities::{FieldChangesetParams, FieldType}; -use crate::services::field::{select_option_operation, SelectOptionPB}; +use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use crate::services::grid_editor::GridRevisionEditor; use flowy_error::FlowyResult; -use flowy_grid_data_model::revision::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataFormat}; +use flowy_grid_data_model::revision::{TypeOptionDataDeserializer, TypeOptionDataFormat}; use std::sync::Arc; -pub async fn edit_field( +pub async fn edit_field_type_option( field_id: &str, editor: Arc, - action: impl FnOnce(&mut T) -> bool, + action: impl FnOnce(&mut T), ) -> FlowyResult<()> where T: TypeOptionDataDeserializer + TypeOptionDataFormat, @@ -19,29 +18,28 @@ where }; if let Some(mut type_option) = get_type_option.await { - if action(&mut type_option) { - let changeset = FieldChangesetParams { ..Default::default() }; - let _ = editor.update_field(changeset).await?; - } + action(&mut type_option); + let bytes = type_option.protobuf_bytes().to_vec(); + let _ = editor + .update_field_type_option(&editor.grid_id, field_id, bytes) + .await?; } Ok(()) } -pub fn insert_single_select_option(field_rev: &mut FieldRevision, options: Vec) -> FlowyResult<()> { - if options.is_empty() { - return Ok(()); - } - let mut type_option = select_option_operation(field_rev)?; - options.into_iter().for_each(|option| type_option.insert_option(option)); - Ok(()) +pub async fn edit_single_select_type_option( + field_id: &str, + editor: Arc, + action: impl FnOnce(&mut SingleSelectTypeOptionPB), +) -> FlowyResult<()> { + edit_field_type_option(field_id, editor, action).await } -pub fn insert_multi_select_option(field_rev: &mut FieldRevision, options: Vec) -> FlowyResult<()> { - if options.is_empty() { - return Ok(()); - } - let mut type_option = select_option_operation(field_rev)?; - options.into_iter().for_each(|option| type_option.insert_option(option)); - Ok(()) +pub async fn edit_multi_select_type_option( + field_id: &str, + editor: Arc, + action: impl FnOnce(&mut MultiSelectTypeOptionPB), +) -> FlowyResult<()> { + edit_field_type_option(field_id, editor, action).await } 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 11e8cb139f..5b8d4e0d91 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -212,7 +212,8 @@ impl GridRevisionEditor { } pub async fn group_field(&self, field_id: &str) -> FlowyResult<()> { - todo!() + let _ = self.view_manager.group_by_field(field_id).await?; + Ok(()) } pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> 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 bfe752ec12..70db181f59 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,8 @@ 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, MoveGroupRowContext, + find_group_field, make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController, + MoveGroupRowContext, }; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ @@ -34,7 +35,6 @@ pub struct GridViewRevisionEditor { group_controller: Arc>>, scheduler: Arc, } - impl GridViewRevisionEditor { #[tracing::instrument(level = "trace", skip_all, err)] pub(crate) async fn new( @@ -52,25 +52,15 @@ 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); - - // Load group - 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 field_revs = field_delegate.get_field_revs().await; - let row_revs = row_delegate.gv_row_revs().await; - let group_controller = make_group_controller( + let group_controller = new_group_controller( + user_id.to_owned(), view_id.clone(), - field_revs, - row_revs, - configuration_reader, - configuration_writer, + pad.clone(), + rev_manager.clone(), + field_delegate.clone(), + row_delegate.clone(), ) .await?; - let user_id = user_id.to_owned(); Ok(Self { pad, @@ -258,6 +248,37 @@ impl GridViewRevisionEditor { Ok(()) } + pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> { + if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await { + let new_group_controller = new_group_controller_with_field_rev( + self.user_id.clone(), + self.view_id.clone(), + self.pad.clone(), + self.rev_manager.clone(), + field_rev, + self.row_delegate.clone(), + ) + .await?; + + let new_groups = new_group_controller.groups().into_iter().map(GroupPB::from).collect(); + + *self.group_controller.write().await = new_group_controller; + let changeset = GroupViewChangesetPB { + view_id: self.view_id.clone(), + new_groups, + ..Default::default() + }; + + debug_assert!(!changeset.is_empty()); + if !changeset.is_empty() { + send_dart_notification(&changeset.view_id, GridNotification::DidGroupByNewField) + .payload(changeset) + .send(); + } + } + Ok(()) + } + pub async fn notify_did_update_group(&self, changeset: GroupChangesetPB) { send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup) .payload(changeset) @@ -314,6 +335,48 @@ impl GridViewRevisionEditor { } } } +async fn new_group_controller( + user_id: String, + view_id: String, + pad: Arc>, + rev_manager: Arc, + field_delegate: Arc, + row_delegate: Arc, +) -> FlowyResult> { + let configuration_reader = GroupConfigurationReaderImpl(pad.clone()); + let field_revs = field_delegate.get_field_revs().await; + // Read the group field or find a new group field + let field_rev = configuration_reader + .get_configuration() + .await + .and_then(|configuration| { + field_revs + .iter() + .find(|field_rev| field_rev.id == configuration.field_id) + .cloned() + }) + .unwrap_or_else(|| find_group_field(&field_revs).unwrap()); + + new_group_controller_with_field_rev(user_id, view_id, pad, rev_manager, field_rev, row_delegate).await +} + +async fn new_group_controller_with_field_rev( + user_id: String, + view_id: String, + pad: Arc>, + rev_manager: Arc, + field_rev: Arc, + row_delegate: Arc, +) -> FlowyResult> { + let configuration_reader = GroupConfigurationReaderImpl(pad.clone()); + let configuration_writer = GroupConfigurationWriterImpl { + user_id, + rev_manager, + view_pad: pad, + }; + let row_revs = row_delegate.gv_row_revs().await; + make_group_controller(view_id, field_rev, row_revs, configuration_reader, configuration_writer).await +} async fn apply_change( user_id: &str, @@ -353,10 +416,10 @@ impl RevisionObjectBuilder for GridViewRevisionPadBuilder { struct GroupConfigurationReaderImpl(Arc>); impl GroupConfigurationReader for GroupConfigurationReaderImpl { - fn get_configuration(&self, field_rev: Arc) -> AFFuture>> { + fn get_configuration(&self) -> 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)?; + let mut groups = view_pad.read().await.get_all_groups(); if groups.is_empty() { None } else { @@ -411,7 +474,7 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc FlowyResult<()> { + let view_editor = self.get_default_view_editor().await?; + let _ = view_editor.group_by_field(field_id).await?; + Ok(()) + } + pub(crate) async fn did_update_cell(&self, row_id: &str, _field_id: &str) { self.did_update_row(row_id).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 da849103a6..196f619290 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupPB, GroupViewChangesetPB, InsertedGroupPB}; +use crate::entities::{GroupPB, GroupViewChangesetPB}; use crate::services::group::{default_group_configuration, GeneratedGroup, Group}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ @@ -12,7 +12,7 @@ use std::marker::PhantomData; use std::sync::Arc; pub trait GroupConfigurationReader: Send + Sync + 'static { - fn get_configuration(&self, field_rev: Arc) -> AFFuture>>; + fn get_configuration(&self) -> AFFuture>>; } pub trait GroupConfigurationWriter: Send + Sync + 'static { @@ -38,8 +38,8 @@ impl std::fmt::Display for GroupContext { } pub struct GroupContext { - view_id: String, - pub configuration: Arc, + pub view_id: String, + configuration: Arc, configuration_content: PhantomData, field_rev: Arc, groups_map: IndexMap, @@ -69,7 +69,7 @@ where rows: vec![], filter_content: "".to_string(), }; - let configuration = match reader.get_configuration(field_rev.clone()).await { + let configuration = match reader.get_configuration().await { None => { let default_configuration = default_group_configuration(&field_rev); writer @@ -133,9 +133,10 @@ where } } - pub(crate) fn init_group_revs( + pub(crate) fn init_groups( &mut self, generated_groups: Vec, + reset: bool, ) -> FlowyResult> { let mut new_groups = vec![]; let mut filter_content_map = HashMap::new(); @@ -149,7 +150,11 @@ where new_group_revs, updated_group_revs: _, deleted_group_revs, - } = merge_groups(&self.configuration.groups, new_groups); + } = if reset { + merge_groups(&[], new_groups) + } else { + merge_groups(&self.configuration.groups, new_groups) + }; let deleted_group_ids = deleted_group_revs .into_iter() @@ -180,7 +185,7 @@ where group_rev.update_with_other(&old_group); // Take the GroupRevision if the name has changed - if is_group_changed(&group_rev, &old_group) { + if is_group_changed(group_rev, &old_group) { old_group.name = group_rev.name.clone(); is_changed = true; configuration.groups.insert(pos, old_group); 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 f0504c23ef..d2784f0e77 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -74,7 +74,7 @@ pub trait GroupControllerSharedOperation: Send + Sync { pub struct GenericGroupController { pub field_id: String, pub type_option: Option, - pub configuration: GroupContext, + pub group_ctx: GroupContext, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData

, } @@ -89,12 +89,12 @@ where let field_type_rev = field_rev.ty; let type_option = field_rev.get_type_option::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); - let _ = configuration.init_group_revs(groups)?; + let _ = configuration.init_groups(groups, false)?; Ok(Self { field_id: field_rev.id.clone(), type_option, - configuration, + group_ctx: configuration, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData, }) @@ -107,7 +107,7 @@ where row_rev: &RowRevision, other_group_changesets: &[GroupChangesetPB], ) -> GroupChangesetPB { - let default_group = self.configuration.get_mut_default_group(); + let default_group = self.group_ctx.get_mut_default_group(); // [other_group_inserted_row] contains all the inserted rows except the default group. let other_group_inserted_row = other_group_changesets @@ -182,11 +182,11 @@ where } fn groups(&self) -> Vec { - self.configuration.clone_groups() + self.group_ctx.clone_groups() } fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { - let group = self.configuration.get_group(group_id)?; + let group = self.group_ctx.get_group(group_id)?; Some((group.0, group.1.clone())) } @@ -197,7 +197,7 @@ where 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() { + for group in self.group_ctx.concrete_groups() { if self.can_group(&group.filter_content, &cell_data) { grouped_rows.push(GroupedRow { row: row_rev.into(), @@ -207,25 +207,25 @@ where } if grouped_rows.is_empty() { - self.configuration.get_mut_default_group().add_row(row_rev.into()); + self.group_ctx.get_mut_default_group().add_row(row_rev.into()); } else { for group_row in grouped_rows { - if let Some(group) = self.configuration.get_mut_group(&group_row.group_id) { + if let Some(group) = self.group_ctx.get_mut_group(&group_row.group_id) { group.add_row(group_row.row); } } } } else { - self.configuration.get_mut_default_group().add_row(row_rev.into()); + self.group_ctx.get_mut_default_group().add_row(row_rev.into()); } } - tracing::Span::current().record("group_result", &format!("{},", self.configuration,).as_str()); + tracing::Span::current().record("group_result", &format!("{},", self.group_ctx,).as_str()); Ok(()) } fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { - self.configuration.move_group(from_group_id, to_group_id) + self.group_ctx.move_group(from_group_id, to_group_id) } fn did_update_row( @@ -273,10 +273,9 @@ where } fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult> { - let field_type_rev = field_rev.ty; - let type_option = field_rev.get_type_option::(field_type_rev); - let groups = G::generate_groups(&field_rev.id, &self.configuration, &type_option); - let changeset = self.configuration.init_group_revs(groups)?; + let type_option = field_rev.get_type_option::(field_rev.ty); + let groups = G::generate_groups(&field_rev.id, &self.group_ctx, &type_option); + let changeset = self.group_ctx.init_groups(groups, false)?; 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 cfae74ecc3..02ff4cb503 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 @@ -5,7 +5,6 @@ use crate::services::group::configuration::GroupContext; use crate::services::group::controller::{ GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, }; -use crate::services::group::entities::Group; use crate::services::group::GeneratedGroup; use flowy_grid_data_model::revision::{CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision}; @@ -54,9 +53,9 @@ impl GroupGenerator for CheckboxGroupGenerator { type TypeOptionType = CheckboxTypeOptionPB; fn generate_groups( - field_id: &str, - group_ctx: &Self::Context, - type_option: &Option, + _field_id: &str, + _group_ctx: &Self::Context, + _type_option: &Option, ) -> Vec { let check_group = GeneratedGroup { group_rev: GroupRevision::new("true".to_string(), CHECK.to_string()), 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 index ff934118ca..4ce5523404 100644 --- 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 @@ -35,46 +35,46 @@ impl GroupControllerSharedOperation for DefaultGroupController { vec![self.group.clone()] } - fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { + 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<()> { + 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<()> { + 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, + _row_rev: &RowRevision, + _field_rev: &FieldRevision, ) -> FlowyResult> { todo!() } fn did_delete_row( &mut self, - row_rev: &RowRevision, - field_rev: &FieldRevision, + _row_rev: &RowRevision, + _field_rev: &FieldRevision, ) -> FlowyResult> { todo!() } - fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult> { + fn move_group_row(&mut self, _context: MoveGroupRowContext) -> FlowyResult> { todo!() } - fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult> { + 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) {} + 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/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 678c53b28d..026843bbcc 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 @@ -7,11 +7,9 @@ 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 crate::services::group::GeneratedGroup; -use flowy_grid_data_model::revision::{ - FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // MultiSelect pub type MultiSelectGroupController = GenericGroupController< @@ -30,7 +28,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| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } @@ -40,7 +38,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| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } @@ -50,7 +48,7 @@ impl GroupAction for MultiSelectGroupController { fn move_row(&mut self, cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { let mut group_changeset = vec![]; - self.configuration.iter_mut_groups(|group| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_select_option_row(group, cell_data, &mut context) { group_changeset.push(changeset); } @@ -61,7 +59,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) { - match self.configuration.get_group(group_id) { + match self.group_ctx.get_group(group_id) { None => tracing::warn!("Can not find the group: {}", group_id), Some((_, group)) => { let cell_rev = insert_select_option_cell(group.id.clone(), field_rev); 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 b2bffed4ec..96b686efe3 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 @@ -10,9 +10,7 @@ use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; use crate::services::group::GeneratedGroup; -use flowy_grid_data_model::revision::{ - FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision, -}; +use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // SingleSelect pub type SingleSelectGroupController = GenericGroupController< @@ -30,7 +28,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| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } @@ -40,7 +38,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| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } @@ -50,7 +48,7 @@ impl GroupAction for SingleSelectGroupController { fn move_row(&mut self, cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { let mut group_changeset = vec![]; - self.configuration.iter_mut_groups(|group| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_select_option_row(group, cell_data, &mut context) { group_changeset.push(changeset); } @@ -61,7 +59,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.configuration.get_mut_group(group_id); + let group: Option<&mut Group> = self.group_ctx.get_mut_group(group_id); match group { None => {} Some(group) => { 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 c60eec49a5..494cd41197 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 @@ -127,8 +127,8 @@ pub fn move_select_option_row( } pub fn generate_select_option_groups( - field_id: &str, - group_ctx: &SelectOptionGroupContext, + _field_id: &str, + _group_ctx: &SelectOptionGroupContext, options: &[SelectOptionPB], ) -> Vec { let groups = options 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 index 1e2ea0f9d6..50d93396d7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/group_util.rs @@ -16,7 +16,7 @@ use std::sync::Arc; #[tracing::instrument(level = "trace", skip_all, err)] pub async fn make_group_controller( view_id: String, - field_revs: Vec>, + field_rev: Arc, row_revs: Vec>, configuration_reader: R, configuration_writer: W, @@ -25,11 +25,12 @@ 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 = @@ -61,7 +62,7 @@ where Ok(group_controller) } -fn find_group_field(field_revs: &[Arc]) -> Option> { +pub fn find_group_field(field_revs: &[Arc]) -> Option> { let field_rev = field_revs .iter() .find(|field_rev| { 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 78cfc17b26..0325f6f008 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -195,6 +195,8 @@ fn make_test_grid() -> BuildGridContext { FieldType::SingleSelect => { row_builder.insert_single_select_cell(|mut options| options.remove(0)) } + FieldType::MultiSelect => row_builder + .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]), FieldType::Checkbox => row_builder.insert_checkbox_cell("true"), _ => "".to_owned(), }; @@ -209,6 +211,8 @@ fn make_test_grid() -> BuildGridContext { FieldType::SingleSelect => { row_builder.insert_single_select_cell(|mut options| options.remove(0)) } + FieldType::MultiSelect => row_builder + .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]), FieldType::Checkbox => row_builder.insert_checkbox_cell("true"), _ => "".to_owned(), }; @@ -223,6 +227,9 @@ fn make_test_grid() -> BuildGridContext { FieldType::SingleSelect => { row_builder.insert_single_select_cell(|mut options| options.remove(1)) } + FieldType::MultiSelect => { + row_builder.insert_multi_select_cell(|mut options| vec![options.remove(0)]) + } FieldType::Checkbox => row_builder.insert_checkbox_cell("false"), _ => "".to_owned(), }; 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 c2f3388c3d..373eabdc88 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,13 +1,13 @@ use crate::grid::grid_editor::GridEditorTest; use flowy_grid::entities::{ - CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB, + CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB, }; use flowy_grid::services::cell::{delete_select_option_cell, insert_select_option_cell}; -use flowy_grid::services::field::{select_option_operation, SelectOptionOperation}; +use flowy_grid::services::field::{ + edit_single_select_type_option, SelectOptionOperation, SelectOptionPB, SingleSelectTypeOptionPB, +}; use flowy_grid_data_model::revision::{FieldRevision, RowChangeset}; use std::sync::Arc; -use std::time::Duration; -use tokio::time::interval; pub enum GroupScript { AssertGroupRowCount { @@ -46,10 +46,10 @@ pub enum GroupScript { from_group_index: usize, to_group_index: usize, }, - UpdateField { - changeset: FieldChangesetParams, + UpdateSingleSelectOption { + inserted_options: Vec, }, - GroupField { + GroupByField { field_id: String, }, } @@ -179,12 +179,15 @@ impl GridGroupTest { assert_eq!(group.group_id, group_pb.group_id); assert_eq!(group.desc, group_pb.desc); } - GroupScript::UpdateField { changeset } => { - self.editor.update_field(changeset).await.unwrap(); - let mut interval = interval(Duration::from_millis(130)); - interval.tick().await; + GroupScript::UpdateSingleSelectOption { inserted_options } => { + self.edit_single_select_type_option(|type_option| { + for inserted_option in inserted_options { + type_option.insert_option(inserted_option); + } + }) + .await; } - GroupScript::GroupField { field_id } => { + GroupScript::GroupByField { field_id } => { self.editor.group_field(&field_id).await.unwrap(); } } @@ -200,6 +203,7 @@ impl GridGroupTest { groups.rows.get(row_index).unwrap().clone() } + #[allow(dead_code)] pub async fn get_multi_select_field(&self) -> Arc { let field = self .inner @@ -211,7 +215,7 @@ impl GridGroupTest { }) .unwrap() .clone(); - return field; + field } pub async fn get_single_select_field(&self) -> Arc { @@ -226,14 +230,11 @@ impl GridGroupTest { .clone() } - pub async fn edit_single_select_type_option(&self, f: impl FnOnce(Box)) { + pub async fn edit_single_select_type_option(&self, action: impl FnOnce(&mut SingleSelectTypeOptionPB)) { let single_select = self.get_single_select_field().await; - let mut field_rev = self.editor.get_field_rev(&single_select.id).await.unwrap(); - let mut_field_rev = Arc::make_mut(&mut field_rev); - let mut type_option = select_option_operation(mut_field_rev)?; - f(type_option); - mut_field_rev.insert_type_option(&*type_option); - let _ = self.editor.replace_field(field_rev).await?; + edit_single_select_type_option(&single_select.id, self.editor.clone(), action) + .await + .unwrap(); } } 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 760f39b2ac..5926f8c022 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 @@ -1,6 +1,7 @@ use crate::grid::group_test::script::GridGroupTest; use crate::grid::group_test::script::GroupScript::*; -use flowy_grid::entities::FieldChangesetParams; + +use flowy_grid::services::field::SelectOptionPB; #[tokio::test] async fn group_init_test() { @@ -370,32 +371,41 @@ async fn group_move_group_test() { } #[tokio::test] -async fn group_update_field_test() { +async fn group_insert_single_select_option_test() { let mut test = GridGroupTest::new().await; - let group = test.group_at_index(0).await; - let changeset = FieldChangesetParams { - field_id: group.field_id.clone(), - grid_id: test.grid_id.clone(), - name: Some("ABC".to_string()), - ..Default::default() - }; - - // group.desc = "ABC".to_string(); + let new_option_name = "New option"; let scripts = vec![ - UpdateField { changeset }, - AssertGroup { - group_index: 0, - expected_group: group, + AssertGroupCount(4), + UpdateSingleSelectOption { + inserted_options: vec![SelectOptionPB::new(new_option_name)], }, + AssertGroupCount(5), + ]; + test.run_scripts(scripts).await; + + // the group at index 4 is the default_group, so the new insert group will be the + // index 3. + let group_3 = test.group_at_index(3).await; + assert_eq!(group_3.desc, new_option_name); +} + +#[tokio::test] +async fn group_group_by_other_field() { + let mut test = GridGroupTest::new().await; + let multi_select_field = test.get_multi_select_field().await; + let scripts = vec![ + GroupByField { + field_id: multi_select_field.id.clone(), + }, + AssertGroupRowCount { + group_index: 0, + row_count: 3, + }, + AssertGroupRowCount { + group_index: 1, + row_count: 2, + }, + AssertGroupCount(4), ]; 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/grid_setting_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_setting_rev.rs index 1f52ae93e2..996b5abcba 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 @@ -60,7 +60,7 @@ where .cloned() } - pub fn get_all_objects(&self, field_revs: &[Arc]) -> Option>>> { + pub fn get_objects_by_field_revs(&self, field_revs: &[Arc]) -> Option>>> { // Get the objects according to the FieldType, so we need iterate the field_revs. let objects_by_field_id = field_revs .iter() @@ -76,6 +76,10 @@ where Some(objects_by_field_id) } + pub fn get_all_objects(&self) -> Vec> { + self.inner.values().map(|map| map.all_objects()).flatten().collect() + } + /// 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 @@ -111,6 +115,10 @@ where pub fn new() -> Self { ObjectIndexMap::default() } + + pub fn all_objects(&self) -> Vec> { + self.object_by_field_type.values().cloned().flatten().collect() + } } impl std::ops::Deref for ObjectIndexMap 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 ddc9c6e05a..e836834265 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 @@ -48,8 +48,12 @@ impl GridViewRevisionPad { Self::from_delta(delta) } - pub fn get_all_groups(&self, field_revs: &[Arc]) -> Option { - self.groups.get_all_objects(field_revs) + pub fn get_groups_by_field_revs(&self, field_revs: &[Arc]) -> Option { + self.groups.get_objects_by_field_revs(field_revs) + } + + pub fn get_all_groups(&self) -> Vec> { + self.groups.get_all_objects() } #[tracing::instrument(level = "trace", skip_all, err)] @@ -111,7 +115,7 @@ impl GridViewRevisionPad { } pub fn get_all_filters(&self, field_revs: &[Arc]) -> Option { - self.filters.get_all_objects(field_revs) + self.filters.get_objects_by_field_revs(field_revs) } pub fn get_filters( diff --git a/shared-lib/lib-ot/src/core/document/document_operation.rs b/shared-lib/lib-ot/src/core/document/document_operation.rs index 4d9d3617eb..29bfdcc04f 100644 --- a/shared-lib/lib-ot/src/core/document/document_operation.rs +++ b/shared-lib/lib-ot/src/core/document/document_operation.rs @@ -178,7 +178,7 @@ mod tests { node_type: "text".into(), attributes: NodeAttributes::new(), delta: None, - children: vec![Box::new(NodeSubTree::new("text".into()))], + children: vec![Box::new(NodeSubTree::new("text"))], })], }; let result = serde_json::to_string(&insert).unwrap(); diff --git a/shared-lib/lib-ot/src/core/document/mod.rs b/shared-lib/lib-ot/src/core/document/mod.rs index b019cb0f71..2dde3ef3e9 100644 --- a/shared-lib/lib-ot/src/core/document/mod.rs +++ b/shared-lib/lib-ot/src/core/document/mod.rs @@ -1,3 +1,4 @@ +#![allow(clippy::module_inception)] mod attributes; mod document; mod document_operation; diff --git a/shared-lib/lib-ot/tests/main.rs b/shared-lib/lib-ot/tests/main.rs index 31e7748b3a..ae7080656e 100644 --- a/shared-lib/lib-ot/tests/main.rs +++ b/shared-lib/lib-ot/tests/main.rs @@ -13,7 +13,7 @@ fn test_documents() { let mut document = DocumentTree::new(); let transaction = { let mut tb = TransactionBuilder::new(&document); - tb.insert_nodes_at_path(&vec![0].into(), &vec![Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![0].into(), &[Box::new(NodeSubTree::new("text"))]); tb.finalize() }; document.apply(transaction).unwrap(); @@ -47,16 +47,16 @@ fn test_inserts_nodes() { let mut document = DocumentTree::new(); let transaction = { let mut tb = TransactionBuilder::new(&document); - tb.insert_nodes_at_path(&vec![0].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![1].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![2].into(), &vec![Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![0].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![1].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![2].into(), &[Box::new(NodeSubTree::new("text"))]); tb.finalize() }; document.apply(transaction).unwrap(); let transaction = { let mut tb = TransactionBuilder::new(&document); - tb.insert_nodes_at_path(&vec![1].into(), &vec![Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![1].into(), &[Box::new(NodeSubTree::new("text"))]); tb.finalize() }; document.apply(transaction).unwrap(); @@ -69,11 +69,11 @@ fn test_inserts_subtrees() { let mut tb = TransactionBuilder::new(&document); tb.insert_nodes_at_path( &vec![0].into(), - &vec![Box::new(NodeSubTree { + &[Box::new(NodeSubTree { node_type: "text".into(), attributes: NodeAttributes::new(), delta: None, - children: vec![Box::new(NodeSubTree::new("image".into()))], + children: vec![Box::new(NodeSubTree::new("image"))], })], ); tb.finalize() @@ -90,9 +90,9 @@ fn test_update_nodes() { let mut document = DocumentTree::new(); let transaction = { let mut tb = TransactionBuilder::new(&document); - tb.insert_nodes_at_path(&vec![0].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![1].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![2].into(), &vec![Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![0].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![1].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![2].into(), &[Box::new(NodeSubTree::new("text"))]); tb.finalize() }; document.apply(transaction).unwrap(); @@ -115,9 +115,9 @@ fn test_delete_nodes() { let mut document = DocumentTree::new(); let transaction = { let mut tb = TransactionBuilder::new(&document); - tb.insert_nodes_at_path(&vec![0].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![1].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![2].into(), &vec![Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![0].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![1].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![2].into(), &[Box::new(NodeSubTree::new("text"))]); tb.finalize() }; document.apply(transaction).unwrap(); @@ -138,8 +138,8 @@ fn test_errors() { let mut document = DocumentTree::new(); let transaction = { let mut tb = TransactionBuilder::new(&document); - tb.insert_nodes_at_path(&vec![0].into(), &vec![Box::new(NodeSubTree::new("text"))]); - tb.insert_nodes_at_path(&vec![100].into(), &vec![Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![0].into(), &[Box::new(NodeSubTree::new("text"))]); + tb.insert_nodes_at_path(&vec![100].into(), &[Box::new(NodeSubTree::new("text"))]); tb.finalize() }; let result = document.apply(transaction); From e73f1438f7abd3ea8d512ecf034ae187c027c5cc Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 2 Sep 2022 22:13:38 +0800 Subject: [PATCH 5/9] chore: config switch group field UI --- .../presentation/toolbar/board_setting.dart | 5 +-- .../widgets/toolbar/grid_group.dart | 31 +++++++++++++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) 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 962ea28e15..d981bd6006 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 @@ -2,6 +2,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/board/application/toolbar/board_setting_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; +import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_group.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; @@ -96,8 +97,8 @@ class BoardSettingList extends StatelessWidget { .show(context); break; case BoardSettingAction.groups: - GridPropertyList( - gridId: settingContext.viewId, + GridGroupList( + viewId: settingContext.viewId, fieldCache: settingContext.fieldCache) .show(context); break; 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 index 5ef4ed7f11..6894cc3df1 100644 --- 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 @@ -1,18 +1,33 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class GridGroupList extends StatelessWidget { - const GridGroupList({Key? key}) : super(key: key); + final String viewId; + final GridFieldCache fieldCache; + const GridGroupList({ + required this.viewId, + required this.fieldCache, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return Container(); } + + void show(BuildContext context) {} } class _GridGroupCell extends StatelessWidget { - const _GridGroupCell({Key? key}) : super(key: key); + final FieldPB field; + const _GridGroupCell({required this.field, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -22,6 +37,16 @@ class _GridGroupCell extends StatelessWidget { // ? svgWidget('home/show', color: theme.iconColor) // : svgWidget('home/hide', color: theme.iconColor); - return Container(); + // Padding( + // padding: const EdgeInsets.only(right: 6), + // child: svgWidget("grid/checkmark"), + // ), + + return FlowyButton( + text: FlowyText.medium(field.name, fontSize: 12), + hoverColor: theme.hover, + leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + onTap: () {}, + ); } } From b3e5bb00ace27ef38cbd4366c0ef2fd342430202 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 2 Sep 2022 22:13:38 +0800 Subject: [PATCH 6/9] chore: config switch group field UI --- .../grid/application/setting/group_bloc.dart | 87 +++++++++++++++++++ .../widgets/toolbar/grid_group.dart | 38 +++++++- .../src/entities/setting_entities.rs | 2 +- .../src/services/grid_view_editor.rs | 12 +-- 4 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart new file mode 100644 index 0000000000..80ab7f91f2 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart @@ -0,0 +1,87 @@ +import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; + +import '../field/field_cache.dart'; + +part 'group_bloc.freezed.dart'; + +class GridGroupBloc extends Bloc { + final GridFieldCache _fieldCache; + Function(List)? _onFieldsFn; + + GridGroupBloc({required String gridId, required GridFieldCache fieldCache}) + : _fieldCache = fieldCache, + super(GridGroupState.initial(gridId, fieldCache.fields)) { + on( + (event, emit) async { + await event.map( + initial: (_Initial value) { + _startListening(); + }, + setFieldVisibility: (_SetFieldVisibility value) async { + final fieldService = + FieldService(gridId: gridId, fieldId: value.fieldId); + final result = + await fieldService.updateField(visibility: value.visibility); + result.fold( + (l) => null, + (err) => Log.error(err), + ); + }, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(fields: value.fields)); + }, + moveField: (_MoveField value) { + // + }, + ); + }, + ); + } + + @override + Future close() async { + if (_onFieldsFn != null) { + _fieldCache.removeListener(onFieldsListener: _onFieldsFn!); + _onFieldsFn = null; + } + return super.close(); + } + + void _startListening() { + _onFieldsFn = (fields) => add(GridGroupEvent.didReceiveFieldUpdate(fields)); + _fieldCache.addListener( + onFields: _onFieldsFn, + listenWhen: () => !isClosed, + ); + } +} + +@freezed +class GridGroupEvent with _$GridGroupEvent { + const factory GridGroupEvent.initial() = _Initial; + const factory GridGroupEvent.setFieldVisibility( + String fieldId, bool visibility) = _SetFieldVisibility; + const factory GridGroupEvent.didReceiveFieldUpdate(List fields) = + _DidReceiveFieldUpdate; + const factory GridGroupEvent.moveField(int fromIndex, int toIndex) = + _MoveField; +} + +@freezed +class GridGroupState with _$GridGroupState { + const factory GridGroupState({ + required String gridId, + required List fields, + }) = _GridGroupState; + + factory GridGroupState.initial(String gridId, List fields) => + GridGroupState( + gridId: gridId, + fields: fields, + ); +} 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 index 6894cc3df1..291413f096 100644 --- 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 @@ -1,12 +1,22 @@ import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +<<<<<<< HEAD +======= +import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; +>>>>>>> 0e1004785 (chore: config switch group field UI) import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +<<<<<<< HEAD +======= +import 'package:flowy_infra_ui/widget/spacing.dart'; +>>>>>>> 0e1004785 (chore: config switch group field UI) import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:app_flowy/plugins/grid/application/setting/group_bloc.dart'; + +import 'package:flutter_bloc/flutter_bloc.dart'; class GridGroupList extends StatelessWidget { final String viewId; @@ -19,7 +29,31 @@ class GridGroupList extends StatelessWidget { @override Widget build(BuildContext context) { - return Container(); + return BlocProvider( + create: (context) => GridGroupBloc(gridId: viewId, fieldCache: fieldCache) + ..add(const GridGroupEvent.initial()), + child: BlocBuilder( + builder: (context, state) { + final cells = state.fields.map((field) { + return _GridGroupCell( + field: field, + key: ValueKey(field.id), + ); + }).toList(); + + return ListView.separated( + shrinkWrap: true, + itemCount: cells.length, + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + separatorBuilder: (BuildContext context, int index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + ); + }, + ), + ); } void show(BuildContext context) {} 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 9c02a2c692..e0397a2673 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs @@ -25,7 +25,7 @@ pub struct GridSettingPB { pub filter_configuration_by_field_id: HashMap, #[pb(index = 4)] - pub group_configuration_by_field_id: HashMap, + pub group_configurations: RepeatedGridGroupConfigurationPB, } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] 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 70db181f59..b97e680f3a 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 @@ -464,7 +464,7 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { 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 + let filter_configuration_by_field_id = view_pad .get_all_filters(field_revs) .map(|filters_by_field_id| { filters_by_field_id @@ -473,21 +473,21 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc>() }) .unwrap_or_default(); - let groups_by_field_id = view_pad + let group_configurations = view_pad .get_groups_by_field_revs(field_revs) .map(|groups_by_field_id| { groups_by_field_id .into_iter() - .map(|(k, v)| (k, v.into())) - .collect::>() + .map(|(_, v)| 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, + filter_configuration_by_field_id, + group_configurations, } } From f57ba8b9a82c70def50b5eed5b211c22b9e21090 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 3 Sep 2022 16:47:58 +0800 Subject: [PATCH 7/9] chore: read setting --- ...text_builder.dart => cell_controller.dart} | 0 .../cell/cell_service/cell_service.dart | 2 +- .../grid/application/field/field_cache.dart | 6 +- .../grid/application/setting/group_bloc.dart | 14 ++++- .../setting/setting_controller.dart | 58 +++++++++++++++++++ .../application/setting/setting_listener.dart | 47 +++++++++++++++ .../application/setting/setting_service.dart | 16 +++++ .../widgets/toolbar/grid_group.dart | 12 ++-- .../flowy-grid/src/dart_notification.rs | 1 + .../src/entities/filter_entities/util.rs | 16 ++--- .../src/entities/setting_entities.rs | 6 +- .../flowy-grid/src/services/grid_editor.rs | 2 +- .../src/services/grid_view_editor.rs | 37 +++++++----- .../src/services/grid_view_manager.rs | 4 +- .../flowy-grid/tests/grid/grid_editor.rs | 2 +- 15 files changed, 178 insertions(+), 45 deletions(-) rename frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/{context_builder.dart => cell_controller.dart} (100%) create mode 100644 frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart create mode 100644 frontend/app_flowy/lib/plugins/grid/application/setting/setting_listener.dart create mode 100644 frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart similarity index 100% rename from frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart rename to frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart index 48e82cc906..eb64543167 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart @@ -21,7 +21,7 @@ import '../../field/type_option/type_option_context.dart'; import 'cell_field_notifier.dart'; part 'cell_service.freezed.dart'; part 'cell_data_loader.dart'; -part 'context_builder.dart'; +part 'cell_controller.dart'; part 'cell_cache.dart'; part 'cell_data_persistence.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart index e521f097ee..b83c261626 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart @@ -52,9 +52,6 @@ class GridFieldCache { _fieldNotifier = null; } - UnmodifiableListView get unmodifiableFields => - UnmodifiableListView(_fieldNotifier?.fields ?? []); - List get fields => [..._fieldNotifier?.fields ?? []]; set fields(List fields) { @@ -158,7 +155,8 @@ class GridRowFieldNotifierImpl extends IGridRowFieldNotifier { GridRowFieldNotifierImpl(GridFieldCache cache) : _cache = cache; @override - UnmodifiableListView get fields => _cache.unmodifiableFields; + UnmodifiableListView get fields => + UnmodifiableListView(_cache.fields); @override void onRowFieldsChanged(VoidCallback callback) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart index 80ab7f91f2..691371bd8a 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart @@ -6,16 +6,19 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import '../field/field_cache.dart'; +import 'setting_controller.dart'; part 'group_bloc.freezed.dart'; class GridGroupBloc extends Bloc { final GridFieldCache _fieldCache; + final SettingController _settingController; Function(List)? _onFieldsFn; - GridGroupBloc({required String gridId, required GridFieldCache fieldCache}) + GridGroupBloc({required String viewId, required GridFieldCache fieldCache}) : _fieldCache = fieldCache, - super(GridGroupState.initial(gridId, fieldCache.fields)) { + _settingController = SettingController(viewId: viewId), + super(GridGroupState.initial(viewId, fieldCache.fields)) { on( (event, emit) async { await event.map( @@ -24,7 +27,7 @@ class GridGroupBloc extends Bloc { }, setFieldVisibility: (_SetFieldVisibility value) async { final fieldService = - FieldService(gridId: gridId, fieldId: value.fieldId); + FieldService(gridId: viewId, fieldId: value.fieldId); final result = await fieldService.updateField(visibility: value.visibility); result.fold( @@ -58,6 +61,11 @@ class GridGroupBloc extends Bloc { onFields: _onFieldsFn, listenWhen: () => !isClosed, ); + + _settingController.startListeing( + onSettingUpdated: (setting) {}, + onError: (err) {}, + ); } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart new file mode 100644 index 0000000000..721e5d35f1 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart @@ -0,0 +1,58 @@ +import 'package:app_flowy/plugins/grid/application/setting/setting_service.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; +import 'setting_listener.dart'; + +typedef OnError = void Function(FlowyError); +typedef OnSettingUpdated = void Function(GridSettingPB); + +class SettingController { + final String viewId; + final SettingFFIService _ffiService; + final SettingListener _listener; + OnSettingUpdated? _onSettingUpdated; + OnError? _onError; + GridSettingPB? _setting; + GridSettingPB? get setting => _setting; + + SettingController({ + required this.viewId, + }) : _ffiService = SettingFFIService(viewId: viewId), + _listener = SettingListener(gridId: viewId) { + // Load setting + _ffiService.getSetting().then((result) { + result.fold( + (newSetting) => updateSetting(newSetting), + (err) => _onError?.call(err), + ); + }); + + // Listen on the seting changes + _listener.start(onSettingUpdated: (result) { + result.fold( + (newSetting) => updateSetting(newSetting), + (err) => _onError?.call(err), + ); + }); + } + + void startListeing({ + required OnSettingUpdated onSettingUpdated, + required OnError onError, + }) { + assert(_onSettingUpdated == null, 'Should call once'); + _onSettingUpdated = onSettingUpdated; + _onError = onError; + } + + void updateSetting(GridSettingPB newSetting) { + _setting = newSetting; + _onSettingUpdated?.call(newSetting); + } + + void dispose() { + _onSettingUpdated = null; + _onError = null; + _listener.stop(); + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_listener.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_listener.dart new file mode 100644 index 0000000000..00de48ca78 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_listener.dart @@ -0,0 +1,47 @@ +import 'dart:typed_data'; + +import 'package:app_flowy/core/grid_notification.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pbserver.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; + +typedef UpdateSettingNotifiedValue = Either; + +class SettingListener { + final String gridId; + GridNotificationListener? _listener; + PublishNotifier? _updateSettingNotifier = + PublishNotifier(); + + SettingListener({required this.gridId}); + + void start({ + required void Function(UpdateSettingNotifiedValue) onSettingUpdated, + }) { + _updateSettingNotifier?.addPublishListener(onSettingUpdated); + _listener = GridNotificationListener(objectId: gridId, handler: _handler); + } + + void _handler(GridNotification ty, Either result) { + switch (ty) { + case GridNotification.DidUpdateGridSetting: + result.fold( + (payload) => _updateSettingNotifier?.value = left( + GridSettingPB.fromBuffer(payload), + ), + (error) => _updateSettingNotifier?.value = right(error), + ); + break; + default: + break; + } + } + + Future stop() async { + await _listener?.stop(); + _updateSettingNotifier?.dispose(); + _updateSettingNotifier = null; + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart new file mode 100644 index 0000000000..8d3774ec1c --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart @@ -0,0 +1,16 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; + +class SettingFFIService { + final String viewId; + + const SettingFFIService({required this.viewId}); + + Future> getSetting() { + final payload = GridIdPB.create()..value = viewId; + return GridEventGetGridSetting(payload).send(); + } +} 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 index 291413f096..770e16e2bf 100644 --- 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 @@ -1,17 +1,11 @@ import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; -<<<<<<< HEAD -======= import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; ->>>>>>> 0e1004785 (chore: config switch group field UI) import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -<<<<<<< HEAD -======= import 'package:flowy_infra_ui/widget/spacing.dart'; ->>>>>>> 0e1004785 (chore: config switch group field UI) import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:app_flowy/plugins/grid/application/setting/group_bloc.dart'; @@ -30,8 +24,10 @@ class GridGroupList extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => GridGroupBloc(gridId: viewId, fieldCache: fieldCache) - ..add(const GridGroupEvent.initial()), + create: (context) => GridGroupBloc( + viewId: viewId, + fieldCache: fieldCache, + )..add(const GridGroupEvent.initial()), child: BlocBuilder( builder: (context, state) { final cells = state.fields.map((field) { diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index ca0f0aa681..8d7ec2ba36 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -14,6 +14,7 @@ pub enum GridNotification { DidUpdateGroupView = 60, DidUpdateGroup = 61, DidGroupByNewField = 62, + DidUpdateGridSetting = 70, } impl std::default::Default for GridNotification { 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 7dff00bf56..f8588944e7 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 @@ -10,33 +10,33 @@ use std::convert::TryInto; use std::sync::Arc; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct GridFilterConfiguration { +pub struct GridFilterConfigurationPB { #[pb(index = 1)] pub id: String, } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct RepeatedGridConfigurationFilterPB { +pub struct RepeatedGridFilterConfigurationPB { #[pb(index = 1)] - pub items: Vec, + pub items: Vec, } -impl std::convert::From<&FilterConfigurationRevision> for GridFilterConfiguration { +impl std::convert::From<&FilterConfigurationRevision> for GridFilterConfigurationPB { fn from(rev: &FilterConfigurationRevision) -> Self { Self { id: rev.id.clone() } } } -impl std::convert::From>> for RepeatedGridConfigurationFilterPB { +impl std::convert::From>> for RepeatedGridFilterConfigurationPB { fn from(revs: Vec>) -> Self { - RepeatedGridConfigurationFilterPB { + RepeatedGridFilterConfigurationPB { items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(), } } } -impl std::convert::From> for RepeatedGridConfigurationFilterPB { - fn from(items: Vec) -> Self { +impl std::convert::From> for RepeatedGridFilterConfigurationPB { + fn from(items: Vec) -> Self { Self { items } } } 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 e0397a2673..47efc11861 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs @@ -1,6 +1,6 @@ use crate::entities::{ CreatGroupParams, CreateFilterParams, CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, DeleteFilterParams, - DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, RepeatedGridConfigurationFilterPB, + DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, RepeatedGridFilterConfigurationPB, RepeatedGridGroupConfigurationPB, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -19,10 +19,10 @@ pub struct GridSettingPB { pub layouts: Vec, #[pb(index = 2)] - pub current_layout_type: GridLayout, + pub layout_type: GridLayout, #[pb(index = 3)] - pub filter_configuration_by_field_id: HashMap, + pub filter_configurations: RepeatedGridFilterConfigurationPB, #[pb(index = 4)] pub group_configurations: RepeatedGridGroupConfigurationPB, 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 5b8d4e0d91..2f72f48d33 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -532,7 +532,7 @@ impl GridRevisionEditor { self.view_manager.get_setting().await } - pub async fn get_grid_filter(&self) -> FlowyResult> { + pub async fn get_grid_filter(&self) -> FlowyResult> { self.view_manager.get_filters().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 b97e680f3a..71d2fb372a 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::{ - CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridLayout, GridLayoutPB, - GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertedGroupPB, InsertedRowPB, MoveGroupParams, - RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RowPB, + CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfigurationPB, GridGroupConfigurationPB, + GridLayout, GridLayoutPB, GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertedGroupPB, + InsertedRowPB, MoveGroupParams, RepeatedGridFilterConfigurationPB, RepeatedGridGroupConfigurationPB, RowPB, }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; @@ -198,14 +198,14 @@ impl GridViewRevisionEditor { grid_setting } - pub(crate) async fn get_filters(&self) -> Vec { + 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) { None => vec![], Some(filters) => filters .into_values() .flatten() - .map(|filter| GridFilterConfiguration::from(filter.as_ref())) + .map(|filter| GridFilterConfigurationPB::from(filter.as_ref())) .collect(), } } @@ -463,31 +463,40 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { } pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc]) -> GridSettingPB { - let current_layout_type: GridLayout = view_pad.layout.clone().into(); - let filter_configuration_by_field_id = view_pad + let layout_type: GridLayout = view_pad.layout.clone().into(); + let filter_configurations = 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::>() + .map(|(_, v)| { + let repeated_filter: RepeatedGridFilterConfigurationPB = v.into(); + repeated_filter.items + }) + .flatten() + .collect::>() }) .unwrap_or_default(); + let group_configurations = view_pad .get_groups_by_field_revs(field_revs) .map(|groups_by_field_id| { groups_by_field_id .into_iter() - .map(|(_, v)| v.into()) - .collect::() + .map(|(_, v)| { + let repeated_group: RepeatedGridGroupConfigurationPB = v.into(); + repeated_group.items + }) + .flatten() + .collect::>() }) .unwrap_or_default(); GridSettingPB { layouts: GridLayoutPB::all(), - current_layout_type, - filter_configuration_by_field_id, - group_configurations, + layout_type, + filter_configurations: filter_configurations.into(), + group_configurations: group_configurations.into(), } } 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 61216cc88b..460be37a44 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,5 @@ use crate::entities::{ - CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridSettingPB, MoveGroupParams, + CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfigurationPB, GridSettingPB, MoveGroupParams, RepeatedGridGroupPB, RowPB, }; use crate::manager::GridUser; @@ -105,7 +105,7 @@ impl GridViewManager { Ok(view_editor.get_setting().await) } - pub(crate) async fn get_filters(&self) -> FlowyResult> { + pub(crate) async fn get_filters(&self) -> FlowyResult> { let view_editor = self.get_default_view_editor().await?; Ok(view_editor.get_filters().await) } 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 0325f6f008..2bbf5874aa 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs @@ -85,7 +85,7 @@ impl GridEditorTest { .row_revs } - pub async fn grid_filters(&self) -> Vec { + pub async fn grid_filters(&self) -> Vec { self.editor.get_grid_filter().await.unwrap() } From 54d6f3709e38ff378431f8733bfcecdd112a796c Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 3 Sep 2022 17:16:48 +0800 Subject: [PATCH 8/9] chore: replace FieldPB with GridField --- .../plugins/board/application/board_bloc.dart | 3 +- .../application/board_data_controller.dart | 45 ++--- .../card/board_date_cell_bloc.dart | 10 +- .../board/application/card/card_bloc.dart | 10 +- .../card/card_data_controller.dart | 8 +- .../board/presentation/board_page.dart | 16 +- .../presentation/toolbar/board_setting.dart | 10 +- .../presentation/toolbar/board_toolbar.dart | 4 +- .../grid/application/block/block_cache.dart | 4 +- .../cell/cell_service/cell_controller.dart | 25 +-- .../cell/cell_service/cell_service.dart | 8 +- .../grid/application/cell/date_cal_bloc.dart | 2 +- .../grid/application/cell/date_cell_bloc.dart | 10 +- .../cell/select_option_service.dart | 2 +- .../grid/application/field/field_cache.dart | 165 +++++++++++++----- .../grid/application/field/field_service.dart | 2 + .../type_option/type_option_context.dart | 1 + .../type_option_data_controller.dart | 7 +- .../plugins/grid/application/grid_bloc.dart | 10 +- .../application/grid_data_controller.dart | 29 +-- .../grid/application/grid_header_bloc.dart | 19 +- .../grid/application/row/row_bloc.dart | 20 ++- .../grid/application/row/row_cache.dart | 7 +- .../application/row/row_data_controller.dart | 8 +- .../grid/application/setting/group_bloc.dart | 29 +-- .../application/setting/property_bloc.dart | 32 ++-- .../setting/setting_controller.dart | 1 + .../plugins/grid/presentation/grid_page.dart | 21 ++- .../grid/presentation/layout/layout.dart | 4 +- .../widgets/header/field_cell.dart | 1 + .../widgets/header/grid_header.dart | 8 +- .../widgets/header/type_option/builder.dart | 10 +- .../presentation/widgets/row/grid_row.dart | 4 +- .../presentation/widgets/row/row_detail.dart | 6 +- .../widgets/toolbar/grid_group.dart | 21 +-- .../widgets/toolbar/grid_property.dart | 32 ++-- .../widgets/toolbar/grid_setting.dart | 6 +- .../widgets/toolbar/grid_toolbar.dart | 6 +- .../app_flowy/lib/startup/deps_resolver.dart | 10 +- 39 files changed, 338 insertions(+), 278 deletions(-) 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 d4ffebd117..b78bc86661 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -25,7 +25,8 @@ class BoardBloc extends Bloc { final MoveRowFFIService _rowService; LinkedHashMap groupControllers = LinkedHashMap(); - GridFieldCache get fieldCache => _gridDataController.fieldCache; + GridFieldController get fieldController => + _gridDataController.fieldController; String get gridId => _gridDataController.gridId; BoardBloc({required ViewPB view}) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index c78621b0a3..5435db2c3a 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -12,7 +12,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'board_listener.dart'; -typedef OnFieldsChanged = void Function(UnmodifiableListView); +typedef OnFieldsChanged = void Function(UnmodifiableListView); typedef OnGridChanged = void Function(GridPB); typedef DidLoadGroups = void Function(List); typedef OnUpdatedGroup = void Function(List); @@ -29,7 +29,7 @@ typedef OnError = void Function(FlowyError); class BoardDataController { final String gridId; final GridFFIService _gridFFIService; - final GridFieldCache fieldCache; + final GridFieldController fieldController; final BoardListener _listener; // key: the block id @@ -56,7 +56,7 @@ class BoardDataController { // ignore: prefer_collection_literals _blocks = LinkedHashMap(), _gridFFIService = GridFFIService(gridId: view.id), - fieldCache = GridFieldCache(gridId: view.id); + fieldController = GridFieldController(gridId: view.id); void addListener({ required OnGridChanged onGridChanged, @@ -75,7 +75,7 @@ class BoardDataController { _onRowsChanged = onRowsChanged; _onError = onError; - fieldCache.addListener(onFields: (fields) { + fieldController.addListener(onFields: (fields) { _onFieldsChanged?.call(UnmodifiableListView(fields)); }); @@ -113,16 +113,15 @@ class BoardDataController { () => result.fold( (grid) async { _onGridChanged?.call(grid); - - return await _loadFields(grid).then((result) { - return result.fold( - (l) { - _loadGroups(grid.blocks); - return left(l); - }, - (err) => right(err), - ); - }); + return await fieldController.loadFields(fieldIds: grid.fields).then( + (result) => result.fold( + (l) { + _loadGroups(grid.blocks); + return left(l); + }, + (err) => right(err), + ), + ); }, (err) => right(err), ), @@ -136,33 +135,19 @@ class BoardDataController { Future dispose() async { await _gridFFIService.closeGrid(); - await fieldCache.dispose(); + await fieldController.dispose(); for (final blockCache in _blocks.values) { blockCache.dispose(); } } - Future> _loadFields(GridPB grid) async { - final result = await _gridFFIService.getFields(fieldIds: grid.fields); - return Future( - () => result.fold( - (fields) { - fieldCache.fields = fields.items; - _onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields)); - return left(unit); - }, - (err) => right(err), - ), - ); - } - Future _loadGroups(List blocks) async { for (final block in blocks) { final cache = GridBlockCache( gridId: gridId, block: block, - fieldCache: fieldCache, + fieldController: fieldController, ); cache.addListener(onRowsChanged: (reason) { diff --git a/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart index b1110f45cc..dd1f77a9d1 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -20,8 +20,6 @@ class BoardDateCellBloc extends Bloc { emit(state.copyWith( data: cellData, dateStr: _dateStrFromCellData(cellData))); }, - didReceiveFieldUpdate: (FieldPB value) => - emit(state.copyWith(field: value)), ); }, ); @@ -53,8 +51,6 @@ class BoardDateCellEvent with _$BoardDateCellEvent { const factory BoardDateCellEvent.initial() = _InitialCell; const factory BoardDateCellEvent.didReceiveCellUpdate(DateCellDataPB? data) = _DidReceiveCellUpdate; - const factory BoardDateCellEvent.didReceiveFieldUpdate(FieldPB field) = - _DidReceiveFieldUpdate; } @freezed @@ -62,14 +58,14 @@ class BoardDateCellState with _$BoardDateCellState { const factory BoardDateCellState({ required DateCellDataPB? data, required String dateStr, - required FieldPB field, + required GridFieldContext fieldContext, }) = _BoardDateCellState; factory BoardDateCellState.initial(GridDateCellController context) { final cellData = context.getCellData(); return BoardDateCellState( - field: context.field, + fieldContext: context.fieldContext, data: cellData, dateStr: _dateStrFromCellData(cellData), ); diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart index ad30d2b250..e4dccbf0df 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart @@ -59,7 +59,7 @@ class BoardCardBloc extends Bloc { return RowInfo( gridId: _rowService.gridId, fields: UnmodifiableListView( - state.cells.map((cell) => cell.identifier.field).toList(), + state.cells.map((cell) => cell.identifier.fieldContext).toList(), ), rowPB: state.rowPB, ); @@ -120,9 +120,9 @@ class BoardCellEquatable extends Equatable { @override List get props => [ - identifier.field.id, - identifier.field.fieldType, - identifier.field.visibility, - identifier.field.width, + identifier.fieldContext.id, + identifier.fieldContext.fieldType, + identifier.fieldContext.visibility, + identifier.fieldContext.width, ]; } diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart index f362fdf0e6..377b0dae50 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart @@ -10,15 +10,15 @@ typedef OnCardChanged = void Function(GridCellMap, RowsChangedReason); class CardDataController extends BoardCellBuilderDelegate { final RowPB rowPB; - final GridFieldCache _fieldCache; + final GridFieldController _fieldController; final GridRowCache _rowCache; final List _onCardChangedListeners = []; CardDataController({ required this.rowPB, - required GridFieldCache fieldCache, + required GridFieldController fieldController, required GridRowCache rowCache, - }) : _fieldCache = fieldCache, + }) : _fieldController = fieldController, _rowCache = rowCache; GridCellMap loadData() { @@ -41,7 +41,7 @@ class CardDataController extends BoardCellBuilderDelegate { @override GridCellFieldNotifier buildFieldNotifier() { return GridCellFieldNotifier( - notifier: GridCellFieldNotifierImpl(_fieldCache)); + notifier: GridCellFieldNotifierImpl(_fieldController)); } @override diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 0b043a2ba7..f52237ad49 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -222,10 +222,10 @@ class _BoardContentState extends State { /// Return placeholder widget if the rowCache is null. if (rowCache == null) return SizedBox(key: ObjectKey(columnItem)); - final fieldCache = context.read().fieldCache; + final fieldController = context.read().fieldController; final gridId = context.read().gridId; final cardController = CardDataController( - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, rowPB: rowPB, ); @@ -252,7 +252,7 @@ class _BoardContentState extends State { dataController: cardController, openCard: (context) => _openCard( gridId, - fieldCache, + fieldController, rowPB, rowCache, context, @@ -271,17 +271,17 @@ class _BoardContentState extends State { ); } - void _openCard(String gridId, GridFieldCache fieldCache, RowPB rowPB, - GridRowCache rowCache, BuildContext context) { + void _openCard(String gridId, GridFieldController fieldController, + RowPB rowPB, GridRowCache rowCache, BuildContext context) { final rowInfo = RowInfo( gridId: gridId, - fields: UnmodifiableListView(fieldCache.fields), + fields: UnmodifiableListView(fieldController.fieldContexts), rowPB: rowPB, ); final dataController = GridRowDataController( rowInfo: rowInfo, - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, ); @@ -302,7 +302,7 @@ class _ToolbarBlocAdaptor extends StatelessWidget { final bloc = context.read(); final toolbarContext = BoardToolbarContext( viewId: bloc.gridId, - fieldCache: bloc.fieldCache, + fieldController: bloc.fieldController, ); return BoardToolbar(toolbarContext: toolbarContext); 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 d981bd6006..a270f50951 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 @@ -19,16 +19,16 @@ import 'board_toolbar.dart'; class BoardSettingContext { final String viewId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; BoardSettingContext({ required this.viewId, - required this.fieldCache, + required this.fieldController, }); factory BoardSettingContext.from(BoardToolbarContext toolbarContext) => BoardSettingContext( viewId: toolbarContext.viewId, - fieldCache: toolbarContext.fieldCache, + fieldController: toolbarContext.fieldController, ); } @@ -93,13 +93,13 @@ class BoardSettingList extends StatelessWidget { case BoardSettingAction.properties: GridPropertyList( gridId: settingContext.viewId, - fieldCache: settingContext.fieldCache) + fieldController: settingContext.fieldController) .show(context); break; case BoardSettingAction.groups: GridGroupList( viewId: settingContext.viewId, - fieldCache: settingContext.fieldCache) + fieldController: settingContext.fieldController) .show(context); break; } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart index fae27851a9..bf8d2e3443 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart @@ -9,11 +9,11 @@ import 'board_setting.dart'; class BoardToolbarContext { final String viewId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; BoardToolbarContext({ required this.viewId, - required this.fieldCache, + required this.fieldController, }); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart index b639700b5f..35ed334cee 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart @@ -19,12 +19,12 @@ class GridBlockCache { GridBlockCache({ required this.gridId, required this.block, - required GridFieldCache fieldCache, + required GridFieldController fieldController, }) { _rowCache = GridRowCache( gridId: gridId, block: block, - notifier: GridRowFieldNotifierImpl(fieldCache), + notifier: GridRowFieldNotifierImpl(fieldController), ); _listener = GridBlockListener(blockId: block.id); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart index d716133d05..29fb521976 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart @@ -148,10 +148,10 @@ class IGridCellController extends Equatable { _cellDataLoader = cellDataLoader, _cellDataPersistence = cellDataPersistence, _fieldNotifier = fieldNotifier, - _fieldService = - FieldService(gridId: cellId.gridId, fieldId: cellId.field.id), - _cacheKey = - GridCellCacheKey(rowId: cellId.rowId, fieldId: cellId.field.id); + _fieldService = FieldService( + gridId: cellId.gridId, fieldId: cellId.fieldContext.id), + _cacheKey = GridCellCacheKey( + rowId: cellId.rowId, fieldId: cellId.fieldContext.id); IGridCellController clone() { return IGridCellController( @@ -166,11 +166,11 @@ class IGridCellController extends Equatable { String get rowId => cellId.rowId; - String get fieldId => cellId.field.id; + String get fieldId => cellId.fieldContext.id; - FieldPB get field => cellId.field; + GridFieldContext get fieldContext => cellId.fieldContext; - FieldType get fieldType => cellId.field.fieldType; + FieldType get fieldType => cellId.fieldContext.fieldType; VoidCallback? startListening( {required void Function(T?) onCellChanged, @@ -182,7 +182,8 @@ class IGridCellController extends Equatable { isListening = true; _cellDataNotifier = ValueNotifier(_cellsCache.get(_cacheKey)); - _cellListener = CellListener(rowId: cellId.rowId, fieldId: cellId.field.id); + _cellListener = + CellListener(rowId: cellId.rowId, fieldId: cellId.fieldContext.id); /// 1.Listen on user edit event and load the new cell data if needed. /// For example: @@ -308,14 +309,14 @@ class IGridCellController extends Equatable { @override List get props => - [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.field.id]; + [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.fieldContext.id]; } class GridCellFieldNotifierImpl extends IGridCellFieldNotifier { - final GridFieldCache _cache; - FieldChangesetCallback? _onChangesetFn; + final GridFieldController _cache; + OnChangeset? _onChangesetFn; - GridCellFieldNotifierImpl(GridFieldCache cache) : _cache = cache; + GridCellFieldNotifierImpl(GridFieldController cache) : _cache = cache; @override void onCellDispose() { diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart index eb64543167..360df60b4e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart @@ -60,17 +60,17 @@ class GridCellIdentifier with _$GridCellIdentifier { const factory GridCellIdentifier({ required String gridId, required String rowId, - required FieldPB field, + required GridFieldContext fieldContext, }) = _GridCellIdentifier; // ignore: unused_element const GridCellIdentifier._(); - String get fieldId => field.id; + String get fieldId => fieldContext.id; - FieldType get fieldType => field.fieldType; + FieldType get fieldType => fieldContext.fieldType; ValueKey key() { - return ValueKey("$rowId$fieldId${field.fieldType}"); + return ValueKey("$rowId$fieldId${fieldContext.fieldType}"); } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart index a7124b7a3d..6fb8e7e5b0 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart @@ -176,7 +176,7 @@ class DateCalBloc extends Bloc { final result = await FieldService.updateFieldTypeOption( gridId: cellController.gridId, - fieldId: cellController.field.id, + fieldId: cellController.fieldContext.id, typeOptionData: newDateTypeOption.writeToBuffer(), ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart index 4d453eca25..ae840e9e54 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart @@ -1,5 +1,5 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -20,8 +20,6 @@ class DateCellBloc extends Bloc { emit(state.copyWith( data: cellData, dateStr: _dateStrFromCellData(cellData))); }, - didReceiveFieldUpdate: (FieldPB value) => - emit(state.copyWith(field: value)), ); }, ); @@ -53,8 +51,6 @@ class DateCellEvent with _$DateCellEvent { const factory DateCellEvent.initial() = _InitialCell; const factory DateCellEvent.didReceiveCellUpdate(DateCellDataPB? data) = _DidReceiveCellUpdate; - const factory DateCellEvent.didReceiveFieldUpdate(FieldPB field) = - _DidReceiveFieldUpdate; } @freezed @@ -62,14 +58,14 @@ class DateCellState with _$DateCellState { const factory DateCellState({ required DateCellDataPB? data, required String dateStr, - required FieldPB field, + required GridFieldContext fieldContext, }) = _DateCellState; factory DateCellState.initial(GridDateCellController context) { final cellData = context.getCellData(); return DateCellState( - field: context.field, + fieldContext: context.fieldContext, data: cellData, dateStr: _dateStrFromCellData(cellData), ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart index 44d4bdd4be..7d5be30eda 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart @@ -11,7 +11,7 @@ class SelectOptionService { SelectOptionService({required this.cellId}); String get gridId => cellId.gridId; - String get fieldId => cellId.field.id; + String get fieldId => cellId.fieldContext.id; String get rowId => cellId.rowId; Future> create({required String name}) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart index b83c261626..da12afff97 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart @@ -1,36 +1,47 @@ import 'dart:collection'; - import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart'; +import 'package:app_flowy/plugins/grid/application/grid_service.dart'; +import 'package:app_flowy/plugins/grid/application/setting/setting_listener.dart'; +import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/foundation.dart'; - import '../row/row_cache.dart'; -class FieldsNotifier extends ChangeNotifier { - List _fields = []; +class _GridFieldNotifier extends ChangeNotifier { + List _fieldContexts = []; - set fields(List fields) { - _fields = fields; + set fieldContexts(List fieldContexts) { + _fieldContexts = fieldContexts; notifyListeners(); } - List get fields => _fields; + void notify() { + notifyListeners(); + } + + List get fieldContexts => _fieldContexts; } -typedef FieldChangesetCallback = void Function(FieldChangesetPB); -typedef FieldsCallback = void Function(List); +typedef OnChangeset = void Function(FieldChangesetPB); +typedef OnReceiveFields = void Function(List); -class GridFieldCache { +class GridFieldController { final String gridId; final GridFieldsListener _fieldListener; - FieldsNotifier? _fieldNotifier = FieldsNotifier(); - final Map _fieldsCallbackMap = {}; - final Map - _changesetCallbackMap = {}; + final SettingListener _settingListener; + final Map _fieldCallbackMap = {}; + final Map _changesetCallbackMap = {}; - GridFieldCache({required this.gridId}) - : _fieldListener = GridFieldsListener(gridId: gridId) { + _GridFieldNotifier? _fieldNotifier = _GridFieldNotifier(); + final GridFFIService _gridFFIService; + + GridFieldController({required this.gridId}) + : _fieldListener = GridFieldsListener(gridId: gridId), + _gridFFIService = GridFFIService(gridId: gridId), + _settingListener = SettingListener(gridId: gridId) { + //Listen on field's changes _fieldListener.start(onFieldsChanged: (result) { result.fold( (changeset) { @@ -44,6 +55,28 @@ class GridFieldCache { (err) => Log.error(err), ); }); + + //Listen on setting changes + _settingListener.start(onSettingUpdated: (result) { + result.fold( + (setting) { + final List groupFieldIds = setting.groupConfigurations.items + .map((item) => item.groupFieldId) + .toList(); + bool isChanged = false; + if (_fieldNotifier != null) { + for (var field in _fieldNotifier!.fieldContexts) { + if (groupFieldIds.contains(field.id)) { + field._isGroupField = true; + isChanged = true; + } + } + if (isChanged) _fieldNotifier?.notify(); + } + }, + (r) => Log.error(r), + ); + }); } Future dispose() async { @@ -52,49 +85,62 @@ class GridFieldCache { _fieldNotifier = null; } - List get fields => [..._fieldNotifier?.fields ?? []]; + List get fieldContexts => + [..._fieldNotifier?.fieldContexts ?? []]; - set fields(List fields) { - _fieldNotifier?.fields = [...fields]; + Future> loadFields( + {required List fieldIds}) async { + final result = await _gridFFIService.getFields(fieldIds: fieldIds); + return Future( + () => result.fold( + (newFields) { + _fieldNotifier?.fieldContexts = newFields.items + .map((field) => GridFieldContext(field: field)) + .toList(); + return left(unit); + }, + (err) => right(err), + ), + ); } void addListener({ - FieldsCallback? onFields, - FieldChangesetCallback? onChangeset, + OnReceiveFields? onFields, + OnChangeset? onChangeset, bool Function()? listenWhen, }) { if (onChangeset != null) { - fn(c) { + callback(c) { if (listenWhen != null && listenWhen() == false) { return; } onChangeset(c); } - _changesetCallbackMap[onChangeset] = fn; + _changesetCallbackMap[onChangeset] = callback; } if (onFields != null) { - fn() { + callback() { if (listenWhen != null && listenWhen() == false) { return; } - onFields(fields); + onFields(fieldContexts); } - _fieldsCallbackMap[onFields] = fn; - _fieldNotifier?.addListener(fn); + _fieldCallbackMap[onFields] = callback; + _fieldNotifier?.addListener(callback); } } void removeListener({ - FieldsCallback? onFieldsListener, - FieldChangesetCallback? onChangesetListener, + OnReceiveFields? onFieldsListener, + OnChangeset? onChangesetListener, }) { if (onFieldsListener != null) { - final fn = _fieldsCallbackMap.remove(onFieldsListener); - if (fn != null) { - _fieldNotifier?.removeListener(fn); + final callback = _fieldCallbackMap.remove(onFieldsListener); + if (callback != null) { + _fieldNotifier?.removeListener(callback); } } @@ -107,56 +153,58 @@ class GridFieldCache { if (deletedFields.isEmpty) { return; } - final List newFields = fields; + final List newFields = fieldContexts; final Map deletedFieldMap = { for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder }; newFields.retainWhere((field) => (deletedFieldMap[field.id] == null)); - _fieldNotifier?.fields = newFields; + _fieldNotifier?.fieldContexts = newFields; } void _insertFields(List insertedFields) { if (insertedFields.isEmpty) { return; } - final List newFields = fields; + final List newFields = fieldContexts; for (final indexField in insertedFields) { + final gridField = GridFieldContext(field: indexField.field_1); if (newFields.length > indexField.index) { - newFields.insert(indexField.index, indexField.field_1); + newFields.insert(indexField.index, gridField); } else { - newFields.add(indexField.field_1); + newFields.add(gridField); } } - _fieldNotifier?.fields = newFields; + _fieldNotifier?.fieldContexts = newFields; } void _updateFields(List updatedFields) { if (updatedFields.isEmpty) { return; } - final List newFields = fields; + final List newFields = fieldContexts; for (final updatedField in updatedFields) { final index = newFields.indexWhere((field) => field.id == updatedField.id); if (index != -1) { newFields.removeAt(index); - newFields.insert(index, updatedField); + final gridField = GridFieldContext(field: updatedField); + newFields.insert(index, gridField); } } - _fieldNotifier?.fields = newFields; + _fieldNotifier?.fieldContexts = newFields; } } class GridRowFieldNotifierImpl extends IGridRowFieldNotifier { - final GridFieldCache _cache; - FieldChangesetCallback? _onChangesetFn; - FieldsCallback? _onFieldFn; - GridRowFieldNotifierImpl(GridFieldCache cache) : _cache = cache; + final GridFieldController _cache; + OnChangeset? _onChangesetFn; + OnReceiveFields? _onFieldFn; + GridRowFieldNotifierImpl(GridFieldController cache) : _cache = cache; @override - UnmodifiableListView get fields => - UnmodifiableListView(_cache.fields); + UnmodifiableListView get fields => + UnmodifiableListView(_cache.fieldContexts); @override void onRowFieldsChanged(VoidCallback callback) { @@ -188,3 +236,26 @@ class GridRowFieldNotifierImpl extends IGridRowFieldNotifier { } } } + +class GridFieldContext { + final FieldPB _field; + bool _isGroupField = false; + + String get id => _field.id; + + FieldType get fieldType => _field.fieldType; + + bool get visibility => _field.visibility; + + double get width => _field.width.toDouble(); + + bool get isPrimary => _field.isPrimary; + + String get name => _field.name; + + FieldPB get field => _field; + + bool get isGroupField => _isGroupField; + + GridFieldContext({required FieldPB field}) : _field = field; +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart index 816f32fe16..5466a8de08 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart @@ -5,6 +5,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'field_cache.dart'; part 'field_service.freezed.dart'; /// FieldService consists of lots of event functions. We define the events in the backend(Rust), diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart index 632e333911..192c4f86f0 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart index 66f4c35c20..6f757be71d 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; @@ -17,12 +18,12 @@ class TypeOptionDataController { TypeOptionDataController({ required this.gridId, required this.loader, - FieldPB? field, + GridFieldContext? fieldContext, }) { - if (field != null) { + if (fieldContext != null) { _data = FieldTypeOptionDataPB.create() ..gridId = gridId - ..field_2 = field; + ..field_2 = fieldContext.field; } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart index 74f23a1b3e..139b08251e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart @@ -7,6 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'block/block_cache.dart'; +import 'field/field_cache.dart'; import 'grid_data_controller.dart'; import 'row/row_cache.dart'; import 'dart:collection'; @@ -101,7 +102,7 @@ class GridEvent with _$GridEvent { RowsChangedReason listState, ) = _DidReceiveRowUpdate; const factory GridEvent.didReceiveFieldUpdate( - UnmodifiableListView fields, + UnmodifiableListView fields, ) = _DidReceiveFieldUpdate; const factory GridEvent.didReceiveGridUpdate( @@ -138,9 +139,9 @@ class GridLoadingState with _$GridLoadingState { } class GridFieldEquatable extends Equatable { - final UnmodifiableListView _fields; + final UnmodifiableListView _fields; const GridFieldEquatable( - UnmodifiableListView fields, + UnmodifiableListView fields, ) : _fields = fields; @override @@ -157,5 +158,6 @@ class GridFieldEquatable extends Equatable { ]; } - UnmodifiableListView get value => UnmodifiableListView(_fields); + UnmodifiableListView get value => + UnmodifiableListView(_fields); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart index 55733b9b7b..6caf699641 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart @@ -4,7 +4,6 @@ import 'package:flowy_sdk/log.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/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; @@ -13,7 +12,7 @@ import 'field/field_cache.dart'; import 'prelude.dart'; import 'row/row_cache.dart'; -typedef OnFieldsChanged = void Function(UnmodifiableListView); +typedef OnFieldsChanged = void Function(UnmodifiableListView); typedef OnGridChanged = void Function(GridPB); typedef OnRowsChanged = void Function( @@ -25,7 +24,7 @@ typedef ListenOnRowChangedCondition = bool Function(); class GridDataController { final String gridId; final GridFFIService _gridFFIService; - final GridFieldCache fieldCache; + final GridFieldController fieldController; // key: the block id final LinkedHashMap _blocks; @@ -49,7 +48,7 @@ class GridDataController { // ignore: prefer_collection_literals _blocks = LinkedHashMap(), _gridFFIService = GridFFIService(gridId: view.id), - fieldCache = GridFieldCache(gridId: view.id); + fieldController = GridFieldController(gridId: view.id); void addListener({ required OnGridChanged onGridChanged, @@ -60,7 +59,7 @@ class GridDataController { _onRowChanged = onRowsChanged; _onFieldsChanged = onFieldsChanged; - fieldCache.addListener(onFields: (fields) { + fieldController.addListener(onFields: (fields) { _onFieldsChanged?.call(UnmodifiableListView(fields)); }); } @@ -72,7 +71,7 @@ class GridDataController { (grid) async { _initialBlocks(grid.blocks); _onGridChanged?.call(grid); - return await _loadFields(grid); + return await fieldController.loadFields(fieldIds: grid.fields); }, (err) => right(err), ), @@ -85,7 +84,7 @@ class GridDataController { Future dispose() async { await _gridFFIService.closeGrid(); - await fieldCache.dispose(); + await fieldController.dispose(); for (final blockCache in _blocks.values) { blockCache.dispose(); @@ -102,7 +101,7 @@ class GridDataController { final cache = GridBlockCache( gridId: gridId, block: block, - fieldCache: fieldCache, + fieldController: fieldController, ); cache.addListener( @@ -114,18 +113,4 @@ class GridDataController { _blocks[block.id] = cache; } } - - Future> _loadFields(GridPB grid) async { - final result = await _gridFFIService.getFields(fieldIds: grid.fields); - return Future( - () => result.fold( - (fields) { - fieldCache.fields = fields.items; - _onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields)); - return left(unit); - }, - (err) => right(err), - ), - ); - } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart index 125bd8d652..b7e1ade527 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart @@ -4,19 +4,18 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - import 'field/field_cache.dart'; part 'grid_header_bloc.freezed.dart'; class GridHeaderBloc extends Bloc { - final GridFieldCache fieldCache; + final GridFieldController fieldController; final String gridId; GridHeaderBloc({ required this.gridId, - required this.fieldCache, - }) : super(GridHeaderState.initial(fieldCache.fields)) { + required this.fieldController, + }) : super(GridHeaderState.initial(fieldController.fieldContexts)) { on( (event, emit) async { await event.map( @@ -36,7 +35,7 @@ class GridHeaderBloc extends Bloc { Future _moveField( _MoveField value, Emitter emit) async { - final fields = List.from(state.fields); + final fields = List.from(state.fields); fields.insert(value.toIndex, fields.removeAt(value.fromIndex)); emit(state.copyWith(fields: fields)); @@ -49,7 +48,7 @@ class GridHeaderBloc extends Bloc { } Future _startListening() async { - fieldCache.addListener( + fieldController.addListener( onFields: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)), listenWhen: () => !isClosed, ); @@ -64,18 +63,18 @@ class GridHeaderBloc extends Bloc { @freezed class GridHeaderEvent with _$GridHeaderEvent { const factory GridHeaderEvent.initial() = _InitialHeader; - const factory GridHeaderEvent.didReceiveFieldUpdate(List fields) = - _DidReceiveFieldUpdate; + const factory GridHeaderEvent.didReceiveFieldUpdate( + List fields) = _DidReceiveFieldUpdate; const factory GridHeaderEvent.moveField( FieldPB field, int fromIndex, int toIndex) = _MoveField; } @freezed class GridHeaderState with _$GridHeaderState { - const factory GridHeaderState({required List fields}) = + const factory GridHeaderState({required List fields}) = _GridHeaderState; - factory GridHeaderState.initial(List fields) { + factory GridHeaderState.initial(List fields) { // final List newFields = List.from(fields); // newFields.retainWhere((field) => field.visibility); return GridHeaderState(fields: fields); diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart index bea25d8008..c5676616b3 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:equatable/equatable.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -35,7 +35,7 @@ class RowBloc extends Bloc { }, didReceiveCells: (_DidReceiveCells value) async { final cells = value.gridCellMap.values - .map((e) => GridCellEquatable(e.field)) + .map((e) => GridCellEquatable(e.fieldContext)) .toList(); emit(state.copyWith( gridCellMap: value.gridCellMap, @@ -87,21 +87,23 @@ class RowState with _$RowState { rowInfo: rowInfo, gridCellMap: cellDataMap, cells: UnmodifiableListView( - cellDataMap.values.map((e) => GridCellEquatable(e.field)).toList(), + cellDataMap.values + .map((e) => GridCellEquatable(e.fieldContext)) + .toList(), ), ); } class GridCellEquatable extends Equatable { - final FieldPB _field; + final GridFieldContext _fieldContext; - const GridCellEquatable(FieldPB field) : _field = field; + const GridCellEquatable(GridFieldContext field) : _fieldContext = field; @override List get props => [ - _field.id, - _field.fieldType, - _field.visibility, - _field.width, + _fieldContext.id, + _fieldContext.fieldType, + _fieldContext.visibility, + _fieldContext.width, ]; } diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart index 618d73cbc1..d1e8eaa1bf 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart @@ -1,5 +1,6 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; @@ -12,7 +13,7 @@ part 'row_cache.freezed.dart'; typedef RowUpdateCallback = void Function(); abstract class IGridRowFieldNotifier { - UnmodifiableListView get fields; + UnmodifiableListView get fields; void onRowFieldsChanged(VoidCallback callback); void onRowFieldChanged(void Function(FieldPB) callback); void onRowDispose(); @@ -217,7 +218,7 @@ class GridRowCache { cellDataMap[field.id] = GridCellIdentifier( rowId: rowId, gridId: gridId, - field: field, + fieldContext: field, ); } } @@ -284,7 +285,7 @@ class _RowChangesetNotifier extends ChangeNotifier { class RowInfo with _$RowInfo { const factory RowInfo({ required String gridId, - required UnmodifiableListView fields, + required UnmodifiableListView fields, required RowPB rowPB, }) = _RowInfo; } diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart index b4618b397a..5ed0f24965 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart @@ -10,14 +10,14 @@ typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason); class GridRowDataController extends GridCellBuilderDelegate { final RowInfo rowInfo; final List _onRowChangedListeners = []; - final GridFieldCache _fieldCache; + final GridFieldController _fieldController; final GridRowCache _rowCache; GridRowDataController({ required this.rowInfo, - required GridFieldCache fieldCache, + required GridFieldController fieldController, required GridRowCache rowCache, - }) : _fieldCache = fieldCache, + }) : _fieldController = fieldController, _rowCache = rowCache; GridCellMap loadData() { @@ -41,7 +41,7 @@ class GridRowDataController extends GridCellBuilderDelegate { @override GridCellFieldNotifier buildFieldNotifier() { return GridCellFieldNotifier( - notifier: GridCellFieldNotifierImpl(_fieldCache)); + notifier: GridCellFieldNotifierImpl(_fieldController)); } @override diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart index 691371bd8a..b960a2c2f0 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -11,14 +10,15 @@ import 'setting_controller.dart'; part 'group_bloc.freezed.dart'; class GridGroupBloc extends Bloc { - final GridFieldCache _fieldCache; + final GridFieldController _fieldController; final SettingController _settingController; - Function(List)? _onFieldsFn; + Function(List)? _onFieldsFn; - GridGroupBloc({required String viewId, required GridFieldCache fieldCache}) - : _fieldCache = fieldCache, + GridGroupBloc( + {required String viewId, required GridFieldController fieldController}) + : _fieldController = fieldController, _settingController = SettingController(viewId: viewId), - super(GridGroupState.initial(viewId, fieldCache.fields)) { + super(GridGroupState.initial(viewId, fieldController.fieldContexts)) { on( (event, emit) async { await event.map( @@ -36,7 +36,7 @@ class GridGroupBloc extends Bloc { ); }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(fields: value.fields)); + emit(state.copyWith(fieldContexts: value.fields)); }, moveField: (_MoveField value) { // @@ -49,7 +49,7 @@ class GridGroupBloc extends Bloc { @override Future close() async { if (_onFieldsFn != null) { - _fieldCache.removeListener(onFieldsListener: _onFieldsFn!); + _fieldController.removeListener(onFieldsListener: _onFieldsFn!); _onFieldsFn = null; } return super.close(); @@ -57,7 +57,7 @@ class GridGroupBloc extends Bloc { void _startListening() { _onFieldsFn = (fields) => add(GridGroupEvent.didReceiveFieldUpdate(fields)); - _fieldCache.addListener( + _fieldController.addListener( onFields: _onFieldsFn, listenWhen: () => !isClosed, ); @@ -74,8 +74,8 @@ class GridGroupEvent with _$GridGroupEvent { const factory GridGroupEvent.initial() = _Initial; const factory GridGroupEvent.setFieldVisibility( String fieldId, bool visibility) = _SetFieldVisibility; - const factory GridGroupEvent.didReceiveFieldUpdate(List fields) = - _DidReceiveFieldUpdate; + const factory GridGroupEvent.didReceiveFieldUpdate( + List fields) = _DidReceiveFieldUpdate; const factory GridGroupEvent.moveField(int fromIndex, int toIndex) = _MoveField; } @@ -84,12 +84,13 @@ class GridGroupEvent with _$GridGroupEvent { class GridGroupState with _$GridGroupState { const factory GridGroupState({ required String gridId, - required List fields, + required List fieldContexts, }) = _GridGroupState; - factory GridGroupState.initial(String gridId, List fields) => + factory GridGroupState.initial( + String gridId, List fieldContexts) => GridGroupState( gridId: gridId, - fields: fields, + fieldContexts: fieldContexts, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart index fc0c2b4b12..2e268aff84 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -10,12 +9,14 @@ import '../field/field_cache.dart'; part 'property_bloc.freezed.dart'; class GridPropertyBloc extends Bloc { - final GridFieldCache _fieldCache; - Function(List)? _onFieldsFn; + final GridFieldController _fieldController; + Function(List)? _onFieldsFn; - GridPropertyBloc({required String gridId, required GridFieldCache fieldCache}) - : _fieldCache = fieldCache, - super(GridPropertyState.initial(gridId, fieldCache.fields)) { + GridPropertyBloc( + {required String gridId, required GridFieldController fieldController}) + : _fieldController = fieldController, + super( + GridPropertyState.initial(gridId, fieldController.fieldContexts)) { on( (event, emit) async { await event.map( @@ -33,7 +34,7 @@ class GridPropertyBloc extends Bloc { ); }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(fields: value.fields)); + emit(state.copyWith(fieldContexts: value.fields)); }, moveField: (_MoveField value) { // @@ -46,7 +47,7 @@ class GridPropertyBloc extends Bloc { @override Future close() async { if (_onFieldsFn != null) { - _fieldCache.removeListener(onFieldsListener: _onFieldsFn!); + _fieldController.removeListener(onFieldsListener: _onFieldsFn!); _onFieldsFn = null; } return super.close(); @@ -55,7 +56,7 @@ class GridPropertyBloc extends Bloc { void _startListening() { _onFieldsFn = (fields) => add(GridPropertyEvent.didReceiveFieldUpdate(fields)); - _fieldCache.addListener( + _fieldController.addListener( onFields: _onFieldsFn, listenWhen: () => !isClosed, ); @@ -67,8 +68,8 @@ class GridPropertyEvent with _$GridPropertyEvent { const factory GridPropertyEvent.initial() = _Initial; const factory GridPropertyEvent.setFieldVisibility( String fieldId, bool visibility) = _SetFieldVisibility; - const factory GridPropertyEvent.didReceiveFieldUpdate(List fields) = - _DidReceiveFieldUpdate; + const factory GridPropertyEvent.didReceiveFieldUpdate( + List fields) = _DidReceiveFieldUpdate; const factory GridPropertyEvent.moveField(int fromIndex, int toIndex) = _MoveField; } @@ -77,12 +78,15 @@ class GridPropertyEvent with _$GridPropertyEvent { class GridPropertyState with _$GridPropertyState { const factory GridPropertyState({ required String gridId, - required List fields, + required List fieldContexts, }) = _GridPropertyState; - factory GridPropertyState.initial(String gridId, List fields) => + factory GridPropertyState.initial( + String gridId, + List fieldContexts, + ) => GridPropertyState( gridId: gridId, - fields: fields, + fieldContexts: fieldContexts, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart index 721e5d35f1..795adc4622 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart @@ -41,6 +41,7 @@ class SettingController { required OnError onError, }) { assert(_onSettingUpdated == null, 'Should call once'); + assert(_onError == null, 'Should call once'); _onSettingUpdated = onSettingUpdated; _onError = onError; } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart index 2c6c1e2180..e8d251c04f 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart @@ -157,10 +157,11 @@ class _FlowyGridState extends State { } Widget _gridHeader(BuildContext context, String gridId) { - final fieldCache = context.read().dataController.fieldCache; + final fieldController = + context.read().dataController.fieldController; return GridHeaderSliverAdaptor( gridId: gridId, - fieldCache: fieldCache, + fieldController: fieldController, anchorScrollController: headerScrollController, ); } @@ -173,10 +174,11 @@ class _GridToolbarAdaptor extends StatelessWidget { Widget build(BuildContext context) { return BlocSelector( selector: (state) { - final fieldCache = context.read().dataController.fieldCache; + final fieldController = + context.read().dataController.fieldController; return GridToolbarContext( gridId: state.gridId, - fieldCache: fieldCache, + fieldController: fieldController, ); }, builder: (context, toolbarContext) { @@ -247,10 +249,11 @@ class _GridRowsState extends State<_GridRows> { /// Return placeholder widget if the rowCache is null. if (rowCache == null) return const SizedBox(); - final fieldCache = context.read().dataController.fieldCache; + final fieldController = + context.read().dataController.fieldController; final dataController = GridRowDataController( rowInfo: rowInfo, - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, ); @@ -264,7 +267,7 @@ class _GridRowsState extends State<_GridRows> { _openRowDetailPage( context, rowInfo, - fieldCache, + fieldController, rowCache, cellBuilder, ); @@ -277,13 +280,13 @@ class _GridRowsState extends State<_GridRows> { void _openRowDetailPage( BuildContext context, RowInfo rowInfo, - GridFieldCache fieldCache, + GridFieldController fieldController, GridRowCache rowCache, GridCellBuilder cellBuilder, ) { final dataController = GridRowDataController( rowInfo: rowInfo, - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart b/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart index e47b47a267..5d09200b33 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart @@ -1,8 +1,8 @@ -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'sizes.dart'; class GridLayout { - static double headerWidth(List fields) { + static double headerWidth(List fields) { if (fields.isEmpty) return 0; final fieldsWidth = fields diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index c1de0eca31..fd5f087c40 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart index c5bdb448c3..fd0a0c2863 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart @@ -18,11 +18,11 @@ import 'field_cell.dart'; class GridHeaderSliverAdaptor extends StatefulWidget { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; final ScrollController anchorScrollController; const GridHeaderSliverAdaptor({ required this.gridId, - required this.fieldCache, + required this.fieldController, required this.anchorScrollController, Key? key, }) : super(key: key); @@ -38,7 +38,7 @@ class _GridHeaderSliverAdaptorState extends State { return BlocProvider( create: (context) { final bloc = getIt( - param1: widget.gridId, param2: widget.fieldCache); + param1: widget.gridId, param2: widget.fieldController); bloc.add(const GridHeaderEvent.initial()); return bloc; }, @@ -84,7 +84,7 @@ class _GridHeaderState extends State<_GridHeader> { final cells = state.fields .where((field) => field.visibility) .map((field) => - GridFieldCellContext(gridId: widget.gridId, field: field)) + GridFieldCellContext(gridId: widget.gridId, field: field.field)) .map((ctx) => GridFieldCell(ctx, key: ValueKey(ctx.field.id))) .toList(); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index 2ea19eb1e8..bce95edb96 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; @@ -129,17 +130,18 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({ TypeOptionContext makeTypeOptionContext({ required String gridId, - required FieldPB field, + required GridFieldContext fieldContext, }) { - final loader = FieldTypeOptionLoader(gridId: gridId, field: field); + final loader = + FieldTypeOptionLoader(gridId: gridId, field: fieldContext.field); final dataController = TypeOptionDataController( gridId: gridId, loader: loader, - field: field, + fieldContext: fieldContext, ); return makeTypeOptionContextWithDataController( gridId: gridId, - fieldType: field.fieldType, + fieldType: fieldContext.fieldType, dataController: dataController, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart index 55ec7b9832..621f53cf1a 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart @@ -189,13 +189,13 @@ class RowContent extends StatelessWidget { final GridCellWidget child = builder.build(cellId); return CellContainer( - width: cellId.field.width.toDouble(), + width: cellId.fieldContext.width.toDouble(), rowStateNotifier: Provider.of(context, listen: false), accessoryBuilder: (buildContext) { final builder = child.accessoryBuilder; List accessories = []; - if (cellId.field.isPrimary) { + if (cellId.fieldContext.isPrimary) { accessories.add(PrimaryCellAccessory( onTapCallback: onExpand, isCellEditing: buildContext.isCellEditing, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index 58e9b2808c..1fbe1bfb84 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -215,7 +215,7 @@ class _RowDetailCell extends StatelessWidget { SizedBox( width: 150, child: FieldCellButton( - field: cellId.field, + field: cellId.fieldContext.fieldContext, onTap: () => _showFieldEditor(context), ), ), @@ -230,10 +230,10 @@ class _RowDetailCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( gridId: cellId.gridId, - fieldName: cellId.field.name, + fieldName: cellId.fieldContext.name, typeOptionLoader: FieldTypeOptionLoader( gridId: cellId.gridId, - field: cellId.field, + field: cellId.fieldContext.fieldContext, ), ).show(context); } 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 index 770e16e2bf..3550c1274c 100644 --- 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 @@ -6,7 +6,6 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:app_flowy/plugins/grid/application/setting/group_bloc.dart'; @@ -14,10 +13,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class GridGroupList extends StatelessWidget { final String viewId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; const GridGroupList({ required this.viewId, - required this.fieldCache, + required this.fieldController, Key? key, }) : super(key: key); @@ -26,13 +25,13 @@ class GridGroupList extends StatelessWidget { return BlocProvider( create: (context) => GridGroupBloc( viewId: viewId, - fieldCache: fieldCache, + fieldController: fieldController, )..add(const GridGroupEvent.initial()), child: BlocBuilder( builder: (context, state) { - final cells = state.fields.map((field) { + final cells = state.fieldContexts.map((field) { return _GridGroupCell( - field: field, + fieldContext: field, key: ValueKey(field.id), ); }).toList(); @@ -56,8 +55,9 @@ class GridGroupList extends StatelessWidget { } class _GridGroupCell extends StatelessWidget { - final FieldPB field; - const _GridGroupCell({required this.field, Key? key}) : super(key: key); + final GridFieldContext fieldContext; + const _GridGroupCell({required this.fieldContext, Key? key}) + : super(key: key); @override Widget build(BuildContext context) { @@ -73,9 +73,10 @@ class _GridGroupCell extends StatelessWidget { // ), return FlowyButton( - text: FlowyText.medium(field.name, fontSize: 12), + text: FlowyText.medium(fieldContext.name, fontSize: 12), hoverColor: theme.hover, - leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + leftIcon: + svgWidget(fieldContext.fieldType.iconName(), color: theme.iconColor), onTap: () {}, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index 08ba3dcd08..e57ff26bcb 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -9,7 +9,6 @@ import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -20,10 +19,10 @@ import '../header/field_editor.dart'; class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; const GridPropertyList({ required this.gridId, - required this.fieldCache, + required this.fieldController, Key? key, }) : super(key: key); @@ -45,13 +44,13 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { Widget build(BuildContext context) { return BlocProvider( create: (context) => - getIt(param1: gridId, param2: fieldCache) + getIt(param1: gridId, param2: fieldController) ..add(const GridPropertyEvent.initial()), child: BlocBuilder( builder: (context, state) { - final cells = state.fields.map((field) { + final cells = state.fieldContexts.map((field) { return _GridPropertyCell( - gridId: gridId, field: field, key: ValueKey(field.id)); + gridId: gridId, fieldContext: field, key: ValueKey(field.id)); }).toList(); return ListView.separated( @@ -78,16 +77,17 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { } class _GridPropertyCell extends StatelessWidget { - final FieldPB field; + final GridFieldContext fieldContext; final String gridId; - const _GridPropertyCell({required this.gridId, required this.field, Key? key}) + const _GridPropertyCell( + {required this.gridId, required this.fieldContext, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); - final checkmark = field.visibility + final checkmark = fieldContext.visibility ? svgWidget('home/show', color: theme.iconColor) : svgWidget('home/hide', color: theme.iconColor); @@ -105,7 +105,7 @@ class _GridPropertyCell extends StatelessWidget { onPressed: () { context.read().add( GridPropertyEvent.setFieldVisibility( - field.id, !field.visibility)); + fieldContext.id, !fieldContext.visibility)); }, icon: checkmark.padding(all: 6), ) @@ -115,14 +115,18 @@ class _GridPropertyCell extends StatelessWidget { FlowyButton _editFieldButton(AppTheme theme, BuildContext context) { return FlowyButton( - text: FlowyText.medium(field.name, fontSize: 12), + text: FlowyText.medium(fieldContext.name, fontSize: 12), hoverColor: theme.hover, - leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + leftIcon: + svgWidget(fieldContext.fieldType.iconName(), color: theme.iconColor), onTap: () { FieldEditor( gridId: gridId, - fieldName: field.name, - typeOptionLoader: FieldTypeOptionLoader(gridId: gridId, field: field), + fieldName: fieldContext.name, + typeOptionLoader: FieldTypeOptionLoader( + gridId: gridId, + field: fieldContext.field, + ), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart index 289d84141f..4bbcd66fe2 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart @@ -17,11 +17,11 @@ import 'grid_property.dart'; class GridSettingContext { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; GridSettingContext({ required this.gridId, - required this.fieldCache, + required this.fieldController, }); } @@ -44,7 +44,7 @@ class GridSettingList extends StatelessWidget { case GridSettingAction.properties: GridPropertyList( gridId: settingContext.gridId, - fieldCache: settingContext.fieldCache) + fieldController: settingContext.fieldController) .show(context); break; } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart index 4ced06bf99..56c6947430 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart @@ -11,10 +11,10 @@ import 'grid_setting.dart'; class GridToolbarContext { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; GridToolbarContext({ required this.gridId, - required this.fieldCache, + required this.fieldController, }); } @@ -26,7 +26,7 @@ class GridToolbar extends StatelessWidget { Widget build(BuildContext context) { final settingContext = GridSettingContext( gridId: toolbarContext.gridId, - fieldCache: toolbarContext.fieldCache, + fieldController: toolbarContext.fieldController, ); return SizedBox( height: 40, diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index be3c617943..cd73c3fbbc 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -154,10 +154,10 @@ void _resolveGridDeps(GetIt getIt) { (view, _) => GridBloc(view: view), ); - getIt.registerFactoryParam( - (gridId, fieldCache) => GridHeaderBloc( + getIt.registerFactoryParam( + (gridId, fieldController) => GridHeaderBloc( gridId: gridId, - fieldCache: fieldCache, + fieldController: fieldController, ), ); @@ -200,7 +200,7 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (gridId, cache) => GridPropertyBloc(gridId: gridId, fieldCache: cache), + getIt.registerFactoryParam( + (gridId, cache) => GridPropertyBloc(gridId: gridId, fieldController: cache), ); } From 4f8e012d543e9aa3f144a7a862054882889fe51a Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 4 Sep 2022 15:33:07 +0800 Subject: [PATCH 9/9] chore: fix bugs when switch group field --- .../plugins/board/application/board_bloc.dart | 8 ++- .../application/board_data_controller.dart | 2 +- .../card/board_date_cell_bloc.dart | 2 +- .../card/card_data_controller.dart | 2 +- .../board/presentation/board_page.dart | 6 +- .../presentation/toolbar/board_setting.dart | 2 +- .../presentation/toolbar/board_toolbar.dart | 2 +- .../grid/application/block/block_cache.dart | 2 +- .../cell/cell_service/cell_service.dart | 2 +- .../grid/application/cell/date_cell_bloc.dart | 2 +- ...field_cache.dart => field_controller.dart} | 56 +++++++++++----- .../grid/application/field/field_service.dart | 1 - .../type_option/type_option_context.dart | 1 - .../type_option_data_controller.dart | 2 +- .../plugins/grid/application/grid_bloc.dart | 2 +- .../application/grid_data_controller.dart | 2 +- .../grid/application/grid_header_bloc.dart | 2 +- .../grid/application/row/row_bloc.dart | 2 +- .../grid/application/row/row_cache.dart | 2 +- .../application/row/row_data_controller.dart | 2 +- .../grid/application/setting/group_bloc.dart | 52 ++++++-------- .../application/setting/property_bloc.dart | 2 +- .../application/setting/setting_service.dart | 16 +++++ .../plugins/grid/presentation/grid_page.dart | 2 +- .../grid/presentation/layout/layout.dart | 2 +- .../widgets/header/field_cell.dart | 1 - .../widgets/header/grid_header.dart | 2 +- .../widgets/header/type_option/builder.dart | 2 +- .../presentation/widgets/row/row_detail.dart | 4 +- .../widgets/toolbar/grid_group.dart | 67 +++++++++++++------ .../widgets/toolbar/grid_property.dart | 2 +- .../widgets/toolbar/grid_setting.dart | 2 +- .../widgets/toolbar/grid_toolbar.dart | 2 +- .../app_flowy/lib/startup/deps_resolver.dart | 2 +- .../lib/src/widgets/board_data.dart | 1 + .../src/entities/filter_entities/util.rs | 12 ++-- .../src/entities/group_entities/group.rs | 10 +-- .../src/entities/setting_entities.rs | 15 ++--- .../rust-lib/flowy-grid/src/event_handler.rs | 26 +++++++ frontend/rust-lib/flowy-grid/src/event_map.rs | 9 ++- .../flowy-grid/src/services/grid_editor.rs | 14 +++- .../src/services/grid_view_editor.rs | 54 ++++++++++++--- .../src/services/grid_view_manager.rs | 22 ++++-- .../src/services/group/configuration.rs | 4 +- .../src/services/group/controller.rs | 2 +- .../controller_impls/default_controller.rs | 2 +- .../src/services/setting/setting_builder.rs | 4 +- .../tests/grid/filter_test/script.rs | 8 +-- .../grid/filter_test/text_filter_test.rs | 10 +-- .../tests/grid/group_test/script.rs | 2 +- .../src/client_grid/view_revision_pad.rs | 4 +- 51 files changed, 297 insertions(+), 162 deletions(-) rename frontend/app_flowy/lib/plugins/grid/application/field/{field_cache.dart => field_controller.dart} (86%) 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 b78bc86661..26dd15038a 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:appflowy_board/appflowy_board.dart'; @@ -204,16 +204,20 @@ class BoardBloc extends Bloc { } }, didLoadGroups: (groups) { + if (isClosed) return; initializeGroups(groups); add(BoardEvent.didReceiveGroups(groups)); }, onDeletedGroup: (groupIds) { + if (isClosed) return; // }, onInsertedGroup: (insertedGroups) { + if (isClosed) return; // }, onUpdatedGroup: (updatedGroups) { + if (isClosed) return; for (final group in updatedGroups) { final columnController = boardController.getColumnController(group.groupId); @@ -224,6 +228,8 @@ class BoardBloc extends Bloc { Log.error(err); }, onResetGroups: (groups) { + if (isClosed) return; + initializeGroups(groups); add(BoardEvent.didReceiveGroups(groups)); }, diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index 5435db2c3a..923bb4ef8c 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart index dd1f77a9d1..a19d7b64a8 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart index 377b0dae50..0e7cf6c153 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/plugins/board/presentation/card/card_cell_builder.dart'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_notifier.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flutter/foundation.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index f52237ad49..d6c5dca609 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -5,7 +5,7 @@ import 'dart:collection'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/cell/cell_builder.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_detail.dart'; @@ -82,8 +82,7 @@ class _BoardContentState extends State { return BlocListener( listener: (context, state) => _handleEditState(state, context), child: BlocBuilder( - buildWhen: (previous, current) => - previous.groupIds.length != current.groupIds.length, + buildWhen: (previous, current) => previous.groupIds != current.groupIds, builder: (context, state) { final theme = context.read(); return Container( @@ -95,6 +94,7 @@ class _BoardContentState extends State { const _ToolbarBlocAdaptor(), Expanded( child: AFBoard( + key: UniqueKey(), scrollManager: scrollManager, scrollController: scrollController, dataController: context.read().boardController, 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 a270f50951..86beac6830 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 @@ -1,6 +1,6 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/board/application/toolbar/board_setting_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_group.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart'; diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart index bf8d2e3443..8bc4dcb0c7 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart index 35ed334cee..b39226f0be 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; -import '../field/field_cache.dart'; +import '../field/field_controller.dart'; import '../row/row_cache.dart'; import 'block_listener.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart index 360df60b4e..b0fbee15cd 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart @@ -16,7 +16,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_listener.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'dart:convert' show utf8; -import '../../field/field_cache.dart'; +import '../../field/field_controller.dart'; import '../../field/type_option/type_option_context.dart'; import 'cell_field_notifier.dart'; part 'cell_service.freezed.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart index ae840e9e54..e44e15a2fa 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart similarity index 86% rename from frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart rename to frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart index da12afff97..e9bda8eef5 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_controller.dart @@ -2,10 +2,12 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart'; import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:app_flowy/plugins/grid/application/setting/setting_listener.dart'; +import 'package:app_flowy/plugins/grid/application/setting/setting_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; import 'package:flutter/foundation.dart'; import '../row/row_cache.dart'; @@ -35,11 +37,17 @@ class GridFieldController { final Map _changesetCallbackMap = {}; _GridFieldNotifier? _fieldNotifier = _GridFieldNotifier(); + List _groupFieldIds = []; final GridFFIService _gridFFIService; + final SettingFFIService _settingFFIService; + + List get fieldContexts => + [..._fieldNotifier?.fieldContexts ?? []]; GridFieldController({required this.gridId}) : _fieldListener = GridFieldsListener(gridId: gridId), _gridFFIService = GridFFIService(gridId: gridId), + _settingFFIService = SettingFFIService(viewId: gridId), _settingListener = SettingListener(gridId: gridId) { //Listen on field's changes _fieldListener.start(onFieldsChanged: (result) { @@ -59,24 +67,38 @@ class GridFieldController { //Listen on setting changes _settingListener.start(onSettingUpdated: (result) { result.fold( - (setting) { - final List groupFieldIds = setting.groupConfigurations.items - .map((item) => item.groupFieldId) - .toList(); - bool isChanged = false; - if (_fieldNotifier != null) { - for (var field in _fieldNotifier!.fieldContexts) { - if (groupFieldIds.contains(field.id)) { - field._isGroupField = true; - isChanged = true; - } - } - if (isChanged) _fieldNotifier?.notify(); - } - }, + (setting) => _updateFieldsWhenSettingChanged(setting), (r) => Log.error(r), ); }); + + _settingFFIService.getSetting().then((result) { + result.fold( + (setting) => _updateFieldsWhenSettingChanged(setting), + (err) => Log.error(err), + ); + }); + } + + void _updateFieldsWhenSettingChanged(GridSettingPB setting) { + _groupFieldIds = setting.groupConfigurations.items + .map((item) => item.groupFieldId) + .toList(); + + _updateFieldContexts(); + } + + void _updateFieldContexts() { + if (_fieldNotifier != null) { + for (var field in _fieldNotifier!.fieldContexts) { + if (_groupFieldIds.contains(field.id)) { + field._isGroupField = true; + } else { + field._isGroupField = false; + } + } + _fieldNotifier?.notify(); + } } Future dispose() async { @@ -85,9 +107,6 @@ class GridFieldController { _fieldNotifier = null; } - List get fieldContexts => - [..._fieldNotifier?.fieldContexts ?? []]; - Future> loadFields( {required List fieldIds}) async { final result = await _gridFFIService.getFields(fieldIds: fieldIds); @@ -97,6 +116,7 @@ class GridFieldController { _fieldNotifier?.fieldContexts = newFields.items .map((field) => GridFieldContext(field: field)) .toList(); + _updateFieldContexts(); return left(unit); }, (err) => right(err), diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart index 5466a8de08..28676d62c1 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart @@ -6,7 +6,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'field_cache.dart'; part 'field_service.freezed.dart'; /// FieldService consists of lots of event functions. We define the events in the backend(Rust), diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart index 192c4f86f0..632e333911 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart index 6f757be71d..65bd057ac5 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart index 139b08251e..0aceab8ccf 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart @@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'block/block_cache.dart'; -import 'field/field_cache.dart'; +import 'field/field_controller.dart'; import 'grid_data_controller.dart'; import 'row/row_cache.dart'; import 'dart:collection'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart index 6caf699641..a8e1a27c39 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart @@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; import 'block/block_cache.dart'; -import 'field/field_cache.dart'; +import 'field/field_controller.dart'; import 'prelude.dart'; import 'row/row_cache.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart index b7e1ade527..c6c9b1fa5b 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart @@ -4,7 +4,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'field/field_cache.dart'; +import 'field/field_controller.dart'; part 'grid_header_bloc.freezed.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart index c5676616b3..5e14c2e445 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart @@ -1,6 +1,6 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart index d1e8eaa1bf..6e25742974 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart @@ -1,6 +1,6 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart index 5ed0f24965..e5fc6161bb 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_ import 'package:flutter/material.dart'; import '../../presentation/widgets/cell/cell_builder.dart'; import '../cell/cell_service/cell_service.dart'; -import '../field/field_cache.dart'; +import '../field/field_controller.dart'; import 'row_cache.dart'; typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason); diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart index b960a2c2f0..8b58d5ea0c 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart @@ -1,46 +1,38 @@ -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; -import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import '../field/field_cache.dart'; -import 'setting_controller.dart'; +import '../field/field_controller.dart'; +import 'setting_service.dart'; part 'group_bloc.freezed.dart'; class GridGroupBloc extends Bloc { final GridFieldController _fieldController; - final SettingController _settingController; + final SettingFFIService _settingFFIService; Function(List)? _onFieldsFn; GridGroupBloc( {required String viewId, required GridFieldController fieldController}) : _fieldController = fieldController, - _settingController = SettingController(viewId: viewId), + _settingFFIService = SettingFFIService(viewId: viewId), super(GridGroupState.initial(viewId, fieldController.fieldContexts)) { on( (event, emit) async { - await event.map( - initial: (_Initial value) { + event.when( + initial: () { _startListening(); }, - setFieldVisibility: (_SetFieldVisibility value) async { - final fieldService = - FieldService(gridId: viewId, fieldId: value.fieldId); - final result = - await fieldService.updateField(visibility: value.visibility); - result.fold( - (l) => null, - (err) => Log.error(err), + didReceiveFieldUpdate: (fieldContexts) { + emit(state.copyWith(fieldContexts: fieldContexts)); + }, + setGroupByField: (String fieldId, FieldType fieldType) { + _settingFFIService.groupByField( + fieldId: fieldId, + fieldType: fieldType, ); }, - didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(fieldContexts: value.fields)); - }, - moveField: (_MoveField value) { - // - }, ); }, ); @@ -56,28 +48,24 @@ class GridGroupBloc extends Bloc { } void _startListening() { - _onFieldsFn = (fields) => add(GridGroupEvent.didReceiveFieldUpdate(fields)); + _onFieldsFn = (fieldContexts) => + add(GridGroupEvent.didReceiveFieldUpdate(fieldContexts)); _fieldController.addListener( onFields: _onFieldsFn, listenWhen: () => !isClosed, ); - - _settingController.startListeing( - onSettingUpdated: (setting) {}, - onError: (err) {}, - ); } } @freezed class GridGroupEvent with _$GridGroupEvent { const factory GridGroupEvent.initial() = _Initial; - const factory GridGroupEvent.setFieldVisibility( - String fieldId, bool visibility) = _SetFieldVisibility; + const factory GridGroupEvent.setGroupByField( + String fieldId, + FieldType fieldType, + ) = _GroupByField; const factory GridGroupEvent.didReceiveFieldUpdate( List fields) = _DidReceiveFieldUpdate; - const factory GridGroupEvent.moveField(int fromIndex, int toIndex) = - _MoveField; } @freezed diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart index 2e268aff84..c54f16ae12 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart @@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import '../field/field_cache.dart'; +import '../field/field_controller.dart'; part 'property_bloc.freezed.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart index 8d3774ec1c..b050809bb5 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_service.dart @@ -1,7 +1,9 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/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'; import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; class SettingFFIService { @@ -13,4 +15,18 @@ class SettingFFIService { final payload = GridIdPB.create()..value = viewId; return GridEventGetGridSetting(payload).send(); } + + Future> groupByField({ + required String fieldId, + required FieldType fieldType, + }) { + final insertGroupPayload = InsertGroupPayloadPB.create() + ..fieldId = fieldId + ..fieldType = fieldType; + final payload = GridSettingChangesetPayloadPB.create() + ..gridId = viewId + ..insertGroup = insertGroupPayload; + + return GridEventUpdateGridSetting(payload).send(); + } } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart index e8d251c04f..be9d2fe4e3 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/grid_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart b/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart index 5d09200b33..72b1eb643d 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'sizes.dart'; class GridLayout { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index fd5f087c40..c1de0eca31 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart index fd0a0c2863..05c1faec08 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index bce95edb96..cfa2f9291f 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index 1fbe1bfb84..266be35a36 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -215,7 +215,7 @@ class _RowDetailCell extends StatelessWidget { SizedBox( width: 150, child: FieldCellButton( - field: cellId.fieldContext.fieldContext, + field: cellId.fieldContext.field, onTap: () => _showFieldEditor(context), ), ), @@ -233,7 +233,7 @@ class _RowDetailCell extends StatelessWidget { fieldName: cellId.fieldContext.name, typeOptionLoader: FieldTypeOptionLoader( gridId: cellId.gridId, - field: cellId.fieldContext.fieldContext, + field: cellId.fieldContext.field, ), ).show(context); } 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 index 3550c1274c..0a82eef4bb 100644 --- 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 @@ -1,8 +1,9 @@ -import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_controller.dart'; import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; @@ -29,10 +30,10 @@ class GridGroupList extends StatelessWidget { )..add(const GridGroupEvent.initial()), child: BlocBuilder( builder: (context, state) { - final cells = state.fieldContexts.map((field) { + final cells = state.fieldContexts.map((fieldContext) { return _GridGroupCell( - fieldContext: field, - key: ValueKey(field.id), + fieldContext: fieldContext, + key: ValueKey(fieldContext.id), ); }).toList(); @@ -51,7 +52,22 @@ class GridGroupList extends StatelessWidget { ); } - void show(BuildContext context) {} + void show(BuildContext context) { + FlowyOverlay.of(context).insertWithAnchor( + widget: OverlayContainer( + constraints: BoxConstraints.loose(const Size(260, 400)), + child: this, + ), + identifier: identifier(), + anchorContext: context, + anchorDirection: AnchorDirection.bottomRight, + style: FlowyOverlayStyle(blur: false), + ); + } + + static String identifier() { + return (GridGroupList).toString(); + } } class _GridGroupCell extends StatelessWidget { @@ -61,23 +77,34 @@ class _GridGroupCell extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = context.watch(); + final theme = context.read(); - // final checkmark = field.visibility - // ? svgWidget('home/show', color: theme.iconColor) - // : svgWidget('home/hide', color: theme.iconColor); + Widget? rightIcon; + if (fieldContext.isGroupField) { + rightIcon = Padding( + padding: const EdgeInsets.all(2.0), + child: svgWidget("grid/checkmark"), + ); + } - // Padding( - // padding: const EdgeInsets.only(right: 6), - // child: svgWidget("grid/checkmark"), - // ), - - return FlowyButton( - text: FlowyText.medium(fieldContext.name, fontSize: 12), - hoverColor: theme.hover, - leftIcon: - svgWidget(fieldContext.fieldType.iconName(), color: theme.iconColor), - onTap: () {}, + return SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(fieldContext.name, fontSize: 12), + hoverColor: theme.hover, + leftIcon: svgWidget(fieldContext.fieldType.iconName(), + color: theme.iconColor), + rightIcon: rightIcon, + onTap: () { + context.read().add( + GridGroupEvent.setGroupByField( + fieldContext.id, + fieldContext.fieldType, + ), + ); + FlowyOverlay.of(context).remove(GridGroupList.identifier()); + }, + ), ); } } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index e57ff26bcb..f5acbcba2a 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -13,7 +13,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; -import '../../../application/field/field_cache.dart'; +import '../../../application/field/field_controller.dart'; import '../../layout/sizes.dart'; import '../header/field_editor.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart index 4bbcd66fe2..c793d7eef1 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; -import '../../../application/field/field_cache.dart'; +import '../../../application/field/field_controller.dart'; import '../../layout/sizes.dart'; import 'grid_property.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart index 56c6947430..61ea099f56 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart @@ -5,7 +5,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../../application/field/field_cache.dart'; +import '../../../application/field/field_controller.dart'; import '../../layout/sizes.dart'; import 'grid_setting.dart'; diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index cd73c3fbbc..cd3cc00ec6 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -21,7 +21,7 @@ import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:get_it/get_it.dart'; -import '../plugins/grid/application/field/field_cache.dart'; +import '../plugins/grid/application/field/field_controller.dart'; class DependencyResolver { static Future resolve(GetIt getIt) async { 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 4c20161691..47e74b37f5 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 @@ -91,6 +91,7 @@ class AFBoardDataController extends ChangeNotifier void clear() { _columnDatas.clear(); + _columnControllers.clear(); notifyListeners(); } 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 f8588944e7..c6737e8e76 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 @@ -78,7 +78,7 @@ pub struct DeleteFilterParams { } #[derive(ProtoBuf, Debug, Default, Clone)] -pub struct CreateGridFilterPayloadPB { +pub struct InsertFilterPayloadPB { #[pb(index = 1)] pub field_id: String, @@ -92,7 +92,7 @@ pub struct CreateGridFilterPayloadPB { pub content: Option, } -impl CreateGridFilterPayloadPB { +impl InsertFilterPayloadPB { #[allow(dead_code)] pub fn new>(field_rev: &FieldRevision, condition: T, content: Option) -> Self { Self { @@ -104,10 +104,10 @@ impl CreateGridFilterPayloadPB { } } -impl TryInto for CreateGridFilterPayloadPB { +impl TryInto for InsertFilterPayloadPB { 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; @@ -130,7 +130,7 @@ impl TryInto for CreateGridFilterPayloadPB { } } - Ok(CreateFilterParams { + Ok(InsertFilterParams { field_id, field_type_rev: self.field_type.into(), condition, @@ -139,7 +139,7 @@ impl TryInto for CreateGridFilterPayloadPB { } } -pub struct CreateFilterParams { +pub struct InsertFilterParams { pub field_id: String, pub field_type_rev: FieldTypeRevision, pub condition: u8, 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 3ed53080ef..de6f920341 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 @@ -130,7 +130,7 @@ impl std::convert::From>> for RepeatedGridGr } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct CreateGridGroupPayloadPB { +pub struct InsertGroupPayloadPB { #[pb(index = 1)] pub field_id: String, @@ -138,22 +138,22 @@ pub struct CreateGridGroupPayloadPB { pub field_type: FieldType, } -impl TryInto for CreateGridGroupPayloadPB { +impl TryInto for InsertGroupPayloadPB { 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(CreatGroupParams { + Ok(InsertGroupParams { field_id, field_type_rev: self.field_type.into(), }) } } -pub struct CreatGroupParams { +pub struct InsertGroupParams { pub field_id: String, pub field_type_rev: FieldTypeRevision, } 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 47efc11861..bbf5af831f 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, DeleteFilterParams, - DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, RepeatedGridFilterConfigurationPB, + DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, InsertFilterParams, + InsertFilterPayloadPB, InsertGroupParams, InsertGroupPayloadPB, RepeatedGridFilterConfigurationPB, 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 std::collections::HashMap; use std::convert::TryInto; use strum::IntoEnumIterator; use strum_macros::EnumIter; @@ -85,13 +84,13 @@ pub struct GridSettingChangesetPayloadPB { pub layout_type: GridLayout, #[pb(index = 3, one_of)] - pub insert_filter: Option, + pub insert_filter: Option, #[pb(index = 4, one_of)] pub delete_filter: Option, #[pb(index = 5, one_of)] - pub insert_group: Option, + pub insert_group: Option, #[pb(index = 6, one_of)] pub delete_group: Option, @@ -102,7 +101,7 @@ impl TryInto for GridSettingChangesetPayloadPB { fn try_into(self) -> Result { let view_id = NotEmptyStr::parse(self.grid_id) - .map_err(|_| ErrorCode::FieldIdIsEmpty)? + .map_err(|_| ErrorCode::ViewIdInvalid)? .0; let insert_filter = match self.insert_filter { @@ -139,9 +138,9 @@ impl TryInto for GridSettingChangesetPayloadPB { pub struct GridSettingChangesetParams { pub grid_id: String, pub layout_type: LayoutRevision, - pub insert_filter: Option, + pub insert_filter: Option, pub delete_filter: Option, - pub insert_group: Option, + pub insert_group: Option, pub delete_group: Option, } diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 8a04b2ea30..c9b6cf4662 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -35,6 +35,32 @@ 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.get_grid_editor(¶ms.grid_id)?; + if let Some(insert_params) = params.insert_group { + let _ = editor.create_group(insert_params).await?; + } + + if let Some(delete_params) = params.delete_group { + let _ = editor.delete_group(delete_params).await?; + } + + if let Some(create_filter) = params.insert_filter { + let _ = editor.create_filter(create_filter).await?; + } + + if let Some(delete_filter) = params.delete_filter { + let _ = editor.delete_filter(delete_filter).await?; + } + Ok(()) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_grid_blocks_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index a78bcb5ed3..e0a5ffcf1b 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) @@ -75,8 +75,8 @@ pub enum GridEvent { /// [UpdateGridSetting] event is used to update the grid's settings. /// - /// The event handler accepts [GridIdPB] and return errors if failed to modify the grid's settings. - #[event(input = "GridIdPB", input = "GridSettingChangesetPayloadPB")] + /// The event handler accepts [GridSettingChangesetPayloadPB] and return errors if failed to modify the grid's settings. + #[event(input = "GridSettingChangesetPayloadPB")] UpdateGridSetting = 3, /// [GetFields] event is used to get the grid's settings. @@ -225,4 +225,7 @@ pub enum GridEvent { #[event(input = "MoveGroupRowPayloadPB")] MoveGroupRow = 112, + + #[event(input = "MoveGroupRowPayloadPB")] + GroupByField = 113, } 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 2f72f48d33..320d41cbff 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -211,7 +211,7 @@ impl GridRevisionEditor { Ok(()) } - pub async fn group_field(&self, field_id: &str) -> FlowyResult<()> { + pub async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> { let _ = self.view_manager.group_by_field(field_id).await?; Ok(()) } @@ -536,8 +536,16 @@ impl GridRevisionEditor { self.view_manager.get_filters().await } - pub async fn update_filter(&self, params: CreateFilterParams) -> FlowyResult<()> { - let _ = self.view_manager.update_filter(params).await?; + pub async fn create_group(&self, params: InsertGroupParams) -> FlowyResult<()> { + self.view_manager.insert_or_update_group(params).await + } + + pub async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> { + self.view_manager.delete_group(params).await + } + + pub async fn create_filter(&self, params: InsertFilterParams) -> FlowyResult<()> { + let _ = self.view_manager.insert_or_update_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 71d2fb372a..ab8e8bd41f 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,15 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::entities::{ - CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfigurationPB, GridGroupConfigurationPB, - GridLayout, GridLayoutPB, GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertedGroupPB, - InsertedRowPB, MoveGroupParams, RepeatedGridFilterConfigurationPB, RepeatedGridGroupConfigurationPB, RowPB, + CreateRowParams, DeleteFilterParams, DeleteGroupParams, GridFilterConfigurationPB, GridGroupConfigurationPB, + GridLayout, GridLayoutPB, GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertFilterParams, + InsertGroupParams, InsertedGroupPB, InsertedRowPB, MoveGroupParams, RepeatedGridFilterConfigurationPB, + RepeatedGridGroupConfigurationPB, RowPB, }; use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; use crate::services::group::{ - find_group_field, make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController, - MoveGroupRowContext, + default_group_configuration, find_group_field, make_group_controller, GroupConfigurationReader, + GroupConfigurationWriter, GroupController, MoveGroupRowContext, }; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ @@ -19,7 +20,6 @@ use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilde 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::future::Future; use std::sync::Arc; use tokio::sync::RwLock; @@ -210,15 +210,40 @@ impl GridViewRevisionEditor { } } - pub(crate) async fn insert_filter(&self, insert_filter: CreateFilterParams) -> FlowyResult<()> { + pub(crate) async fn insert_group(&self, params: InsertGroupParams) -> FlowyResult<()> { + if let Some(field_rev) = self.field_delegate.get_field_rev(¶ms.field_id).await { + let _ = self + .modify(|pad| { + let configuration = default_group_configuration(&field_rev); + let changeset = pad.insert_group(¶ms.field_id, ¶ms.field_type_rev, configuration)?; + Ok(changeset) + }) + .await?; + } + if self.group_controller.read().await.field_id() != params.field_id { + let _ = self.group_by_field(¶ms.field_id).await?; + self.notify_did_update_setting().await; + } + Ok(()) + } + + pub(crate) async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> { + self.modify(|pad| { + let changeset = pad.delete_filter(¶ms.field_id, ¶ms.field_type_rev, ¶ms.group_id)?; + Ok(changeset) + }) + .await + } + + pub(crate) async fn insert_filter(&self, params: InsertFilterParams) -> 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, + field_id: params.field_id.clone(), + condition: params.condition, + content: params.content, }; - let changeset = pad.insert_filter(&insert_filter.field_id, &insert_filter.field_type_rev, filter_rev)?; + let changeset = pad.insert_filter(¶ms.field_id, ¶ms.field_type_rev, filter_rev)?; Ok(changeset) }) .await @@ -279,6 +304,13 @@ impl GridViewRevisionEditor { Ok(()) } + async fn notify_did_update_setting(&self) { + let setting = self.get_setting().await; + send_dart_notification(&self.view_id, GridNotification::DidUpdateGridSetting) + .payload(setting) + .send(); + } + pub async fn notify_did_update_group(&self, changeset: GroupChangesetPB) { send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup) .payload(changeset) 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 460be37a44..b1041a818c 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,6 +1,6 @@ use crate::entities::{ - CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfigurationPB, GridSettingPB, MoveGroupParams, - RepeatedGridGroupPB, RowPB, + CreateRowParams, DeleteFilterParams, DeleteGroupParams, GridFilterConfigurationPB, GridSettingPB, + InsertFilterParams, InsertGroupParams, MoveGroupParams, RepeatedGridGroupPB, RowPB, }; use crate::manager::GridUser; use crate::services::grid_editor_task::GridServiceTaskScheduler; @@ -110,14 +110,14 @@ impl GridViewManager { Ok(view_editor.get_filters().await) } - pub(crate) async fn update_filter(&self, insert_filter: CreateFilterParams) -> FlowyResult<()> { + pub(crate) async fn insert_or_update_filter(&self, params: InsertFilterParams) -> FlowyResult<()> { let view_editor = self.get_default_view_editor().await?; - view_editor.insert_filter(insert_filter).await + view_editor.insert_filter(params).await } - pub(crate) async fn delete_filter(&self, delete_filter: DeleteFilterParams) -> FlowyResult<()> { + pub(crate) async fn delete_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> { let view_editor = self.get_default_view_editor().await?; - view_editor.delete_filter(delete_filter).await + view_editor.delete_filter(params).await } pub(crate) async fn load_groups(&self) -> FlowyResult { @@ -126,6 +126,16 @@ impl GridViewManager { Ok(RepeatedGridGroupPB { items: groups }) } + pub(crate) async fn insert_or_update_group(&self, params: InsertGroupParams) -> FlowyResult<()> { + let view_editor = self.get_default_view_editor().await?; + view_editor.insert_group(params).await + } + + pub(crate) async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> { + let view_editor = self.get_default_view_editor().await?; + view_editor.delete_group(params).await + } + pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> { let view_editor = self.get_default_view_editor().await?; let _ = view_editor.move_group(params).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 196f619290..c110d01ad4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -133,6 +133,7 @@ where } } + #[tracing::instrument(level = "debug", skip(self, generated_groups), err)] pub(crate) fn init_groups( &mut self, generated_groups: Vec, @@ -316,7 +317,8 @@ where fn merge_groups(old_groups: &[GroupRevision], new_groups: Vec) -> MergeGroupResult { let mut merge_result = MergeGroupResult::new(); if old_groups.is_empty() { - merge_result.all_group_revs = new_groups; + merge_result.all_group_revs = new_groups.clone(); + merge_result.new_group_revs = new_groups; return merge_result; } 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 d2784f0e77..54d001d4a7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -89,7 +89,7 @@ where let field_type_rev = field_rev.ty; let type_option = field_rev.get_type_option::(field_type_rev); let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); - let _ = configuration.init_groups(groups, false)?; + let _ = configuration.init_groups(groups, true)?; Ok(Self { field_id: field_rev.id.clone(), 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 index 4ce5523404..938bdd127e 100644 --- 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 @@ -16,7 +16,7 @@ impl DefaultGroupController { let group = Group::new( DEFAULT_GROUP_CONTROLLER.to_owned(), field_rev.id.clone(), - "Oops".to_owned(), + "".to_owned(), "".to_owned(), ); Self { 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 16ee630cc7..2bf8f1bbeb 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,4 +1,4 @@ -use crate::entities::{CreateFilterParams, DeleteFilterParams, GridLayout, GridSettingChangesetParams}; +use crate::entities::{DeleteFilterParams, GridLayout, GridSettingChangesetParams, InsertFilterParams}; pub struct GridSettingChangesetBuilder { params: GridSettingChangesetParams, @@ -17,7 +17,7 @@ impl GridSettingChangesetBuilder { Self { params } } - pub fn insert_filter(mut self, params: CreateFilterParams) -> Self { + pub fn insert_filter(mut self, params: InsertFilterParams) -> 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 a1f0b8a0c6..0eff7edaa4 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,14 +3,14 @@ #![allow(dead_code)] #![allow(unused_imports)] -use flowy_grid::entities::{CreateFilterParams, CreateGridFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB}; +use flowy_grid::entities::{InsertFilterParams, InsertFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB}; use flowy_grid::services::setting::GridSettingChangesetBuilder; use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision}; use crate::grid::grid_editor::GridEditorTest; pub enum FilterScript { InsertGridTableFilter { - payload: CreateGridFilterPayloadPB, + payload: InsertFilterPayloadPB, }, AssertTableFilterCount { count: i32, @@ -47,8 +47,8 @@ impl GridFilterTest { match script { FilterScript::InsertGridTableFilter { payload } => { - let params: CreateFilterParams = payload.try_into().unwrap(); - let _ = self.editor.update_filter(params).await.unwrap(); + let params: InsertFilterParams = payload.try_into().unwrap(); + let _ = self.editor.create_filter(params).await.unwrap(); } FilterScript::AssertTableFilterCount { count } => { let filters = self.editor.get_grid_filter().await.unwrap(); diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs index 3e45a4053d..5868e16c2d 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs @@ -1,13 +1,13 @@ use crate::grid::filter_test::script::FilterScript::*; use crate::grid::filter_test::script::*; -use flowy_grid::entities::{CreateGridFilterPayloadPB, FieldType, TextFilterCondition}; +use flowy_grid::entities::{FieldType, InsertFilterPayloadPB, TextFilterCondition}; use flowy_grid_data_model::revision::FieldRevision; #[tokio::test] async fn grid_filter_create_test() { let mut test = GridFilterTest::new().await; let field_rev = test.get_field_rev(FieldType::RichText); - let payload = CreateGridFilterPayloadPB::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned())); + let payload = InsertFilterPayloadPB::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned())); let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }]; test.run_scripts(scripts).await; } @@ -19,7 +19,7 @@ async fn grid_filter_invalid_condition_panic_test() { let field_rev = test.get_field_rev(FieldType::RichText).clone(); // 100 is not a valid condition, so this test should be panic. - let payload = CreateGridFilterPayloadPB::new(&field_rev, 100, Some("".to_owned())); + let payload = InsertFilterPayloadPB::new(&field_rev, 100, Some("".to_owned())); let scripts = vec![InsertGridTableFilter { payload }]; test.run_scripts(scripts).await; } @@ -46,6 +46,6 @@ async fn grid_filter_delete_test() { #[tokio::test] async fn grid_filter_get_rows_test() {} -fn create_filter(field_rev: &FieldRevision, condition: TextFilterCondition, s: &str) -> CreateGridFilterPayloadPB { - CreateGridFilterPayloadPB::new(field_rev, condition, Some(s.to_owned())) +fn create_filter(field_rev: &FieldRevision, condition: TextFilterCondition, s: &str) -> InsertFilterPayloadPB { + InsertFilterPayloadPB::new(field_rev, condition, Some(s.to_owned())) } 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 373eabdc88..ce6044c39e 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 @@ -188,7 +188,7 @@ impl GridGroupTest { .await; } GroupScript::GroupByField { field_id } => { - self.editor.group_field(&field_id).await.unwrap(); + self.editor.group_by_field(&field_id).await.unwrap(); } } } 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 e836834265..45989f5b1c 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 @@ -61,12 +61,12 @@ impl GridViewRevisionPad { &mut self, field_id: &str, field_type: &FieldTypeRevision, - group_rev: GroupConfigurationRevision, + group_configuration_rev: GroupConfigurationRevision, ) -> CollaborateResult> { self.modify(|view| { // Only save one group view.groups.clear(); - view.groups.add_object(field_id, field_type, group_rev); + view.groups.add_object(field_id, field_type, group_configuration_rev); Ok(Some(())) }) }