mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: save group rev without apply change
This commit is contained in:
parent
23efbc00c1
commit
93f5b5d754
@ -66,6 +66,7 @@ impl FlowyError {
|
||||
static_flowy_error!(user_not_exist, ErrorCode::UserNotExist);
|
||||
static_flowy_error!(text_too_long, ErrorCode::TextTooLong);
|
||||
static_flowy_error!(invalid_data, ErrorCode::InvalidData);
|
||||
static_flowy_error!(out_of_bounds, ErrorCode::OutOfBounds);
|
||||
}
|
||||
|
||||
impl std::convert::From<ErrorCode> for FlowyError {
|
||||
|
@ -109,10 +109,19 @@ pub struct GroupViewChangesetPB {
|
||||
pub view_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub inserted_groups: Vec<GroupPB>,
|
||||
pub inserted_groups: Vec<InsertedGroupPB>,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub deleted_groups: Vec<String>,
|
||||
}
|
||||
|
||||
impl GroupViewChangesetPB {}
|
||||
|
||||
#[derive(Debug, Default, ProtoBuf)]
|
||||
pub struct InsertedGroupPB {
|
||||
#[pb(index = 1)]
|
||||
pub group: GroupPB,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub index: i32,
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
use crate::dart_notification::{send_dart_notification, GridNotification};
|
||||
use crate::entities::{
|
||||
CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridLayout, GridLayoutPB,
|
||||
GridSettingChangesetParams, GridSettingPB, GroupPB, GroupRowsChangesetPB, GroupViewChangesetPB, InsertedRowPB,
|
||||
GridSettingPB, GroupPB, GroupRowsChangesetPB, GroupViewChangesetPB, InsertedGroupPB, InsertedRowPB,
|
||||
MoveGroupParams, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RowPB,
|
||||
};
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
|
||||
use crate::services::group::{
|
||||
default_group_configuration, GroupConfigurationReader, GroupConfigurationWriter, GroupService,
|
||||
};
|
||||
use crate::services::group::{GroupConfigurationReader, GroupConfigurationWriter, GroupService};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::revision::{
|
||||
gen_grid_filter_id, FieldRevision, FieldTypeRevision, FilterConfigurationRevision, GroupConfigurationRevision,
|
||||
@ -19,6 +17,7 @@ use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
|
||||
use flowy_sync::entities::revision::Revision;
|
||||
use lib_infra::future::{wrap_future, AFFuture, FutureResult};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
@ -37,6 +36,7 @@ pub struct GridViewRevisionEditor {
|
||||
}
|
||||
|
||||
impl GridViewRevisionEditor {
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub(crate) async fn new(
|
||||
user_id: &str,
|
||||
token: &str,
|
||||
@ -109,7 +109,7 @@ impl GridViewRevisionEditor {
|
||||
// Send the group notification if the current view has groups;
|
||||
if let Some(changesets) = self
|
||||
.group_service
|
||||
.write()
|
||||
.read()
|
||||
.await
|
||||
.did_delete_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
||||
.await
|
||||
@ -123,7 +123,7 @@ impl GridViewRevisionEditor {
|
||||
pub(crate) async fn did_update_row(&self, row_rev: &RowRevision) {
|
||||
if let Some(changesets) = self
|
||||
.group_service
|
||||
.write()
|
||||
.read()
|
||||
.await
|
||||
.did_update_row(row_rev, |field_id| self.field_delegate.get_field_rev(&field_id))
|
||||
.await
|
||||
@ -142,7 +142,7 @@ impl GridViewRevisionEditor {
|
||||
) {
|
||||
if let Some(changesets) = self
|
||||
.group_service
|
||||
.write()
|
||||
.read()
|
||||
.await
|
||||
.did_move_row(row_rev, row_changeset, upper_row_id, |field_id| {
|
||||
self.field_delegate.get_field_rev(&field_id)
|
||||
@ -156,11 +156,13 @@ impl GridViewRevisionEditor {
|
||||
}
|
||||
}
|
||||
|
||||
#[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) {
|
||||
self.did_load_group.store(true, Ordering::SeqCst);
|
||||
let field_revs = self.field_delegate.get_field_revs().await;
|
||||
let row_revs = self.row_delegate.gv_row_revs().await;
|
||||
|
||||
match self
|
||||
.group_service
|
||||
.write()
|
||||
@ -174,11 +176,37 @@ impl GridViewRevisionEditor {
|
||||
} else {
|
||||
self.group_service.read().await.groups().await
|
||||
};
|
||||
|
||||
tracing::trace!("Number of groups: {}", groups.len());
|
||||
Ok(groups.into_iter().map(GroupPB::from).collect())
|
||||
}
|
||||
|
||||
pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
|
||||
todo!()
|
||||
let _ = self
|
||||
.group_service
|
||||
.read()
|
||||
.await
|
||||
.move_group(¶ms.from_group_id, ¶ms.to_group_id)
|
||||
.await?;
|
||||
|
||||
match self.group_service.read().await.get_group(¶ms.from_group_id).await {
|
||||
None => {}
|
||||
Some((index, group)) => {
|
||||
let inserted_group = InsertedGroupPB {
|
||||
group: GroupPB::from(group),
|
||||
index: index as i32,
|
||||
};
|
||||
|
||||
let changeset = GroupViewChangesetPB {
|
||||
view_id: "".to_string(),
|
||||
inserted_groups: vec![inserted_group],
|
||||
deleted_groups: vec![params.from_group_id.clone()],
|
||||
};
|
||||
|
||||
self.notify_did_update_view(changeset).await;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn get_setting(&self) -> GridSettingPB {
|
||||
@ -291,17 +319,19 @@ impl RevisionObjectBuilder for GridViewRevisionPadBuilder {
|
||||
struct GroupConfigurationReaderImpl(Arc<RwLock<GridViewRevisionPad>>);
|
||||
|
||||
impl GroupConfigurationReader for GroupConfigurationReaderImpl {
|
||||
fn get_group_configuration(&self, field_rev: Arc<FieldRevision>) -> AFFuture<Arc<GroupConfigurationRevision>> {
|
||||
fn get_group_configuration(
|
||||
&self,
|
||||
field_rev: Arc<FieldRevision>,
|
||||
) -> AFFuture<Option<Arc<GroupConfigurationRevision>>> {
|
||||
let view_pad = self.0.clone();
|
||||
wrap_future(async move {
|
||||
let view_pad = view_pad.read().await;
|
||||
let configurations = view_pad.get_groups(&field_rev.id, &field_rev.ty);
|
||||
match configurations {
|
||||
None => {
|
||||
let default_configuration = default_group_configuration(&field_rev);
|
||||
Arc::new(default_configuration)
|
||||
}
|
||||
Some(configuration) => configuration,
|
||||
let mut groups = view_pad.read().await.groups.get_objects(&field_rev.id, &field_rev.ty)?;
|
||||
|
||||
if groups.is_empty() {
|
||||
None
|
||||
} else {
|
||||
debug_assert_eq!(groups.len(), 1);
|
||||
Some(groups.pop().unwrap())
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -328,17 +358,25 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl {
|
||||
let field_id = field_id.to_owned();
|
||||
|
||||
wrap_future(async move {
|
||||
match view_pad.write().await.get_mut_group(
|
||||
let is_contained = view_pad.read().await.contains_group(&field_id, &field_type);
|
||||
let changeset = if is_contained {
|
||||
view_pad.write().await.with_mut_group(
|
||||
&field_id,
|
||||
&field_type,
|
||||
&configuration_id,
|
||||
|group_configuration| {
|
||||
group_configuration.content = content;
|
||||
},
|
||||
)? {
|
||||
None => Ok(()),
|
||||
Some(changeset) => apply_change(&user_id, rev_manager, changeset).await,
|
||||
)?
|
||||
} else {
|
||||
let group_rev = GroupConfigurationRevision::new(field_id.clone(), field_type, content)?;
|
||||
view_pad.write().await.insert_group(&field_id, &field_type, group_rev)?
|
||||
};
|
||||
|
||||
if let Some(changeset) = changeset {
|
||||
let _ = apply_change(&user_id, rev_manager, changeset).await?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -371,3 +409,17 @@ pub fn make_grid_setting(view_pad: &GridViewRevisionPad, field_revs: &[Arc<Field
|
||||
group_configuration_by_field_id: groups_by_field_id,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use lib_ot::core::TextDelta;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let s1 = r#"[{"insert":"{\"view_id\":\"fTURELffPr\",\"grid_id\":\"fTURELffPr\",\"layout\":0,\"filters\":[],\"groups\":[]}"}]"#;
|
||||
let _delta_1 = TextDelta::from_json(s1).unwrap();
|
||||
|
||||
let s2 = r#"[{"retain":195},{"insert":"{\\\"group_id\\\":\\\"wD9i\\\",\\\"visible\\\":true},{\\\"group_id\\\":\\\"xZtv\\\",\\\"visible\\\":true},{\\\"group_id\\\":\\\"tFV2\\\",\\\"visible\\\":true}"},{"retain":10}]"#;
|
||||
let _delta_2 = TextDelta::from_json(s2).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::entities::{
|
||||
CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridSettingChangesetParams,
|
||||
GridSettingPB, MoveGroupParams, RepeatedGridGroupPB, RowPB,
|
||||
CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfiguration, GridSettingPB, MoveGroupParams,
|
||||
RepeatedGridGroupPB, RowPB,
|
||||
};
|
||||
use crate::manager::GridUser;
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
@ -122,7 +122,7 @@ impl GridViewManager {
|
||||
|
||||
pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
|
||||
let view_editor = self.get_default_view_editor().await?;
|
||||
let _s = view_editor.move_group(params).await?;
|
||||
let _ = view_editor.move_group(params).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -175,12 +175,11 @@ async fn make_view_editor(
|
||||
row_delegate: Arc<dyn GridViewRowDelegate>,
|
||||
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
||||
) -> FlowyResult<GridViewRevisionEditor> {
|
||||
tracing::trace!("Open view:{} editor", view_id);
|
||||
|
||||
let rev_manager = make_grid_view_rev_manager(user, view_id).await?;
|
||||
let user_id = user.user_id()?;
|
||||
let token = user.token()?;
|
||||
let view_id = view_id.to_owned();
|
||||
|
||||
GridViewRevisionEditor::new(
|
||||
&user_id,
|
||||
&token,
|
||||
@ -194,7 +193,6 @@ async fn make_view_editor(
|
||||
}
|
||||
|
||||
pub async fn make_grid_view_rev_manager(user: &Arc<dyn GridUser>, view_id: &str) -> FlowyResult<RevisionManager> {
|
||||
tracing::trace!("Open view:{} editor", view_id);
|
||||
let user_id = user.user_id()?;
|
||||
let pool = user.db_pool()?;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::services::group::Group;
|
||||
use flowy_error::FlowyResult;
|
||||
use crate::services::group::{default_group_configuration, Group};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::revision::{
|
||||
FieldRevision, FieldTypeRevision, GroupConfigurationContent, GroupConfigurationRevision, GroupRecordRevision,
|
||||
};
|
||||
@ -9,7 +9,10 @@ use lib_infra::future::AFFuture;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait GroupConfigurationReader: Send + Sync + 'static {
|
||||
fn get_group_configuration(&self, field_rev: Arc<FieldRevision>) -> AFFuture<Arc<GroupConfigurationRevision>>;
|
||||
fn get_group_configuration(
|
||||
&self,
|
||||
field_rev: Arc<FieldRevision>,
|
||||
) -> AFFuture<Option<Arc<GroupConfigurationRevision>>>;
|
||||
}
|
||||
|
||||
pub trait GroupConfigurationWriter: Send + Sync + 'static {
|
||||
@ -39,7 +42,22 @@ where
|
||||
reader: Arc<dyn GroupConfigurationReader>,
|
||||
writer: Arc<dyn GroupConfigurationWriter>,
|
||||
) -> FlowyResult<Self> {
|
||||
let configuration_rev = reader.get_group_configuration(field_rev.clone()).await;
|
||||
let configuration_rev = match reader.get_group_configuration(field_rev.clone()).await {
|
||||
None => {
|
||||
let default_group_configuration = default_group_configuration(&field_rev);
|
||||
writer
|
||||
.save_group_configuration(
|
||||
&field_rev.id,
|
||||
field_rev.ty,
|
||||
&default_group_configuration.id,
|
||||
default_group_configuration.content.clone(),
|
||||
)
|
||||
.await?;
|
||||
Arc::new(default_group_configuration)
|
||||
}
|
||||
Some(configuration) => configuration,
|
||||
};
|
||||
|
||||
let configuration_id = configuration_rev.id.clone();
|
||||
let configuration = C::from_configuration_content(&configuration_rev.content)?;
|
||||
Ok(Self {
|
||||
@ -63,6 +81,8 @@ where
|
||||
let (group_revs, groups) = merge_groups(self.configuration.get_groups(), groups);
|
||||
self.configuration.set_groups(group_revs);
|
||||
let _ = self.save_configuration().await?;
|
||||
|
||||
tracing::trace!("merge new groups: {}", groups.len());
|
||||
groups.into_iter().for_each(|group| {
|
||||
self.groups_map.insert(group.id.clone(), group);
|
||||
});
|
||||
@ -97,8 +117,25 @@ where
|
||||
self.groups_map.get_mut(group_id)
|
||||
}
|
||||
|
||||
pub(crate) fn get_group(&mut self, group_id: &str) -> Option<&Group> {
|
||||
self.groups_map.get(group_id)
|
||||
pub(crate) fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
|
||||
let from_group_index = self.groups_map.get_index_of(from_group_id);
|
||||
let to_group_index = self.groups_map.get_index_of(to_group_id);
|
||||
match (from_group_index, to_group_index) {
|
||||
(Some(from_index), Some(to_index)) => {
|
||||
self.groups_map.swap_indices(from_index, to_index);
|
||||
self.configuration.swap_group(from_group_id, to_group_id);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(FlowyError::out_of_bounds()),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the index and group specified by the group_id
|
||||
pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &Group)> {
|
||||
match (self.groups_map.get_index_of(group_id), self.groups_map.get(group_id)) {
|
||||
(Some(index), Some(group)) => Some((index, group)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn save_configuration(&self) -> FlowyResult<()> {
|
||||
@ -111,17 +148,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> GroupConfigurationReader for Arc<T>
|
||||
where
|
||||
T: GroupConfigurationReader,
|
||||
{
|
||||
fn get_group_configuration(&self, field_rev: Arc<FieldRevision>) -> AFFuture<Arc<GroupConfigurationRevision>> {
|
||||
(**self).get_group_configuration(field_rev)
|
||||
}
|
||||
}
|
||||
// impl<T> GroupConfigurationReader for Arc<T>
|
||||
// where
|
||||
// T: GroupConfigurationReader,
|
||||
// {
|
||||
// fn get_group_configuration(&self, field_rev: Arc<FieldRevision>) -> AFFuture<Arc<GroupConfigurationRevision>> {
|
||||
// (**self).get_group_configuration(field_rev)
|
||||
// }
|
||||
// }
|
||||
|
||||
fn merge_groups(old_group_revs: &[GroupRecordRevision], groups: Vec<Group>) -> (Vec<GroupRecordRevision>, Vec<Group>) {
|
||||
// tracing::trace!("Merge group: old: {}, new: {}", old_group.len(), groups.len());
|
||||
tracing::trace!("Merge group: old: {}, new: {}", old_group_revs.len(), groups.len());
|
||||
if old_group_revs.is_empty() {
|
||||
let new_groups = groups
|
||||
.iter()
|
||||
|
@ -36,7 +36,9 @@ pub trait GroupControllerSharedOperation: Send + Sync {
|
||||
// The field that is used for grouping the rows
|
||||
fn field_id(&self) -> &str;
|
||||
fn groups(&self) -> Vec<Group>;
|
||||
fn get_group(&self, group_id: &str) -> Option<(usize, Group)>;
|
||||
fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<Vec<Group>>;
|
||||
fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()>;
|
||||
fn did_update_row(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
@ -118,6 +120,11 @@ where
|
||||
self.configuration.clone_groups()
|
||||
}
|
||||
|
||||
fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
||||
let group = self.configuration.get_group(group_id)?;
|
||||
Some((group.0, group.1.clone()))
|
||||
}
|
||||
|
||||
fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<Vec<Group>> {
|
||||
for row_rev in row_revs {
|
||||
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
|
||||
@ -156,6 +163,10 @@ where
|
||||
Ok(groups)
|
||||
}
|
||||
|
||||
fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
|
||||
self.configuration.move_group(from_group_id, to_group_id)
|
||||
}
|
||||
|
||||
fn did_update_row(
|
||||
&mut self,
|
||||
row_rev: &RowRevision,
|
||||
|
@ -71,10 +71,9 @@ impl GroupAction for MultiSelectGroupController {
|
||||
|
||||
impl GroupController for MultiSelectGroupController {
|
||||
fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str) {
|
||||
let group: Option<&Group> = self.configuration.get_group(group_id);
|
||||
match group {
|
||||
match self.configuration.get_group(group_id) {
|
||||
None => tracing::warn!("Can not find the group: {}", group_id),
|
||||
Some(group) => {
|
||||
Some((_, group)) => {
|
||||
let cell_rev = insert_select_option_cell(group.id.clone(), field_rev);
|
||||
row_rev.cells.insert(field_rev.id.clone(), cell_rev);
|
||||
}
|
||||
|
@ -43,6 +43,14 @@ impl GroupService {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_group(&self, group_id: &str) -> Option<(usize, Group)> {
|
||||
if let Some(group_controller) = self.group_controller.as_ref() {
|
||||
group_controller.read().await.get_group(group_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn load_groups(
|
||||
&mut self,
|
||||
field_revs: &[Arc<FieldRevision>],
|
||||
@ -164,9 +172,20 @@ impl GroupService {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all)]
|
||||
pub(crate) async fn move_group(&self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> {
|
||||
match self.group_controller.as_ref() {
|
||||
None => Ok(()),
|
||||
Some(group_controller) => {
|
||||
let _ = group_controller.write().await.move_group(from_group_id, to_group_id)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all)]
|
||||
async fn make_group_controller(
|
||||
&mut self,
|
||||
&self,
|
||||
field_type: &FieldType,
|
||||
field_rev: &Arc<FieldRevision>,
|
||||
) -> FlowyResult<Option<Arc<RwLock<dyn GroupController>>>> {
|
||||
|
@ -4,11 +4,15 @@ use flowy_grid::services::cell::insert_select_option_cell;
|
||||
use flowy_grid_data_model::revision::RowChangeset;
|
||||
|
||||
pub enum GroupScript {
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: usize,
|
||||
row_count: usize,
|
||||
},
|
||||
AssertGroupCount(usize),
|
||||
AssertGroup {
|
||||
group_index: usize,
|
||||
expected_group: GroupPB,
|
||||
},
|
||||
AssertRow {
|
||||
group_index: usize,
|
||||
row_index: usize,
|
||||
@ -56,7 +60,7 @@ impl GridGroupTest {
|
||||
|
||||
pub async fn run_script(&mut self, script: GroupScript) {
|
||||
match script {
|
||||
GroupScript::AssertGroup { group_index, row_count } => {
|
||||
GroupScript::AssertGroupRowCount { group_index, row_count } => {
|
||||
assert_eq!(row_count, self.group_at_index(group_index).await.rows.len());
|
||||
}
|
||||
GroupScript::AssertGroupCount(count) => {
|
||||
@ -142,6 +146,13 @@ impl GridGroupTest {
|
||||
self.editor.move_group(params).await.unwrap();
|
||||
//
|
||||
}
|
||||
GroupScript::AssertGroup {
|
||||
group_index,
|
||||
expected_group: group_pb,
|
||||
} => {
|
||||
let group = self.group_at_index(group_index).await;
|
||||
assert_eq!(group.group_id, group_pb.group_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,15 +6,15 @@ async fn board_init_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let scripts = vec![
|
||||
AssertGroupCount(3),
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 2,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 1,
|
||||
row_count: 2,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 2,
|
||||
row_count: 1,
|
||||
},
|
||||
@ -34,7 +34,7 @@ async fn board_move_row_test() {
|
||||
to_group_index: 0,
|
||||
to_row_index: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 2,
|
||||
},
|
||||
@ -58,11 +58,11 @@ async fn board_move_row_to_other_group_test() {
|
||||
to_group_index: 1,
|
||||
to_row_index: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 1,
|
||||
row_count: 3,
|
||||
},
|
||||
@ -106,13 +106,13 @@ async fn board_create_row_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let scripts = vec![
|
||||
CreateRow { group_index: 0 },
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 3,
|
||||
},
|
||||
CreateRow { group_index: 1 },
|
||||
CreateRow { group_index: 1 },
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 1,
|
||||
row_count: 4,
|
||||
},
|
||||
@ -128,7 +128,7 @@ async fn board_delete_row_test() {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 1,
|
||||
},
|
||||
@ -148,7 +148,7 @@ async fn board_delete_all_row_test() {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 0,
|
||||
},
|
||||
@ -166,11 +166,11 @@ async fn board_update_row_test() {
|
||||
row_index: 0,
|
||||
to_group_index: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 1,
|
||||
row_count: 3,
|
||||
},
|
||||
@ -188,14 +188,36 @@ async fn board_reorder_group_test() {
|
||||
row_index: 0,
|
||||
to_group_index: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 0,
|
||||
row_count: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
AssertGroupRowCount {
|
||||
group_index: 1,
|
||||
row_count: 3,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn board_move_group_test() {
|
||||
let mut test = GridGroupTest::new().await;
|
||||
let group_0 = test.group_at_index(0).await;
|
||||
let group_1 = test.group_at_index(1).await;
|
||||
let scripts = vec![
|
||||
MoveGroup {
|
||||
from_group_index: 0,
|
||||
to_group_index: 1,
|
||||
},
|
||||
AssertGroup {
|
||||
group_index: 0,
|
||||
expected_group: group_1,
|
||||
},
|
||||
AssertGroup {
|
||||
group_index: 1,
|
||||
expected_group: group_0,
|
||||
},
|
||||
];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ fn crate_log_filter(level: String) -> String {
|
||||
filters.push(format!("lib_ot={}", level));
|
||||
filters.push(format!("lib_ws={}", 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!("lib_dispatch={}", level));
|
||||
|
||||
|
@ -125,6 +125,9 @@ pub enum ErrorCode {
|
||||
|
||||
#[display(fmt = "Invalid data")]
|
||||
InvalidData = 1000,
|
||||
|
||||
#[display(fmt = "Out of bounds")]
|
||||
OutOfBounds = 10001,
|
||||
}
|
||||
|
||||
impl ErrorCode {
|
||||
|
@ -49,7 +49,7 @@ where
|
||||
.get_mut(field_id)
|
||||
.and_then(|object_rev_map| object_rev_map.get_mut(field_type));
|
||||
if value.is_none() {
|
||||
tracing::warn!("Can't find the {:?} with", std::any::type_name::<T>());
|
||||
tracing::warn!("[Configuration] Can't find the {:?} with", std::any::type_name::<T>());
|
||||
}
|
||||
value
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
use crate::revision::{
|
||||
FieldRevision, FieldTypeRevision, FilterConfiguration, FilterConfigurationRevision, FilterConfigurationsByFieldId,
|
||||
GroupConfiguration, GroupConfigurationRevision, GroupConfigurationsByFieldId,
|
||||
};
|
||||
use crate::revision::{FilterConfiguration, GroupConfiguration};
|
||||
use nanoid::nanoid;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn gen_grid_view_id() -> String {
|
||||
@ -40,15 +36,15 @@ pub struct GridViewRevision {
|
||||
|
||||
pub layout: LayoutRevision,
|
||||
|
||||
#[serde(default)]
|
||||
pub filters: FilterConfiguration,
|
||||
|
||||
#[serde(default)]
|
||||
pub groups: GroupConfiguration,
|
||||
|
||||
// For the moment, we just use the order returned from the GridRevision
|
||||
#[allow(dead_code)]
|
||||
#[serde(skip, rename = "row")]
|
||||
pub row_orders: Vec<RowOrderRevision>,
|
||||
// // For the moment, we just use the order returned from the GridRevision
|
||||
// #[allow(dead_code)]
|
||||
// #[serde(skip, rename = "rows")]
|
||||
// pub row_orders: Vec<RowOrderRevision>,
|
||||
}
|
||||
|
||||
impl GridViewRevision {
|
||||
@ -59,78 +55,33 @@ impl GridViewRevision {
|
||||
layout: Default::default(),
|
||||
filters: Default::default(),
|
||||
groups: Default::default(),
|
||||
row_orders: vec![],
|
||||
// row_orders: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_groups(&self, field_revs: &[Arc<FieldRevision>]) -> Option<GroupConfigurationsByFieldId> {
|
||||
self.groups.get_all_objects(field_revs)
|
||||
}
|
||||
|
||||
pub fn get_groups(
|
||||
&self,
|
||||
field_id: &str,
|
||||
field_type_rev: &FieldTypeRevision,
|
||||
) -> Option<Arc<GroupConfigurationRevision>> {
|
||||
let mut groups = self.groups.get_objects(field_id, field_type_rev)?;
|
||||
if groups.is_empty() {
|
||||
debug_assert_eq!(groups.len(), 1);
|
||||
Some(groups.pop().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut_groups(
|
||||
&mut self,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
) -> Option<&mut Vec<Arc<GroupConfigurationRevision>>> {
|
||||
self.groups.get_mut_objects(field_id, field_type)
|
||||
}
|
||||
|
||||
pub fn insert_group(
|
||||
&mut self,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
group_rev: GroupConfigurationRevision,
|
||||
) {
|
||||
// only one group can be set
|
||||
self.groups.remove_all();
|
||||
self.groups.insert_object(field_id, field_type, group_rev);
|
||||
}
|
||||
|
||||
pub fn get_all_filters(&self, field_revs: &[Arc<FieldRevision>]) -> Option<FilterConfigurationsByFieldId> {
|
||||
self.filters.get_all_objects(field_revs)
|
||||
}
|
||||
|
||||
pub fn get_filters(
|
||||
&self,
|
||||
field_id: &str,
|
||||
field_type_rev: &FieldTypeRevision,
|
||||
) -> Option<Vec<Arc<FilterConfigurationRevision>>> {
|
||||
self.filters.get_objects(field_id, field_type_rev)
|
||||
}
|
||||
|
||||
pub fn get_mut_filters(
|
||||
&mut self,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
) -> Option<&mut Vec<Arc<FilterConfigurationRevision>>> {
|
||||
self.filters.get_mut_objects(field_id, field_type)
|
||||
}
|
||||
|
||||
pub fn insert_filter(
|
||||
&mut self,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
filter_rev: FilterConfigurationRevision,
|
||||
) {
|
||||
self.filters.insert_object(field_id, field_type, filter_rev);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct RowOrderRevision {
|
||||
pub row_id: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::revision::GridViewRevision;
|
||||
|
||||
#[test]
|
||||
fn grid_view_revision_serde_test() {
|
||||
let grid_view_revision = GridViewRevision {
|
||||
view_id: "1".to_string(),
|
||||
grid_id: "1".to_string(),
|
||||
layout: Default::default(),
|
||||
filters: Default::default(),
|
||||
groups: Default::default(),
|
||||
};
|
||||
let s = serde_json::to_string(&grid_view_revision).unwrap();
|
||||
assert_eq!(
|
||||
s,
|
||||
r#"{"view_id":"1","grid_id":"1","layout":0,"filters":[],"groups":[]}"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,23 @@ pub trait GroupConfigurationContent: Sized {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn mut_groups(&mut self) -> &mut Vec<GroupRecordRevision> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_groups(&mut self, _new_groups: Vec<GroupRecordRevision>) {}
|
||||
|
||||
fn swap_group(&mut self, from_group_id: &str, to_group_id: &str) {
|
||||
let from_index = self
|
||||
.get_groups()
|
||||
.iter()
|
||||
.position(|group| group.group_id == from_group_id);
|
||||
let to_index = self.get_groups().iter().position(|group| group.group_id == to_group_id);
|
||||
if let (Some(from), Some(to)) = (from_index, to_index) {
|
||||
self.mut_groups().swap(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
fn with_mut_group<F>(&mut self, _group_id: &str, _f: F)
|
||||
where
|
||||
F: FnOnce(&mut GroupRecordRevision),
|
||||
@ -120,6 +135,10 @@ impl GroupConfigurationContent for SelectOptionGroupConfigurationRevision {
|
||||
&self.groups
|
||||
}
|
||||
|
||||
fn mut_groups(&mut self) -> &mut Vec<GroupRecordRevision> {
|
||||
&mut self.groups
|
||||
}
|
||||
|
||||
fn set_groups(&mut self, new_groups: Vec<GroupRecordRevision>) {
|
||||
self.groups = new_groups;
|
||||
}
|
||||
|
@ -52,7 +52,26 @@ impl GridViewRevisionPad {
|
||||
self.groups.get_all_objects(field_revs)
|
||||
}
|
||||
|
||||
pub fn get_mut_group<F: FnOnce(&mut GroupConfigurationRevision)>(
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub fn insert_group(
|
||||
&mut self,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
group_rev: GroupConfigurationRevision,
|
||||
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
|
||||
self.modify(|view| {
|
||||
view.groups.insert_object(field_id, field_type, group_rev);
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all)]
|
||||
pub fn contains_group(&self, field_id: &str, field_type: &FieldTypeRevision) -> bool {
|
||||
self.view.groups.get_objects(field_id, field_type).is_some()
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub fn with_mut_group<F: FnOnce(&mut GroupConfigurationRevision)>(
|
||||
&mut self,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
@ -147,6 +166,8 @@ impl GridViewRevisionPad {
|
||||
None => Ok(None),
|
||||
Some(delta) => {
|
||||
self.delta = self.delta.compose(&delta)?;
|
||||
tracing::info!("GridView: {:?}", delta);
|
||||
|
||||
let md5 = md5(&self.delta.json_bytes());
|
||||
Ok(Some(GridViewRevisionChangeset { delta, md5 }))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user