diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs index ef5632b0c5..fe825c2ebc 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager.rs @@ -54,7 +54,7 @@ impl GridBlockManager { pub(crate) async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult> { let block_id = self.persistence.get_block_id(row_id)?; - Ok(self.get_block_editor(&block_id).await?) + self.get_block_editor(&block_id).await } #[tracing::instrument(level = "trace", skip(self, start_row_id), err)] diff --git a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs index 3adea9a853..6342ba0099 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_manager_trait_impl.rs @@ -30,8 +30,7 @@ impl GridViewRowDelegate for Arc { let blocks = block_manager.get_block_snapshots(None).await.unwrap(); blocks .into_iter() - .map(|block| block.row_revs) - .flatten() + .flat_map(|block| block.row_revs) .collect::>>() }) } diff --git a/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs b/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs index f7ef205435..1f64ca9ebb 100644 --- a/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs +++ b/frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs @@ -113,11 +113,15 @@ impl AnyCellData { /// * Use URLCellData to parse the data when the FieldType is URL. /// * Use String to parse the data when the FieldType is RichText, Number, or Checkbox. /// * Check out the implementation of CellDataOperation trait for more information. -#[derive(Default)] +#[derive(Default, Debug)] pub struct CellBytes(pub Bytes); +pub trait CellDataIsEmpty { + fn is_empty(&self) -> bool; +} + pub trait CellBytesParser { - type Object; + type Object: CellDataIsEmpty; fn parser(bytes: &Bytes) -> FlowyResult; } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs index cfe6a7b65d..1cd64e3f4c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs @@ -1,4 +1,4 @@ -use crate::services::cell::{CellBytesParser, FromCellString}; +use crate::services::cell::{CellBytesParser, CellDataIsEmpty, FromCellString}; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; use std::str::FromStr; @@ -61,6 +61,13 @@ impl ToString for CheckboxCellData { self.0.clone() } } + +impl CellDataIsEmpty for CheckboxCellData { + fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + pub struct CheckboxCellDataParser(); impl CellBytesParser for CheckboxCellDataParser { type Object = CheckboxCellData; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option_entities.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option_entities.rs index ff2dc3fc4f..5b73176796 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option_entities.rs @@ -1,6 +1,6 @@ use crate::entities::CellChangesetPB; use crate::entities::{GridCellIdPB, GridCellIdParams}; -use crate::services::cell::{CellBytesParser, FromCellChangeset, FromCellString}; +use crate::services::cell::{CellBytesParser, CellDataIsEmpty, FromCellChangeset, FromCellString}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -200,6 +200,12 @@ impl std::default::Default for TimeFormat { } } +impl CellDataIsEmpty for DateCellDataPB { + fn is_empty(&self) -> bool { + self.date.is_empty() + } +} + pub struct DateCellDataParser(); impl CellBytesParser for DateCellDataParser { type Object = DateCellDataPB; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option_entities.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option_entities.rs index aa372222b8..bdb227ad37 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option_entities.rs @@ -1,4 +1,4 @@ -use crate::services::cell::{CellBytesCustomParser, CellBytesParser}; +use crate::services::cell::{CellBytesCustomParser, CellBytesParser, CellDataIsEmpty}; use crate::services::field::number_currency::Currency; use crate::services::field::{strip_currency_symbol, NumberFormat, STRIP_SYMBOL}; use bytes::Bytes; @@ -93,6 +93,12 @@ impl ToString for NumberCellData { } } } + +impl CellDataIsEmpty for NumberCellData { + fn is_empty(&self) -> bool { + self.decimal.is_none() + } +} pub struct NumberCellDataParser(); impl CellBytesParser for NumberCellDataParser { type Object = NumberCellData; 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 93d80e85c0..21eb2b7a54 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 @@ -117,12 +117,12 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { match field_type { FieldType::Checkbox => { //Add Yes and No options if it's not exist. - if self.0.options.iter().find(|option| option.name == CHECK).is_none() { + if !self.0.options.iter().any(|option| option.name == CHECK) { let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green); self.0.options.push(check_option); } - if self.0.options.iter().find(|option| option.name == UNCHECK).is_none() { + if !self.0.options.iter().any(|option| option.name == UNCHECK) { let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow); self.0.options.push(uncheck_option); } 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 c85dfd000b..db8156b865 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs @@ -1,5 +1,7 @@ use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams}; -use crate::services::cell::{CellBytes, CellBytesParser, CellData, CellDisplayable, FromCellChangeset, FromCellString}; +use crate::services::cell::{ + CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString, +}; use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -233,7 +235,7 @@ impl ToString for SelectOptionIds { impl std::convert::From> for SelectOptionIds { fn from(s: Option) -> Self { match s { - None => Self { 0: vec![] }, + None => Self(vec![]), Some(s) => Self::from(s), } } @@ -252,6 +254,13 @@ impl std::ops::DerefMut for SelectOptionIds { &mut self.0 } } + +impl CellDataIsEmpty for SelectOptionIds { + fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + pub struct SelectOptionIdsParser(); impl CellBytesParser for SelectOptionIdsParser { type Object = SelectOptionIds; @@ -263,6 +272,12 @@ impl CellBytesParser for SelectOptionIdsParser { } } +impl CellDataIsEmpty for SelectOptionCellDataPB { + fn is_empty(&self) -> bool { + self.select_options.is_empty() + } +} + pub struct SelectOptionCellDataParser(); impl CellBytesParser for SelectOptionCellDataParser { type Object = SelectOptionCellDataPB; 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 78331c8c0f..2d6db7e61c 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 @@ -61,7 +61,6 @@ impl CellDataOperation for SingleSel _cell_rev: Option, ) -> Result { let content_changeset = changeset.try_into_inner()?; - let new_cell_data: String; let mut insert_option_ids = content_changeset .insert_option_ids @@ -73,14 +72,12 @@ impl CellDataOperation for SingleSel // Sometimes, the insert_option_ids may contain list of option ids. For example, // copy/paste a ids string. if insert_option_ids.is_empty() { - new_cell_data = "".to_string() + Ok("".to_string()) } else { // Just take the first select option let _ = insert_option_ids.drain(1..); - new_cell_data = insert_option_ids.pop().unwrap(); + Ok(insert_option_ids.pop().unwrap()) } - - Ok(new_cell_data) } } @@ -109,12 +106,12 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder { match field_type { FieldType::Checkbox => { //add Yes and No options if it's not exist. - if self.0.options.iter().find(|option| option.name == CHECK).is_none() { + if !self.0.options.iter().any(|option| option.name == CHECK) { let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green); self.0.options.push(check_option); } - if self.0.options.iter().find(|option| option.name == UNCHECK).is_none() { + if !self.0.options.iter().any(|option| option.name == UNCHECK) { let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow); self.0.options.push(uncheck_option); } 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 1375e4a799..d7a5b248c3 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 @@ -1,8 +1,8 @@ use crate::entities::FieldType; use crate::impl_type_option; use crate::services::cell::{ - decode_cell_data_to_string, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataOperation, - CellDisplayable, FromCellString, + decode_cell_data_to_string, CellBytes, CellBytesParser, CellData, CellDataChangeset, CellDataIsEmpty, + CellDataOperation, CellDisplayable, FromCellString, }; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use bytes::Bytes; @@ -125,6 +125,12 @@ impl ToString for TextCellData { } } +impl CellDataIsEmpty for TextCellData { + fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + pub struct TextCellDataParser(); impl CellBytesParser for TextCellDataParser { type Object = TextCellData; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option_entities.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option_entities.rs index 46e67fdf18..a368f48fd2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option_entities.rs @@ -1,4 +1,4 @@ -use crate::services::cell::{CellBytesParser, FromCellString}; +use crate::services::cell::{CellBytesParser, CellDataIsEmpty, FromCellString}; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::{internal_error, FlowyResult}; @@ -26,6 +26,12 @@ impl URLCellDataPB { } } +impl CellDataIsEmpty for URLCellDataPB { + fn is_empty(&self) -> bool { + self.content.is_empty() + } +} + pub struct URLCellDataParser(); impl CellBytesParser for URLCellDataParser { type Object = URLCellDataPB; 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 8b19904879..6aa96a4e81 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 @@ -123,8 +123,8 @@ impl GridViewRevisionEditor { }) .await; + tracing::trace!("Delete row in view changeset: {:?}", changesets); if let Some(changesets) = changesets { - tracing::trace!("{:?}", changesets); for changeset in changesets { self.notify_did_update_group(changeset).await; } @@ -539,11 +539,10 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc>() }) .unwrap_or_default(); @@ -553,11 +552,10 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc>() }) .unwrap_or_default(); diff --git a/frontend/rust-lib/flowy-grid/src/services/group/action.rs b/frontend/rust-lib/flowy-grid/src/services/group/action.rs index 271b2f4603..27f0a3d90c 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/action.rs @@ -1,4 +1,5 @@ use crate::entities::{GroupChangesetPB, GroupViewChangesetPB}; +use crate::services::cell::CellDataIsEmpty; use crate::services::group::controller::MoveGroupRowContext; use crate::services::group::Group; use flowy_error::FlowyResult; @@ -10,7 +11,7 @@ use std::sync::Arc; /// For example, the `CheckboxGroupController` implements this trait to provide custom behavior. /// pub trait GroupControllerCustomActions: Send + Sync { - type CellDataType; + type CellDataType: CellDataIsEmpty; /// Returns the a value of the cell, default value is None /// /// Determine which group the row is placed in based on the data of the cell. If the cell data @@ -20,22 +21,20 @@ pub trait GroupControllerCustomActions: Send + Sync { None } - /// Returns a bool value to determine the `No status` group should show or hide. - /// - fn use_no_status_group(&self) -> bool { - true - } - /// Returns a bool value to determine whether the group should contain this cell or not. fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; - /// Adding a new row to the group if the cell data match the group filter. + /// Adds or removes a row if the cell data match the group filter. /// It gets called after editing the cell or row /// - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; + fn add_or_remove_row_in_groups_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec; - /// - fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; + /// Deletes the row from the group + fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; /// Move row from one group to another fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs index 6fd261fa8b..ab554f195e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/configuration.rs @@ -1,5 +1,5 @@ use crate::entities::{GroupPB, GroupViewChangesetPB}; -use crate::services::group::{default_group_configuration, make_no_status_group, GeneratedGroupConfig, Group}; +use crate::services::group::{default_group_configuration, GeneratedGroupContext, Group}; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision, @@ -118,8 +118,16 @@ where } } - /// Iterate mut the groups. The default group will be the last one that get mutated. - pub(crate) fn iter_mut_all_groups(&mut self, mut each: impl FnMut(&mut Group)) { + /// Iterate mut the groups without `No status` group + pub(crate) fn iter_mut_status_groups(&mut self, mut each: impl FnMut(&mut Group)) { + self.groups_map.iter_mut().for_each(|(_, group)| { + if group.id != self.field_rev.id { + each(group); + } + }); + } + + pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) { self.groups_map.iter_mut().for_each(|(_, group)| { each(group); }); @@ -172,14 +180,19 @@ where /// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged /// while keeping the order of the old groups. /// - #[tracing::instrument(level = "trace", skip(self, generated_group_configs), err)] + #[tracing::instrument(level = "trace", skip(self, generated_group_context), err)] pub(crate) fn init_groups( &mut self, - generated_group_configs: Vec, + generated_group_context: GeneratedGroupContext, ) -> FlowyResult> { + let GeneratedGroupContext { + no_status_group, + group_configs, + } = generated_group_context; + let mut new_groups = vec![]; let mut filter_content_map = HashMap::new(); - generated_group_configs.into_iter().for_each(|generate_group| { + group_configs.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); }); @@ -190,12 +203,9 @@ where old_groups.clear(); } - // When grouping by a new field, there is no `No status` group. So it needs - // to insert a `No status` group at index 0 // The `No status` group index is initialized to 0 - // - if !old_groups.iter().any(|group| group.id == self.field_rev.id) { - old_groups.insert(0, make_no_status_group(&self.field_rev)); + if let Some(no_status_group) = no_status_group { + old_groups.insert(0, no_status_group); } // The `all_group_revs` is the combination of the new groups and old groups @@ -236,9 +246,9 @@ where Some(pos) => { let mut old_group = configuration.groups.get_mut(pos).unwrap(); // Take the old group setting - group_rev.update_with_other(&old_group); + group_rev.update_with_other(old_group); if !is_changed { - is_changed = is_group_changed(group_rev, &old_group); + is_changed = is_group_changed(group_rev, old_group); } // Consider the the name of the `group_rev` as the newest. old_group.name = group_rev.name.clone(); 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 cb442070cb..899193b5d4 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -1,5 +1,5 @@ use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB}; -use crate::services::cell::{decode_any_cell_data, CellBytesParser}; +use crate::services::cell::{decode_any_cell_data, CellBytesParser, CellDataIsEmpty}; use crate::services::group::action::{GroupControllerCustomActions, GroupControllerSharedActions}; use crate::services::group::configuration::GroupContext; use crate::services::group::entities::Group; @@ -29,10 +29,15 @@ pub trait GroupGenerator { type TypeOptionType; fn generate_groups( - field_id: &str, + field_rev: &FieldRevision, group_ctx: &Self::Context, type_option: &Option, - ) -> Vec; + ) -> GeneratedGroupContext; +} + +pub struct GeneratedGroupContext { + pub no_status_group: Option, + pub group_configs: Vec, } pub struct GeneratedGroupConfig { @@ -67,8 +72,8 @@ where { pub async fn new(field_rev: &Arc, mut configuration: GroupContext) -> FlowyResult { let type_option = field_rev.get_type_option::(field_rev.ty); - let groups = G::generate_groups(&field_rev.id, &configuration, &type_option); - let _ = configuration.init_groups(groups)?; + let generated_group_context = G::generate_groups(field_rev, &configuration, &type_option); + let _ = configuration.init_groups(generated_group_context)?; Ok(Self { field_id: field_rev.id.clone(), @@ -161,16 +166,7 @@ where } fn groups(&self) -> Vec { - if self.use_no_status_group() { - self.group_ctx.groups().into_iter().cloned().collect() - } else { - self.group_ctx - .groups() - .into_iter() - .filter(|group| group.id != self.field_id) - .cloned() - .collect::>() - } + self.group_ctx.groups().into_iter().cloned().collect() } fn get_group(&self, group_id: &str) -> Option<(usize, Group)> { @@ -230,13 +226,14 @@ where if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_data = cell_bytes.parser::

()?; - let mut changesets = self.add_row_if_match(row_rev, &cell_data); - // if let Some(default_group_changeset) = self.update_default_group(row_rev, &changesets) { - // tracing::trace!("default_group_changeset: {}", default_group_changeset); - // if !default_group_changeset.is_empty() { - // changesets.push(default_group_changeset); - // } - // } + let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data); + + if let Some(default_group_changeset) = self.update_default_group(row_rev, &changesets) { + tracing::trace!("default_group_changeset: {}", default_group_changeset); + if !default_group_changeset.is_empty() { + changesets.push(default_group_changeset); + } + } Ok(changesets) } else { Ok(vec![]) @@ -248,18 +245,30 @@ where row_rev: &RowRevision, field_rev: &FieldRevision, ) -> FlowyResult> { - // if the cell_rev is none, then the row must be crated from the default group. + // if the cell_rev is none, then the row must in the default group. if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_data = cell_bytes.parser::

()?; - Ok(self.remove_row_if_match(row_rev, &cell_data)) - } else if let Some(group) = self.group_ctx.get_no_status_group() { - Ok(vec![GroupChangesetPB::delete( - group.id.clone(), - vec![row_rev.id.clone()], - )]) - } else { - Ok(vec![]) + if !cell_data.is_empty() { + tracing::error!("did_delete_delete_row {:?}", cell_rev.data); + return Ok(self.delete_row(row_rev, &cell_data)); + } + } + + match self.group_ctx.get_no_status_group() { + None => { + tracing::error!("Unexpected None value. It should have the no status group"); + Ok(vec![]) + } + Some(no_status_group) => { + if !no_status_group.contains_row(&row_rev.id) { + tracing::error!("The row: {} should be in the no status group", row_rev.id); + } + Ok(vec![GroupChangesetPB::delete( + no_status_group.id.clone(), + vec![row_rev.id.clone()], + )]) + } } } 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 f64f96a194..3187b216f4 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 @@ -7,7 +7,7 @@ use crate::services::group::controller::{ }; use crate::services::cell::insert_checkbox_cell; -use crate::services::group::{move_group_row, GeneratedGroupConfig}; +use crate::services::group::{move_group_row, GeneratedGroupConfig, GeneratedGroupContext}; use flowy_grid_data_model::revision::{ CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision, }; @@ -27,10 +27,6 @@ impl GroupControllerCustomActions for CheckboxGroupController { Some(CellRevision::new(UNCHECK.to_string())) } - fn use_no_status_group(&self) -> bool { - false - } - fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool { if cell_data.is_check() { content == CHECK @@ -39,9 +35,13 @@ impl GroupControllerCustomActions for CheckboxGroupController { } } - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn add_or_remove_row_in_groups_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_status_groups(|group| { let mut changeset = GroupChangesetPB::new(group.id.clone()); let is_not_contained = !group.contains_row(&row_rev.id); if group.id == CHECK { @@ -81,9 +81,9 @@ impl GroupControllerCustomActions for CheckboxGroupController { changesets } - fn remove_row_if_match(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec { + fn delete_row(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_groups(|group| { let mut changeset = GroupChangesetPB::new(group.id.clone()); if group.contains_row(&row_rev.id) { changeset.deleted_rows.push(row_rev.id.clone()); @@ -99,7 +99,7 @@ impl GroupControllerCustomActions for CheckboxGroupController { fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -133,10 +133,10 @@ impl GroupGenerator for CheckboxGroupGenerator { type TypeOptionType = CheckboxTypeOptionPB; fn generate_groups( - _field_id: &str, + _field_rev: &FieldRevision, _group_ctx: &Self::Context, _type_option: &Option, - ) -> Vec { + ) -> GeneratedGroupContext { let check_group = GeneratedGroupConfig { group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()), filter_content: CHECK.to_string(), @@ -146,6 +146,10 @@ impl GroupGenerator for CheckboxGroupGenerator { group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()), filter_content: UNCHECK.to_string(), }; - vec![check_group, uncheck_group] + + GeneratedGroupContext { + no_status_group: None, + group_configs: 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 index 122a2848b7..d262d625c1 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 @@ -1,5 +1,6 @@ use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB}; -use crate::services::group::{Group, GroupController, GroupControllerSharedActions, MoveGroupRowContext}; +use crate::services::group::action::GroupControllerSharedActions; +use crate::services::group::{Group, GroupController, MoveGroupRowContext}; use flowy_error::FlowyResult; use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use std::sync::Arc; 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 5529f0a13f..58bb4a23d0 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,7 @@ use crate::services::group::controller::{ }; use crate::services::group::controller_impls::select_option_controller::util::*; -use crate::services::group::GeneratedGroupConfig; +use crate::services::group::{make_no_status_group, GeneratedGroupContext}; use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // MultiSelect @@ -26,19 +26,23 @@ impl GroupControllerCustomActions for MultiSelectGroupController { cell_data.select_options.iter().any(|option| option.id == content) } - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn add_or_remove_row_in_groups_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { - if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) { + self.group_ctx.iter_mut_status_groups(|group| { + if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } }); changesets } - fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_status_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } @@ -48,7 +52,7 @@ impl GroupControllerCustomActions for MultiSelectGroupController { fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -79,14 +83,20 @@ pub struct MultiSelectGroupGenerator(); impl GroupGenerator for MultiSelectGroupGenerator { type Context = SelectOptionGroupContext; type TypeOptionType = MultiSelectTypeOptionPB; + fn generate_groups( - field_id: &str, + field_rev: &FieldRevision, group_ctx: &Self::Context, type_option: &Option, - ) -> Vec { - match type_option { + ) -> GeneratedGroupContext { + let group_configs = match type_option { None => vec![], - Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options), + Some(type_option) => generate_select_option_groups(&field_rev.id, group_ctx, &type_option.options), + }; + + GeneratedGroupContext { + no_status_group: Some(make_no_status_group(field_rev)), + group_configs, } } } 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 0d53e0dee6..203e4f1675 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,7 @@ use crate::services::group::controller::{ use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::Group; -use crate::services::group::GeneratedGroupConfig; +use crate::services::group::{make_no_status_group, GeneratedGroupContext}; use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision}; // SingleSelect @@ -26,19 +26,23 @@ impl GroupControllerCustomActions for SingleSelectGroupController { cell_data.select_options.iter().any(|option| option.id == content) } - fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn add_or_remove_row_in_groups_if_match( + &mut self, + row_rev: &RowRevision, + cell_data: &Self::CellDataType, + ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { - if let Some(changeset) = add_select_option_row(group, cell_data, row_rev) { + self.group_ctx.iter_mut_status_groups(|group| { + if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } }); changesets } - fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_status_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { changesets.push(changeset); } @@ -48,7 +52,7 @@ impl GroupControllerCustomActions for SingleSelectGroupController { fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_all_groups(|group| { + self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -80,13 +84,18 @@ impl GroupGenerator for SingleSelectGroupGenerator { type Context = SelectOptionGroupContext; type TypeOptionType = SingleSelectTypeOptionPB; fn generate_groups( - field_id: &str, + field_rev: &FieldRevision, group_ctx: &Self::Context, type_option: &Option, - ) -> Vec { - match type_option { + ) -> GeneratedGroupContext { + let group_configs = match type_option { None => vec![], - Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options), + Some(type_option) => generate_select_option_groups(&field_rev.id, group_ctx, &type_option.options), + }; + + GeneratedGroupContext { + no_status_group: Some(make_no_status_group(field_rev)), + group_configs, } } } 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 71fbfb410e..29bbd8f0f9 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 @@ -10,7 +10,7 @@ use flowy_grid_data_model::revision::{ pub type SelectOptionGroupContext = GroupContext; -pub fn add_select_option_row( +pub fn add_or_remove_select_option_row( group: &mut Group, cell_data: &SelectOptionCellDataPB, row_rev: &RowRevision, 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 5c6180c859..c8116d6897 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 @@ -97,7 +97,7 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat let field_id = field_rev.id.clone(); let field_type_rev = field_rev.ty; let field_type: FieldType = field_rev.ty.into(); - let mut group_configuration_rev = match field_type { + match field_type { FieldType::RichText => { GroupConfigurationRevision::new(field_id, field_type_rev, TextGroupConfigurationRevision::default()) .unwrap() @@ -130,11 +130,7 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat FieldType::URL => { GroupConfigurationRevision::new(field_id, field_type_rev, UrlGroupConfigurationRevision::default()).unwrap() } - }; - - // Append the no `status` group - group_configuration_rev.groups.push(make_no_status_group(field_rev)); - group_configuration_rev + } } pub fn make_no_status_group(field_rev: &FieldRevision) -> GroupRevision { diff --git a/frontend/rust-lib/flowy-net/src/http_server/document.rs b/frontend/rust-lib/flowy-net/src/http_server/document.rs index b286e5c102..1a6b66ca59 100644 --- a/frontend/rust-lib/flowy-net/src/http_server/document.rs +++ b/frontend/rust-lib/flowy-net/src/http_server/document.rs @@ -42,7 +42,7 @@ impl TextEditorCloudService for BlockHttpCloudService { pub async fn create_document_request(token: &str, params: CreateTextBlockParams, url: &str) -> Result<(), FlowyError> { let _ = request_builder() - .post(&url.to_owned()) + .post(url) .header(HEADER_TOKEN, token) .protobuf(params)? .send() @@ -56,7 +56,7 @@ pub async fn read_document_request( url: &str, ) -> Result, FlowyError> { let doc = request_builder() - .get(&url.to_owned()) + .get(url) .header(HEADER_TOKEN, token) .protobuf(params)? .option_response() @@ -67,7 +67,7 @@ pub async fn read_document_request( pub async fn reset_doc_request(token: &str, params: ResetTextBlockParams, url: &str) -> Result<(), FlowyError> { let _ = request_builder() - .patch(&url.to_owned()) + .patch(url) .header(HEADER_TOKEN, token) .protobuf(params)? .send() diff --git a/frontend/rust-lib/flowy-net/src/http_server/user.rs b/frontend/rust-lib/flowy-net/src/http_server/user.rs index 7768c91bb6..406de3d1bc 100644 --- a/frontend/rust-lib/flowy-net/src/http_server/user.rs +++ b/frontend/rust-lib/flowy-net/src/http_server/user.rs @@ -66,35 +66,23 @@ impl UserCloudService for UserHttpCloudService { } pub async fn user_sign_up_request(params: SignUpParams, url: &str) -> Result { - let response = request_builder() - .post(&url.to_owned()) - .protobuf(params)? - .response() - .await?; + let response = request_builder().post(url).protobuf(params)?.response().await?; Ok(response) } pub async fn user_sign_in_request(params: SignInParams, url: &str) -> Result { - let response = request_builder() - .post(&url.to_owned()) - .protobuf(params)? - .response() - .await?; + let response = request_builder().post(url).protobuf(params)?.response().await?; Ok(response) } pub async fn user_sign_out_request(token: &str, url: &str) -> Result<(), ServerError> { - let _ = request_builder() - .delete(&url.to_owned()) - .header(HEADER_TOKEN, token) - .send() - .await?; + let _ = request_builder().delete(url).header(HEADER_TOKEN, token).send().await?; Ok(()) } pub async fn get_user_profile_request(token: &str, url: &str) -> Result { let user_profile = request_builder() - .get(&url.to_owned()) + .get(url) .header(HEADER_TOKEN, token) .response() .await?; @@ -107,7 +95,7 @@ pub async fn update_user_profile_request( url: &str, ) -> Result<(), ServerError> { let _ = request_builder() - .patch(&url.to_owned()) + .patch(url) .header(HEADER_TOKEN, token) .protobuf(params)? .send() diff --git a/frontend/rust-lib/flowy-revision/src/rev_manager.rs b/frontend/rust-lib/flowy-revision/src/rev_manager.rs index 73592cad85..1776956d1c 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_manager.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_manager.rs @@ -164,7 +164,7 @@ impl RevisionManager { } pub async fn next_sync_revision(&self) -> FlowyResult> { - Ok(self.rev_persistence.next_sync_revision().await?) + self.rev_persistence.next_sync_revision().await } pub async fn get_revision(&self, rev_id: i64) -> Option { diff --git a/frontend/rust-lib/flowy-revision/src/rev_persistence.rs b/frontend/rust-lib/flowy-revision/src/rev_persistence.rs index 2124598400..9360182eba 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_persistence.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_persistence.rs @@ -130,7 +130,6 @@ impl RevisionPersistence { #[tracing::instrument(level = "trace", skip(self, revisions), err)] pub(crate) async fn reset(&self, revisions: Vec) -> FlowyResult<()> { let records = revisions - .to_vec() .into_iter() .map(|revision| RevisionRecord { revision, diff --git a/frontend/rust-lib/lib-log/src/layer.rs b/frontend/rust-lib/lib-log/src/layer.rs index 14efa4c90e..b2eaabcc22 100644 --- a/frontend/rust-lib/lib-log/src/layer.rs +++ b/frontend/rust-lib/lib-log/src/layer.rs @@ -114,11 +114,10 @@ fn format_event_message tracing_subscriber::registry::Lo let mut message = event_visitor .values() .get("message") - .map(|v| match v { + .and_then(|v| match v { Value::String(s) => Some(s.as_str()), _ => None, }) - .flatten() .unwrap_or_else(|| event.metadata().target()) .to_owned(); diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs index ba113810f6..57bcf1b017 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_block.rs @@ -73,4 +73,8 @@ impl CellRevision { pub fn new(data: String) -> Self { Self { data } } + + pub fn is_empty(&self) -> bool { + self.data.is_empty() + } }