chore: fix some bugs

This commit is contained in:
appflowy 2022-08-17 14:33:45 +08:00
parent 9922645e59
commit 0ecb15cfa3
10 changed files with 270 additions and 145 deletions

View File

@ -112,6 +112,12 @@ pub struct InsertedRowPB {
pub index: Option<i32>, pub index: Option<i32>,
} }
impl InsertedRowPB {
pub fn new(row: RowPB) -> Self {
Self { row, index: None }
}
}
impl std::convert::From<RowPB> for InsertedRowPB { impl std::convert::From<RowPB> for InsertedRowPB {
fn from(row: RowPB) -> Self { fn from(row: RowPB) -> Self {
Self { row, index: None } Self { row, index: None }

View File

@ -17,6 +17,9 @@ pub struct GroupRowsChangesetPB {
} }
impl GroupRowsChangesetPB { impl GroupRowsChangesetPB {
pub fn is_empty(&self) -> bool {
self.inserted_rows.is_empty() && self.deleted_rows.is_empty() && self.updated_rows.is_empty()
}
pub fn insert(group_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self { pub fn insert(group_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self {
Self { Self {
group_id, group_id,

View File

@ -3,7 +3,7 @@ use crate::entities::GridCellIdParams;
use crate::entities::*; use crate::entities::*;
use crate::manager::{GridTaskSchedulerRwLock, GridUser}; use crate::manager::{GridTaskSchedulerRwLock, GridUser};
use crate::services::block_manager::GridBlockManager; use crate::services::block_manager::GridBlockManager;
use crate::services::block_manager_trait_impl::*;
use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data, CellBytes}; use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data, CellBytes};
use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder}; use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
use crate::services::filter::GridFilterService; use crate::services::filter::GridFilterService;
@ -405,7 +405,7 @@ impl GridRevisionEditor {
content = Some(apply_cell_data_changeset(content.unwrap(), cell_rev, field_rev)?); content = Some(apply_cell_data_changeset(content.unwrap(), cell_rev, field_rev)?);
let cell_changeset = CellChangesetPB { let cell_changeset = CellChangesetPB {
grid_id, grid_id,
row_id, row_id: row_id.clone(),
field_id, field_id,
content, content,
}; };
@ -413,6 +413,8 @@ impl GridRevisionEditor {
.block_manager .block_manager
.update_cell(cell_changeset, make_row_from_row_rev) .update_cell(cell_changeset, make_row_from_row_rev)
.await?; .await?;
self.view_manager.did_update_row(&row_id).await;
Ok(()) Ok(())
} }
} }

View File

@ -5,7 +5,7 @@ use crate::entities::{
}; };
use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_editor_task::GridServiceTaskScheduler;
use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate}; use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
use crate::services::group::{default_group_configuration, Group, GroupConfigurationDelegate, GroupService}; use crate::services::group::{default_group_configuration, GroupConfigurationDelegate, GroupService};
use crate::services::setting::make_grid_setting; use crate::services::setting::make_grid_setting;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowRevision}; use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowRevision};
@ -105,11 +105,16 @@ impl GridViewRevisionEditor {
} }
} }
pub(crate) async fn did_update_row(&self, row_rev: Arc<RowRevision>) { pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
match self.group_id_of_row(&row_rev.id).await { if let Some(changesets) = self
None => {} .group_service
Some(group_id) => { .write()
// self.get_mut_group(&group_id, |group| Ok(())); .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;
} }
} }
} }
@ -117,7 +122,7 @@ impl GridViewRevisionEditor {
async fn group_id_of_row(&self, row_id: &str) -> Option<String> { async fn group_id_of_row(&self, row_id: &str) -> Option<String> {
let read_guard = &self.group_service.read().await.groups; let read_guard = &self.group_service.read().await.groups;
for group in read_guard.iter() { for group in read_guard.iter() {
if group.rows.iter().any(|row| row.id == row_id) { if group.contains_row(row_id) {
return Some(group.id.clone()); return Some(group.id.clone());
} }
} }

View File

@ -2,7 +2,7 @@ use crate::entities::{
CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, MoveRowParams, RepeatedGridGroupPB, RowPB, CreateRowParams, GridFilterConfiguration, GridLayout, GridSettingPB, MoveRowParams, RepeatedGridGroupPB, RowPB,
}; };
use crate::manager::GridUser; use crate::manager::GridUser;
use crate::services::block_manager::GridBlockManager;
use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_editor_task::GridServiceTaskScheduler;
use crate::services::grid_view_editor::GridViewRevisionEditor; use crate::services::grid_view_editor::GridViewRevisionEditor;
use bytes::Bytes; use bytes::Bytes;
@ -11,13 +11,12 @@ use flowy_error::FlowyResult;
use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
use flowy_revision::disk::SQLiteGridViewRevisionPersistence; use flowy_revision::disk::SQLiteGridViewRevisionPersistence;
use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence}; use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence};
use flowy_sync::client_grid::GridRevisionPad;
use flowy_sync::entities::grid::GridSettingChangesetParams; use flowy_sync::entities::grid::GridSettingChangesetParams;
use flowy_sync::entities::revision::Revision; use flowy_sync::entities::revision::Revision;
use flowy_sync::util::make_text_delta_from_revisions; use flowy_sync::util::make_text_delta_from_revisions;
use lib_infra::future::{wrap_future, AFFuture}; use lib_infra::future::AFFuture;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock;
type ViewId = String; type ViewId = String;
@ -74,7 +73,16 @@ impl GridViewManager {
} }
pub(crate) async fn did_update_row(&self, row_id: &str) { pub(crate) async fn did_update_row(&self, row_id: &str) {
let row = self.row_delegate.gv_get_row_rev(row_id).await; match self.row_delegate.gv_get_row_rev(row_id).await {
None => {
tracing::warn!("Can not find the row in grid view");
}
Some(row_rev) => {
for view_editor in self.view_editors.iter() {
view_editor.did_update_row(&row_rev).await;
}
}
}
} }
pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) { pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) {

View File

@ -1,13 +1,16 @@
use crate::entities::CheckboxGroupConfigurationPB; use crate::entities::{CheckboxGroupConfigurationPB, GroupRowsChangesetPB};
use flowy_error::FlowyResult;
use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
use std::sync::Arc;
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
use crate::services::group::{Group, GroupActionHandler, GroupController, GroupGenerator, Groupable}; use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable};
pub type CheckboxGroupController = pub type CheckboxGroupController = GenericGroupController<
GroupController<CheckboxGroupConfigurationPB, CheckboxTypeOptionPB, CheckboxGroupGenerator, CheckboxCellDataParser>; CheckboxGroupConfigurationPB,
CheckboxTypeOptionPB,
CheckboxGroupGenerator,
CheckboxCellDataParser,
>;
impl Groupable for CheckboxGroupController { impl Groupable for CheckboxGroupController {
type CellDataType = CheckboxCellData; type CellDataType = CheckboxCellData;
@ -15,21 +18,13 @@ impl Groupable for CheckboxGroupController {
fn can_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool { fn can_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool {
false false
} }
fn group_row(&mut self, _row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupRowsChangesetPB> {
todo!()
}
} }
impl GroupActionHandler for CheckboxGroupController { impl GroupController for CheckboxGroupController {
fn field_id(&self) -> &str {
&self.field_id
}
fn build_groups(&self) -> Vec<Group> {
self.make_groups()
}
fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
self.handle_rows(row_revs, field_rev)
}
fn fill_row(&self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) { fn fill_row(&self, _row_rev: &mut RowRevision, _field_rev: &FieldRevision, _group_id: &str) {
todo!() todo!()
} }
@ -44,20 +39,8 @@ impl GroupGenerator for CheckboxGroupGenerator {
_configuration: &Option<Self::ConfigurationType>, _configuration: &Option<Self::ConfigurationType>,
_type_option: &Option<Self::TypeOptionType>, _type_option: &Option<Self::TypeOptionType>,
) -> Vec<Group> { ) -> Vec<Group> {
let check_group = Group { let check_group = Group::new("true".to_string(), "".to_string(), CHECK.to_string());
id: "true".to_string(), let uncheck_group = Group::new("false".to_string(), "".to_string(), UNCHECK.to_string());
desc: "".to_string(),
rows: vec![],
content: CHECK.to_string(),
};
let uncheck_group = Group {
id: "false".to_string(),
desc: "".to_string(),
rows: vec![],
content: UNCHECK.to_string(),
};
vec![check_group, uncheck_group] vec![check_group, uncheck_group]
} }
} }

