diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart index c853bb867b..4122de9503 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart @@ -163,17 +163,22 @@ class RepeatedFieldOrder extends $pb.GeneratedMessage { class RowOrder extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RowOrder', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') ..hasRequiredFields = false ; RowOrder._() : super(); factory RowOrder({ $core.String? rowId, + $core.String? blockId, }) { final _result = create(); if (rowId != null) { _result.rowId = rowId; } + if (blockId != null) { + _result.blockId = blockId; + } return _result; } factory RowOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -205,6 +210,15 @@ class RowOrder extends $pb.GeneratedMessage { $core.bool hasRowId() => $_has(0); @$pb.TagNumber(1) void clearRowId() => clearField(1); + + @$pb.TagNumber(2) + $core.String get blockId => $_getSZ(1); + @$pb.TagNumber(2) + set blockId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasBlockId() => $_has(1); + @$pb.TagNumber(2) + void clearBlockId() => clearField(2); } class RepeatedRowOrder extends $pb.GeneratedMessage { @@ -360,22 +374,17 @@ class RepeatedRow extends $pb.GeneratedMessage { class Cell extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Cell', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content') + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content') ..hasRequiredFields = false ; Cell._() : super(); factory Cell({ - $core.String? id, $core.String? fieldId, $core.String? content, }) { final _result = create(); - if (id != null) { - _result.id = id; - } if (fieldId != null) { _result.fieldId = fieldId; } @@ -406,31 +415,22 @@ class Cell extends $pb.GeneratedMessage { static Cell? _defaultInstance; @$pb.TagNumber(1) - $core.String get id => $_getSZ(0); + $core.String get fieldId => $_getSZ(0); @$pb.TagNumber(1) - set id($core.String v) { $_setString(0, v); } + set fieldId($core.String v) { $_setString(0, v); } @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); + $core.bool hasFieldId() => $_has(0); @$pb.TagNumber(1) - void clearId() => clearField(1); + void clearFieldId() => clearField(1); @$pb.TagNumber(2) - $core.String get fieldId => $_getSZ(1); + $core.String get content => $_getSZ(1); @$pb.TagNumber(2) - set fieldId($core.String v) { $_setString(1, v); } + set content($core.String v) { $_setString(1, v); } @$pb.TagNumber(2) - $core.bool hasFieldId() => $_has(1); + $core.bool hasContent() => $_has(1); @$pb.TagNumber(2) - void clearFieldId() => clearField(2); - - @$pb.TagNumber(3) - $core.String get content => $_getSZ(2); - @$pb.TagNumber(3) - set content($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasContent() => $_has(2); - @$pb.TagNumber(3) - void clearContent() => clearField(3); + void clearContent() => clearField(2); } class CreateGridPayload extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart index 96bfd55dfd..2c1a16296d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart @@ -45,11 +45,12 @@ const RowOrder$json = const { '1': 'RowOrder', '2': const [ const {'1': 'row_id', '3': 1, '4': 1, '5': 9, '10': 'rowId'}, + const {'1': 'block_id', '3': 2, '4': 1, '5': 9, '10': 'blockId'}, ], }; /// Descriptor for `RowOrder`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List rowOrderDescriptor = $convert.base64Decode('CghSb3dPcmRlchIVCgZyb3dfaWQYASABKAlSBXJvd0lk'); +final $typed_data.Uint8List rowOrderDescriptor = $convert.base64Decode('CghSb3dPcmRlchIVCgZyb3dfaWQYASABKAlSBXJvd0lkEhkKCGJsb2NrX2lkGAIgASgJUgdibG9ja0lk'); @$core.Deprecated('Use repeatedRowOrderDescriptor instead') const RepeatedRowOrder$json = const { '1': 'RepeatedRowOrder', @@ -97,14 +98,13 @@ final $typed_data.Uint8List repeatedRowDescriptor = $convert.base64Decode('CgtSZ const Cell$json = const { '1': 'Cell', '2': const [ - const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'content', '3': 3, '4': 1, '5': 9, '10': 'content'}, + const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'content', '3': 2, '4': 1, '5': 9, '10': 'content'}, ], }; /// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEg4KAmlkGAEgASgJUgJpZBIZCghmaWVsZF9pZBgCIAEoCVIHZmllbGRJZBIYCgdjb250ZW50GAMgASgJUgdjb250ZW50'); +final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhgKB2NvbnRlbnQYAiABKAlSB2NvbnRlbnQ='); @$core.Deprecated('Use createGridPayloadDescriptor instead') const CreateGridPayload$json = const { '1': 'CreateGridPayload', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index 92532babbe..25104afa46 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -897,38 +897,23 @@ class RowMetaChangeset extends $pb.GeneratedMessage { class CellMeta extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CellMeta', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId') - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') - ..aOM(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', subBuilder: AnyData.create) - ..a<$core.int>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'height', $pb.PbFieldType.O3) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data') ..hasRequiredFields = false ; CellMeta._() : super(); factory CellMeta({ - $core.String? id, - $core.String? rowId, $core.String? fieldId, - AnyData? data, - $core.int? height, + $core.String? data, }) { final _result = create(); - if (id != null) { - _result.id = id; - } - if (rowId != null) { - _result.rowId = rowId; - } if (fieldId != null) { _result.fieldId = fieldId; } if (data != null) { _result.data = data; } - if (height != null) { - _result.height = height; - } return _result; } factory CellMeta.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -953,50 +938,21 @@ class CellMeta extends $pb.GeneratedMessage { static CellMeta? _defaultInstance; @$pb.TagNumber(1) - $core.String get id => $_getSZ(0); + $core.String get fieldId => $_getSZ(0); @$pb.TagNumber(1) - set id($core.String v) { $_setString(0, v); } + set fieldId($core.String v) { $_setString(0, v); } @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); + $core.bool hasFieldId() => $_has(0); @$pb.TagNumber(1) - void clearId() => clearField(1); + void clearFieldId() => clearField(1); @$pb.TagNumber(2) - $core.String get rowId => $_getSZ(1); + $core.String get data => $_getSZ(1); @$pb.TagNumber(2) - set rowId($core.String v) { $_setString(1, v); } + set data($core.String v) { $_setString(1, v); } @$pb.TagNumber(2) - $core.bool hasRowId() => $_has(1); + $core.bool hasData() => $_has(1); @$pb.TagNumber(2) - void clearRowId() => clearField(2); - - @$pb.TagNumber(3) - $core.String get fieldId => $_getSZ(2); - @$pb.TagNumber(3) - set fieldId($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasFieldId() => $_has(2); - @$pb.TagNumber(3) - void clearFieldId() => clearField(3); - - @$pb.TagNumber(4) - AnyData get data => $_getN(3); - @$pb.TagNumber(4) - set data(AnyData v) { setField(4, v); } - @$pb.TagNumber(4) - $core.bool hasData() => $_has(3); - @$pb.TagNumber(4) - void clearData() => clearField(4); - @$pb.TagNumber(4) - AnyData ensureData() => $_ensure(3); - - @$pb.TagNumber(5) - $core.int get height => $_getIZ(4); - @$pb.TagNumber(5) - set height($core.int v) { $_setSignedInt32(4, v); } - @$pb.TagNumber(5) - $core.bool hasHeight() => $_has(4); - @$pb.TagNumber(5) - void clearHeight() => clearField(5); + void clearData() => clearField(2); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index 82d830f6e1..322b477e30 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -179,13 +179,10 @@ final $typed_data.Uint8List rowMetaChangesetDescriptor = $convert.base64Decode(' const CellMeta$json = const { '1': 'CellMeta', '2': const [ - const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - const {'1': 'row_id', '3': 2, '4': 1, '5': 9, '10': 'rowId'}, - const {'1': 'field_id', '3': 3, '4': 1, '5': 9, '10': 'fieldId'}, - const {'1': 'data', '3': 4, '4': 1, '5': 11, '6': '.AnyData', '10': 'data'}, - const {'1': 'height', '3': 5, '4': 1, '5': 5, '10': 'height'}, + const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'}, + const {'1': 'data', '3': 2, '4': 1, '5': 9, '10': 'data'}, ], }; /// Descriptor for `CellMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List cellMetaDescriptor = $convert.base64Decode('CghDZWxsTWV0YRIOCgJpZBgBIAEoCVICaWQSFQoGcm93X2lkGAIgASgJUgVyb3dJZBIZCghmaWVsZF9pZBgDIAEoCVIHZmllbGRJZBIcCgRkYXRhGAQgASgLMgguQW55RGF0YVIEZGF0YRIWCgZoZWlnaHQYBSABKAVSBmhlaWdodA=='); +final $typed_data.Uint8List cellMetaDescriptor = $convert.base64Decode('CghDZWxsTWV0YRIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBISCgRkYXRhGAIgASgJUgRkYXRh'); diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 02f9a89206..0861f2aaa1 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -24,7 +24,7 @@ pub(crate) async fn get_rows_handler( ) -> DataResult { let payload: QueryRowPayload = data.into_inner(); let editor = manager.get_grid_editor(&payload.grid_id)?; - let repeated_row = editor.get_rows(payload.row_orders).await?; + let repeated_row: RepeatedRow = editor.get_rows(Some(payload.row_orders)).await?.into(); data_result(repeated_row) } @@ -35,7 +35,7 @@ pub(crate) async fn get_fields_handler( ) -> DataResult { let payload: QueryFieldPayload = data.into_inner(); let editor = manager.get_grid_editor(&payload.grid_id)?; - let repeated_field = editor.get_fields(Some(payload.field_orders)).await?; + let repeated_field: RepeatedField = editor.get_fields(Some(payload.field_orders)).await?.into(); data_result(repeated_field) } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs index 157e5145c2..61b5889e68 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/mod.rs @@ -1,7 +1,5 @@ -mod cell_stringify; mod field_builder; mod type_options; -pub use cell_stringify::*; pub use field_builder::*; pub use type_options::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options.rs index 2b82d94f3a..b192a1e118 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options.rs @@ -1,6 +1,6 @@ #![allow(clippy::upper_case_acronyms)] use crate::impl_from_and_to_type_option; -use crate::services::field::StringifyCellData; +use crate::services::row::StringifyCellData; use crate::services::util::*; use bytes::Bytes; use chrono::format::strftime::StrftimeItems; 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 9b3ce9eecf..4b7250079e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -1,7 +1,7 @@ use crate::manager::GridUser; use crate::services::kv_persistence::{GridKVPersistence, KVTransaction}; -use crate::services::grid_meta_editor::ClientGridBlockMetaEditor; +use crate::services::grid_meta_editor::{ClientGridBlockMetaEditor, GridBlockMetaEditorManager}; use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::client_grid::{GridChange, GridMetaPad}; @@ -9,7 +9,8 @@ use flowy_collaboration::entities::revision::Revision; use flowy_collaboration::util::make_delta_from_revisions; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::{ - Field, FieldChangeset, Grid, GridBlock, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder, + Field, FieldChangeset, Grid, GridBlock, GridBlockChangeset, RepeatedField, RepeatedFieldOrder, RepeatedRow, + RepeatedRowOrder, Row, }; use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence; use flowy_sync::{ @@ -43,7 +44,7 @@ impl ClientGridEditor { let grid_meta_pad = Arc::new(RwLock::new(grid_pad)); let block_meta_manager = - Arc::new(GridBlockMetaEditorManager::new(&user, grid_meta_pad.read().await.get_blocks()).await?); + Arc::new(GridBlockMetaEditorManager::new(&user, grid_meta_pad.read().await.get_blocks().clone()).await?); Ok(Arc::new(Self { grid_id: grid_id.to_owned(), @@ -70,27 +71,60 @@ impl ClientGridEditor { Ok(()) } + pub async fn create_block(&self, grid_block: GridBlock) -> FlowyResult<()> { + let _ = self.modify(|grid| Ok(grid.create_block(grid_block)?)).await?; + Ok(()) + } + + pub async fn update_block(&self, change: GridBlockChangeset) -> FlowyResult<()> { + let _ = self.modify(|grid| Ok(grid.update_block(change)?)).await?; + Ok(()) + } + pub async fn create_row(&self) -> FlowyResult<()> { - todo!() + let fields = self.grid_meta_pad.read().await.get_fields(None)?; + match self.grid_meta_pad.read().await.get_blocks().last() { + None => Err(FlowyError::internal().context("There is no grid block in this grid")), + Some(grid_block) => { + let row_count = self.block_meta_manager.create_row(fields, grid_block).await?; + let change = GridBlockChangeset::from_row_count(&grid_block.id, row_count); + let _ = self.update_block(change).await?; + Ok(()) + } + } } - pub async fn get_rows(&self, _row_orders: RepeatedRowOrder) -> FlowyResult { - todo!() + pub async fn get_rows(&self, row_orders: Option) -> FlowyResult> { + let fields = self.grid_meta_pad.read().await.get_fields(None)?; + let rows = self.block_meta_manager.get_rows(fields, row_orders).await?; + Ok(rows) } - pub async fn delete_rows(&self, _ids: Vec) -> FlowyResult<()> { - todo!() + pub async fn delete_rows(&self, row_orders: Option) -> FlowyResult<()> { + let row_counts = self.block_meta_manager.delete_rows(row_orders).await?; + for (block_id, row_count) in row_counts { + let _ = self + .update_block(GridBlockChangeset::from_row_count(&block_id, row_count)) + .await?; + } + + Ok(()) } pub async fn grid_data(&self) -> Grid { todo!() } - pub async fn get_fields(&self, field_orders: Option) -> FlowyResult { + pub async fn get_fields(&self, field_orders: Option) -> FlowyResult> { let fields = self.grid_meta_pad.read().await.get_fields(field_orders)?; Ok(fields) } + pub async fn get_blocks(&self) -> FlowyResult> { + let grid_blocks = self.grid_meta_pad.read().await.get_blocks(); + Ok(grid_blocks) + } + pub async fn delta_str(&self) -> String { self.grid_meta_pad.read().await.delta_str() } @@ -184,90 +218,3 @@ impl RevisionCompactor for GridRevisionCompactor { Ok(delta.to_bytes()) } } - -struct GridBlockMetaEditorManager { - editor_map: DashMap>, -} - -impl GridBlockMetaEditorManager { - async fn new(user: &Arc, blocks: Vec) -> FlowyResult { - let editor_map = make_block_meta_editor_map(user, blocks).await?; - let manager = Self { editor_map }; - Ok(manager) - } - - async fn get_editor(&self, _block_id: &str) -> Arc { - todo!() - } - - pub async fn get_rows(&self, _row_orders: RepeatedRowOrder) -> FlowyResult { - // let ids = row_orders - // .items - // .into_iter() - // .map(|row_order| row_order.row_id) - // .collect::>(); - // let row_metas: Vec = self.kv_persistence.batch_get(ids)?; - // - // let make_cell = |field_id: String, raw_cell: CellMeta| { - // let some_field = self.field_map.get(&field_id); - // if some_field.is_none() { - // tracing::error!("Can't find the field with {}", field_id); - // return None; - // } - // self.cell_map.insert(raw_cell.id.clone(), raw_cell.clone()); - // - // let field = some_field.unwrap(); - // match stringify_deserialize(raw_cell.data, field.value()) { - // Ok(content) => { - // let cell = Cell { - // id: raw_cell.id, - // field_id: field_id.clone(), - // content, - // }; - // Some((field_id, cell)) - // } - // Err(_) => None, - // } - // }; - // - // let rows = row_metas - // .into_par_iter() - // .map(|row_meta| { - // let mut row = Row { - // id: row_meta.id.clone(), - // cell_by_field_id: Default::default(), - // height: row_meta.height, - // }; - // row.cell_by_field_id = row_meta - // .cell_by_field_id - // .into_par_iter() - // .flat_map(|(field_id, raw_cell)| make_cell(field_id, raw_cell)) - // .collect::>(); - // row - // }) - // .collect::>(); - // - // Ok(rows.into()) - todo!() - } -} - -async fn make_block_meta_editor_map( - user: &Arc, - blocks: Vec, -) -> FlowyResult>> { - let token = user.token()?; - let user_id = user.user_id()?; - let pool = user.db_pool()?; - - let editor_map = DashMap::new(); - for block in blocks { - let disk_cache = Arc::new(SQLiteGridBlockMetaRevisionPersistence::new(&user_id, pool.clone())); - let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, &block.id, disk_cache)); - let rev_manager = RevisionManager::new(&user_id, &block.id, rev_persistence); - let editor = ClientGridBlockMetaEditor::new(&user_id, &token, &block.id, rev_manager).await?; - editor_map.insert(block.id, Arc::new(editor)); - } - - Ok(editor_map) -} diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs index 10160e115a..5358b4cde5 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs @@ -1,15 +1,110 @@ +use crate::manager::GridUser; +use crate::services::row::{make_row_ids_per_block, make_rows, sort_rows, RowBuilder}; use bytes::Bytes; +use dashmap::mapref::one::Ref; +use dashmap::DashMap; use flowy_collaboration::client_grid::{GridBlockMetaChange, GridBlockMetaPad}; use flowy_collaboration::entities::revision::Revision; use flowy_collaboration::util::make_delta_from_revisions; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{RowMeta, RowMetaChangeset}; -use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; +use flowy_grid_data_model::entities::{ + Field, GridBlock, RepeatedRow, RepeatedRowOrder, Row, RowMeta, RowMetaChangeset, +}; +use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence; +use flowy_sync::{ + RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence, +}; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; +use lib_sqlite::ConnectionPool; +use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; +pub(crate) struct GridBlockMetaEditorManager { + user: Arc, + editor_map: DashMap>, +} + +impl GridBlockMetaEditorManager { + pub(crate) async fn new(user: &Arc, blocks: Vec) -> FlowyResult { + let editor_map = make_block_meta_editor_map(user, blocks).await?; + let user = user.clone(); + let manager = Self { user, editor_map }; + Ok(manager) + } + + pub(crate) async fn get_editor(&self, block_id: &str) -> FlowyResult> { + match self.editor_map.get(block_id) { + None => { + tracing::error!("The is a fatal error, block is not exist"); + let editor = Arc::new(make_block_meta_editor(&self.user, block_id).await?); + self.editor_map.insert(block_id.to_owned(), editor.clone()); + Ok(editor) + } + Some(editor) => Ok(editor.clone()), + } + } + + pub(crate) async fn create_row(&self, fields: Vec, grid_block: &GridBlock) -> FlowyResult { + let row = RowBuilder::new(&fields, &grid_block.id).build(); + let editor = self.get_editor(&grid_block.id).await?; + editor.create_row(row).await + } + + pub(crate) async fn delete_rows(&self, row_orders: Option) -> FlowyResult> { + Ok(vec![("".to_owned(), 2)]) + } + + pub(crate) async fn get_rows( + &self, + fields: Vec, + row_orders: Option, + ) -> FlowyResult> { + match row_orders { + None => { + let rows = vec![]; + Ok(rows) + } + Some(row_orders) => { + let row_ids_per_blocks = make_row_ids_per_block(&row_orders); + let mut rows = vec![]; + for row_ids_per_block in row_ids_per_blocks { + let editor = self.get_editor(&row_ids_per_block.block_id).await?; + let row_metas = editor.get_rows(row_ids_per_block.row_ids).await?; + rows.extend(make_rows(&fields, row_metas)); + } + sort_rows(&mut rows, row_orders); + Ok(rows) + } + } + } +} + +async fn make_block_meta_editor_map( + user: &Arc, + blocks: Vec, +) -> FlowyResult>> { + let editor_map = DashMap::new(); + for block in blocks { + let editor = make_block_meta_editor(user, &block.id).await?; + editor_map.insert(block.id, Arc::new(editor)); + } + + Ok(editor_map) +} + +async fn make_block_meta_editor(user: &Arc, block_id: &str) -> FlowyResult { + let token = user.token()?; + let user_id = user.user_id()?; + let pool = user.db_pool()?; + + let disk_cache = Arc::new(SQLiteGridBlockMetaRevisionPersistence::new(&user_id, pool)); + let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, block_id, disk_cache)); + let rev_manager = RevisionManager::new(&user_id, block_id, rev_persistence); + ClientGridBlockMetaEditor::new(&user_id, &token, block_id, rev_manager).await +} + pub struct ClientGridBlockMetaEditor { user_id: String, pub block_id: String, @@ -40,10 +135,17 @@ impl ClientGridBlockMetaEditor { }) } - async fn create_row(&self) -> FlowyResult<()> { - let row = RowMeta::new(&self.block_id, vec![]); - let _ = self.modify(|pad| Ok(pad.add_row(row)?)).await?; - Ok(()) + async fn create_row(&self, row: RowMeta) -> FlowyResult { + let mut row_count = 0; + let _ = self + .modify(|pad| { + let change = pad.add_row(row)?; + row_count = pad.number_of_rows(); + Ok(change) + }) + .await?; + + Ok(row_count) } pub async fn delete_rows(&self, ids: Vec) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-grid/src/services/mod.rs b/frontend/rust-lib/flowy-grid/src/services/mod.rs index 552f8cfe56..0a7918b5d6 100644 --- a/frontend/rust-lib/flowy-grid/src/services/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/mod.rs @@ -4,3 +4,4 @@ pub mod field; pub mod grid_editor; pub mod grid_meta_editor; pub mod kv_persistence; +pub mod row; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/cell_stringify.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_stringify.rs similarity index 100% rename from frontend/rust-lib/flowy-grid/src/services/field/cell_stringify.rs rename to frontend/rust-lib/flowy-grid/src/services/row/cell_stringify.rs diff --git a/frontend/rust-lib/flowy-grid/src/services/row/mod.rs b/frontend/rust-lib/flowy-grid/src/services/row/mod.rs new file mode 100644 index 0000000000..baac627e00 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/row/mod.rs @@ -0,0 +1,7 @@ +mod cell_stringify; +mod row_builder; +mod row_loader; + +pub use cell_stringify::*; +pub use row_builder::*; +pub use row_loader::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs new file mode 100644 index 0000000000..d88b580788 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_builder.rs @@ -0,0 +1,24 @@ +use flowy_grid_data_model::entities::{CellMeta, Field, RowMeta}; + +pub struct RowBuilder<'a> { + fields: &'a Vec, + row: RowMeta, +} + +impl<'a> RowBuilder<'a> { + pub fn new(fields: &'a Vec, block_id: &'a String) -> Self { + let row = RowMeta::new(block_id); + Self { fields, row } + } + + #[allow(dead_code)] + pub fn add_cell(mut self, field_id: &str, data: String) -> Self { + let cell = CellMeta::new(field_id, data); + self.row.cell_by_field_id.insert(field_id.to_owned(), cell); + self + } + + pub fn build(self) -> RowMeta { + self.row + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs new file mode 100644 index 0000000000..f9092a5d89 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -0,0 +1,68 @@ +use flowy_grid_data_model::entities::{Field, RepeatedRowOrder, Row, RowMeta}; +use std::collections::HashMap; + +pub(crate) struct RowIdsPerBlock { + pub(crate) block_id: String, + pub(crate) row_ids: Vec, +} + +pub(crate) fn make_row_ids_per_block(row_orders: &RepeatedRowOrder) -> Vec { + let mut map: HashMap = HashMap::new(); + row_orders.iter().for_each(|row_order| { + let block_id = row_order.block_id.clone(); + let entry = map.entry(block_id.clone()).or_insert(RowIdsPerBlock { + block_id, + row_ids: vec![], + }); + entry.row_ids.push(row_order.row_id.clone()); + }); + map.into_values().collect::>() +} + +pub(crate) fn sort_rows(rows: &mut Vec, row_orders: RepeatedRowOrder) { + todo!() +} + +pub(crate) fn make_rows(fields: &Vec, rows: Vec) -> Vec { + // let make_cell = |field_id: String, raw_cell: CellMeta| { + // let some_field = self.field_map.get(&field_id); + // if some_field.is_none() { + // tracing::error!("Can't find the field with {}", field_id); + // return None; + // } + // self.cell_map.insert(raw_cell.id.clone(), raw_cell.clone()); + // + // let field = some_field.unwrap(); + // match stringify_deserialize(raw_cell.data, field.value()) { + // Ok(content) => { + // let cell = Cell { + // id: raw_cell.id, + // field_id: field_id.clone(), + // content, + // }; + // Some((field_id, cell)) + // } + // Err(_) => None, + // } + // }; + // + // let rows = row_metas + // .into_par_iter() + // .map(|row_meta| { + // let mut row = Row { + // id: row_meta.id.clone(), + // cell_by_field_id: Default::default(), + // height: row_meta.height, + // }; + // row.cell_by_field_id = row_meta + // .cell_by_field_id + // .into_par_iter() + // .flat_map(|(field_id, raw_cell)| make_cell(field_id, raw_cell)) + // .collect::>(); + // row + // }) + // .collect::>(); + // + // Ok(rows.into()) + todo!() +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index cbdb457577..42af2ef4c4 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -1,7 +1,7 @@ use crate::grid::script::EditorScript::*; use crate::grid::script::*; use flowy_grid::services::field::{SelectOption, SingleSelectDescription}; -use flowy_grid_data_model::entities::FieldChangeset; +use flowy_grid_data_model::entities::{FieldChangeset, GridBlock, GridBlockChangeset}; #[tokio::test] async fn default_grid_test() { @@ -35,6 +35,23 @@ async fn grid_create_field() { GridEditorTest::new().await.run_scripts(scripts).await; } +#[tokio::test] +async fn grid_create_duplicate_field() { + let text_field = create_text_field(); + let scripts = vec![ + AssertFieldCount(2), + CreateField { + field: text_field.clone(), + }, + AssertFieldCount(3), + CreateField { + field: text_field.clone(), + }, + AssertFieldCount(3), + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} + #[tokio::test] async fn grid_update_field_with_empty_change() { let single_select_field = create_single_select_field(); @@ -98,3 +115,60 @@ async fn grid_update_field() { ]; GridEditorTest::new().await.run_scripts(scripts).await; } + +#[tokio::test] +async fn grid_delete_field() { + let text_field = create_text_field(); + let scripts = vec![ + CreateField { + field: text_field.clone(), + }, + AssertFieldCount(3), + DeleteField { field: text_field }, + AssertFieldCount(2), + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_create_block() { + let grid_block = GridBlock::new(); + let scripts = vec![ + AssertBlockCount(1), + CreateBlock { block: grid_block }, + AssertBlockCount(2), + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_update_block() { + let grid_block = GridBlock::new(); + let mut cloned_grid_block = grid_block.clone(); + let change = GridBlockChangeset { + block_id: grid_block.id.clone(), + start_row_index: Some(2), + row_count: Some(10), + }; + + cloned_grid_block.start_row_index = 2; + cloned_grid_block.row_count = 10; + + let scripts = vec![ + AssertBlockCount(1), + CreateBlock { block: grid_block }, + UpdateBlock { change }, + AssertBlockCount(2), + AssertBlockEqual { + block_index: 1, + block: cloned_grid_block, + }, + ]; + GridEditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn grid_create_row() { + let scripts = vec![AssertRowCount(2), CreateRow, CreateRow, CreateRow, AssertRowCount(5)]; + GridEditorTest::new().await.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 523e1d4e12..277cd6b4da 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 flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; -use flowy_grid_data_model::entities::{AnyData, Field, FieldChangeset, FieldType}; +use flowy_grid_data_model::entities::{AnyData, Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset}; use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_test::event_builder::FolderEventBuilder; use flowy_test::helper::ViewTest; @@ -12,10 +12,17 @@ use tokio::time::sleep; pub enum EditorScript { CreateField { field: Field }, UpdateField { change: FieldChangeset }, + DeleteField { field: Field }, AssertFieldCount(usize), AssertFieldEqual { field_index: usize, field: Field }, - AssertGridMetaPad, + CreateBlock { block: GridBlock }, + UpdateBlock { change: GridBlockChangeset }, + AssertBlockCount(usize), + AssertBlockEqual { block_index: usize, block: GridBlock }, CreateRow, + AssertRowCount(usize), + // AssertRowEqual{ row_index: usize, row: RowMeta}, + AssertGridMetaPad, } pub struct GridEditorTest { @@ -53,6 +60,9 @@ impl GridEditorTest { EditorScript::UpdateField { change } => { self.editor.update_field(change).await.unwrap(); } + EditorScript::DeleteField { field } => { + self.editor.delete_field(&field.id).await.unwrap(); + } EditorScript::AssertFieldCount(count) => { assert_eq!(self.editor.get_fields(None).await.unwrap().len(), count); } @@ -61,13 +71,32 @@ impl GridEditorTest { let compared_field = repeated_fields[field_index].clone(); assert_eq!(compared_field, field); } + EditorScript::CreateBlock { block } => { + self.editor.create_block(block).await.unwrap(); + } + EditorScript::UpdateBlock { change } => { + self.editor.update_block(change).await.unwrap(); + } + EditorScript::AssertBlockCount(count) => { + assert_eq!(self.editor.get_blocks().await.unwrap().len(), count); + } + EditorScript::AssertBlockEqual { block_index, block } => { + let blocks = self.editor.get_blocks().await.unwrap(); + let compared_block = blocks[block_index].clone(); + assert_eq!(compared_block, block); + } + EditorScript::CreateRow => { + self.editor.create_row().await.unwrap(); + } + EditorScript::AssertRowCount(count) => { + assert_eq!(self.editor.get_rows(None).await.unwrap().len(), count); + } EditorScript::AssertGridMetaPad => { sleep(Duration::from_millis(2 * REVISION_WRITE_INTERVAL_IN_MILLIS)).await; let mut grid_rev_manager = grid_manager.make_grid_rev_manager(&self.grid_id, pool.clone()).unwrap(); let grid_pad = grid_rev_manager.load::(None).await.unwrap(); println!("{}", grid_pad.delta_str()); } - EditorScript::CreateRow => {} } } } diff --git a/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs b/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs index 1252f0d842..b63c667cbd 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs @@ -69,6 +69,10 @@ impl GridBlockMetaPad { .collect::>()) } + pub fn number_of_rows(&self) -> i32 { + self.rows.len() as i32 + } + pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult> { let row_id = changeset.row_id.clone(); self.modify_row(&row_id, |row| { diff --git a/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs b/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs index 30cd8cd2e0..9ba6cc7ff5 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs @@ -31,7 +31,7 @@ impl GridBuilder { } pub fn add_empty_row(mut self) -> Self { - let row = RowMeta::new(&self.grid_block.id, vec![]); + let row = RowMeta::new(&self.grid_block.id); self.grid_block_meta.rows.push(row); self } diff --git a/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs b/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs index 12d1b14c5b..304919a310 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs @@ -36,8 +36,13 @@ impl GridMetaPad { pub fn create_field(&mut self, field: Field) -> CollaborateResult> { self.modify_grid(|grid| { - grid.fields.push(field); - Ok(Some(())) + if grid.fields.contains(&field) { + tracing::warn!("Duplicate grid field"); + Ok(None) + } else { + grid.fields.push(field); + Ok(Some(())) + } }) } @@ -51,7 +56,7 @@ impl GridMetaPad { }) } - pub fn get_fields(&self, field_orders: Option) -> CollaborateResult { + pub fn get_fields(&self, field_orders: Option) -> CollaborateResult> { match field_orders { None => Ok(self.grid_meta.fields.clone().into()), Some(field_orders) => { @@ -72,7 +77,7 @@ impl GridMetaPad { Some(field) => Some((*field).clone()), }) .collect::>(); - Ok(fields.into()) + Ok(fields) } } } @@ -122,8 +127,13 @@ impl GridMetaPad { pub fn create_block(&mut self, block: GridBlock) -> CollaborateResult> { self.modify_grid(|grid| { - grid.blocks.push(block); - Ok(Some(())) + if grid.blocks.iter().find(|b| b.id == block.id).is_some() { + tracing::warn!("Duplicate grid block"); + Ok(None) + } else { + grid.blocks.push(block); + Ok(Some(())) + } }) } @@ -141,6 +151,11 @@ impl GridMetaPad { is_changed = Some(()); } + if let Some(start_row_index) = change.start_row_index { + block.start_row_index = start_row_index; + is_changed = Some(()); + } + Ok(is_changed) }) } diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index 00c3981d79..d2bf2173f3 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -45,11 +45,17 @@ impl std::ops::Deref for RepeatedFieldOrder { pub struct RowOrder { #[pb(index = 1)] pub row_id: String, + + #[pb(index = 2)] + pub block_id: String, } impl std::convert::From<&RowMeta> for RowOrder { fn from(row: &RowMeta) -> Self { - Self { row_id: row.id.clone() } + Self { + row_id: row.id.clone(), + block_id: row.block_id.clone(), + } } } @@ -111,12 +117,9 @@ impl std::convert::From> for RepeatedRow { #[derive(Debug, Default, ProtoBuf)] pub struct Cell { #[pb(index = 1)] - pub id: String, - - #[pb(index = 2)] pub field_id: String, - #[pb(index = 3)] + #[pb(index = 2)] pub content: String, } diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index 8ef8df08e4..2813759448 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -18,7 +18,7 @@ pub struct GridMeta { pub blocks: Vec, } -#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, ProtoBuf)] pub struct GridBlock { #[pb(index = 1)] pub id: String, @@ -45,6 +45,16 @@ pub struct GridBlockChangeset { pub row_count: Option, } +impl GridBlockChangeset { + pub fn from_row_count(block_id: &str, row_count: i32) -> Self { + Self { + block_id: block_id.to_string(), + start_row_index: None, + row_count: Some(row_count), + } + } +} + #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] pub struct GridBlockMeta { #[pb(index = 1)] @@ -225,7 +235,7 @@ impl ToString for AnyData { } } -#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, ProtoBuf)] pub struct RowMeta { #[pb(index = 1)] pub id: String, @@ -244,16 +254,11 @@ pub struct RowMeta { } impl RowMeta { - pub fn new(block_id: &str, cells: Vec) -> Self { - let cell_by_field_id = cells - .into_iter() - .map(|cell| (cell.id.clone(), cell)) - .collect::>(); - + pub fn new(block_id: &str) -> Self { Self { id: uuid::Uuid::new_v4().to_string(), block_id: block_id.to_owned(), - cell_by_field_id, + cell_by_field_id: Default::default(), height: DEFAULT_ROW_HEIGHT, visibility: true, } @@ -275,20 +280,20 @@ pub struct RowMetaChangeset { pub cell_by_field_id: HashMap, } -#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ProtoBuf)] pub struct CellMeta { #[pb(index = 1)] - pub id: String, - - #[pb(index = 2)] - pub row_id: String, - - #[pb(index = 3)] pub field_id: String, - #[pb(index = 4)] - pub data: AnyData, - - #[pb(index = 5)] - pub height: i32, + #[pb(index = 2)] + pub data: String, +} + +impl CellMeta { + pub fn new(field_id: &str, data: String) -> Self { + Self { + field_id: field_id.to_string(), + data, + } + } } diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs index c4f57568e9..e7a7561068 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs @@ -609,6 +609,7 @@ impl ::protobuf::reflect::ProtobufValue for RepeatedFieldOrder { pub struct RowOrder { // message fields pub row_id: ::std::string::String, + pub block_id: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -650,6 +651,32 @@ impl RowOrder { pub fn take_row_id(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) } + + // string block_id = 2; + + + pub fn get_block_id(&self) -> &str { + &self.block_id + } + pub fn clear_block_id(&mut self) { + self.block_id.clear(); + } + + // Param is passed by value, moved + pub fn set_block_id(&mut self, v: ::std::string::String) { + self.block_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_block_id(&mut self) -> &mut ::std::string::String { + &mut self.block_id + } + + // Take field + pub fn take_block_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) + } } impl ::protobuf::Message for RowOrder { @@ -664,6 +691,9 @@ impl ::protobuf::Message for RowOrder { 1 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -679,6 +709,9 @@ impl ::protobuf::Message for RowOrder { if !self.row_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.row_id); } + if !self.block_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.block_id); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -688,6 +721,9 @@ impl ::protobuf::Message for RowOrder { if !self.row_id.is_empty() { os.write_string(1, &self.row_id)?; } + if !self.block_id.is_empty() { + os.write_string(2, &self.block_id)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -731,6 +767,11 @@ impl ::protobuf::Message for RowOrder { |m: &RowOrder| { &m.row_id }, |m: &mut RowOrder| { &mut m.row_id }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "block_id", + |m: &RowOrder| { &m.block_id }, + |m: &mut RowOrder| { &mut m.block_id }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "RowOrder", fields, @@ -748,6 +789,7 @@ impl ::protobuf::Message for RowOrder { impl ::protobuf::Clear for RowOrder { fn clear(&mut self) { self.row_id.clear(); + self.block_id.clear(); self.unknown_fields.clear(); } } @@ -1330,7 +1372,6 @@ impl ::protobuf::reflect::ProtobufValue for RepeatedRow { #[derive(PartialEq,Clone,Default)] pub struct Cell { // message fields - pub id: ::std::string::String, pub field_id: ::std::string::String, pub content: ::std::string::String, // special fields @@ -1349,33 +1390,7 @@ impl Cell { ::std::default::Default::default() } - // string id = 1; - - - pub fn get_id(&self) -> &str { - &self.id - } - pub fn clear_id(&mut self) { - self.id.clear(); - } - - // Param is passed by value, moved - pub fn set_id(&mut self, v: ::std::string::String) { - self.id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_id(&mut self) -> &mut ::std::string::String { - &mut self.id - } - - // Take field - pub fn take_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.id, ::std::string::String::new()) - } - - // string field_id = 2; + // string field_id = 1; pub fn get_field_id(&self) -> &str { @@ -1401,7 +1416,7 @@ impl Cell { ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) } - // string content = 3; + // string content = 2; pub fn get_content(&self) -> &str { @@ -1438,12 +1453,9 @@ impl ::protobuf::Message for Cell { let (field_number, wire_type) = is.read_tag_unpack()?; match field_number { 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; - }, - 2 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; }, - 3 => { + 2 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.content)?; }, _ => { @@ -1458,14 +1470,11 @@ impl ::protobuf::Message for Cell { #[allow(unused_variables)] fn compute_size(&self) -> u32 { let mut my_size = 0; - if !self.id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.id); - } if !self.field_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.field_id); + my_size += ::protobuf::rt::string_size(1, &self.field_id); } if !self.content.is_empty() { - my_size += ::protobuf::rt::string_size(3, &self.content); + my_size += ::protobuf::rt::string_size(2, &self.content); } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -1473,14 +1482,11 @@ impl ::protobuf::Message for Cell { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.id.is_empty() { - os.write_string(1, &self.id)?; - } if !self.field_id.is_empty() { - os.write_string(2, &self.field_id)?; + os.write_string(1, &self.field_id)?; } if !self.content.is_empty() { - os.write_string(3, &self.content)?; + os.write_string(2, &self.content)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -1520,11 +1526,6 @@ impl ::protobuf::Message for Cell { static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; descriptor.get(|| { let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "id", - |m: &Cell| { &m.id }, - |m: &mut Cell| { &mut m.id }, - )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "field_id", |m: &Cell| { &m.field_id }, @@ -1551,7 +1552,6 @@ impl ::protobuf::Message for Cell { impl ::protobuf::Clear for Cell { fn clear(&mut self) { - self.id.clear(); self.field_id.clear(); self.content.clear(); self.unknown_fields.clear(); @@ -2326,17 +2326,17 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ders\x12(\n\nrow_orders\x18\x03\x20\x03(\x0b2\t.RowOrderR\trowOrders\"'\ \n\nFieldOrder\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"7\n\ \x12RepeatedFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOr\ - derR\x05items\"!\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\ - \x05rowId\"3\n\x10RepeatedRowOrder\x12\x1f\n\x05items\x18\x01\x20\x03(\ - \x0b2\t.RowOrderR\x05items\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\ - \x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.\ - Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\ - \x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\ - \x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.Cel\ - lR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\ - \x03(\x0b2\x04.RowR\x05items\"K\n\x04Cell\x12\x0e\n\x02id\x18\x01\x20\ - \x01(\tR\x02id\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12\ - \x18\n\x07content\x18\x03\x20\x01(\tR\x07content\"'\n\x11CreateGridPaylo\ + derR\x05items\"<\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\ + \x05rowId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\"3\n\x10R\ + epeatedRowOrder\x12\x1f\n\x05items\x18\x01\x20\x03(\x0b2\t.RowOrderR\x05\ + items\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12@\ + \n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\ + \rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\ + \n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\ + \x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\ + \x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05ite\ + ms\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\ + \x18\n\x07content\x18\x02\x20\x01(\tR\x07content\"'\n\x11CreateGridPaylo\ ad\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\ \x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"d\n\x11QueryFieldPayload\ \x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orde\ diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index cd222c2868..a9fccf6d54 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -2758,11 +2758,8 @@ impl ::protobuf::reflect::ProtobufValue for RowMetaChangeset { #[derive(PartialEq,Clone,Default)] pub struct CellMeta { // message fields - pub id: ::std::string::String, - pub row_id: ::std::string::String, pub field_id: ::std::string::String, - pub data: ::protobuf::SingularPtrField, - pub height: i32, + pub data: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -2779,59 +2776,7 @@ impl CellMeta { ::std::default::Default::default() } - // string id = 1; - - - pub fn get_id(&self) -> &str { - &self.id - } - pub fn clear_id(&mut self) { - self.id.clear(); - } - - // Param is passed by value, moved - pub fn set_id(&mut self, v: ::std::string::String) { - self.id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_id(&mut self) -> &mut ::std::string::String { - &mut self.id - } - - // Take field - pub fn take_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.id, ::std::string::String::new()) - } - - // string row_id = 2; - - - pub fn get_row_id(&self) -> &str { - &self.row_id - } - pub fn clear_row_id(&mut self) { - self.row_id.clear(); - } - - // Param is passed by value, moved - pub fn set_row_id(&mut self, v: ::std::string::String) { - self.row_id = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_row_id(&mut self) -> &mut ::std::string::String { - &mut self.row_id - } - - // Take field - pub fn take_row_id(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.row_id, ::std::string::String::new()) - } - - // string field_id = 3; + // string field_id = 1; pub fn get_field_id(&self) -> &str { @@ -2857,62 +2802,35 @@ impl CellMeta { ::std::mem::replace(&mut self.field_id, ::std::string::String::new()) } - // .AnyData data = 4; + // string data = 2; - pub fn get_data(&self) -> &AnyData { - self.data.as_ref().unwrap_or_else(|| ::default_instance()) + pub fn get_data(&self) -> &str { + &self.data } pub fn clear_data(&mut self) { self.data.clear(); } - pub fn has_data(&self) -> bool { - self.data.is_some() - } - // Param is passed by value, moved - pub fn set_data(&mut self, v: AnyData) { - self.data = ::protobuf::SingularPtrField::some(v); + pub fn set_data(&mut self, v: ::std::string::String) { + self.data = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_data(&mut self) -> &mut AnyData { - if self.data.is_none() { - self.data.set_default(); - } - self.data.as_mut().unwrap() + pub fn mut_data(&mut self) -> &mut ::std::string::String { + &mut self.data } // Take field - pub fn take_data(&mut self) -> AnyData { - self.data.take().unwrap_or_else(|| AnyData::new()) - } - - // int32 height = 5; - - - pub fn get_height(&self) -> i32 { - self.height - } - pub fn clear_height(&mut self) { - self.height = 0; - } - - // Param is passed by value, moved - pub fn set_height(&mut self, v: i32) { - self.height = v; + pub fn take_data(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.data, ::std::string::String::new()) } } impl ::protobuf::Message for CellMeta { fn is_initialized(&self) -> bool { - for v in &self.data { - if !v.is_initialized() { - return false; - } - }; true } @@ -2921,23 +2839,10 @@ impl ::protobuf::Message for CellMeta { let (field_number, wire_type) = is.read_tag_unpack()?; match field_number { 1 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; - }, - 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?; - }, - 3 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?; }, - 4 => { - ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.data)?; - }, - 5 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - let tmp = is.read_int32()?; - self.height = tmp; + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -2951,21 +2856,11 @@ impl ::protobuf::Message for CellMeta { #[allow(unused_variables)] fn compute_size(&self) -> u32 { let mut my_size = 0; - if !self.id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.id); - } - if !self.row_id.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.row_id); - } if !self.field_id.is_empty() { - my_size += ::protobuf::rt::string_size(3, &self.field_id); + my_size += ::protobuf::rt::string_size(1, &self.field_id); } - if let Some(ref v) = self.data.as_ref() { - let len = v.compute_size(); - my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; - } - if self.height != 0 { - my_size += ::protobuf::rt::value_size(5, self.height, ::protobuf::wire_format::WireTypeVarint); + if !self.data.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.data); } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -2973,22 +2868,11 @@ impl ::protobuf::Message for CellMeta { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if !self.id.is_empty() { - os.write_string(1, &self.id)?; - } - if !self.row_id.is_empty() { - os.write_string(2, &self.row_id)?; - } if !self.field_id.is_empty() { - os.write_string(3, &self.field_id)?; + os.write_string(1, &self.field_id)?; } - if let Some(ref v) = self.data.as_ref() { - os.write_tag(4, ::protobuf::wire_format::WireTypeLengthDelimited)?; - os.write_raw_varint32(v.get_cached_size())?; - v.write_to_with_cached_sizes(os)?; - } - if self.height != 0 { - os.write_int32(5, self.height)?; + if !self.data.is_empty() { + os.write_string(2, &self.data)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -3028,31 +2912,16 @@ impl ::protobuf::Message for CellMeta { static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; descriptor.get(|| { let mut fields = ::std::vec::Vec::new(); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "id", - |m: &CellMeta| { &m.id }, - |m: &mut CellMeta| { &mut m.id }, - )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "row_id", - |m: &CellMeta| { &m.row_id }, - |m: &mut CellMeta| { &mut m.row_id }, - )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "field_id", |m: &CellMeta| { &m.field_id }, |m: &mut CellMeta| { &mut m.field_id }, )); - fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "data", |m: &CellMeta| { &m.data }, |m: &mut CellMeta| { &mut m.data }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>( - "height", - |m: &CellMeta| { &m.height }, - |m: &mut CellMeta| { &mut m.height }, - )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CellMeta", fields, @@ -3069,11 +2938,8 @@ impl ::protobuf::Message for CellMeta { impl ::protobuf::Clear for CellMeta { fn clear(&mut self) { - self.id.clear(); - self.row_id.clear(); self.field_id.clear(); self.data.clear(); - self.height = 0; self.unknown_fields.clear(); } } @@ -3191,14 +3057,12 @@ static file_descriptor_proto_data: &'static [u8] = b"\ field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rce\ llByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\ \x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05\ - value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"\x82\ - \x01\n\x08CellMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x15\n\ - \x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\ - \x20\x01(\tR\x07fieldId\x12\x1c\n\x04data\x18\x04\x20\x01(\x0b2\x08.AnyD\ - ataR\x04data\x12\x16\n\x06height\x18\x05\x20\x01(\x05R\x06height*d\n\tFi\ - eldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\ - \x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMult\ - iSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\ + value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"9\n\ + \x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\ + \x12\n\x04data\x18\x02\x20\x01(\tR\x04data*d\n\tFieldType\x12\x0c\n\x08R\ + ichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\ + \x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\ + \x0c\n\x08Checkbox\x10\x05b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index b8577c6e3c..4e395edc92 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto @@ -13,6 +13,7 @@ message RepeatedFieldOrder { } message RowOrder { string row_id = 1; + string block_id = 2; } message RepeatedRowOrder { repeated RowOrder items = 1; @@ -26,9 +27,8 @@ message RepeatedRow { repeated Row items = 1; } message Cell { - string id = 1; - string field_id = 2; - string content = 3; + string field_id = 1; + string content = 2; } message CreateGridPayload { string name = 1; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 503284f7b5..190c400f04 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -55,11 +55,8 @@ message RowMetaChangeset { map cell_by_field_id = 4; } message CellMeta { - string id = 1; - string row_id = 2; - string field_id = 3; - AnyData data = 4; - int32 height = 5; + string field_id = 1; + string data = 2; } enum FieldType { RichText = 0;