From e0b969595cae57835333529d9c75b74041628259 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 1 Apr 2022 16:38:51 +0800 Subject: [PATCH] chore: save type option data as map --- .../flowy-grid-data-model/meta.pb.dart | 59 +++- .../flowy-grid-data-model/meta.pbjson.dart | 25 +- .../rust-lib/flowy-grid/src/event_handler.rs | 8 +- frontend/rust-lib/flowy-grid/src/macros.rs | 84 ++--- .../src/services/field/field_builder.rs | 54 ++-- .../type_options/checkbox_type_option.rs | 25 +- .../field/type_options/date_type_option.rs | 19 +- .../src/services/field/type_options/mod.rs | 1 + .../field/type_options/number_type_option.rs | 16 +- .../type_options/selection_type_option.rs | 28 +- .../field/type_options/text_type_option.rs | 16 +- .../field/type_options/type_option_data.rs | 9 + .../flowy-grid/src/services/grid_editor.rs | 20 +- .../src/services/row/cell_data_serde.rs | 32 +- .../rust-lib/flowy-grid/tests/grid/script.rs | 2 +- .../src/entities/meta.rs | 57 +++- .../src/protobuf/model/meta.rs | 295 ++++++++++++++---- .../src/protobuf/proto/meta.proto | 5 +- .../src/client_grid/grid_meta_pad.rs | 4 +- 19 files changed, 524 insertions(+), 235 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs 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 bc29686021..c391040543 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 @@ -215,7 +215,7 @@ class FieldMeta extends $pb.GeneratedMessage { ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3) - ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionJson') + ..aOM(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionByFieldTypeId', subBuilder: TypeOptionDataByFieldTypeId.create) ..hasRequiredFields = false ; @@ -228,7 +228,7 @@ class FieldMeta extends $pb.GeneratedMessage { $core.bool? frozen, $core.bool? visibility, $core.int? width, - $core.String? typeOptionJson, + TypeOptionDataByFieldTypeId? typeOptionByFieldTypeId, }) { final _result = create(); if (id != null) { @@ -252,8 +252,8 @@ class FieldMeta extends $pb.GeneratedMessage { if (width != null) { _result.width = width; } - if (typeOptionJson != null) { - _result.typeOptionJson = typeOptionJson; + if (typeOptionByFieldTypeId != null) { + _result.typeOptionByFieldTypeId = typeOptionByFieldTypeId; } return _result; } @@ -342,13 +342,56 @@ class FieldMeta extends $pb.GeneratedMessage { void clearWidth() => clearField(7); @$pb.TagNumber(8) - $core.String get typeOptionJson => $_getSZ(7); + TypeOptionDataByFieldTypeId get typeOptionByFieldTypeId => $_getN(7); @$pb.TagNumber(8) - set typeOptionJson($core.String v) { $_setString(7, v); } + set typeOptionByFieldTypeId(TypeOptionDataByFieldTypeId v) { setField(8, v); } @$pb.TagNumber(8) - $core.bool hasTypeOptionJson() => $_has(7); + $core.bool hasTypeOptionByFieldTypeId() => $_has(7); @$pb.TagNumber(8) - void clearTypeOptionJson() => clearField(8); + void clearTypeOptionByFieldTypeId() => clearField(8); + @$pb.TagNumber(8) + TypeOptionDataByFieldTypeId ensureTypeOptionByFieldTypeId() => $_ensure(7); +} + +class TypeOptionDataByFieldTypeId extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TypeOptionDataByFieldTypeId', createEmptyInstance: create) + ..m<$core.String, $core.String>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'map', entryClassName: 'TypeOptionDataByFieldTypeId.MapEntry', keyFieldType: $pb.PbFieldType.OS, valueFieldType: $pb.PbFieldType.OS) + ..hasRequiredFields = false + ; + + TypeOptionDataByFieldTypeId._() : super(); + factory TypeOptionDataByFieldTypeId({ + $core.Map<$core.String, $core.String>? map, + }) { + final _result = create(); + if (map != null) { + _result.map.addAll(map); + } + return _result; + } + factory TypeOptionDataByFieldTypeId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TypeOptionDataByFieldTypeId.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + TypeOptionDataByFieldTypeId clone() => TypeOptionDataByFieldTypeId()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TypeOptionDataByFieldTypeId copyWith(void Function(TypeOptionDataByFieldTypeId) updates) => super.copyWith((message) => updates(message as TypeOptionDataByFieldTypeId)) as TypeOptionDataByFieldTypeId; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static TypeOptionDataByFieldTypeId create() => TypeOptionDataByFieldTypeId._(); + TypeOptionDataByFieldTypeId createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TypeOptionDataByFieldTypeId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TypeOptionDataByFieldTypeId? _defaultInstance; + + @$pb.TagNumber(1) + $core.Map<$core.String, $core.String> get map => $_getMap(0); } enum FieldChangesetPayload_OneOfName { 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 7c690f7b1e..74a4ffe802 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 @@ -69,12 +69,33 @@ const FieldMeta$json = const { const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'}, const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'}, const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'}, - const {'1': 'type_option_json', '3': 8, '4': 1, '5': 9, '10': 'typeOptionJson'}, + const {'1': 'type_option_by_field_type_id', '3': 8, '4': 1, '5': 11, '6': '.TypeOptionDataByFieldTypeId', '10': 'typeOptionByFieldTypeId'}, ], }; /// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSKAoQdHlwZV9vcHRpb25fanNvbhgIIAEoCVIOdHlwZU9wdGlvbkpzb24='); +final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSWwocdHlwZV9vcHRpb25fYnlfZmllbGRfdHlwZV9pZBgIIAEoCzIcLlR5cGVPcHRpb25EYXRhQnlGaWVsZFR5cGVJZFIXdHlwZU9wdGlvbkJ5RmllbGRUeXBlSWQ='); +@$core.Deprecated('Use typeOptionDataByFieldTypeIdDescriptor instead') +const TypeOptionDataByFieldTypeId$json = const { + '1': 'TypeOptionDataByFieldTypeId', + '2': const [ + const {'1': 'map', '3': 1, '4': 3, '5': 11, '6': '.TypeOptionDataByFieldTypeId.MapEntry', '10': 'map'}, + ], + '3': const [TypeOptionDataByFieldTypeId_MapEntry$json], +}; + +@$core.Deprecated('Use typeOptionDataByFieldTypeIdDescriptor instead') +const TypeOptionDataByFieldTypeId_MapEntry$json = const { + '1': 'MapEntry', + '2': const [ + const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, + const {'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'}, + ], + '7': const {'7': true}, +}; + +/// Descriptor for `TypeOptionDataByFieldTypeId`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List typeOptionDataByFieldTypeIdDescriptor = $convert.base64Decode('ChtUeXBlT3B0aW9uRGF0YUJ5RmllbGRUeXBlSWQSNwoDbWFwGAEgAygLMiUuVHlwZU9wdGlvbkRhdGFCeUZpZWxkVHlwZUlkLk1hcEVudHJ5UgNtYXAaNgoITWFwRW50cnkSEAoDa2V5GAEgASgJUgNrZXkSFAoFdmFsdWUYAiABKAlSBXZhbHVlOgI4AQ=='); @$core.Deprecated('Use fieldChangesetPayloadDescriptor instead') const FieldChangesetPayload$json = const { '1': 'FieldChangesetPayload', diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 25f11c3010..53660bdea2 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -1,5 +1,5 @@ use crate::manager::GridManager; -use crate::services::field::{type_option_data_from_str, SelectOption}; +use crate::services::field::{type_option_builder_from_json_str, SelectOption}; use crate::services::grid_editor::ClientGridEditor; use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::entities::*; @@ -115,9 +115,11 @@ pub(crate) async fn get_field_context_handler( ) -> DataResult { let params = data.into_inner(); let editor = manager.get_grid_editor(¶ms.grid_id)?; - let mut field_meta = get_or_create_field_meta(¶ms, editor).await?; - let type_option_data = type_option_data_from_str(&field_meta.type_option_json, &field_meta.field_type); + let s = field_meta.get_type_option_str().unwrap(); + let builder = type_option_builder_from_json_str(&s, &field_meta.field_type); + let type_option_data = builder.entry().protobuf_bytes().to_vec(); + let field: Field = field_meta.into(); let edit_context = EditFieldContext { grid_id: params.grid_id, diff --git a/frontend/rust-lib/flowy-grid/src/macros.rs b/frontend/rust-lib/flowy-grid/src/macros.rs index 932d93c6ed..2afa9eeda2 100644 --- a/frontend/rust-lib/flowy-grid/src/macros.rs +++ b/frontend/rust-lib/flowy-grid/src/macros.rs @@ -9,15 +9,16 @@ macro_rules! impl_into_box_type_option_builder { }; } -macro_rules! impl_from_json_str_and_from_bytes { +macro_rules! impl_builder_from_json_str_and_from_bytes { ($target: ident,$type_option: ident) => { impl $target { - pub fn from_json_str(s: &str) -> $target { - $target($type_option::from(s)) + pub fn from_protobuf_bytes(bytes: Bytes) -> $target { + let type_option = $type_option::from_protobuf_bytes(bytes); + $target(type_option) } - pub fn from_bytes(bytes: Bytes) -> $target { - let type_option = $type_option::try_from(bytes).unwrap_or($type_option::default()); + pub fn from_json_str(s: &str) -> $target { + let type_option = $type_option::from_json_str(s); $target(type_option) } } @@ -25,48 +26,33 @@ macro_rules! impl_from_json_str_and_from_bytes { } #[macro_export] -macro_rules! impl_from_and_to_type_option { +macro_rules! impl_type_option { ($target: ident, $field_type:expr) => { - impl_from_field_type_option!($target); - impl_to_field_type_option!($target, $field_type); - }; -} - -#[macro_export] -macro_rules! impl_from_field_type_option { - ($target: ident) => { impl std::convert::From<&FieldMeta> for $target { fn from(field_meta: &FieldMeta) -> $target { - $target::from(field_meta.type_option_json.as_str()) - } - } - - impl std::convert::From<&str> for $target { - fn from(type_option_str: &str) -> $target { - match serde_json::from_str(type_option_str) { - Ok(obj) => obj, - Err(err) => { - tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err); - $target::default() - } + match field_meta + .type_option_by_field_type_id + .get_entry::<$target>(&$field_type) + { + None => $target::default(), + Some(target) => target, } } } - }; -} - -#[macro_export] -macro_rules! impl_to_field_type_option { - ($target: ident, $field_type:expr) => { - impl $target { - pub fn field_type(&self) -> FieldType { - $field_type - } - } impl std::convert::From<$target> for String { - fn from(field_description: $target) -> Self { - match serde_json::to_string(&field_description) { + fn from(type_option: $target) -> String { + type_option.json_str() + } + } + + impl TypeOptionDataEntry for $target { + fn field_type(&self) -> FieldType { + $field_type + } + + fn json_str(&self) -> String { + match serde_json::to_string(&self) { Ok(s) => s, Err(e) => { tracing::error!("Field type data convert to AnyData fail, error: {:?}", e); @@ -74,6 +60,26 @@ macro_rules! impl_to_field_type_option { } } } + + fn protobuf_bytes(&self) -> Bytes { + self.clone().try_into().unwrap() + } + } + + impl TypeOptionDataFrom for $target { + fn from_json_str(s: &str) -> $target { + match serde_json::from_str(s) { + Ok(obj) => obj, + Err(err) => { + tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err); + $target::default() + } + } + } + + fn from_protobuf_bytes(bytes: Bytes) -> $target { + $target::try_from(bytes).unwrap_or($target::default()) + } } }; } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs index 474a97e885..d978951425 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs @@ -1,6 +1,8 @@ use crate::services::field::type_options::*; use bytes::Bytes; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{ + Field, FieldMeta, FieldType, TypeOptionDataByFieldTypeId, TypeOptionDataEntry, TypeOptionDataFrom, +}; pub struct FieldBuilder { field_meta: FieldMeta, @@ -24,6 +26,23 @@ impl FieldBuilder { Self::new(type_option_builder) } + pub fn from_field(field: Field, type_option_builder: Box) -> Self { + let field_meta = FieldMeta { + id: field.id, + name: field.name, + desc: field.desc, + field_type: field.field_type, + frozen: field.frozen, + visibility: field.visibility, + width: field.width, + type_option_by_field_type_id: TypeOptionDataByFieldTypeId::default(), + }; + Self { + field_meta, + type_option_builder, + } + } + pub fn name(mut self, name: &str) -> Self { self.field_meta.name = name.to_owned(); self @@ -52,16 +71,16 @@ impl FieldBuilder { pub fn build(self) -> FieldMeta { debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type()); let mut field_meta = self.field_meta; - let type_option_json = self.type_option_builder.build_type_option_str(); - field_meta.type_option_json = type_option_json; + field_meta + .type_option_by_field_type_id + .insert_entry(self.type_option_builder.entry()); field_meta } } pub trait TypeOptionBuilder { fn field_type(&self) -> FieldType; - fn build_type_option_str(&self) -> String; - fn build_type_option_data(&self) -> Bytes; + fn entry(&self) -> &dyn TypeOptionDataEntry; } pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box { @@ -88,23 +107,14 @@ pub fn type_option_builder_from_json_str(s: &str, field_type: &FieldType) -> Box } } -pub fn type_option_builder_from_bytes(bytes: Bytes, field_type: &FieldType) -> Box { +pub fn type_option_builder_from_bytes>(bytes: T, field_type: &FieldType) -> Box { + let bytes = bytes.into(); match field_type { - FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_bytes(bytes)), - FieldType::Number => Box::new(NumberTypeOptionBuilder::from_bytes(bytes)), - FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_bytes(bytes)), - FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_bytes(bytes)), - FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_bytes(bytes)), - FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_bytes(bytes)), + FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::Number => Box::new(NumberTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_protobuf_bytes(bytes)), + FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_protobuf_bytes(bytes)), } } - -pub fn type_option_data_from_str(s: &str, field_type: &FieldType) -> Vec { - let builder = type_option_builder_from_json_str(s, field_type); - builder.build_type_option_data().to_vec() -} - -pub fn type_option_json_str_from_bytes(bytes: Vec, field_type: &FieldType) -> String { - let builder = type_option_builder_from_bytes(Bytes::from(bytes), field_type); - builder.build_type_option_str() -} diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs index f6e07c831a..99fd2290db 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option.rs @@ -1,16 +1,19 @@ -use crate::impl_from_and_to_type_option; -use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; +use crate::impl_type_option; +use crate::services::field::{ + BoxTypeOptionBuilder, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RichTextTypeOption, + SingleSelectTypeOption, TypeOptionBuilder, +}; use crate::services::row::CellDataSerde; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use serde::{Deserialize, Serialize}; #[derive(Default)] pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); impl_into_box_type_option_builder!(CheckboxTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(CheckboxTypeOptionBuilder, CheckboxTypeOption); +impl_builder_from_json_str_and_from_bytes!(CheckboxTypeOptionBuilder, CheckboxTypeOption); impl CheckboxTypeOptionBuilder { pub fn set_selected(mut self, is_selected: bool) -> Self { @@ -24,12 +27,8 @@ impl TypeOptionBuilder for CheckboxTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -38,7 +37,7 @@ pub struct CheckboxTypeOption { #[pb(index = 1)] pub is_selected: bool, } -impl_from_and_to_type_option!(CheckboxTypeOption, FieldType::Checkbox); +impl_type_option!(CheckboxTypeOption, FieldType::Checkbox); impl CellDataSerde for CheckboxTypeOption { fn deserialize_cell_data(&self, data: String) -> String { @@ -47,8 +46,8 @@ impl CellDataSerde for CheckboxTypeOption { fn serialize_cell_data(&self, data: &str) -> Result { let s = match string_to_bool(data) { - true => "1", - false => "0", + true => "No", + false => "Yes", }; Ok(s.to_owned()) } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs index dca1654b3e..92d01cf90b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs @@ -1,15 +1,14 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::row::CellDataSerde; use bytes::Bytes; - use chrono::format::strftime::StrftimeItems; use chrono::NaiveDateTime; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use serde::{Deserialize, Serialize}; -use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; +use crate::services::field::{BoxTypeOptionBuilder, RichTextTypeOption, TypeOptionBuilder}; use strum_macros::EnumIter; // Date @@ -21,7 +20,7 @@ pub struct DateTypeOption { #[pb(index = 2)] pub time_format: TimeFormat, } -impl_from_and_to_type_option!(DateTypeOption, FieldType::DateTime); +impl_type_option!(DateTypeOption, FieldType::DateTime); impl DateTypeOption { #[allow(dead_code)] @@ -66,7 +65,7 @@ impl CellDataSerde for DateTypeOption { #[derive(Default)] pub struct DateTypeOptionBuilder(DateTypeOption); impl_into_box_type_option_builder!(DateTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOption); +impl_builder_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOption); impl DateTypeOptionBuilder { pub fn date_format(mut self, date_format: DateFormat) -> Self { @@ -84,12 +83,8 @@ impl TypeOptionBuilder for DateTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs index 958edf2664..b5cab79b97 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/mod.rs @@ -3,6 +3,7 @@ mod date_type_option; mod number_type_option; mod selection_type_option; mod text_type_option; +mod type_option_data; pub use checkbox_type_option::*; pub use date_type_option::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 67de271309..fc052df8e7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -1,8 +1,8 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::row::CellDataSerde; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use lazy_static::lazy_static; use rust_decimal::prelude::Zero; use rust_decimal::Decimal; @@ -22,7 +22,7 @@ lazy_static! { #[derive(Default)] pub struct NumberTypeOptionBuilder(NumberTypeOption); impl_into_box_type_option_builder!(NumberTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption); +impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption); impl NumberTypeOptionBuilder { pub fn name(mut self, name: &str) -> Self { @@ -51,12 +51,8 @@ impl TypeOptionBuilder for NumberTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -78,7 +74,7 @@ pub struct NumberTypeOption { #[pb(index = 5)] pub name: String, } -impl_from_and_to_type_option!(NumberTypeOption, FieldType::Number); +impl_type_option!(NumberTypeOption, FieldType::Number); impl std::default::Default for NumberTypeOption { fn default() -> Self { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs index 015bf2257b..c712c747ec 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs @@ -1,11 +1,11 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use crate::services::util::*; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::{FlowyError, FlowyResult}; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -21,7 +21,7 @@ pub struct SingleSelectTypeOption { #[pb(index = 2)] pub disable_color: bool, } -impl_from_and_to_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); +impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); impl CellDataSerde for SingleSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { @@ -36,7 +36,7 @@ impl CellDataSerde for SingleSelectTypeOption { #[derive(Default)] pub struct SingleSelectTypeOptionBuilder(SingleSelectTypeOption); impl_into_box_type_option_builder!(SingleSelectTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOption); +impl_builder_from_json_str_and_from_bytes!(SingleSelectTypeOptionBuilder, SingleSelectTypeOption); impl SingleSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { @@ -50,12 +50,8 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -68,7 +64,7 @@ pub struct MultiSelectTypeOption { #[pb(index = 2)] pub disable_color: bool, } -impl_from_and_to_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); +impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); impl CellDataSerde for MultiSelectTypeOption { fn deserialize_cell_data(&self, data: String) -> String { @@ -83,7 +79,7 @@ impl CellDataSerde for MultiSelectTypeOption { #[derive(Default)] pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption); impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption); +impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption); impl MultiSelectTypeOptionBuilder { pub fn option(mut self, opt: SelectOption) -> Self { self.0.options.push(opt); @@ -96,12 +92,8 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs index 3b2cfa051d..a1441f28c7 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option.rs @@ -1,28 +1,24 @@ -use crate::impl_from_and_to_type_option; +use crate::impl_type_option; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::row::CellDataSerde; use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::FlowyError; -use flowy_grid_data_model::entities::{FieldMeta, FieldType}; +use flowy_grid_data_model::entities::{FieldMeta, FieldType, TypeOptionDataEntry, TypeOptionDataFrom}; use serde::{Deserialize, Serialize}; #[derive(Default)] pub struct RichTextTypeOptionBuilder(RichTextTypeOption); impl_into_box_type_option_builder!(RichTextTypeOptionBuilder); -impl_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOption); +impl_builder_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOption); impl TypeOptionBuilder for RichTextTypeOptionBuilder { fn field_type(&self) -> FieldType { self.0.field_type() } - fn build_type_option_str(&self) -> String { - self.0.clone().into() - } - - fn build_type_option_data(&self) -> Bytes { - self.0.clone().try_into().unwrap() + fn entry(&self) -> &dyn TypeOptionDataEntry { + &self.0 } } @@ -31,7 +27,7 @@ pub struct RichTextTypeOption { #[pb(index = 1)] pub format: String, } -impl_from_and_to_type_option!(RichTextTypeOption, FieldType::RichText); +impl_type_option!(RichTextTypeOption, FieldType::RichText); impl CellDataSerde for RichTextTypeOption { fn deserialize_cell_data(&self, data: String) -> String { diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs new file mode 100644 index 0000000000..330cc4fb10 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option_data.rs @@ -0,0 +1,9 @@ +use flowy_grid_data_model::entities::FieldType; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +// #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] +// pub struct TypeOptionData { +// #[pb(index = 1)] +// pub map: HashMap, +// } 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 3b48f244d5..226949a5d2 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::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::GridBlockMetaEditorManager; -use crate::services::field::{type_option_json_str_from_bytes, FieldBuilder}; +use crate::services::field::{type_option_builder_from_bytes, FieldBuilder}; use crate::services::row::*; use bytes::Bytes; use flowy_error::{ErrorCode, FlowyError, FlowyResult}; @@ -74,17 +74,9 @@ impl ClientGridEditor { }; Ok(grid.update_field(changeset, deserializer)?) } else { - let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); - let field_meta = FieldMeta { - id: field.id, - name: field.name, - desc: field.desc, - field_type: field.field_type, - frozen: field.frozen, - visibility: field.visibility, - width: field.width, - type_option_json, - }; + // let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); + let builder = type_option_builder_from_bytes(type_option_data, &field.field_type); + let field_meta = FieldBuilder::from_field(field, builder).build(); Ok(grid.create_field(field_meta, start_field_id)?) } }) @@ -409,7 +401,7 @@ impl TypeOptionDataDeserializer for TypeOptionChangesetDeserializer { // The type_option_data is serialized by protobuf. But the type_option_data should be // serialized by utf-8. So we must transform the data here. - let type_option_json = type_option_json_str_from_bytes(type_option_data, &self.0); - Ok(type_option_json) + let builder = type_option_builder_from_bytes(type_option_data, &self.0); + Ok(builder.entry().json_str()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs index 3d1c1939d7..1e60583df8 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/cell_data_serde.rs @@ -8,25 +8,25 @@ pub trait CellDataSerde { } #[allow(dead_code)] -pub fn serialize_cell_data(data: &str, field: &FieldMeta) -> Result { - match field.field_type { - FieldType::RichText => RichTextTypeOption::from(field).serialize_cell_data(data), - FieldType::Number => NumberTypeOption::from(field).serialize_cell_data(data), - FieldType::DateTime => DateTypeOption::from(field).serialize_cell_data(data), - FieldType::SingleSelect => SingleSelectTypeOption::from(field).serialize_cell_data(data), - FieldType::MultiSelect => MultiSelectTypeOption::from(field).serialize_cell_data(data), - FieldType::Checkbox => CheckboxTypeOption::from(field).serialize_cell_data(data), +pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result { + match field_meta.field_type { + FieldType::RichText => RichTextTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::Number => NumberTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::DateTime => DateTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).serialize_cell_data(data), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).serialize_cell_data(data), } } -pub fn deserialize_cell_data(data: String, field: &FieldMeta) -> Result { - let s = match field.field_type { - FieldType::RichText => RichTextTypeOption::from(field).deserialize_cell_data(data), - FieldType::Number => NumberTypeOption::from(field).deserialize_cell_data(data), - FieldType::DateTime => DateTypeOption::from(field).deserialize_cell_data(data), - FieldType::SingleSelect => SingleSelectTypeOption::from(field).deserialize_cell_data(data), - FieldType::MultiSelect => MultiSelectTypeOption::from(field).deserialize_cell_data(data), - FieldType::Checkbox => CheckboxTypeOption::from(field).deserialize_cell_data(data), +pub fn deserialize_cell_data(data: String, field_meta: &FieldMeta) -> Result { + let s = match field_meta.field_type { + FieldType::RichText => RichTextTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::Number => NumberTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::DateTime => DateTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).deserialize_cell_data(data), + FieldType::Checkbox => CheckboxTypeOption::from(field_meta).deserialize_cell_data(data), }; Ok(s) } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 7739356531..49fc16bb5a 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -3,7 +3,7 @@ use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid_data_model::entities::{ - BuildGridContext, CellMetaChangeset, Field, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, + BuildGridContext, CellMetaChangeset, CreateFieldParams, Field, FieldChangeset, FieldMeta, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder, }; use flowy_grid_data_model::parser::CreateFieldParams; 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 90074cadff..a09ced64b8 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -1,8 +1,11 @@ use crate::parser::NotEmptyUuid; +use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error_code::ErrorCode; use serde::{Deserialize, Serialize}; +use std::any::Any; use std::collections::HashMap; +use std::ops::Deref; use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; pub const DEFAULT_ROW_HEIGHT: i32 = 36; @@ -76,7 +79,7 @@ pub struct GridBlockMetaSerde { pub row_metas: Vec, } -#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] pub struct FieldMeta { #[pb(index = 1)] pub id: String, @@ -100,7 +103,7 @@ pub struct FieldMeta { pub width: i32, #[pb(index = 8)] - pub type_option_json: String, + pub type_option_by_field_type_id: TypeOptionDataByFieldTypeId, } impl FieldMeta { @@ -113,7 +116,55 @@ impl FieldMeta { frozen: false, visibility: true, width: DEFAULT_FIELD_WIDTH, - type_option_json: Default::default(), + type_option_by_field_type_id: Default::default(), + } + } + + pub fn get_type_option_str(&self) -> Option { + match self.type_option_by_field_type_id.get(&self.field_type) { + None => None, + Some(s) => Some(s.to_owned()), + } + } +} + +pub trait TypeOptionDataEntry { + fn field_type(&self) -> FieldType; + fn json_str(&self) -> String; + fn protobuf_bytes(&self) -> Bytes; +} + +pub trait TypeOptionDataFrom { + fn from_json_str(s: &str) -> Self; + fn from_protobuf_bytes(bytes: Bytes) -> Self; +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] +pub struct TypeOptionDataByFieldTypeId { + #[pb(index = 1)] + pub map: HashMap, +} + +impl TypeOptionDataByFieldTypeId { + pub fn insert_entry(&mut self, entry: &T) { + self.map.insert(entry.field_type().type_id(), entry.json_str()); + } + + pub fn insert(&mut self, field_type: &FieldType, json_str: String) { + self.map.insert(field_type.type_id(), json_str); + } + + pub fn get_entry(&self, field_type: &FieldType) -> Option { + match self.map.get(&field_type.type_id()) { + None => None, + Some(s) => Some(T::from_json_str(s)), + } + } + + pub fn get(&self, field_type: &FieldType) -> Option { + match self.map.get(&field_type.type_id()) { + None => None, + Some(s) => Some(s.to_owned()), } } } 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 f22a7c00a2..4b0de2d3fb 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 @@ -727,7 +727,7 @@ pub struct FieldMeta { pub frozen: bool, pub visibility: bool, pub width: i32, - pub type_option_json: ::std::string::String, + pub type_option_by_field_type_id: ::protobuf::SingularPtrField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -882,35 +882,47 @@ impl FieldMeta { self.width = v; } - // string type_option_json = 8; + // .TypeOptionDataByFieldTypeId type_option_by_field_type_id = 8; - pub fn get_type_option_json(&self) -> &str { - &self.type_option_json + pub fn get_type_option_by_field_type_id(&self) -> &TypeOptionDataByFieldTypeId { + self.type_option_by_field_type_id.as_ref().unwrap_or_else(|| ::default_instance()) } - pub fn clear_type_option_json(&mut self) { - self.type_option_json.clear(); + pub fn clear_type_option_by_field_type_id(&mut self) { + self.type_option_by_field_type_id.clear(); + } + + pub fn has_type_option_by_field_type_id(&self) -> bool { + self.type_option_by_field_type_id.is_some() } // Param is passed by value, moved - pub fn set_type_option_json(&mut self, v: ::std::string::String) { - self.type_option_json = v; + pub fn set_type_option_by_field_type_id(&mut self, v: TypeOptionDataByFieldTypeId) { + self.type_option_by_field_type_id = ::protobuf::SingularPtrField::some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_type_option_json(&mut self) -> &mut ::std::string::String { - &mut self.type_option_json + pub fn mut_type_option_by_field_type_id(&mut self) -> &mut TypeOptionDataByFieldTypeId { + if self.type_option_by_field_type_id.is_none() { + self.type_option_by_field_type_id.set_default(); + } + self.type_option_by_field_type_id.as_mut().unwrap() } // Take field - pub fn take_type_option_json(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.type_option_json, ::std::string::String::new()) + pub fn take_type_option_by_field_type_id(&mut self) -> TypeOptionDataByFieldTypeId { + self.type_option_by_field_type_id.take().unwrap_or_else(|| TypeOptionDataByFieldTypeId::new()) } } impl ::protobuf::Message for FieldMeta { fn is_initialized(&self) -> bool { + for v in &self.type_option_by_field_type_id { + if !v.is_initialized() { + return false; + } + }; true } @@ -952,7 +964,7 @@ impl ::protobuf::Message for FieldMeta { self.width = tmp; }, 8 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.type_option_json)?; + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.type_option_by_field_type_id)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -987,8 +999,9 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint); } - if !self.type_option_json.is_empty() { - my_size += ::protobuf::rt::string_size(8, &self.type_option_json); + if let Some(ref v) = self.type_option_by_field_type_id.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -1017,8 +1030,10 @@ impl ::protobuf::Message for FieldMeta { if self.width != 0 { os.write_int32(7, self.width)?; } - if !self.type_option_json.is_empty() { - os.write_string(8, &self.type_option_json)?; + if let Some(ref v) = self.type_option_by_field_type_id.as_ref() { + os.write_tag(8, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -1093,10 +1108,10 @@ impl ::protobuf::Message for FieldMeta { |m: &FieldMeta| { &m.width }, |m: &mut FieldMeta| { &mut m.width }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "type_option_json", - |m: &FieldMeta| { &m.type_option_json }, - |m: &mut FieldMeta| { &mut m.type_option_json }, + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "type_option_by_field_type_id", + |m: &FieldMeta| { &m.type_option_by_field_type_id }, + |m: &mut FieldMeta| { &mut m.type_option_by_field_type_id }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "FieldMeta", @@ -1121,7 +1136,7 @@ impl ::protobuf::Clear for FieldMeta { self.frozen = false; self.visibility = false; self.width = 0; - self.type_option_json.clear(); + self.type_option_by_field_type_id.clear(); self.unknown_fields.clear(); } } @@ -1138,6 +1153,160 @@ impl ::protobuf::reflect::ProtobufValue for FieldMeta { } } +#[derive(PartialEq,Clone,Default)] +pub struct TypeOptionDataByFieldTypeId { + // message fields + pub map: ::std::collections::HashMap<::std::string::String, ::std::string::String>, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a TypeOptionDataByFieldTypeId { + fn default() -> &'a TypeOptionDataByFieldTypeId { + ::default_instance() + } +} + +impl TypeOptionDataByFieldTypeId { + pub fn new() -> TypeOptionDataByFieldTypeId { + ::std::default::Default::default() + } + + // repeated .TypeOptionDataByFieldTypeId.MapEntry map = 1; + + + pub fn get_map(&self) -> &::std::collections::HashMap<::std::string::String, ::std::string::String> { + &self.map + } + pub fn clear_map(&mut self) { + self.map.clear(); + } + + // Param is passed by value, moved + pub fn set_map(&mut self, v: ::std::collections::HashMap<::std::string::String, ::std::string::String>) { + self.map = v; + } + + // Mutable pointer to the field. + pub fn mut_map(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, ::std::string::String> { + &mut self.map + } + + // Take field + pub fn take_map(&mut self) -> ::std::collections::HashMap<::std::string::String, ::std::string::String> { + ::std::mem::replace(&mut self.map, ::std::collections::HashMap::new()) + } +} + +impl ::protobuf::Message for TypeOptionDataByFieldTypeId { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(wire_type, is, &mut self.map)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(1, &self.map); + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(1, &self.map, os)?; + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> TypeOptionDataByFieldTypeId { + TypeOptionDataByFieldTypeId::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + 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_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>( + "map", + |m: &TypeOptionDataByFieldTypeId| { &m.map }, + |m: &mut TypeOptionDataByFieldTypeId| { &mut m.map }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "TypeOptionDataByFieldTypeId", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static TypeOptionDataByFieldTypeId { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(TypeOptionDataByFieldTypeId::new) + } +} + +impl ::protobuf::Clear for TypeOptionDataByFieldTypeId { + fn clear(&mut self) { + self.map.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for TypeOptionDataByFieldTypeId { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for TypeOptionDataByFieldTypeId { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct FieldChangesetPayload { // message fields @@ -3507,51 +3676,55 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"V\n\x12GridBlockMet\ aSerde\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_\ - metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xe6\x01\n\tFieldM\ + metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\x99\x02\n\tFieldM\ eta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ - idth\x12(\n\x10type_option_json\x18\x08\x20\x01(\tR\x0etypeOptionJson\"\ - \xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\x20\ - \x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\ - \x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\ - \x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n\ - .FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\ - \x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibi\ - lity\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\x10ty\ - pe_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\r\n\x0bone_of\ - _nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_fro\ - zenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x19\n\x17one_of_\ - type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\t\ - R\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\ - \n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08blo\ - ck_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\ - \x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\ - \x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\ - \x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ - \x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.C\ - ellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\ - \x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\ - \x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\ - \nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaCh\ - angeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\ + idth\x12[\n\x1ctype_option_by_field_type_id\x18\x08\x20\x01(\x0b2\x1c.Ty\ + peOptionDataByFieldTypeIdR\x17typeOptionByFieldTypeId\"\x8e\x01\n\x1bTyp\ + eOptionDataByFieldTypeId\x127\n\x03map\x18\x01\x20\x03(\x0b2%.TypeOption\ + DataByFieldTypeId.MapEntryR\x03map\x1a6\n\x08MapEntry\x12\x10\n\x03key\ + \x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05va\ + lue:\x028\x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\ + \x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\ + \x06gridId\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\ + \x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\ + \x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\ + \x01(\x08H\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\ + \x04R\nvisibility\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\ + \x12*\n\x10type_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\ + \r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\ + \n\rone_of_frozenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\ + \x19\n\x17one_of_type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\ + \x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\ + \x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02\ + id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_b\ + y_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellBy\ + FieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nv\ + isibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\ \x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\ - \x20\x01(\x0b2\t.CellMetaR\x05value:\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\"\ - \x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ - \x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\ - \x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\ - \x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridCont\ - ext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\ - \x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMe\ - tas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSer\ - deR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\ - \x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSele\ - ct\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\ - \x05b\x06proto3\ + \x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChan\ + geset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06heig\ + ht\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\ + \x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\ + \x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12Cel\ + lByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\ + \x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\ro\ + ne_of_heightB\x13\n\x11one_of_visibility\"9\n\x08CellMeta\x12\x19\n\x08f\ + ield_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01\ + (\tR\x04data\"\x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05ro\ + wId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04da\ + ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10Bui\ + ldGridContext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\n\ + fieldMetas\x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMeta\ + R\nblockMetas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBl\ + ockMetaSerdeR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\ + \x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSi\ + ngleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbo\ + x\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/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 2c5bd41f86..897143247b 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 @@ -22,7 +22,10 @@ message FieldMeta { bool frozen = 5; bool visibility = 6; int32 width = 7; - string type_option_json = 8; + TypeOptionDataByFieldTypeId type_option_by_field_type_id = 8; +} +message TypeOptionDataByFieldTypeId { + map map = 1; } message FieldChangesetPayload { string field_id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs index 362fe924b0..5d7085e92c 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs @@ -129,8 +129,8 @@ impl GridMetaPad { if let Some(type_option_data) = changeset.type_option_data { match deserializer.deserialize(type_option_data) { - Ok(type_option_json) => { - field.type_option_json = type_option_json; + Ok(json_str) => { + field.type_option_by_field_type_id.insert(&field.field_type, json_str); is_changed = Some(()) } Err(err) => {