diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index beac8ddc0c..d02b2d59ca 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -30,6 +30,17 @@ pub(crate) async fn get_grid_setting_handler( data_result(grid_setting) } +#[tracing::instrument(level = "trace", skip(data, manager), err)] +pub(crate) async fn update_grid_setting_handler( + data: Data, + manager: AppData>, +) -> Result<(), FlowyError> { + let params: GridSettingChangesetParams = data.into_inner().try_into()?; + let editor = manager.open_grid(¶ms.grid_id).await?; + let _ = editor.update_grid_setting(params).await?; + Ok(()) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_grid_blocks_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index 8e30ba6051..166ac9eea3 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -11,6 +11,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetGridData, get_grid_data_handler) .event(GridEvent::GetGridBlocks, get_grid_blocks_handler) .event(GridEvent::GetGridSetting, get_grid_setting_handler) + .event(GridEvent::UpdateGridSetting, get_grid_setting_handler) // Field .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) @@ -53,6 +54,9 @@ pub enum GridEvent { #[event(input = "GridId", output = "GridSetting")] GetGridSetting = 2, + #[event(input = "GridId", input = "GridSettingChangesetPayload")] + UpdateGridSetting = 3, + #[event(input = "QueryFieldPayload", output = "RepeatedField")] GetFields = 10, diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 12ebd1b74a..1930417fc4 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -1,4 +1,4 @@ -use crate::services::grid_editor::GridMetaEditor; +use crate::services::grid_editor::GridRevisionEditor; use crate::services::persistence::block_index::BlockIndexCache; use crate::services::persistence::kv::GridKVPersistence; use crate::services::persistence::GridDatabase; @@ -6,7 +6,7 @@ use bytes::Bytes; use dashmap::DashMap; use flowy_database::ConnectionPool; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::revision::{BuildGridContext, GridInfoRevision, GridRevision}; +use flowy_grid_data_model::revision::{BuildGridContext, GridRevision, GridSettingRevision}; use flowy_revision::disk::{SQLiteGridBlockMetaRevisionPersistence, SQLiteGridRevisionPersistence}; use flowy_revision::{RevisionManager, RevisionPersistence, RevisionWebSocket}; use flowy_sync::client_grid::{make_block_meta_delta, make_grid_delta}; @@ -20,7 +20,7 @@ pub trait GridUser: Send + Sync { } pub struct GridManager { - editor_map: Arc>>, + editor_map: Arc>>, grid_user: Arc, block_index_cache: Arc, #[allow(dead_code)] @@ -67,7 +67,7 @@ impl GridManager { } #[tracing::instrument(level = "debug", skip_all, fields(grid_id), err)] - pub async fn open_grid>(&self, grid_id: T) -> FlowyResult> { + pub async fn open_grid>(&self, grid_id: T) -> FlowyResult> { let grid_id = grid_id.as_ref(); tracing::Span::current().record("grid_id", &grid_id); self.get_or_create_grid_editor(grid_id).await @@ -92,14 +92,14 @@ impl GridManager { // pub fn update_grid_info() // #[tracing::instrument(level = "debug", skip(self), err)] - pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult> { + pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult> { match self.editor_map.get(grid_id) { None => Err(FlowyError::internal().context("Should call open_grid function first")), Some(editor) => Ok(editor.clone()), } } - async fn get_or_create_grid_editor(&self, grid_id: &str) -> FlowyResult> { + async fn get_or_create_grid_editor(&self, grid_id: &str) -> FlowyResult> { match self.editor_map.get(grid_id) { None => { tracing::trace!("Create grid editor with id: {}", grid_id); @@ -121,10 +121,10 @@ impl GridManager { &self, grid_id: &str, pool: Arc, - ) -> Result, FlowyError> { + ) -> Result, FlowyError> { let user = self.grid_user.clone(); let rev_manager = self.make_grid_rev_manager(grid_id, pool.clone())?; - let grid_editor = GridMetaEditor::new(grid_id, user, rev_manager, self.block_index_cache.clone()).await?; + let grid_editor = GridRevisionEditor::new(grid_id, user, rev_manager, self.block_index_cache.clone()).await?; Ok(grid_editor) } @@ -160,7 +160,7 @@ pub async fn make_grid_view_data( grid_id: view_id.to_string(), fields: build_context.field_revs, blocks: build_context.blocks, - info: GridInfoRevision::default(), + setting: GridSettingRevision::default(), }; // Create grid diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index f78c185f26..33d260f1d3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -20,7 +20,7 @@ use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; -pub struct GridMetaEditor { +pub struct GridRevisionEditor { grid_id: String, user: Arc, grid_pad: Arc>, @@ -28,13 +28,13 @@ pub struct GridMetaEditor { block_manager: Arc, } -impl Drop for GridMetaEditor { +impl Drop for GridRevisionEditor { fn drop(&mut self) { tracing::trace!("Drop GridMetaEditor"); } } -impl GridMetaEditor { +impl GridRevisionEditor { pub async fn new( grid_id: &str, user: Arc, @@ -46,7 +46,7 @@ impl GridMetaEditor { let grid_pad = rev_manager.load::(Some(cloud)).await?; let rev_manager = Arc::new(rev_manager); let grid_pad = Arc::new(RwLock::new(grid_pad)); - let blocks = grid_pad.read().await.get_block_metas(); + let blocks = grid_pad.read().await.get_block_revs(); let block_meta_manager = Arc::new(GridBlockManager::new(grid_id, &user, blocks, persistence).await?); Ok(Arc::new(Self { @@ -165,13 +165,15 @@ impl GridMetaEditor { pub async fn replace_field(&self, field_rev: FieldRevision) -> FlowyResult<()> { let field_id = field_rev.id.clone(); - let _ = self.modify(|pad| Ok(pad.replace_field_rev(field_rev)?)).await?; + let _ = self + .modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev)?)) + .await?; let _ = self.notify_did_update_grid_field(&field_id).await?; Ok(()) } pub async fn delete_field(&self, field_id: &str) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.delete_field_rev(field_id)?)).await?; + let _ = self.modify(|grid_pad| Ok(grid_pad.delete_field_rev(field_id)?)).await?; let field_order = FieldOrder::from(field_id); let notified_changeset = GridFieldChangeset::delete(&self.grid_id, vec![field_order]); let _ = self.notify_did_update_grid(notified_changeset).await?; @@ -242,12 +244,16 @@ impl GridMetaEditor { } pub async fn create_block(&self, grid_block: GridBlockRevision) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.create_block_meta(grid_block)?)).await?; + let _ = self + .modify(|grid_pad| Ok(grid_pad.create_block_rev(grid_block)?)) + .await?; Ok(()) } pub async fn update_block(&self, changeset: GridBlockRevisionChangeset) -> FlowyResult<()> { - let _ = self.modify(|grid| Ok(grid.update_block_meta(changeset)?)).await?; + let _ = self + .modify(|grid_pad| Ok(grid_pad.update_block_rev(changeset)?)) + .await?; Ok(()) } @@ -400,7 +406,7 @@ impl GridMetaEditor { } pub async fn get_block_metas(&self) -> FlowyResult> { - let grid_blocks = self.grid_pad.read().await.get_block_metas(); + let grid_blocks = self.grid_pad.read().await.get_block_revs(); Ok(grid_blocks) } @@ -416,7 +422,7 @@ impl GridMetaEditor { let pad_read_guard = self.grid_pad.read().await; let field_orders = pad_read_guard.get_field_orders(); let mut block_orders = vec![]; - for block_order in pad_read_guard.get_block_metas() { + for block_order in pad_read_guard.get_block_revs() { let row_orders = self.block_manager.get_row_orders(&block_order.block_id).await?; let block_order = GridBlockOrder { block_id: block_order.block_id, @@ -433,7 +439,16 @@ impl GridMetaEditor { } pub async fn get_grid_setting(&self) -> FlowyResult { - todo!() + let pad_read_guard = self.grid_pad.read().await; + let grid_setting_rev = pad_read_guard.get_grid_setting_rev(); + Ok(grid_setting_rev.into()) + } + + pub async fn update_grid_setting(&self, params: GridSettingChangesetParams) -> FlowyResult<()> { + let _ = self + .modify(|grid_pad| Ok(grid_pad.update_grid_setting_rev(params)?)) + .await?; + Ok(()) } pub async fn grid_block_snapshots(&self, block_ids: Option>) -> FlowyResult> { @@ -442,7 +457,7 @@ impl GridMetaEditor { .grid_pad .read() .await - .get_block_metas() + .get_block_revs() .into_iter() .map(|block_meta| block_meta.block_id) .collect::>(), @@ -492,7 +507,7 @@ impl GridMetaEditor { pub async fn duplicate_grid(&self) -> FlowyResult { let grid_pad = self.grid_pad.read().await; - let original_blocks = grid_pad.get_block_metas(); + let original_blocks = grid_pad.get_block_revs(); let (duplicated_fields, duplicated_blocks) = grid_pad.duplicate_grid_meta().await; let mut blocks_meta_data = vec![]; @@ -551,7 +566,7 @@ impl GridMetaEditor { } async fn block_id(&self) -> FlowyResult { - match self.grid_pad.read().await.get_block_metas().last() { + match self.grid_pad.read().await.get_block_revs().last() { None => Err(FlowyError::internal().context("There is no grid block in this grid")), Some(grid_block) => Ok(grid_block.block_id.clone()), } @@ -597,7 +612,7 @@ impl GridMetaEditor { } #[cfg(feature = "flowy_unit_test")] -impl GridMetaEditor { +impl GridRevisionEditor { pub fn rev_manager(&self) -> Arc { self.rev_manager.clone() } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index ec46976b0d..a6e7d1fc2c 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -1,6 +1,6 @@ use bytes::Bytes; use flowy_grid::services::field::*; -use flowy_grid::services::grid_editor::{GridMetaEditor, GridPadBuilder}; +use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ CellChangeset, Field, FieldChangesetParams, FieldOrder, FieldType, InsertFieldParams, RowOrder, @@ -75,7 +75,7 @@ pub enum EditorScript { pub struct GridEditorTest { pub sdk: FlowySDKTest, pub grid_id: String, - pub editor: Arc, + pub editor: Arc, pub field_revs: Vec, pub grid_block_revs: Vec, pub row_revs: Vec>, @@ -101,9 +101,9 @@ impl GridEditorTest { sdk, grid_id, editor, - field_revs: field_revs, + field_revs, grid_block_revs: grid_blocks, - row_revs: row_revs, + row_revs, field_count: FieldType::COUNT, row_order_by_row_id: HashMap::default(), } @@ -239,7 +239,7 @@ impl GridEditorTest { } } -async fn get_row_revs(editor: &Arc) -> Vec> { +async fn get_row_revs(editor: &Arc) -> Vec> { editor.grid_block_snapshots(None).await.unwrap().pop().unwrap().row_revs } diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs b/shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs index 64b094aabf..ef96bf0714 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid_setting.rs @@ -69,7 +69,7 @@ pub struct GridSettingChangesetPayload { } pub struct GridSettingChangesetParams { - pub view_id: String, + pub grid_id: String, pub layout_type: GridLayoutType, pub filter: Option, pub group: Option, @@ -100,7 +100,7 @@ impl TryInto for GridSettingChangesetPayload { }; Ok(GridSettingChangesetParams { - view_id, + grid_id: view_id, layout_type: self.layout_type, filter, group, diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs index 24a5721cc4..163d44eeba 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_info_rev.rs @@ -5,7 +5,7 @@ use serde_repr::*; use std::collections::HashMap; #[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct GridInfoRevision { +pub struct GridSettingRevision { #[serde(with = "indexmap::serde_seq")] pub filter: IndexMap, @@ -36,6 +36,24 @@ impl std::default::Default for GridLayoutRevision { } } +impl std::convert::From for GridLayoutType { + fn from(rev: GridLayoutRevision) -> Self { + match rev { + GridLayoutRevision::Table => GridLayoutType::Table, + GridLayoutRevision::Board => GridLayoutType::Board, + } + } +} + +impl std::convert::From for GridLayoutRevision { + fn from(layout: GridLayoutType) -> Self { + match layout { + GridLayoutType::Table => GridLayoutRevision::Table, + GridLayoutType::Board => GridLayoutRevision::Board, + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct GridFilterRevision { pub field_id: Option, @@ -49,7 +67,7 @@ pub struct GridGroupRevision { #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct GridSortRevision { - field_id: Option, + pub field_id: Option, } impl std::convert::From for GridFilter { @@ -73,17 +91,8 @@ impl std::convert::From for GridSort { } } -impl std::convert::From for GridLayoutType { - fn from(rev: GridLayoutRevision) -> Self { - match rev { - GridLayoutRevision::Table => GridLayoutType::Table, - GridLayoutRevision::Board => GridLayoutType::Board, - } - } -} - -impl std::convert::From for GridSetting { - fn from(rev: GridInfoRevision) -> Self { +impl std::convert::From for GridSetting { + fn from(rev: GridSettingRevision) -> Self { let filter: HashMap = rev .filter .into_iter() diff --git a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs index 641cd3d6e0..669dcc48ec 100644 --- a/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs +++ b/shared-lib/flowy-grid-data-model/src/revision/grid_rev.rs @@ -1,5 +1,5 @@ use crate::entities::{CellChangeset, Field, FieldOrder, FieldType, RowOrder}; -use crate::revision::GridInfoRevision; +use crate::revision::GridSettingRevision; use bytes::Bytes; use indexmap::IndexMap; use nanoid::nanoid; @@ -31,9 +31,7 @@ pub struct GridRevision { pub grid_id: String, pub fields: Vec, pub blocks: Vec, - - #[serde(default, skip)] - pub info: GridInfoRevision, + pub setting: GridSettingRevision, } impl GridRevision { @@ -42,7 +40,7 @@ impl GridRevision { grid_id: grid_id.to_owned(), fields: vec![], blocks: vec![], - info: GridInfoRevision::default(), + setting: GridSettingRevision::default(), } } } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs index 101acf594e..ade4ddfa53 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_builder.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_builder.rs @@ -79,7 +79,7 @@ mod tests { grid_id, fields: build_context.field_revs, blocks: build_context.blocks, - info: Default::default(), + setting: Default::default(), }; let grid_meta_delta = make_grid_delta(&grid_rev); diff --git a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs index 98a5fe9f58..62de70f16d 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs @@ -2,10 +2,11 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; use bytes::Bytes; -use flowy_grid_data_model::entities::FieldType; use flowy_grid_data_model::entities::{FieldChangesetParams, FieldOrder}; +use flowy_grid_data_model::entities::{FieldType, GridSettingChangesetParams}; use flowy_grid_data_model::revision::{ - gen_block_id, gen_grid_id, FieldRevision, GridBlockRevision, GridBlockRevisionChangeset, GridRevision, + gen_block_id, gen_grid_id, FieldRevision, GridBlockRevision, GridBlockRevisionChangeset, GridFilterRevision, + GridGroupRevision, GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision, }; use lib_infra::util::move_vec_element; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; @@ -279,7 +280,7 @@ impl GridRevisionPad { } } - pub fn create_block_meta(&mut self, block: GridBlockRevision) -> CollaborateResult> { + pub fn create_block_rev(&mut self, block: GridBlockRevision) -> CollaborateResult> { self.modify_grid(|grid_meta| { if grid_meta.blocks.iter().any(|b| b.block_id == block.block_id) { tracing::warn!("Duplicate grid block"); @@ -302,11 +303,11 @@ impl GridRevisionPad { }) } - pub fn get_block_metas(&self) -> Vec { + pub fn get_block_revs(&self) -> Vec { self.grid_rev.blocks.clone() } - pub fn update_block_meta( + pub fn update_block_rev( &mut self, changeset: GridBlockRevisionChangeset, ) -> CollaborateResult> { @@ -328,6 +329,53 @@ impl GridRevisionPad { }) } + pub fn get_grid_setting_rev(&self) -> GridSettingRevision { + self.grid_rev.setting.clone() + } + + pub fn update_grid_setting_rev( + &mut self, + changeset: GridSettingChangesetParams, + ) -> CollaborateResult> { + self.modify_grid(|grid_rev| { + let mut is_changed = None; + let layout_rev: GridLayoutRevision = changeset.layout_type.into(); + + if let Some(filter) = changeset.filter { + grid_rev.setting.filter.insert( + layout_rev.clone(), + GridFilterRevision { + field_id: filter.field_id, + }, + ); + is_changed = Some(()) + } + + if let Some(group) = changeset.group { + grid_rev.setting.group.insert( + layout_rev.clone(), + GridGroupRevision { + group_field_id: group.group_field_id, + sub_group_field_id: group.sub_group_field_id, + }, + ); + is_changed = Some(()) + } + + if let Some(sort) = changeset.sort { + grid_rev.setting.sort.insert( + layout_rev.clone(), + GridSortRevision { + field_id: sort.field_id, + }, + ); + is_changed = Some(()) + } + + Ok(is_changed) + }) + } + pub fn md5(&self) -> String { md5(&self.delta.to_delta_bytes()) } @@ -365,32 +413,32 @@ impl GridRevisionPad { } } - pub fn modify_block(&mut self, block_id: &str, f: F) -> CollaborateResult> + fn modify_block(&mut self, block_id: &str, f: F) -> CollaborateResult> where F: FnOnce(&mut GridBlockRevision) -> CollaborateResult>, { self.modify_grid( - |grid_meta| match grid_meta.blocks.iter().position(|block| block.block_id == block_id) { + |grid_rev| match grid_rev.blocks.iter().position(|block| block.block_id == block_id) { None => { tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id); Ok(None) } - Some(index) => f(&mut grid_meta.blocks[index]), + Some(index) => f(&mut grid_rev.blocks[index]), }, ) } - pub fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> + fn modify_field(&mut self, field_id: &str, f: F) -> CollaborateResult> where F: FnOnce(&mut FieldRevision) -> CollaborateResult>, { self.modify_grid( - |grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) { + |grid_rev| match grid_rev.fields.iter().position(|field| field.id == field_id) { None => { tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id); Ok(None) } - Some(index) => f(&mut grid_meta.fields[index]), + Some(index) => f(&mut grid_rev.fields[index]), }, ) }