View File

@ -1,13 +1,11 @@
use crate::entities::{GroupPB, RowPB}; use crate::entities::{GroupPB, GroupRowsChangesetPB, RowPB};
use crate::services::cell::{decode_any_cell_data, CellBytesParser}; use crate::services::cell::{decode_any_cell_data, CellBytesParser};
use bytes::Bytes; use bytes::Bytes;
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
use flowy_grid_data_model::revision::{ use flowy_grid_data_model::revision::{
FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer, FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer,
}; };
use indexmap::IndexMap; use indexmap::IndexMap;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
@ -21,30 +19,35 @@ pub trait GroupGenerator {
) -> Vec<Group>; ) -> Vec<Group>;
} }
pub trait Groupable { pub trait Groupable: Send + Sync {
type CellDataType; type CellDataType;
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool; fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
fn group_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupRowsChangesetPB>;
} }
pub trait GroupActionHandler: Send + Sync { pub trait GroupController: GroupControllerSharedAction + Send + Sync {
fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
}
pub trait GroupControllerSharedAction: Send + Sync {
// The field that is used for grouping the rows // The field that is used for grouping the rows
fn field_id(&self) -> &str; fn field_id(&self) -> &str;
fn build_groups(&self) -> Vec<Group>; fn build_groups(&self) -> Vec<Group>;
fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>; fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>;
fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); fn did_update_row(
} &mut self,
row_rev: &RowRevision,
pub trait GroupActionHandler2: Send + Sync { field_rev: &FieldRevision,
fn create_card(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str); ) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
} }
const DEFAULT_GROUP_ID: &str = "default_group"; const DEFAULT_GROUP_ID: &str = "default_group";
/// C: represents the group configuration structure /// C: represents the group configuration structure
/// T: the type option data deserializer that impl [TypeOptionDataDeserializer] /// T: the type option data deserializer that impl [TypeOptionDataDeserializer]
/// G: the group container generator /// G: the group generator, [GroupGenerator]
/// P: the parser that impl [CellBytesParser] for the CellBytes /// P: the parser that impl [CellBytesParser] for the CellBytes
pub struct GroupController<C, T, G, P> { pub struct GenericGroupController<C, T, G, P> {
pub field_id: String, pub field_id: String,
pub groups_map: IndexMap<String, Group>, pub groups_map: IndexMap<String, Group>,
default_group: Group, default_group: Group,
@ -58,7 +61,7 @@ pub struct GroupController<C, T, G, P> {
pub struct Group { pub struct Group {
pub id: String, pub id: String,
pub desc: String, pub desc: String,
pub rows: Vec<RowPB>, rows: Vec<RowPB>,
pub content: String, pub content: String,
} }
@ -72,7 +75,40 @@ impl std::convert::From<Group> for GroupPB {
} }
} }
impl<C, T, G, P> GroupController<C, T, G, P> impl Group {
pub fn new(id: String, desc: String, content: String) -> Self {
Self {
id,
desc,
rows: vec![],
content,
}
}
pub fn contains_row(&self, row_id: &str) -> bool {
self.rows.iter().any(|row| row.id == row_id)
}
pub fn remove_row(&mut self, row_id: &str) {
match self.rows.iter().position(|row| row.id == row_id) {
None => {}
Some(pos) => {
self.rows.remove(pos);
}
}
}
pub fn add_row(&mut self, row_pb: RowPB) {
match self.rows.iter().find(|row| row.id == row_pb.id) {
None => {
self.rows.push(row_pb);
}
Some(_) => {}
}
}
}
impl<C, T, G, P> GenericGroupController<C, T, G, P>
where where
C: TryFrom<Bytes, Error = protobuf::ProtobufError>, C: TryFrom<Bytes, Error = protobuf::ProtobufError>,
T: TypeOptionDataDeserializer, T: TypeOptionDataDeserializer,
@ -87,12 +123,11 @@ where
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev); let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
let groups = G::generate_groups(&configuration, &type_option); let groups = G::generate_groups(&configuration, &type_option);
let default_group = Group { let default_group = Group::new(
id: DEFAULT_GROUP_ID.to_owned(), DEFAULT_GROUP_ID.to_owned(),
desc: format!("No {}", field_rev.name), format!("No {}", field_rev.name),
rows: vec![], "".to_string(),
content: "".to_string(), );
};
Ok(Self { Ok(Self {
field_id: field_rev.id.clone(), field_id: field_rev.id.clone(),
@ -104,8 +139,18 @@ where
cell_parser_phantom: PhantomData, cell_parser_phantom: PhantomData,
}) })
} }
}
pub fn make_groups(&self) -> Vec<Group> { impl<C, T, G, P> GroupControllerSharedAction for GenericGroupController<C, T, G, P>
where
P: CellBytesParser,
Self: Groupable<CellDataType = P::Object>,
{
fn field_id(&self) -> &str {
&self.field_id
}
fn build_groups(&self) -> Vec<Group> {
let default_group = self.default_group.clone(); let default_group = self.default_group.clone();
let mut groups: Vec<Group> = self.groups_map.values().cloned().collect(); let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
if !default_group.rows.is_empty() { if !default_group.rows.is_empty() {
@ -113,35 +158,28 @@ where
} }
groups groups
} }
}
impl<C, T, G, P> GroupController<C, T, G, P> fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
where
P: CellBytesParser,
Self: Groupable<CellDataType = P::Object>,
{
pub fn handle_rows(&mut self, rows: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
// The field_rev might be None if corresponding field_rev is deleted.
if self.configuration.is_none() { if self.configuration.is_none() {
return Ok(()); return Ok(());
} }
for row in rows { for row_rev in row_revs {
if let Some(cell_rev) = row.cells.get(&self.field_id) { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
let mut records: Vec<GroupRecord> = vec![]; let mut records: Vec<GroupRecord> = vec![];
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev); let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev);
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
for group in self.groups_map.values() { for group in self.groups_map.values() {
if self.can_group(&group.content, &cell_data) { if self.can_group(&group.content, &cell_data) {
records.push(GroupRecord { records.push(GroupRecord {
row: row.into(), row: row_rev.into(),
group_id: group.id.clone(), group_id: group.id.clone(),
}); });
} }
} }
if records.is_empty() { if records.is_empty() {
self.default_group.rows.push(row.into()); self.default_group.rows.push(row_rev.into());
} else { } else {
for record in records { for record in records {
if let Some(group) = self.groups_map.get_mut(&record.group_id) { if let Some(group) = self.groups_map.get_mut(&record.group_id) {
@ -150,14 +188,71 @@ where
} }
} }
} else { } else {
self.default_group.rows.push(row.into()); self.default_group.rows.push(row_rev.into());
} }
} }
Ok(()) Ok(())
} }
fn did_update_row(
&mut self,
row_rev: &RowRevision,
field_rev: &FieldRevision,
) -> FlowyResult<Vec<GroupRowsChangesetPB>> {
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);
let cell_data = cell_bytes.parser::<P>()?;
Ok(self.group_row(row_rev, &cell_data))
} else {
Ok(vec![])
}
}
} }
// impl<C, T, G, P> GroupController<C, T, G, P>
// where
// P: CellBytesParser,
// Self: Groupable<CellDataType = P::Object>,
// {
// pub fn handle_rows(&mut self, rows: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
// // The field_rev might be None if corresponding field_rev is deleted.
// if self.configuration.is_none() {
// return Ok(());
// }
//
// for row in rows {
// if let Some(cell_rev) = row.cells.get(&self.field_id) {
// let mut records: Vec<GroupRecord> = vec![];
// let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev);
// let cell_data = cell_bytes.parser::<P>()?;
// for group in self.groups_map.values() {
// if self.can_group(&group.content, &cell_data) {
// records.push(GroupRecord {
// row: row.into(),
// group_id: group.id.clone(),
// });
// }
// }
//
// if records.is_empty() {
// self.default_group.rows.push(row.into());
// } else {
// for record in records {
// if let Some(group) = self.groups_map.get_mut(&record.group_id) {
// group.rows.push(record.row);
// }
// }
// }
// } else {
// self.default_group.rows.push(row.into());
// }
// }
//
// Ok(())
// }
// }
struct GroupRecord { struct GroupRecord {
row: RowPB, row: RowPB,
group_id: String, group_id: String,

View File

@ -1,17 +1,14 @@
use crate::entities::SelectOptionGroupConfigurationPB; use crate::entities::{GroupRowsChangesetPB, InsertedRowPB, RowPB, SelectOptionGroupConfigurationPB};
use crate::services::cell::insert_select_option_cell; use crate::services::cell::insert_select_option_cell;
use flowy_error::FlowyResult;
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
use std::sync::Arc;
use crate::services::field::{ use crate::services::field::{
MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB, MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB,
}; };
use crate::services::group::{Group, GroupActionHandler, GroupController, GroupGenerator, Groupable}; use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable};
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
// SingleSelect // SingleSelect
pub type SingleSelectGroupController = GroupController< pub type SingleSelectGroupController = GenericGroupController<
SelectOptionGroupConfigurationPB, SelectOptionGroupConfigurationPB,
SingleSelectTypeOptionPB, SingleSelectTypeOptionPB,
SingleSelectGroupGenerator, SingleSelectGroupGenerator,
@ -23,21 +20,17 @@ impl Groupable for SingleSelectGroupController {
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
cell_data.select_options.iter().any(|option| option.id == content) cell_data.select_options.iter().any(|option| option.id == content)
} }
fn group_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupRowsChangesetPB> {
let mut changesets = vec![];
self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| {
group_select_option_row(group, &mut changesets, cell_data, row_rev);
});
changesets
}
} }
impl GroupActionHandler for SingleSelectGroupController { impl GroupController for SingleSelectGroupController {
fn field_id(&self) -> &str {
&self.field_id
}
fn build_groups(&self) -> Vec<Group> {
self.make_groups()
}
fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
self.handle_rows(row_revs, field_rev)
}
fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
let group: Option<&Group> = self.groups_map.get(group_id); let group: Option<&Group> = self.groups_map.get(group_id);
match group { match group {
@ -63,19 +56,14 @@ impl GroupGenerator for SingleSelectGroupGenerator {
Some(type_option) => type_option Some(type_option) => type_option
.options .options
.iter() .iter()
.map(|option| Group { .map(|option| Group::new(option.id.clone(), option.name.clone(), option.id.clone()))
id: option.id.clone(),
desc: option.name.clone(),
rows: vec![],
content: option.id.clone(),
})
.collect(), .collect(),
} }
} }
} }
// MultiSelect // MultiSelect
pub type MultiSelectGroupController = GroupController< pub type MultiSelectGroupController = GenericGroupController<
SelectOptionGroupConfigurationPB, SelectOptionGroupConfigurationPB,
MultiSelectTypeOptionPB, MultiSelectTypeOptionPB,
MultiSelectGroupGenerator, MultiSelectGroupGenerator,
@ -84,24 +72,22 @@ pub type MultiSelectGroupController = GroupController<
impl Groupable for MultiSelectGroupController { impl Groupable for MultiSelectGroupController {
type CellDataType = SelectOptionCellDataPB; type CellDataType = SelectOptionCellDataPB;
fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool { fn can_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
cell_data.select_options.iter().any(|option| option.id == content) cell_data.select_options.iter().any(|option| option.id == content)
} }
fn group_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupRowsChangesetPB> {
let mut changesets = vec![];
self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| {
group_select_option_row(group, &mut changesets, cell_data, row_rev);
});
changesets
}
} }
impl GroupActionHandler for MultiSelectGroupController { impl GroupController for MultiSelectGroupController {
fn field_id(&self) -> &str {
&self.field_id
}
fn build_groups(&self) -> Vec<Group> {
self.make_groups()
}
fn group_rows(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()> {
self.handle_rows(row_revs, field_rev)
}
fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) { fn fill_row(&self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
let group: Option<&Group> = self.groups_map.get(group_id); let group: Option<&Group> = self.groups_map.get(group_id);
match group { match group {
@ -128,13 +114,31 @@ impl GroupGenerator for MultiSelectGroupGenerator {
Some(type_option) => type_option Some(type_option) => type_option
.options .options
.iter() .iter()
.map(|option| Group { .map(|option| Group::new(option.id.clone(), option.name.clone(), option.id.clone()))
id: option.id.clone(),
desc: option.name.clone(),
rows: vec![],
content: option.id.clone(),
})
.collect(), .collect(),
} }
} }
} }
fn group_select_option_row(
group: &mut Group,
changesets: &mut Vec<GroupRowsChangesetPB>,
cell_data: &SelectOptionCellDataPB,
row_rev: &RowRevision,
) {
cell_data.select_options.iter().for_each(|option| {
if option.id == group.id {
if !group.contains_row(&row_rev.id) {
let row_pb = RowPB::from(row_rev);
changesets.push(GroupRowsChangesetPB::insert(
group.id.clone(),
vec![InsertedRowPB::new(row_pb.clone())],
));
group.add_row(row_pb);
}
} else if group.contains_row(&row_rev.id) {
group.remove_row(&row_rev.id);
changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
}
});
}

View File

@ -1,9 +1,9 @@
use crate::entities::{ use crate::entities::{
CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, NumberGroupConfigurationPB, CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupRowsChangesetPB,
SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB, NumberGroupConfigurationPB, SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB,
}; };
use crate::services::group::{ use crate::services::group::{
CheckboxGroupController, Group, GroupActionHandler, MultiSelectGroupController, SingleSelectGroupController, CheckboxGroupController, Group, GroupController, MultiSelectGroupController, SingleSelectGroupController,
}; };
use bytes::Bytes; use bytes::Bytes;
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -20,7 +20,7 @@ pub trait GroupConfigurationDelegate: Send + Sync + 'static {
pub(crate) struct GroupService { pub(crate) struct GroupService {
pub groups: Vec<Group>, pub groups: Vec<Group>,
delegate: Box<dyn GroupConfigurationDelegate>, delegate: Box<dyn GroupConfigurationDelegate>,
group_action: Option<Arc<RwLock<dyn GroupActionHandler>>>, group_controller: Option<Arc<RwLock<dyn GroupController>>>,
} }
impl GroupService { impl GroupService {
@ -28,7 +28,7 @@ impl GroupService {
Self { Self {
groups: vec![], groups: vec![],
delegate, delegate,
group_action: None, group_controller: None,
} }
} }
@ -52,24 +52,43 @@ impl GroupService {
} }
} }
pub(crate) async fn fill_row<F, O>(&self, row_rev: &mut RowRevision, group_id: &str, f: F) pub(crate) async fn fill_row<F, O>(&self, row_rev: &mut RowRevision, group_id: &str, get_field_fn: F)
where where
F: FnOnce(String) -> O, F: FnOnce(String) -> O,
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static, O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
{ {
if let Some(group_action) = self.group_action.as_ref() { if let Some(group_controller) = self.group_controller.as_ref() {
let field_id = group_action.read().await.field_id().to_owned(); let field_id = group_controller.read().await.field_id().to_owned();
match f(field_id).await { match get_field_fn(field_id).await {
None => {} None => {}
Some(field_rev) => { Some(field_rev) => {
group_action.write().await.fill_row(row_rev, &field_rev, group_id); group_controller.write().await.fill_row(row_rev, &field_rev, group_id);
} }
} }
} }
} }
pub(crate) async fn did_update_row(&self, row_rev: Arc<RowRevision>) { #[tracing::instrument(level = "trace", skip_all)]
if let Some(group_action) = self.group_action.as_ref() {} pub(crate) async fn did_update_row<F, O>(
&self,
row_rev: &RowRevision,
get_field_fn: F,
) -> Option<Vec<GroupRowsChangesetPB>>
where
F: FnOnce(String) -> O,
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
{
let group_controller = self.group_controller.as_ref()?;
let field_id = group_controller.read().await.field_id().to_owned();
let field_rev = get_field_fn(field_id).await?;
match group_controller.write().await.did_update_row(row_rev, &field_rev) {
Ok(changeset) => Some(changeset),
Err(e) => {
tracing::error!("Update group data failed, {:?}", e);
None
}
}
} }
#[tracing::instrument(level = "trace", skip_all, err)] #[tracing::instrument(level = "trace", skip_all, err)]
@ -92,15 +111,15 @@ impl GroupService {
} }
FieldType::SingleSelect => { FieldType::SingleSelect => {
let controller = SingleSelectGroupController::new(field_rev, configuration)?; let controller = SingleSelectGroupController::new(field_rev, configuration)?;
self.group_action = Some(Arc::new(RwLock::new(controller))); self.group_controller = Some(Arc::new(RwLock::new(controller)));
} }
FieldType::MultiSelect => { FieldType::MultiSelect => {
let controller = MultiSelectGroupController::new(field_rev, configuration)?; let controller = MultiSelectGroupController::new(field_rev, configuration)?;
self.group_action = Some(Arc::new(RwLock::new(controller))); self.group_controller = Some(Arc::new(RwLock::new(controller)));
} }
FieldType::Checkbox => { FieldType::Checkbox => {
let controller = CheckboxGroupController::new(field_rev, configuration)?; let controller = CheckboxGroupController::new(field_rev, configuration)?;
self.group_action = Some(Arc::new(RwLock::new(controller))); self.group_controller = Some(Arc::new(RwLock::new(controller)));
} }
FieldType::URL => { FieldType::URL => {
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration); // let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
@ -108,7 +127,7 @@ impl GroupService {
}; };
let mut groups = vec![]; let mut groups = vec![];
if let Some(group_action_handler) = self.group_action.as_ref() { if let Some(group_action_handler) = self.group_controller.as_ref() {
let mut write_guard = group_action_handler.write().await; let mut write_guard = group_action_handler.write().await;
let _ = write_guard.group_rows(&row_revs, field_rev)?; let _ = write_guard.group_rows(&row_revs, field_rev)?;
groups = write_guard.build_groups(); groups = write_guard.build_groups();

View File

@ -75,7 +75,7 @@ fn crate_log_filter(level: String) -> String {
filters.push(format!("lib_ws={}", level)); filters.push(format!("lib_ws={}", level));
filters.push(format!("lib_infra={}", level)); filters.push(format!("lib_infra={}", level));
filters.push(format!("flowy_sync={}", level)); filters.push(format!("flowy_sync={}", level));
filters.push(format!("flowy_revision={}", level)); // filters.push(format!("flowy_revision={}", level));
// filters.push(format!("lib_dispatch={}", level)); // filters.push(format!("lib_dispatch={}", level));
filters.push(format!("dart_ffi={}", "info")); filters.push(format!("dart_ffi={}", "info"));