mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #898 from AppFlowy-IO/feat/board_update_when_field_change
Feat/board update when field change
This commit is contained in:
@ -30,7 +30,7 @@ impl BlockPB {
|
||||
}
|
||||
|
||||
/// [RowPB] Describes a row. Has the id of the parent Block. Has the metadata of the row.
|
||||
#[derive(Debug, Default, Clone, ProtoBuf)]
|
||||
#[derive(Debug, Default, Clone, ProtoBuf, Eq, PartialEq)]
|
||||
pub struct RowPB {
|
||||
#[pb(index = 1)]
|
||||
pub block_id: String,
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::entities::{CreateRowParams, FieldType, GridLayout, RowPB};
|
||||
use crate::services::group::Group;
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::ErrorCode;
|
||||
use flowy_grid_data_model::parser::NotEmptyStr;
|
||||
@ -82,6 +83,17 @@ pub struct GroupPB {
|
||||
pub rows: Vec<RowPB>,
|
||||
}
|
||||
|
||||
impl std::convert::From<Group> for GroupPB {
|
||||
fn from(group: Group) -> Self {
|
||||
Self {
|
||||
field_id: group.field_id,
|
||||
group_id: group.id,
|
||||
desc: group.name,
|
||||
rows: group.rows,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct RepeatedGridGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
|
@ -5,21 +5,24 @@ use flowy_grid_data_model::parser::NotEmptyStr;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
#[derive(Debug, Default, ProtoBuf)]
|
||||
pub struct GroupRowsChangesetPB {
|
||||
pub struct GroupChangesetPB {
|
||||
#[pb(index = 1)]
|
||||
pub group_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub inserted_rows: Vec<InsertedRowPB>,
|
||||
#[pb(index = 2, one_of)]
|
||||
pub group_name: Option<String>,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub deleted_rows: Vec<String>,
|
||||
pub inserted_rows: Vec<InsertedRowPB>,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub deleted_rows: Vec<String>,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub updated_rows: Vec<RowPB>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GroupRowsChangesetPB {
|
||||
impl std::fmt::Display for GroupChangesetPB {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
for inserted_row in &self.inserted_rows {
|
||||
let _ = f.write_fmt(format_args!(
|
||||
@ -36,10 +39,29 @@ impl std::fmt::Display for GroupRowsChangesetPB {
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupRowsChangesetPB {
|
||||
impl GroupChangesetPB {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.inserted_rows.is_empty() && self.deleted_rows.is_empty() && self.updated_rows.is_empty()
|
||||
self.group_name.is_none()
|
||||
&& self.inserted_rows.is_empty()
|
||||
&& self.deleted_rows.is_empty()
|
||||
&& self.updated_rows.is_empty()
|
||||
}
|
||||
|
||||
pub fn new(group_id: String) -> Self {
|
||||
Self {
|
||||
group_id,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(group_id: String, name: &str) -> Self {
|
||||
Self {
|
||||
group_id,
|
||||
group_name: Some(name.to_owned()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(group_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self {
|
||||
Self {
|
||||
group_id,
|
||||
@ -113,9 +135,16 @@ pub struct GroupViewChangesetPB {
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub deleted_groups: Vec<String>,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub update_groups: Vec<GroupPB>,
|
||||
}
|
||||
|
||||
impl GroupViewChangesetPB {}
|
||||
impl GroupViewChangesetPB {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.inserted_groups.is_empty() && self.deleted_groups.is_empty() && self.update_groups.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, ProtoBuf)]
|
||||
pub struct InsertedGroupPB {
|
||||
|
@ -188,8 +188,13 @@ impl GridRevisionEditor {
|
||||
pub async fn replace_field(&self, field_rev: Arc<FieldRevision>) -> FlowyResult<()> {
|
||||
let field_id = field_rev.id.clone();
|
||||
let _ = self
|
||||
.modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev)?))
|
||||
.modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev.clone())?))
|
||||
.await?;
|
||||
|
||||
match self.view_manager.did_update_field(&field_rev.id).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => tracing::error!("View manager update field failed: {:?}", e),
|
||||
}
|
||||
let _ = self.notify_did_update_grid_field(&field_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
@ -263,59 +268,65 @@ impl GridRevisionEditor {
|
||||
}
|
||||
|
||||
async fn update_field_rev(&self, params: FieldChangesetParams, field_type: FieldType) -> FlowyResult<()> {
|
||||
self.modify(|grid| {
|
||||
let deserializer = TypeOptionJsonDeserializer(field_type);
|
||||
let _ = self
|
||||
.modify(|grid| {
|
||||
let deserializer = TypeOptionJsonDeserializer(field_type);
|
||||
let changeset = grid.modify_field(¶ms.field_id, |field| {
|
||||
let mut is_changed = None;
|
||||
if let Some(name) = params.name {
|
||||
field.name = name;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
let changeset = grid.modify_field(¶ms.field_id, |field| {
|
||||
let mut is_changed = None;
|
||||
if let Some(name) = params.name {
|
||||
field.name = name;
|
||||
is_changed = Some(())
|
||||
}
|
||||
if let Some(desc) = params.desc {
|
||||
field.desc = desc;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(desc) = params.desc {
|
||||
field.desc = desc;
|
||||
is_changed = Some(())
|
||||
}
|
||||
if let Some(field_type) = params.field_type {
|
||||
field.ty = field_type;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(field_type) = params.field_type {
|
||||
field.ty = field_type;
|
||||
is_changed = Some(())
|
||||
}
|
||||
if let Some(frozen) = params.frozen {
|
||||
field.frozen = frozen;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(frozen) = params.frozen {
|
||||
field.frozen = frozen;
|
||||
is_changed = Some(())
|
||||
}
|
||||
if let Some(visibility) = params.visibility {
|
||||
field.visibility = visibility;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(visibility) = params.visibility {
|
||||
field.visibility = visibility;
|
||||
is_changed = Some(())
|
||||
}
|
||||
if let Some(width) = params.width {
|
||||
field.width = width;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(width) = params.width {
|
||||
field.width = width;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(type_option_data) = params.type_option_data {
|
||||
match deserializer.deserialize(type_option_data) {
|
||||
Ok(json_str) => {
|
||||
let field_type = field.ty;
|
||||
field.insert_type_option_str(&field_type, json_str);
|
||||
is_changed = Some(())
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Deserialize data to type option json failed: {}", err);
|
||||
if let Some(type_option_data) = params.type_option_data {
|
||||
match deserializer.deserialize(type_option_data) {
|
||||
Ok(json_str) => {
|
||||
let field_type = field.ty;
|
||||
field.insert_type_option_str(&field_type, json_str);
|
||||
is_changed = Some(())
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("Deserialize data to type option json failed: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(is_changed)
|
||||
})?;
|
||||
Ok(changeset)
|
||||
})
|
||||
.await
|
||||
Ok(is_changed)
|
||||
})?;
|
||||
Ok(changeset)
|
||||
})
|
||||
.await?;
|
||||
|
||||
match self.view_manager.did_update_field(¶ms.field_id).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => tracing::error!("View manager update field failed: {:?}", e),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn create_block(&self, block_meta_rev: GridBlockMetaRevision) -> FlowyResult<()> {
|
||||
@ -571,7 +582,7 @@ impl GridRevisionEditor {
|
||||
|
||||
pub async fn move_group_row(&self, params: MoveGroupRowParams) -> FlowyResult<()> {
|
||||
let MoveGroupRowParams {
|
||||
view_id: _,
|
||||
view_id,
|
||||
from_row_id,
|
||||
to_group_id,
|
||||
to_row_id,
|
||||
@ -585,10 +596,23 @@ impl GridRevisionEditor {
|
||||
.move_group_row(row_rev, to_group_id, to_row_id.clone())
|
||||
.await
|
||||
{
|
||||
match self.block_manager.update_row(row_changeset).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
tracing::error!("Apply row changeset error:{:?}", e);
|
||||
tracing::trace!("Move group row cause row data changed: {:?}", row_changeset);
|
||||
|
||||
let cell_changesets = row_changeset
|
||||
.cell_by_field_id
|
||||
.into_iter()
|
||||
.map(|(field_id, cell_rev)| CellChangesetPB {
|
||||
grid_id: view_id.clone(),
|
||||
row_id: row_changeset.row_id.clone(),
|
||||
field_id,
|
||||
content: cell_rev.data,
|
||||
})
|
||||
.collect::<Vec<CellChangesetPB>>();
|
||||
|
||||
for cell_changeset in cell_changesets {
|
||||
match self.block_manager.update_cell(cell_changeset).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => tracing::error!("Apply cell changeset error:{:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::dart_notification::{send_dart_notification, GridNotification};
|
||||
use crate::entities::{
|
||||
CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridLayout, GridLayoutPB,
|
||||
GridSettingPB, GroupPB, GroupRowsChangesetPB, GroupViewChangesetPB, InsertedGroupPB, InsertedRowPB,
|
||||
MoveGroupParams, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RowPB,
|
||||
GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertedGroupPB, InsertedRowPB, MoveGroupParams,
|
||||
RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RowPB,
|
||||
};
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
|
||||
@ -59,7 +59,7 @@ impl GridViewRevisionEditor {
|
||||
rev_manager: rev_manager.clone(),
|
||||
view_pad: pad.clone(),
|
||||
};
|
||||
let group_service = GroupService::new(configuration_reader, configuration_writer).await;
|
||||
let group_service = GroupService::new(view_id.clone(), configuration_reader, configuration_writer).await;
|
||||
let user_id = user_id.to_owned();
|
||||
let did_load_group = AtomicBool::new(false);
|
||||
Ok(Self {
|
||||
@ -99,8 +99,8 @@ impl GridViewRevisionEditor {
|
||||
row: row_pb.clone(),
|
||||
index: None,
|
||||
};
|
||||
let changeset = GroupRowsChangesetPB::insert(group_id.clone(), vec![inserted_row]);
|
||||
self.notify_did_update_group_rows(changeset).await;
|
||||
let changeset = GroupChangesetPB::insert(group_id.clone(), vec![inserted_row]);
|
||||
self.notify_did_update_group(changeset).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,7 @@ impl GridViewRevisionEditor {
|
||||
.await
|
||||
{
|
||||
for changeset in changesets {
|
||||
self.notify_did_update_group_rows(changeset).await;
|
||||
self.notify_did_update_group(changeset).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,7 @@ impl GridViewRevisionEditor {
|
||||
.await
|
||||
{
|
||||
for changeset in changesets {
|
||||
self.notify_did_update_group_rows(changeset).await;
|
||||
self.notify_did_update_group(changeset).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,11 +151,11 @@ impl GridViewRevisionEditor {
|
||||
.await
|
||||
{
|
||||
for changeset in changesets {
|
||||
self.notify_did_update_group_rows(changeset).await;
|
||||
self.notify_did_update_group(changeset).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only call once after grid view editor initialized
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
pub(crate) async fn load_groups(&self) -> FlowyResult<Vec<GroupPB>> {
|
||||
let groups = if !self.did_load_group.load(Ordering::SeqCst) {
|
||||
@ -198,9 +198,10 @@ impl GridViewRevisionEditor {
|
||||
};
|
||||
|
||||
let changeset = GroupViewChangesetPB {
|
||||
view_id: "".to_string(),
|
||||
view_id: self.view_id.clone(),
|
||||
inserted_groups: vec![inserted_group],
|
||||
deleted_groups: vec![params.from_group_id.clone()],
|
||||
update_groups: vec![],
|
||||
};
|
||||
|
||||
self.notify_did_update_view(changeset).await;
|
||||
@ -252,8 +253,20 @@ impl GridViewRevisionEditor {
|
||||
})
|
||||
.await
|
||||
}
|
||||
#[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? {
|
||||
None => {}
|
||||
Some(changeset) => {
|
||||
self.notify_did_update_view(changeset).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn notify_did_update_group_rows(&self, changeset: GroupRowsChangesetPB) {
|
||||
async fn notify_did_update_group(&self, changeset: GroupChangesetPB) {
|
||||
send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup)
|
||||
.payload(changeset)
|
||||
.send();
|
||||
@ -265,7 +278,6 @@ impl GridViewRevisionEditor {
|
||||
.send();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
async fn modify<F>(&self, f: F) -> FlowyResult<()>
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut GridViewRevisionPad) -> FlowyResult<Option<GridViewRevisionChangeset>>,
|
||||
|
@ -142,13 +142,19 @@ impl GridViewManager {
|
||||
.await;
|
||||
}
|
||||
|
||||
if row_changeset.has_changed() {
|
||||
Some(row_changeset)
|
||||
} else {
|
||||
if row_changeset.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(row_changeset)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn did_update_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||
let view_editor = self.get_default_view_editor().await?;
|
||||
let _ = view_editor.did_update_field(field_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn get_view_editor(&self, view_id: &str) -> FlowyResult<Arc<GridViewRevisionEditor>> {
|
||||
debug_assert!(!view_id.is_empty());
|
||||
match self.view_editors.get(view_id) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::GroupRowsChangesetPB;
|
||||
use crate::entities::GroupChangesetPB;
|
||||
|
||||
use crate::services::group::controller::MoveGroupRowContext;
|
||||
use flowy_grid_data_model::revision::RowRevision;
|
||||
@ -6,12 +6,8 @@ use flowy_grid_data_model::revision::RowRevision;
|
||||
pub trait GroupAction: Send + Sync {
|
||||
type CellDataType;
|
||||
fn can_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupRowsChangesetPB>;
|
||||
fn remove_row_if_match(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
cell_data: &Self::CellDataType,
|
||||
) -> Vec<GroupRowsChangesetPB>;
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
|
||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB>;
|
||||
|
||||
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupRowsChangesetPB>;
|
||||
fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec<GroupChangesetPB>;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::entities::{GroupPB, GroupViewChangesetPB, InsertedGroupPB};
|
||||
use crate::services::group::{default_group_configuration, Group};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::revision::{
|
||||
FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRecordRevision,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use lib_infra::future::AFFuture;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait GroupConfigurationReader: Send + Sync + 'static {
|
||||
@ -26,6 +26,7 @@ pub trait GroupConfigurationWriter: Send + Sync + 'static {
|
||||
}
|
||||
|
||||
pub struct GenericGroupConfiguration<C> {
|
||||
view_id: String,
|
||||
pub configuration: Arc<GroupConfigurationRevision>,
|
||||
configuration_content: PhantomData<C>,
|
||||
field_rev: Arc<FieldRevision>,
|
||||
@ -39,6 +40,7 @@ where
|
||||
{
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub async fn new(
|
||||
view_id: String,
|
||||
field_rev: Arc<FieldRevision>,
|
||||
reader: Arc<dyn GroupConfigurationReader>,
|
||||
writer: Arc<dyn GroupConfigurationWriter>,
|
||||
@ -56,6 +58,7 @@ where
|
||||
|
||||
// let configuration = C::from_configuration_content(&configuration_rev.content)?;
|
||||
Ok(Self {
|
||||
view_id,
|
||||
field_rev,
|
||||
groups_map: IndexMap::new(),
|
||||
writer,
|
||||
@ -72,8 +75,18 @@ where
|
||||
self.groups_map.values().cloned().collect()
|
||||
}
|
||||
|
||||
pub(crate) async fn merge_groups(&mut self, groups: Vec<Group>) -> FlowyResult<()> {
|
||||
let (group_revs, groups) = merge_groups(&self.configuration.groups, groups);
|
||||
pub(crate) fn merge_groups(&mut self, groups: Vec<Group>) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||
let MergeGroupResult {
|
||||
groups,
|
||||
inserted_groups,
|
||||
updated_groups,
|
||||
} = merge_groups(&self.configuration.groups, groups);
|
||||
|
||||
let group_revs = groups
|
||||
.iter()
|
||||
.map(|group| GroupRecordRevision::new(group.id.clone(), group.name.clone()))
|
||||
.collect();
|
||||
|
||||
self.mut_configuration(move |configuration| {
|
||||
configuration.groups = group_revs;
|
||||
true
|
||||
@ -82,7 +95,14 @@ where
|
||||
groups.into_iter().for_each(|group| {
|
||||
self.groups_map.insert(group.id.clone(), group);
|
||||
});
|
||||
Ok(())
|
||||
|
||||
let changeset = make_group_view_changeset(self.view_id.clone(), inserted_groups, updated_groups);
|
||||
tracing::trace!("Group changeset: {:?}", changeset);
|
||||
if changeset.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(changeset))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -101,7 +121,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn with_mut_groups(&mut self, mut each: impl FnMut(&mut 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);
|
||||
})
|
||||
@ -189,33 +209,82 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec<Group>) -> (Vec<GroupRecordRevision>, Vec<Group>) {
|
||||
if old_group_revs.is_empty() {
|
||||
let new_groups = groups
|
||||
.iter()
|
||||
.map(|group| GroupRecordRevision::new(group.id.clone()))
|
||||
.collect();
|
||||
return (new_groups, groups);
|
||||
fn merge_groups(old_groups: &[GroupRecordRevision], groups: Vec<Group>) -> MergeGroupResult {
|
||||
let mut merge_result = MergeGroupResult::new();
|
||||
if old_groups.is_empty() {
|
||||
merge_result.groups = groups;
|
||||
return merge_result;
|
||||
}
|
||||
|
||||
// group_map is a helper map is used to filter out the new groups.
|
||||
let mut group_map: IndexMap<String, Group> = IndexMap::new();
|
||||
groups.into_iter().for_each(|group| {
|
||||
group_map.insert(group.id.clone(), group);
|
||||
});
|
||||
|
||||
// Inert
|
||||
let mut sorted_groups: Vec<Group> = vec![];
|
||||
for group_rev in old_group_revs {
|
||||
// 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.group_id) {
|
||||
sorted_groups.push(group);
|
||||
if group.name == group_rev.name {
|
||||
merge_result.add_group(group);
|
||||
} else {
|
||||
merge_result.add_updated_group(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
sorted_groups.extend(group_map.into_values().collect::<Vec<Group>>());
|
||||
let new_group_revs = sorted_groups
|
||||
.iter()
|
||||
.map(|group| GroupRecordRevision::new(group.id.clone()))
|
||||
.collect::<Vec<GroupRecordRevision>>();
|
||||
|
||||
tracing::trace!("group revs: {}, groups: {}", new_group_revs.len(), sorted_groups.len());
|
||||
(new_group_revs, sorted_groups)
|
||||
// Find out the new groups
|
||||
let new_groups = group_map.into_values().collect::<Vec<Group>>();
|
||||
for (index, group) in new_groups.into_iter().enumerate() {
|
||||
merge_result.add_insert_group(index, group);
|
||||
}
|
||||
merge_result
|
||||
}
|
||||
|
||||
struct MergeGroupResult {
|
||||
groups: Vec<Group>,
|
||||
inserted_groups: Vec<InsertedGroupPB>,
|
||||
updated_groups: Vec<Group>,
|
||||
}
|
||||
|
||||
impl MergeGroupResult {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
groups: vec![],
|
||||
inserted_groups: vec![],
|
||||
updated_groups: 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.clone());
|
||||
}
|
||||
|
||||
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<InsertedGroupPB>,
|
||||
updated_group: Vec<Group>,
|
||||
) -> GroupViewChangesetPB {
|
||||
let changeset = GroupViewChangesetPB {
|
||||
view_id,
|
||||
inserted_groups,
|
||||
deleted_groups: vec![],
|
||||
update_groups: updated_group.into_iter().map(GroupPB::from).collect(),
|
||||
};
|
||||
changeset
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{GroupRowsChangesetPB, RowPB};
|
||||
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
|
||||
use crate::services::cell::{decode_any_cell_data, CellBytesParser};
|
||||
use crate::services::group::action::GroupAction;
|
||||
use crate::services::group::configuration::GenericGroupConfiguration;
|
||||
@ -51,15 +51,17 @@ pub trait GroupControllerSharedOperation: Send + Sync {
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
field_rev: &FieldRevision,
|
||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||
) -> FlowyResult<Vec<GroupChangesetPB>>;
|
||||
|
||||
fn did_delete_row(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
field_rev: &FieldRevision,
|
||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||
) -> FlowyResult<Vec<GroupChangesetPB>>;
|
||||
|
||||
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupChangesetPB>>;
|
||||
|
||||
fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>>;
|
||||
}
|
||||
|
||||
/// C: represents the group configuration that impl [GroupConfigurationSerde]
|
||||
@ -89,7 +91,7 @@ where
|
||||
let field_type_rev = field_rev.ty;
|
||||
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
|
||||
let groups = G::generate_groups(&field_rev.id, &configuration, &type_option);
|
||||
let _ = configuration.merge_groups(groups).await?;
|
||||
let _ = configuration.merge_groups(groups)?;
|
||||
let default_group = Group::new(
|
||||
DEFAULT_GROUP_ID.to_owned(),
|
||||
field_rev.id.clone(),
|
||||
@ -112,6 +114,9 @@ impl<C, T, G, P> GroupControllerSharedOperation for GenericGroupController<C, T,
|
||||
where
|
||||
P: CellBytesParser,
|
||||
C: GroupConfigurationContentSerde,
|
||||
T: TypeOptionDataDeserializer,
|
||||
G: GroupGenerator<ConfigurationType = GenericGroupConfiguration<C>, TypeOptionType = T>,
|
||||
|
||||
Self: GroupAction<CellDataType = P::Object>,
|
||||
{
|
||||
fn field_id(&self) -> &str {
|
||||
@ -173,11 +178,12 @@ where
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
field_rev: &FieldRevision,
|
||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>> {
|
||||
) -> FlowyResult<Vec<GroupChangesetPB>> {
|
||||
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.add_row_if_match(row_rev, &cell_data))
|
||||
let changesets = self.add_row_if_match(row_rev, &cell_data);
|
||||
Ok(changesets)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
@ -187,7 +193,7 @@ where
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
field_rev: &FieldRevision,
|
||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>> {
|
||||
) -> FlowyResult<Vec<GroupChangesetPB>> {
|
||||
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>()?;
|
||||
@ -197,7 +203,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupRowsChangesetPB>> {
|
||||
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupChangesetPB>> {
|
||||
if let Some(cell_rev) = context.row_rev.cells.get(&self.field_id) {
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), context.field_rev);
|
||||
let cell_data = cell_bytes.parser::<P>()?;
|
||||
@ -206,6 +212,14 @@ where
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||
let field_type_rev = field_rev.ty;
|
||||
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
|
||||
let groups = G::generate_groups(&field_rev.id, &self.configuration, &type_option);
|
||||
let changeset = self.configuration.merge_groups(groups)?;
|
||||
Ok(changeset)
|
||||
}
|
||||
}
|
||||
|
||||
struct GroupRow {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::GroupRowsChangesetPB;
|
||||
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;
|
||||
@ -24,11 +24,7 @@ impl GroupAction for CheckboxGroupController {
|
||||
false
|
||||
}
|
||||
|
||||
fn add_row_if_match(
|
||||
&mut self,
|
||||
_row_rev: &RowRevision,
|
||||
_cell_data: &Self::CellDataType,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
fn add_row_if_match(&mut self, _row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -36,15 +32,11 @@ impl GroupAction for CheckboxGroupController {
|
||||
&mut self,
|
||||
_row_rev: &RowRevision,
|
||||
_cell_data: &Self::CellDataType,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
) -> Vec<GroupChangesetPB> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn move_row(
|
||||
&mut self,
|
||||
_cell_data: &Self::CellDataType,
|
||||
_context: MoveGroupRowContext,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
fn move_row(&mut self, _cell_data: &Self::CellDataType, _context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::GroupRowsChangesetPB;
|
||||
use crate::entities::GroupChangesetPB;
|
||||
use crate::services::cell::insert_select_option_cell;
|
||||
use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser};
|
||||
use crate::services::group::action::GroupAction;
|
||||
@ -25,34 +25,32 @@ impl GroupAction 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<GroupRowsChangesetPB> {
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.configuration.with_mut_groups(|group| {
|
||||
add_row(group, &mut changesets, cell_data, row_rev);
|
||||
self.configuration.iter_mut_groups(|group| {
|
||||
if let Some(changeset) = add_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<GroupRowsChangesetPB> {
|
||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.configuration.with_mut_groups(|group| {
|
||||
remove_row(group, &mut changesets, cell_data, row_rev);
|
||||
self.configuration.iter_mut_groups(|group| {
|
||||
if let Some(changeset) = remove_row(group, cell_data, row_rev) {
|
||||
changesets.push(changeset);
|
||||
}
|
||||
});
|
||||
changesets
|
||||
}
|
||||
|
||||
fn move_row(
|
||||
&mut self,
|
||||
cell_data: &Self::CellDataType,
|
||||
mut context: MoveGroupRowContext,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
fn move_row(&mut self, cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||
let mut group_changeset = vec![];
|
||||
self.configuration.with_mut_groups(|group| {
|
||||
move_select_option_row(group, &mut group_changeset, cell_data, &mut context);
|
||||
self.configuration.iter_mut_groups(|group| {
|
||||
if let Some(changeset) = move_select_option_row(group, cell_data, &mut context) {
|
||||
group_changeset.push(changeset);
|
||||
}
|
||||
});
|
||||
group_changeset
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{GroupRowsChangesetPB, RowPB};
|
||||
use crate::entities::{GroupChangesetPB, RowPB};
|
||||
use crate::services::cell::insert_select_option_cell;
|
||||
use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB};
|
||||
use crate::services::group::action::GroupAction;
|
||||
@ -25,34 +25,32 @@ impl GroupAction 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<GroupRowsChangesetPB> {
|
||||
fn add_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.configuration.with_mut_groups(|group| {
|
||||
add_row(group, &mut changesets, cell_data, row_rev);
|
||||
self.configuration.iter_mut_groups(|group| {
|
||||
if let Some(changeset) = add_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<GroupRowsChangesetPB> {
|
||||
fn remove_row_if_match(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec<GroupChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
self.configuration.with_mut_groups(|group| {
|
||||
remove_row(group, &mut changesets, cell_data, row_rev);
|
||||
self.configuration.iter_mut_groups(|group| {
|
||||
if let Some(changeset) = remove_row(group, cell_data, row_rev) {
|
||||
changesets.push(changeset);
|
||||
}
|
||||
});
|
||||
changesets
|
||||
}
|
||||
|
||||
fn move_row(
|
||||
&mut self,
|
||||
cell_data: &Self::CellDataType,
|
||||
mut context: MoveGroupRowContext,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
fn move_row(&mut self, cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec<GroupChangesetPB> {
|
||||
let mut group_changeset = vec![];
|
||||
self.configuration.with_mut_groups(|group| {
|
||||
move_select_option_row(group, &mut group_changeset, cell_data, &mut context);
|
||||
self.configuration.iter_mut_groups(|group| {
|
||||
if let Some(changeset) = move_select_option_row(group, cell_data, &mut context) {
|
||||
group_changeset.push(changeset);
|
||||
}
|
||||
});
|
||||
group_changeset
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{GroupRowsChangesetPB, InsertedRowPB, RowPB};
|
||||
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;
|
||||
@ -11,47 +11,56 @@ pub type SelectOptionGroupConfiguration = GenericGroupConfiguration<SelectOption
|
||||
|
||||
pub fn add_row(
|
||||
group: &mut Group,
|
||||
changesets: &mut Vec<GroupRowsChangesetPB>,
|
||||
cell_data: &SelectOptionCellDataPB,
|
||||
row_rev: &RowRevision,
|
||||
) {
|
||||
) -> Option<GroupChangesetPB> {
|
||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||
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())],
|
||||
));
|
||||
changeset.inserted_rows.push(InsertedRowPB::new(row_pb.clone()));
|
||||
group.add_row(row_pb);
|
||||
}
|
||||
} else if group.contains_row(&row_rev.id) {
|
||||
changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||
changeset.deleted_rows.push(row_rev.id.clone());
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
});
|
||||
|
||||
if changeset.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(changeset)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_row(
|
||||
group: &mut Group,
|
||||
changesets: &mut Vec<GroupRowsChangesetPB>,
|
||||
cell_data: &SelectOptionCellDataPB,
|
||||
row_rev: &RowRevision,
|
||||
) {
|
||||
) -> Option<GroupChangesetPB> {
|
||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||
cell_data.select_options.iter().for_each(|option| {
|
||||
if option.id == group.id && group.contains_row(&row_rev.id) {
|
||||
changesets.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||
changeset.deleted_rows.push(row_rev.id.clone());
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
});
|
||||
|
||||
if changeset.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(changeset)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_select_option_row(
|
||||
group: &mut Group,
|
||||
group_changeset: &mut Vec<GroupRowsChangesetPB>,
|
||||
_cell_data: &SelectOptionCellDataPB,
|
||||
context: &mut MoveGroupRowContext,
|
||||
) {
|
||||
) -> Option<GroupChangesetPB> {
|
||||
let mut changeset = GroupChangesetPB::new(group.id.clone());
|
||||
let MoveGroupRowContext {
|
||||
row_rev,
|
||||
row_changeset,
|
||||
@ -68,7 +77,7 @@ pub fn move_select_option_row(
|
||||
|
||||
// Remove the row in which group contains it
|
||||
if from_index.is_some() {
|
||||
group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||
changeset.deleted_rows.push(row_rev.id.clone());
|
||||
tracing::debug!("Group:{} remove row:{}", group.id, row_rev.id);
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
@ -78,7 +87,7 @@ pub fn move_select_option_row(
|
||||
let mut inserted_row = InsertedRowPB::new(row_pb.clone());
|
||||
match to_index {
|
||||
None => {
|
||||
group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row]));
|
||||
changeset.inserted_rows.push(inserted_row);
|
||||
tracing::debug!("Group:{} append row:{}", group.id, row_rev.id);
|
||||
group.add_row(row_pb);
|
||||
}
|
||||
@ -91,7 +100,7 @@ pub fn move_select_option_row(
|
||||
tracing::debug!("Group:{} append row:{}", group.id, row_rev.id);
|
||||
group.add_row(row_pb);
|
||||
}
|
||||
group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row]));
|
||||
changeset.inserted_rows.push(inserted_row);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,6 +109,12 @@ pub fn move_select_option_row(
|
||||
tracing::debug!("Mark row:{} belong to group:{}", row_rev.id, group.id);
|
||||
let cell_rev = insert_select_option_cell(group.id.clone(), field_rev);
|
||||
row_changeset.cell_by_field_id.insert(field_rev.id.clone(), cell_rev);
|
||||
changeset.updated_rows.push(RowPB::from(*row_rev));
|
||||
}
|
||||
}
|
||||
if changeset.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(changeset)
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,22 @@
|
||||
use crate::entities::{GroupPB, RowPB};
|
||||
use crate::entities::RowPB;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Group {
|
||||
pub id: String,
|
||||
pub field_id: String,
|
||||
pub desc: String,
|
||||
rows: Vec<RowPB>,
|
||||
pub name: String,
|
||||
pub(crate) rows: Vec<RowPB>,
|
||||
|
||||
/// [content] is used to determine which group the cell belongs to.
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl std::convert::From<Group> for GroupPB {
|
||||
fn from(group: Group) -> Self {
|
||||
Self {
|
||||
field_id: group.field_id,
|
||||
group_id: group.id,
|
||||
desc: group.desc,
|
||||
rows: group.rows,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Group {
|
||||
pub fn new(id: String, field_id: String, desc: String, content: String) -> Self {
|
||||
pub fn new(id: String, field_id: String, name: String, content: String) -> Self {
|
||||
Self {
|
||||
id,
|
||||
field_id,
|
||||
desc,
|
||||
name,
|
||||
rows: vec![],
|
||||
content,
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{FieldType, GroupRowsChangesetPB};
|
||||
use crate::entities::{FieldType, GroupChangesetPB, GroupViewChangesetPB};
|
||||
use crate::services::group::configuration::GroupConfigurationReader;
|
||||
use crate::services::group::controller::{GroupController, MoveGroupRowContext};
|
||||
use crate::services::group::{
|
||||
@ -15,18 +15,20 @@ use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(crate) struct GroupService {
|
||||
view_id: String,
|
||||
configuration_reader: Arc<dyn GroupConfigurationReader>,
|
||||
configuration_writer: Arc<dyn GroupConfigurationWriter>,
|
||||
group_controller: Option<Box<dyn GroupController>>,
|
||||
}
|
||||
|
||||
impl GroupService {
|
||||
pub(crate) async fn new<R, W>(configuration_reader: R, configuration_writer: W) -> Self
|
||||
pub(crate) async fn new<R, W>(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,
|
||||
@ -36,8 +38,8 @@ impl GroupService {
|
||||
pub(crate) async fn groups(&self) -> Vec<Group> {
|
||||
self.group_controller
|
||||
.as_ref()
|
||||
.and_then(|group_controller| Some(group_controller.groups()))
|
||||
.unwrap_or(vec![])
|
||||
.map(|group_controller| group_controller.groups())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
||||
@ -86,7 +88,7 @@ impl GroupService {
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
) -> Option<Vec<GroupChangesetPB>>
|
||||
where
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||
@ -111,7 +113,7 @@ impl GroupService {
|
||||
to_group_id: &str,
|
||||
to_row_id: Option<String>,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
) -> Option<Vec<GroupChangesetPB>>
|
||||
where
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||
@ -141,7 +143,7 @@ impl GroupService {
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
) -> Option<Vec<GroupChangesetPB>>
|
||||
where
|
||||
F: FnOnce(String) -> O,
|
||||
O: Future<Output = Option<Arc<FieldRevision>>> + Send + Sync + 'static,
|
||||
@ -170,6 +172,17 @@ impl GroupService {
|
||||
}
|
||||
}
|
||||
|
||||
#[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<Option<GroupViewChangesetPB>> {
|
||||
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,
|
||||
@ -189,6 +202,7 @@ impl GroupService {
|
||||
}
|
||||
FieldType::SingleSelect => {
|
||||
let configuration = SelectOptionGroupConfiguration::new(
|
||||
self.view_id.clone(),
|
||||
field_rev.clone(),
|
||||
self.configuration_reader.clone(),
|
||||
self.configuration_writer.clone(),
|
||||
@ -199,6 +213,7 @@ impl GroupService {
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let configuration = SelectOptionGroupConfiguration::new(
|
||||
self.view_id.clone(),
|
||||
field_rev.clone(),
|
||||
self.configuration_reader.clone(),
|
||||
self.configuration_writer.clone(),
|
||||
@ -209,6 +224,7 @@ impl GroupService {
|
||||
}
|
||||
FieldType::Checkbox => {
|
||||
let configuration = CheckboxGroupConfiguration::new(
|
||||
self.view_id.clone(),
|
||||
field_rev.clone(),
|
||||
self.configuration_reader.clone(),
|
||||
self.configuration_writer.clone(),
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::grid::grid_editor::GridEditorTest;
|
||||
use flowy_grid::entities::{
|
||||
CreateRowParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB,
|
||||
CreateRowParams, FieldChangesetParams, FieldType, GridLayout, GroupPB, MoveGroupParams, MoveGroupRowParams, RowPB,
|
||||
};
|
||||
use flowy_grid::services::cell::insert_select_option_cell;
|
||||
use flowy_grid_data_model::revision::RowChangeset;
|
||||
use std::time::Duration;
|
||||
use tokio::time::interval;
|
||||
|
||||
pub enum GroupScript {
|
||||
AssertGroupRowCount {
|
||||
@ -42,6 +44,9 @@ pub enum GroupScript {
|
||||
from_group_index: usize,
|
||||
to_group_index: usize,
|
||||
},
|
||||
UpdateField {
|
||||
changeset: FieldChangesetParams,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct GridGroupTest {
|
||||
@ -156,6 +161,12 @@ impl GridGroupTest {
|
||||
} => {
|
||||
let group = self.group_at_index(group_index).await;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::grid::group_test::script::GridGroupTest;
|
||||
use crate::grid::group_test::script::GroupScript::*;
|
||||
use flowy_grid::entities::FieldChangesetParams;
|
||||
|
||||
#[tokio::test]
|
||||
async fn group_init_test() {
|
||||
@ -314,3 +315,25 @@ async fn group_move_group_test() {
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn group_update_field_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let mut 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 scripts = vec![
|
||||
UpdateField { changeset },
|
||||
AssertGroup {
|
||||
group_index: 0,
|
||||
expected_group: group,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
Reference in New Issue
Block a user