mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: Update row when moving row caused cell data changed
This commit is contained in:
parent
c4514e421a
commit
4856a024a2
@ -1,8 +1,10 @@
|
||||
import 'package:app_flowy/plugins/board/application/card/board_text_cell_bloc.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class BoardTextCell extends StatefulWidget {
|
||||
final GridCellControllerBuilder cellControllerBuilder;
|
||||
|
@ -84,20 +84,28 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
||||
Log.debug(
|
||||
'[$AFBoardColumnDataController] $columnData insert $item at $index');
|
||||
|
||||
if (columnData._items.length > index) {
|
||||
columnData._items.insert(index, item);
|
||||
if (_containsItem(item)) {
|
||||
return false;
|
||||
} else {
|
||||
columnData._items.add(item);
|
||||
}
|
||||
if (columnData._items.length > index) {
|
||||
columnData._items.insert(index, item);
|
||||
} else {
|
||||
columnData._items.add(item);
|
||||
}
|
||||
|
||||
if (notify) notifyListeners();
|
||||
return true;
|
||||
if (notify) notifyListeners();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool add(AFColumnItem item, {bool notify = true}) {
|
||||
columnData._items.add(item);
|
||||
if (notify) notifyListeners();
|
||||
return true;
|
||||
if (_containsItem(item)) {
|
||||
return false;
|
||||
} else {
|
||||
columnData._items.add(item);
|
||||
if (notify) notifyListeners();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the item at index with the [newItem].
|
||||
@ -114,6 +122,11 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool _containsItem(AFColumnItem item) {
|
||||
return columnData._items.indexWhere((element) => element.id == item.id) !=
|
||||
-1;
|
||||
}
|
||||
}
|
||||
|
||||
/// [AFBoardColumnData] represents the data of each Column of the Board.
|
||||
|
@ -1,7 +1,7 @@
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::ErrorCode;
|
||||
use flowy_grid_data_model::parser::NotEmptyStr;
|
||||
use flowy_grid_data_model::revision::{CellRevision, RowMetaChangeset};
|
||||
use flowy_grid_data_model::revision::{CellRevision, RowChangeset};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(ProtoBuf, Default)]
|
||||
@ -135,7 +135,7 @@ pub struct CellChangesetPB {
|
||||
pub content: Option<String>,
|
||||
}
|
||||
|
||||
impl std::convert::From<CellChangesetPB> for RowMetaChangeset {
|
||||
impl std::convert::From<CellChangesetPB> for RowChangeset {
|
||||
fn from(changeset: CellChangesetPB) -> Self {
|
||||
let mut cell_by_field_id = HashMap::with_capacity(1);
|
||||
let field_id = changeset.field_id;
|
||||
@ -144,7 +144,7 @@ impl std::convert::From<CellChangesetPB> for RowMetaChangeset {
|
||||
};
|
||||
cell_by_field_id.insert(field_id, cell_rev);
|
||||
|
||||
RowMetaChangeset {
|
||||
RowChangeset {
|
||||
row_id: changeset.row_id,
|
||||
height: None,
|
||||
visibility: None,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::entities::RowPB;
|
||||
use bytes::Bytes;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision};
|
||||
use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowChangeset, RowRevision};
|
||||
use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
|
||||
use flowy_sync::client_grid::{GridBlockRevisionChangeset, GridBlockRevisionPad};
|
||||
use flowy_sync::entities::revision::Revision;
|
||||
@ -88,7 +88,7 @@ impl GridBlockRevisionEditor {
|
||||
Ok(row_count)
|
||||
}
|
||||
|
||||
pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
|
||||
pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> {
|
||||
let _ = self.modify(|block_pad| Ok(block_pad.update_row(changeset)?)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::services::row::{block_from_row_orders, make_row_from_row_rev, GridBlo
|
||||
use dashmap::DashMap;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{
|
||||
GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision,
|
||||
GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowChangeset, RowRevision,
|
||||
};
|
||||
use flowy_revision::disk::SQLiteGridBlockRevisionPersistence;
|
||||
use flowy_revision::{RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence};
|
||||
@ -103,17 +103,15 @@ impl GridBlockManager {
|
||||
Ok(changesets)
|
||||
}
|
||||
|
||||
pub async fn update_row<F>(&self, changeset: RowMetaChangeset, row_builder: F) -> FlowyResult<()>
|
||||
where
|
||||
F: FnOnce(Arc<RowRevision>) -> RowPB,
|
||||
{
|
||||
pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> {
|
||||
let editor = self.get_editor_from_row_id(&changeset.row_id).await?;
|
||||
let _ = editor.update_row(changeset.clone()).await?;
|
||||
match editor.get_row_rev(&changeset.row_id).await? {
|
||||
None => tracing::error!("Internal error: can't find the row with id: {}", changeset.row_id),
|
||||
Some(row_rev) => {
|
||||
let row_pb = make_row_from_row_rev(row_rev.clone());
|
||||
let block_order_changeset =
|
||||
GridBlockChangesetPB::update(&editor.block_id, vec![row_builder(row_rev.clone())]);
|
||||
GridBlockChangesetPB::update(&editor.block_id, vec![row_pb]);
|
||||
let _ = self
|
||||
.notify_did_update_block(&editor.block_id, block_order_changeset)
|
||||
.await?;
|
||||
@ -191,12 +189,10 @@ impl GridBlockManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_cell<F>(&self, changeset: CellChangesetPB, row_builder: F) -> FlowyResult<()>
|
||||
where
|
||||
F: FnOnce(Arc<RowRevision>) -> RowPB,
|
||||
pub async fn update_cell(&self, changeset: CellChangesetPB ) -> FlowyResult<()>
|
||||
{
|
||||
let row_changeset: RowMetaChangeset = changeset.clone().into();
|
||||
let _ = self.update_row(row_changeset, row_builder).await?;
|
||||
let row_changeset: RowChangeset = changeset.clone().into();
|
||||
let _ = self.update_row(row_changeset, ).await?;
|
||||
self.notify_did_update_cell(changeset).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -314,9 +314,9 @@ impl GridRevisionEditor {
|
||||
Ok(row_orders)
|
||||
}
|
||||
|
||||
pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
|
||||
pub async fn update_row(&self, changeset: RowChangeset) -> FlowyResult<()> {
|
||||
let row_id = changeset.row_id.clone();
|
||||
let _ = self.block_manager.update_row(changeset, make_row_from_row_rev).await?;
|
||||
let _ = self.block_manager.update_row(changeset).await?;
|
||||
self.view_manager.did_update_row(&row_id).await;
|
||||
Ok(())
|
||||
}
|
||||
@ -395,12 +395,11 @@ impl GridRevisionEditor {
|
||||
|
||||
match self.grid_pad.read().await.get_field_rev(&field_id) {
|
||||
None => {
|
||||
let msg = format!("Field not found with id: {}", &field_id);
|
||||
let msg = format!("Field:{} not found", &field_id);
|
||||
Err(FlowyError::internal().context(msg))
|
||||
}
|
||||
Some((_, field_rev)) => {
|
||||
tracing::trace!("field changeset: id:{} / value:{:?}", &field_id, content);
|
||||
|
||||
let cell_rev = self.get_cell_rev(&row_id, &field_id).await?;
|
||||
// Update the changeset.data property with the return value.
|
||||
content = Some(apply_cell_data_changeset(content.unwrap(), cell_rev, field_rev)?);
|
||||
@ -410,11 +409,7 @@ impl GridRevisionEditor {
|
||||
field_id,
|
||||
content,
|
||||
};
|
||||
let _ = self
|
||||
.block_manager
|
||||
.update_cell(cell_changeset, make_row_from_row_rev)
|
||||
.await?;
|
||||
|
||||
let _ = self.block_manager.update_cell(cell_changeset).await?;
|
||||
self.view_manager.did_update_row(&row_id).await;
|
||||
Ok(())
|
||||
}
|
||||
@ -512,10 +507,19 @@ impl GridRevisionEditor {
|
||||
.block_manager
|
||||
.move_row(row_rev.clone(), from_index, to_index)
|
||||
.await?;
|
||||
self.view_manager.move_row(row_rev, to_row_id.clone()).await;
|
||||
|
||||
if let Some(row_changeset) = self.view_manager.move_row(row_rev, to_row_id.clone()).await {
|
||||
tracing::trace!("Receive row changeset after moving the row");
|
||||
match self.block_manager.update_row(row_changeset).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
tracing::error!("Apply row changeset error:{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(_, None) => tracing::error!("Can not find the from row id: {}", from_row_id),
|
||||
(None, _) => tracing::error!("Can not find the to row id: {}", to_row_id),
|
||||
(_, None) => tracing::warn!("Can not find the from row id: {}", from_row_id),
|
||||
(None, _) => tracing::warn!("Can not find the to row id: {}", to_row_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDeleg
|
||||
use crate::services::group::{default_group_configuration, GroupConfigurationDelegate, GroupService};
|
||||
use crate::services::setting::make_grid_setting;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowRevision};
|
||||
use flowy_grid_data_model::revision::{FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision};
|
||||
use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilder};
|
||||
use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
|
||||
use flowy_sync::entities::grid::GridSettingChangesetParams;
|
||||
@ -117,12 +117,12 @@ impl GridViewRevisionEditor {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, upper_row_id: &str) {
|
||||
pub(crate) async fn did_move_row(&self, row_rev: &RowRevision, row_changeset: &mut RowChangeset, upper_row_id: &str) {
|
||||
if let Some(changesets) = self
|
||||
.group_service
|
||||
.write()
|
||||
.await
|
||||
.did_move_row(row_rev, upper_row_id, |field_id| {
|
||||
.did_move_row(row_rev, row_changeset, upper_row_id, |field_id| {
|
||||
self.field_delegate.get_field_rev(&field_id)
|
||||
})
|
||||
.await
|
||||
|
@ -1,13 +1,11 @@
|
||||
use crate::entities::{
|
||||
CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB,
|
||||
};
|
||||
use crate::entities::{CreateRowParams, GridFilterConfiguration, GridSettingPB, RepeatedGridGroupPB, RowPB};
|
||||
use crate::manager::GridUser;
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use crate::services::grid_view_editor::GridViewRevisionEditor;
|
||||
use bytes::Bytes;
|
||||
use dashmap::DashMap;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision};
|
||||
use flowy_revision::disk::SQLiteGridViewRevisionPersistence;
|
||||
use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence};
|
||||
use flowy_sync::entities::grid::GridSettingChangesetParams;
|
||||
@ -56,18 +54,21 @@ impl GridViewManager {
|
||||
})
|
||||
}
|
||||
|
||||
/// When the row was created, we may need to modify the [RowRevision] according to the [CreateRowParams].
|
||||
pub(crate) async fn will_create_row(&self, row_rev: &mut RowRevision, params: &CreateRowParams) {
|
||||
for view_editor in self.view_editors.iter() {
|
||||
view_editor.will_create_row(row_rev, params).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Notify the view that the row was created. For the moment, the view is just sending notifications.
|
||||
pub(crate) async fn did_create_row(&self, row_pb: &RowPB, params: &CreateRowParams) {
|
||||
for view_editor in self.view_editors.iter() {
|
||||
view_editor.did_create_row(row_pb, params).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert/Delete the group's row if the corresponding data was changed.
|
||||
pub(crate) async fn did_update_row(&self, row_id: &str) {
|
||||
match self.row_delegate.gv_get_row_rev(row_id).await {
|
||||
None => {
|
||||
@ -109,9 +110,19 @@ impl GridViewManager {
|
||||
Ok(RepeatedGridGroupPB { items: groups })
|
||||
}
|
||||
|
||||
pub(crate) async fn move_row(&self, row_rev: Arc<RowRevision>, to_row_id: String) {
|
||||
/// It may generate a RowChangeset when the Row was moved from one group to another.
|
||||
/// The return value, [RowChangeset], contains the changes made by the groups.
|
||||
///
|
||||
pub(crate) async fn move_row(&self, row_rev: Arc<RowRevision>, to_row_id: String) -> Option<RowChangeset> {
|
||||
let mut row_changeset = RowChangeset::new(row_rev.id.clone());
|
||||
for view_editor in self.view_editors.iter() {
|
||||
view_editor.did_move_row(&row_rev, &to_row_id).await;
|
||||
view_editor.did_move_row(&row_rev, &mut row_changeset, &to_row_id).await;
|
||||
}
|
||||
|
||||
if row_changeset.has_changed() {
|
||||
Some(row_changeset)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::entities::{CheckboxGroupConfigurationPB, GroupRowsChangesetPB};
|
||||
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision};
|
||||
|
||||
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
||||
use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable};
|
||||
@ -37,7 +37,9 @@ impl Groupable for CheckboxGroupController {
|
||||
|
||||
fn move_row_if_match(
|
||||
&mut self,
|
||||
field_rev: &FieldRevision,
|
||||
_row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
_cell_data: &Self::CellDataType,
|
||||
_to_row_id: &str,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
@ -57,11 +59,22 @@ impl GroupGenerator for CheckboxGroupGenerator {
|
||||
type TypeOptionType = CheckboxTypeOptionPB;
|
||||
|
||||
fn generate_groups(
|
||||
field_id: &str,
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
_type_option: &Option<Self::TypeOptionType>,
|
||||
) -> Vec<Group> {
|
||||
let check_group = Group::new("true".to_string(), "".to_string(), CHECK.to_string());
|
||||
let uncheck_group = Group::new("false".to_string(), "".to_string(), UNCHECK.to_string());
|
||||
let check_group = Group::new(
|
||||
"true".to_string(),
|
||||
field_id.to_owned(),
|
||||
"".to_string(),
|
||||
CHECK.to_string(),
|
||||
);
|
||||
let uncheck_group = Group::new(
|
||||
"false".to_string(),
|
||||
field_id.to_owned(),
|
||||
"".to_string(),
|
||||
UNCHECK.to_string(),
|
||||
);
|
||||
vec![check_group, uncheck_group]
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::services::cell::{decode_any_cell_data, CellBytesParser};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{
|
||||
FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer,
|
||||
FieldRevision, GroupConfigurationRevision, RowChangeset, RowRevision, TypeOptionDataDeserializer,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
use std::marker::PhantomData;
|
||||
@ -14,6 +14,7 @@ pub trait GroupGenerator {
|
||||
type TypeOptionType;
|
||||
|
||||
fn generate_groups(
|
||||
field_id: &str,
|
||||
configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
) -> Vec<Group>;
|
||||
@ -31,7 +32,9 @@ pub trait Groupable: Send + Sync {
|
||||
|
||||
fn move_row_if_match(
|
||||
&mut self,
|
||||
field_rev: &FieldRevision,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
cell_data: &Self::CellDataType,
|
||||
to_row_id: &str,
|
||||
) -> Vec<GroupRowsChangesetPB>;
|
||||
@ -61,6 +64,7 @@ pub trait GroupControllerSharedAction: Send + Sync {
|
||||
fn did_move_row(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
field_rev: &FieldRevision,
|
||||
to_row_id: &str,
|
||||
) -> FlowyResult<Vec<GroupRowsChangesetPB>>;
|
||||
@ -85,6 +89,7 @@ pub struct GenericGroupController<C, T, G, P> {
|
||||
#[derive(Clone)]
|
||||
pub struct Group {
|
||||
pub id: String,
|
||||
pub field_id: String,
|
||||
pub desc: String,
|
||||
rows: Vec<RowPB>,
|
||||
pub content: String,
|
||||
@ -101,9 +106,10 @@ impl std::convert::From<Group> for GroupPB {
|
||||
}
|
||||
|
||||
impl Group {
|
||||
pub fn new(id: String, desc: String, content: String) -> Self {
|
||||
pub fn new(id: String, field_id: String, desc: String, content: String) -> Self {
|
||||
Self {
|
||||
id,
|
||||
field_id,
|
||||
desc,
|
||||
rows: vec![],
|
||||
content,
|
||||
@ -158,10 +164,11 @@ where
|
||||
};
|
||||
let field_type_rev = field_rev.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(&field_rev.id, &configuration, &type_option);
|
||||
|
||||
let default_group = Group::new(
|
||||
DEFAULT_GROUP_ID.to_owned(),
|
||||
field_rev.id.clone(),
|
||||
format!("No {}", field_rev.name),
|
||||
"".to_string(),
|
||||
);
|
||||
@ -263,62 +270,20 @@ where
|
||||
fn did_move_row(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
field_rev: &FieldRevision,
|
||||
to_row_id: &str,
|
||||
) -> 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.move_row_if_match(row_rev, &cell_data, to_row_id))
|
||||
Ok(self.move_row_if_match(field_rev, row_rev, row_changeset, &cell_data, to_row_id))
|
||||
} 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 {
|
||||
row: RowPB,
|
||||
group_id: String,
|
||||
|
@ -5,7 +5,7 @@ use crate::services::field::{
|
||||
};
|
||||
use crate::services::group::{GenericGroupController, Group, GroupController, GroupGenerator, Groupable};
|
||||
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision};
|
||||
|
||||
// SingleSelect
|
||||
pub type SingleSelectGroupController = GenericGroupController<
|
||||
@ -43,15 +43,25 @@ impl Groupable for SingleSelectGroupController {
|
||||
|
||||
fn move_row_if_match(
|
||||
&mut self,
|
||||
field_rev: &FieldRevision,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
cell_data: &Self::CellDataType,
|
||||
to_row_id: &str,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
let mut group_changeset = vec![];
|
||||
self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| {
|
||||
move_row(group, &mut changesets, cell_data, row_rev, to_row_id);
|
||||
move_row(
|
||||
group,
|
||||
&mut group_changeset,
|
||||
field_rev,
|
||||
row_rev,
|
||||
row_changeset,
|
||||
cell_data,
|
||||
to_row_id,
|
||||
);
|
||||
});
|
||||
changesets
|
||||
group_changeset
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +84,7 @@ impl GroupGenerator for SingleSelectGroupGenerator {
|
||||
type ConfigurationType = SelectOptionGroupConfigurationPB;
|
||||
type TypeOptionType = SingleSelectTypeOptionPB;
|
||||
fn generate_groups(
|
||||
field_id: &str,
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
) -> Vec<Group> {
|
||||
@ -82,7 +93,14 @@ impl GroupGenerator for SingleSelectGroupGenerator {
|
||||
Some(type_option) => type_option
|
||||
.options
|
||||
.iter()
|
||||
.map(|option| Group::new(option.id.clone(), option.name.clone(), option.id.clone()))
|
||||
.map(|option| {
|
||||
Group::new(
|
||||
option.id.clone(),
|
||||
field_id.to_owned(),
|
||||
option.name.clone(),
|
||||
option.id.clone(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
@ -125,15 +143,25 @@ impl Groupable for MultiSelectGroupController {
|
||||
|
||||
fn move_row_if_match(
|
||||
&mut self,
|
||||
field_rev: &FieldRevision,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
cell_data: &Self::CellDataType,
|
||||
to_row_id: &str,
|
||||
) -> Vec<GroupRowsChangesetPB> {
|
||||
let mut changesets = vec![];
|
||||
let mut group_changeset = vec![];
|
||||
self.groups_map.iter_mut().for_each(|(_, group): (_, &mut Group)| {
|
||||
move_row(group, &mut changesets, cell_data, row_rev, to_row_id);
|
||||
move_row(
|
||||
group,
|
||||
&mut group_changeset,
|
||||
field_rev,
|
||||
row_rev,
|
||||
row_changeset,
|
||||
cell_data,
|
||||
to_row_id,
|
||||
);
|
||||
});
|
||||
changesets
|
||||
group_changeset
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +184,7 @@ impl GroupGenerator for MultiSelectGroupGenerator {
|
||||
type TypeOptionType = MultiSelectTypeOptionPB;
|
||||
|
||||
fn generate_groups(
|
||||
field_id: &str,
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
) -> Vec<Group> {
|
||||
@ -164,7 +193,14 @@ impl GroupGenerator for MultiSelectGroupGenerator {
|
||||
Some(type_option) => type_option
|
||||
.options
|
||||
.iter()
|
||||
.map(|option| Group::new(option.id.clone(), option.name.clone(), option.id.clone()))
|
||||
.map(|option| {
|
||||
Group::new(
|
||||
option.id.clone(),
|
||||
field_id.to_owned(),
|
||||
option.name.clone(),
|
||||
option.id.clone(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
@ -204,25 +240,30 @@ fn remove_row(
|
||||
|
||||
fn move_row(
|
||||
group: &mut Group,
|
||||
changesets: &mut Vec<GroupRowsChangesetPB>,
|
||||
cell_data: &SelectOptionCellDataPB,
|
||||
group_changeset: &mut Vec<GroupRowsChangesetPB>,
|
||||
field_rev: &FieldRevision,
|
||||
row_rev: &RowRevision,
|
||||
upper_row_id: &str,
|
||||
row_changeset: &mut RowChangeset,
|
||||
cell_data: &SelectOptionCellDataPB,
|
||||
to_row_id: &str,
|
||||
) {
|
||||
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()]));
|
||||
group_changeset.push(GroupRowsChangesetPB::delete(group.id.clone(), vec![row_rev.id.clone()]));
|
||||
group.remove_row(&row_rev.id);
|
||||
}
|
||||
|
||||
if let Some(index) = group.index_of_row(upper_row_id) {
|
||||
if let Some(index) = group.index_of_row(to_row_id) {
|
||||
let row_pb = RowPB::from(row_rev);
|
||||
let inserted_row = InsertedRowPB {
|
||||
row: row_pb.clone(),
|
||||
index: Some(index as i32),
|
||||
};
|
||||
changesets.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row]));
|
||||
group_changeset.push(GroupRowsChangesetPB::insert(group.id.clone(), vec![inserted_row]));
|
||||
group.insert_row(index, row_pb);
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::services::group::{
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision};
|
||||
use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision, RowChangeset};
|
||||
use lib_infra::future::AFFuture;
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
@ -96,6 +96,7 @@ impl GroupService {
|
||||
pub(crate) async fn did_move_row<F, O>(
|
||||
&self,
|
||||
row_rev: &RowRevision,
|
||||
row_changeset: &mut RowChangeset,
|
||||
upper_row_id: &str,
|
||||
get_field_fn: F,
|
||||
) -> Option<Vec<GroupRowsChangesetPB>>
|
||||
@ -110,7 +111,7 @@ impl GroupService {
|
||||
match group_controller
|
||||
.write()
|
||||
.await
|
||||
.did_move_row(row_rev, &field_rev, upper_row_id)
|
||||
.did_move_row(row_rev, row_changeset, &field_rev, upper_row_id)
|
||||
{
|
||||
Ok(changesets) => Some(changesets),
|
||||
Err(e) => {
|
||||
|
@ -3,7 +3,7 @@ use crate::grid::block_test::script::{CreateRowScriptBuilder, GridRowTest};
|
||||
use crate::grid::grid_editor::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, TWITTER};
|
||||
use flowy_grid::entities::FieldType;
|
||||
use flowy_grid::services::field::{SELECTION_IDS_SEPARATOR, UNCHECK};
|
||||
use flowy_grid_data_model::revision::RowMetaChangeset;
|
||||
use flowy_grid_data_model::revision::RowChangeset;
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_create_row_count_test() {
|
||||
@ -24,7 +24,7 @@ async fn grid_create_row_count_test() {
|
||||
async fn grid_update_row() {
|
||||
let mut test = GridRowTest::new().await;
|
||||
let row_rev = test.row_builder().build();
|
||||
let changeset = RowMetaChangeset {
|
||||
let changeset = RowChangeset {
|
||||
row_id: row_rev.id.clone(),
|
||||
height: None,
|
||||
visibility: None,
|
||||
|
@ -5,7 +5,7 @@ use crate::grid::grid_editor::GridEditorTest;
|
||||
use flowy_grid::entities::{CreateRowParams, FieldType, GridCellIdParams, GridLayout, RowPB};
|
||||
use flowy_grid::services::field::*;
|
||||
use flowy_grid_data_model::revision::{
|
||||
GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision,
|
||||
GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowChangeset, RowRevision,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
@ -17,7 +17,7 @@ pub enum RowScript {
|
||||
row_rev: RowRevision,
|
||||
},
|
||||
UpdateRow {
|
||||
changeset: RowMetaChangeset,
|
||||
changeset: RowChangeset,
|
||||
},
|
||||
AssertRow {
|
||||
expected_row: RowRevision,
|
||||
|
@ -42,13 +42,28 @@ impl RowRevision {
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct RowMetaChangeset {
|
||||
pub struct RowChangeset {
|
||||
pub row_id: String,
|
||||
pub height: Option<i32>,
|
||||
pub visibility: Option<bool>,
|
||||
pub cell_by_field_id: HashMap<FieldId, CellRevision>,
|
||||
}
|
||||
|
||||
impl RowChangeset {
|
||||
pub fn new(row_id: String) -> Self {
|
||||
Self {
|
||||
row_id,
|
||||
height: None,
|
||||
visibility: None,
|
||||
cell_by_field_id: Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_changed(&self) -> bool {
|
||||
self.height.is_some() || self.visibility.is_some() || !self.cell_by_field_id.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
|
||||
pub struct CellRevision {
|
||||
pub data: String,
|
||||
|
@ -2,7 +2,7 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision};
|
||||
use crate::errors::{CollaborateError, CollaborateResult};
|
||||
use crate::util::{cal_diff, make_text_delta_from_revisions};
|
||||
use flowy_grid_data_model::revision::{
|
||||
gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision,
|
||||
gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowChangeset, RowRevision,
|
||||
};
|
||||
use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder};
|
||||
use std::borrow::Cow;
|
||||
@ -143,7 +143,7 @@ impl GridBlockRevisionPad {
|
||||
self.block.rows.iter().position(|row| row.id == row_id)
|
||||
}
|
||||
|
||||
pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult<Option<GridBlockRevisionChangeset>> {
|
||||
pub fn update_row(&mut self, changeset: RowChangeset) -> CollaborateResult<Option<GridBlockRevisionChangeset>> {
|
||||
let row_id = changeset.row_id.clone();
|
||||
self.modify_row(&row_id, |row| {
|
||||
let mut is_changed = None;
|
||||
|
Loading…
Reference in New Issue
Block a user