chore: save type option data as map

This commit is contained in:
appflowy 2022-04-01 16:38:51 +08:00
parent 80f82fa5b1
commit e0b969595c
19 changed files with 524 additions and 235 deletions

View File

@ -215,7 +215,7 @@ class FieldMeta extends $pb.GeneratedMessage {
..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen') ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen')
..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility') ..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) ..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<TypeOptionDataByFieldTypeId>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionByFieldTypeId', subBuilder: TypeOptionDataByFieldTypeId.create)
..hasRequiredFields = false ..hasRequiredFields = false
; ;
@ -228,7 +228,7 @@ class FieldMeta extends $pb.GeneratedMessage {
$core.bool? frozen, $core.bool? frozen,
$core.bool? visibility, $core.bool? visibility,
$core.int? width, $core.int? width,
$core.String? typeOptionJson, TypeOptionDataByFieldTypeId? typeOptionByFieldTypeId,
}) { }) {
final _result = create(); final _result = create();
if (id != null) { if (id != null) {
@ -252,8 +252,8 @@ class FieldMeta extends $pb.GeneratedMessage {
if (width != null) { if (width != null) {
_result.width = width; _result.width = width;
} }
if (typeOptionJson != null) { if (typeOptionByFieldTypeId != null) {
_result.typeOptionJson = typeOptionJson; _result.typeOptionByFieldTypeId = typeOptionByFieldTypeId;
} }
return _result; return _result;
} }
@ -342,13 +342,56 @@ class FieldMeta extends $pb.GeneratedMessage {
void clearWidth() => clearField(7); void clearWidth() => clearField(7);
@$pb.TagNumber(8) @$pb.TagNumber(8)
$core.String get typeOptionJson => $_getSZ(7); TypeOptionDataByFieldTypeId get typeOptionByFieldTypeId => $_getN(7);
@$pb.TagNumber(8) @$pb.TagNumber(8)
set typeOptionJson($core.String v) { $_setString(7, v); } set typeOptionByFieldTypeId(TypeOptionDataByFieldTypeId v) { setField(8, v); }
@$pb.TagNumber(8) @$pb.TagNumber(8)
$core.bool hasTypeOptionJson() => $_has(7); $core.bool hasTypeOptionByFieldTypeId() => $_has(7);
@$pb.TagNumber(8) @$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<TypeOptionDataByFieldTypeId> createRepeated() => $pb.PbList<TypeOptionDataByFieldTypeId>();
@$core.pragma('dart2js:noInline')
static TypeOptionDataByFieldTypeId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TypeOptionDataByFieldTypeId>(create);
static TypeOptionDataByFieldTypeId? _defaultInstance;
@$pb.TagNumber(1)
$core.Map<$core.String, $core.String> get map => $_getMap(0);
} }
enum FieldChangesetPayload_OneOfName { enum FieldChangesetPayload_OneOfName {

View File

@ -69,12 +69,33 @@ const FieldMeta$json = const {
const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'}, const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'},
const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'}, const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'},
const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'}, 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`. /// 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') @$core.Deprecated('Use fieldChangesetPayloadDescriptor instead')
const FieldChangesetPayload$json = const { const FieldChangesetPayload$json = const {
'1': 'FieldChangesetPayload', '1': 'FieldChangesetPayload',

View File

@ -1,5 +1,5 @@
use crate::manager::GridManager; 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 crate::services::grid_editor::ClientGridEditor;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::*; use flowy_grid_data_model::entities::*;
@ -115,9 +115,11 @@ pub(crate) async fn get_field_context_handler(
) -> DataResult<EditFieldContext, FlowyError> { ) -> DataResult<EditFieldContext, FlowyError> {
let params = data.into_inner(); let params = data.into_inner();
let editor = manager.get_grid_editor(&params.grid_id)?; let editor = manager.get_grid_editor(&params.grid_id)?;
let mut field_meta = get_or_create_field_meta(&params, editor).await?; let mut field_meta = get_or_create_field_meta(&params, 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 field: Field = field_meta.into();
let edit_context = EditFieldContext { let edit_context = EditFieldContext {
grid_id: params.grid_id, grid_id: params.grid_id,

View File

@ -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) => { ($target: ident,$type_option: ident) => {
impl $target { impl $target {
pub fn from_json_str(s: &str) -> $target { pub fn from_protobuf_bytes(bytes: Bytes) -> $target {
$target($type_option::from(s)) let type_option = $type_option::from_protobuf_bytes(bytes);
$target(type_option)
} }
pub fn from_bytes(bytes: Bytes) -> $target { pub fn from_json_str(s: &str) -> $target {
let type_option = $type_option::try_from(bytes).unwrap_or($type_option::default()); let type_option = $type_option::from_json_str(s);
$target(type_option) $target(type_option)
} }
} }
@ -25,48 +26,33 @@ macro_rules! impl_from_json_str_and_from_bytes {
} }
#[macro_export] #[macro_export]
macro_rules! impl_from_and_to_type_option { macro_rules! impl_type_option {
($target: ident, $field_type:expr) => { ($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 { impl std::convert::From<&FieldMeta> for $target {
fn from(field_meta: &FieldMeta) -> $target { fn from(field_meta: &FieldMeta) -> $target {
$target::from(field_meta.type_option_json.as_str()) match field_meta
.type_option_by_field_type_id
.get_entry::<$target>(&$field_type)
{
None => $target::default(),
Some(target) => target,
} }
} }
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()
}
}
}
}
};
}
#[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 { impl std::convert::From<$target> for String {
fn from(field_description: $target) -> Self { fn from(type_option: $target) -> String {
match serde_json::to_string(&field_description) { 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, Ok(s) => s,
Err(e) => { Err(e) => {
tracing::error!("Field type data convert to AnyData fail, error: {:?}", 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())
}
} }
}; };
} }

View File

@ -1,6 +1,8 @@
use crate::services::field::type_options::*; use crate::services::field::type_options::*;
use bytes::Bytes; 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 { pub struct FieldBuilder {
field_meta: FieldMeta, field_meta: FieldMeta,
@ -24,6 +26,23 @@ impl FieldBuilder {
Self::new(type_option_builder) Self::new(type_option_builder)
} }
pub fn from_field(field: Field, type_option_builder: Box<dyn TypeOptionBuilder>) -> 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 { pub fn name(mut self, name: &str) -> Self {
self.field_meta.name = name.to_owned(); self.field_meta.name = name.to_owned();
self self
@ -52,16 +71,16 @@ impl FieldBuilder {
pub fn build(self) -> FieldMeta { pub fn build(self) -> FieldMeta {
debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type()); debug_assert_eq!(self.field_meta.field_type, self.type_option_builder.field_type());
let mut field_meta = self.field_meta; let mut field_meta = self.field_meta;
let type_option_json = self.type_option_builder.build_type_option_str(); field_meta
field_meta.type_option_json = type_option_json; .type_option_by_field_type_id
.insert_entry(self.type_option_builder.entry());
field_meta field_meta
} }
} }
pub trait TypeOptionBuilder { pub trait TypeOptionBuilder {
fn field_type(&self) -> FieldType; fn field_type(&self) -> FieldType;
fn build_type_option_str(&self) -> String; fn entry(&self) -> &dyn TypeOptionDataEntry;
fn build_type_option_data(&self) -> Bytes;
} }
pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box<dyn TypeOptionBuilder> { pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box<dyn TypeOptionBuilder> {
@ -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<dyn TypeOptionBuilder> { pub fn type_option_builder_from_bytes<T: Into<Bytes>>(bytes: T, field_type: &FieldType) -> Box<dyn TypeOptionBuilder> {
let bytes = bytes.into();
match field_type { match field_type {
FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_bytes(bytes)), FieldType::RichText => Box::new(RichTextTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::Number => Box::new(NumberTypeOptionBuilder::from_bytes(bytes)), FieldType::Number => Box::new(NumberTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_bytes(bytes)), FieldType::DateTime => Box::new(DateTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_bytes(bytes)), FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_bytes(bytes)), FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_bytes(bytes)), FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_protobuf_bytes(bytes)),
} }
} }
pub fn type_option_data_from_str(s: &str, field_type: &FieldType) -> Vec<u8> {
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<u8>, field_type: &FieldType) -> String {
let builder = type_option_builder_from_bytes(Bytes::from(bytes), field_type);
builder.build_type_option_str()
}

View File

@ -1,16 +1,19 @@
use crate::impl_from_and_to_type_option; use crate::impl_type_option;
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{
BoxTypeOptionBuilder, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RichTextTypeOption,
SingleSelectTypeOption, TypeOptionBuilder,
};
use crate::services::row::CellDataSerde; use crate::services::row::CellDataSerde;
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::FlowyError; 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 serde::{Deserialize, Serialize};
#[derive(Default)] #[derive(Default)]
pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption); pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption);
impl_into_box_type_option_builder!(CheckboxTypeOptionBuilder); 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 { impl CheckboxTypeOptionBuilder {
pub fn set_selected(mut self, is_selected: bool) -> Self { pub fn set_selected(mut self, is_selected: bool) -> Self {
@ -24,12 +27,8 @@ impl TypeOptionBuilder for CheckboxTypeOptionBuilder {
self.0.field_type() self.0.field_type()
} }
fn build_type_option_str(&self) -> String { fn entry(&self) -> &dyn TypeOptionDataEntry {
self.0.clone().into() &self.0
}
fn build_type_option_data(&self) -> Bytes {
self.0.clone().try_into().unwrap()
} }
} }
@ -38,7 +37,7 @@ pub struct CheckboxTypeOption {
#[pb(index = 1)] #[pb(index = 1)]
pub is_selected: bool, pub is_selected: bool,
} }
impl_from_and_to_type_option!(CheckboxTypeOption, FieldType::Checkbox); impl_type_option!(CheckboxTypeOption, FieldType::Checkbox);
impl CellDataSerde for CheckboxTypeOption { impl CellDataSerde for CheckboxTypeOption {
fn deserialize_cell_data(&self, data: String) -> String { fn deserialize_cell_data(&self, data: String) -> String {
@ -47,8 +46,8 @@ impl CellDataSerde for CheckboxTypeOption {
fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> { fn serialize_cell_data(&self, data: &str) -> Result<String, FlowyError> {
let s = match string_to_bool(data) { let s = match string_to_bool(data) {
true => "1", true => "No",
false => "0", false => "Yes",
}; };
Ok(s.to_owned()) Ok(s.to_owned())
} }

View File

@ -1,15 +1,14 @@
use crate::impl_from_and_to_type_option; use crate::impl_type_option;
use crate::services::row::CellDataSerde; use crate::services::row::CellDataSerde;
use bytes::Bytes; use bytes::Bytes;
use chrono::format::strftime::StrftimeItems; use chrono::format::strftime::StrftimeItems;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::FlowyError; 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 serde::{Deserialize, Serialize};
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, RichTextTypeOption, TypeOptionBuilder};
use strum_macros::EnumIter; use strum_macros::EnumIter;
// Date // Date
@ -21,7 +20,7 @@ pub struct DateTypeOption {
#[pb(index = 2)] #[pb(index = 2)]
pub time_format: TimeFormat, pub time_format: TimeFormat,
} }
impl_from_and_to_type_option!(DateTypeOption, FieldType::DateTime); impl_type_option!(DateTypeOption, FieldType::DateTime);
impl DateTypeOption { impl DateTypeOption {
#[allow(dead_code)] #[allow(dead_code)]
@ -66,7 +65,7 @@ impl CellDataSerde for DateTypeOption {
#[derive(Default)] #[derive(Default)]
pub struct DateTypeOptionBuilder(DateTypeOption); pub struct DateTypeOptionBuilder(DateTypeOption);
impl_into_box_type_option_builder!(DateTypeOptionBuilder); 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 { impl DateTypeOptionBuilder {
pub fn date_format(mut self, date_format: DateFormat) -> Self { pub fn date_format(mut self, date_format: DateFormat) -> Self {
@ -84,12 +83,8 @@ impl TypeOptionBuilder for DateTypeOptionBuilder {
self.0.field_type() self.0.field_type()
} }
fn build_type_option_str(&self) -> String { fn entry(&self) -> &dyn TypeOptionDataEntry {
self.0.clone().into() &self.0
}
fn build_type_option_data(&self) -> Bytes {
self.0.clone().try_into().unwrap()
} }
} }

View File

@ -3,6 +3,7 @@ mod date_type_option;
mod number_type_option; mod number_type_option;
mod selection_type_option; mod selection_type_option;
mod text_type_option; mod text_type_option;
mod type_option_data;
pub use checkbox_type_option::*; pub use checkbox_type_option::*;
pub use date_type_option::*; pub use date_type_option::*;

View File

@ -1,8 +1,8 @@
use crate::impl_from_and_to_type_option; use crate::impl_type_option;
use crate::services::row::CellDataSerde; use crate::services::row::CellDataSerde;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::FlowyError; 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 lazy_static::lazy_static;
use rust_decimal::prelude::Zero; use rust_decimal::prelude::Zero;
use rust_decimal::Decimal; use rust_decimal::Decimal;
@ -22,7 +22,7 @@ lazy_static! {
#[derive(Default)] #[derive(Default)]
pub struct NumberTypeOptionBuilder(NumberTypeOption); pub struct NumberTypeOptionBuilder(NumberTypeOption);
impl_into_box_type_option_builder!(NumberTypeOptionBuilder); 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 { impl NumberTypeOptionBuilder {
pub fn name(mut self, name: &str) -> Self { pub fn name(mut self, name: &str) -> Self {
@ -51,12 +51,8 @@ impl TypeOptionBuilder for NumberTypeOptionBuilder {
self.0.field_type() self.0.field_type()
} }
fn build_type_option_str(&self) -> String { fn entry(&self) -> &dyn TypeOptionDataEntry {
self.0.clone().into() &self.0
}
fn build_type_option_data(&self) -> Bytes {
self.0.clone().try_into().unwrap()
} }
} }
@ -78,7 +74,7 @@ pub struct NumberTypeOption {
#[pb(index = 5)] #[pb(index = 5)]
pub name: String, pub name: String,
} }
impl_from_and_to_type_option!(NumberTypeOption, FieldType::Number); impl_type_option!(NumberTypeOption, FieldType::Number);
impl std::default::Default for NumberTypeOption { impl std::default::Default for NumberTypeOption {
fn default() -> Self { fn default() -> Self {

View File

@ -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::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use crate::services::row::CellDataSerde; use crate::services::row::CellDataSerde;
use crate::services::util::*; use crate::services::util::*;
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::{FlowyError, FlowyResult}; 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 rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
@ -21,7 +21,7 @@ pub struct SingleSelectTypeOption {
#[pb(index = 2)] #[pb(index = 2)]
pub disable_color: bool, pub disable_color: bool,
} }
impl_from_and_to_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect);
impl CellDataSerde for SingleSelectTypeOption { impl CellDataSerde for SingleSelectTypeOption {
fn deserialize_cell_data(&self, data: String) -> String { fn deserialize_cell_data(&self, data: String) -> String {
@ -36,7 +36,7 @@ impl CellDataSerde for SingleSelectTypeOption {
#[derive(Default)] #[derive(Default)]
pub struct SingleSelectTypeOptionBuilder(SingleSelectTypeOption); pub struct SingleSelectTypeOptionBuilder(SingleSelectTypeOption);
impl_into_box_type_option_builder!(SingleSelectTypeOptionBuilder); 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 { impl SingleSelectTypeOptionBuilder {
pub fn option(mut self, opt: SelectOption) -> Self { pub fn option(mut self, opt: SelectOption) -> Self {
@ -50,12 +50,8 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder {
self.0.field_type() self.0.field_type()
} }
fn build_type_option_str(&self) -> String { fn entry(&self) -> &dyn TypeOptionDataEntry {
self.0.clone().into() &self.0
}
fn build_type_option_data(&self) -> Bytes {
self.0.clone().try_into().unwrap()
} }
} }
@ -68,7 +64,7 @@ pub struct MultiSelectTypeOption {
#[pb(index = 2)] #[pb(index = 2)]
pub disable_color: bool, pub disable_color: bool,
} }
impl_from_and_to_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect);
impl CellDataSerde for MultiSelectTypeOption { impl CellDataSerde for MultiSelectTypeOption {
fn deserialize_cell_data(&self, data: String) -> String { fn deserialize_cell_data(&self, data: String) -> String {
@ -83,7 +79,7 @@ impl CellDataSerde for MultiSelectTypeOption {
#[derive(Default)] #[derive(Default)]
pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption); pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption);
impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder); 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 { impl MultiSelectTypeOptionBuilder {
pub fn option(mut self, opt: SelectOption) -> Self { pub fn option(mut self, opt: SelectOption) -> Self {
self.0.options.push(opt); self.0.options.push(opt);
@ -96,12 +92,8 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder {
self.0.field_type() self.0.field_type()
} }
fn build_type_option_str(&self) -> String { fn entry(&self) -> &dyn TypeOptionDataEntry {
self.0.clone().into() &self.0
}
fn build_type_option_data(&self) -> Bytes {
self.0.clone().try_into().unwrap()
} }
} }

View File

@ -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::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use crate::services::row::CellDataSerde; use crate::services::row::CellDataSerde;
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::FlowyError; 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 serde::{Deserialize, Serialize};
#[derive(Default)] #[derive(Default)]
pub struct RichTextTypeOptionBuilder(RichTextTypeOption); pub struct RichTextTypeOptionBuilder(RichTextTypeOption);
impl_into_box_type_option_builder!(RichTextTypeOptionBuilder); 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 { impl TypeOptionBuilder for RichTextTypeOptionBuilder {
fn field_type(&self) -> FieldType { fn field_type(&self) -> FieldType {
self.0.field_type() self.0.field_type()
} }
fn build_type_option_str(&self) -> String { fn entry(&self) -> &dyn TypeOptionDataEntry {
self.0.clone().into() &self.0
}
fn build_type_option_data(&self) -> Bytes {
self.0.clone().try_into().unwrap()
} }
} }
@ -31,7 +27,7 @@ pub struct RichTextTypeOption {
#[pb(index = 1)] #[pb(index = 1)]
pub format: String, pub format: String,
} }
impl_from_and_to_type_option!(RichTextTypeOption, FieldType::RichText); impl_type_option!(RichTextTypeOption, FieldType::RichText);
impl CellDataSerde for RichTextTypeOption { impl CellDataSerde for RichTextTypeOption {
fn deserialize_cell_data(&self, data: String) -> String { fn deserialize_cell_data(&self, data: String) -> String {

View File

@ -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<FieldType, String>,
// }

View File

@ -1,7 +1,7 @@
use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::dart_notification::{send_dart_notification, GridNotification};
use crate::manager::GridUser; use crate::manager::GridUser;
use crate::services::block_meta_editor::GridBlockMetaEditorManager; 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 crate::services::row::*;
use bytes::Bytes; use bytes::Bytes;
use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_error::{ErrorCode, FlowyError, FlowyResult};
@ -74,17 +74,9 @@ impl ClientGridEditor {
}; };
Ok(grid.update_field(changeset, deserializer)?) Ok(grid.update_field(changeset, deserializer)?)
} else { } else {
let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type); // let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type);
let field_meta = FieldMeta { let builder = type_option_builder_from_bytes(type_option_data, &field.field_type);
id: field.id, let field_meta = FieldBuilder::from_field(field, builder).build();
name: field.name,
desc: field.desc,
field_type: field.field_type,
frozen: field.frozen,
visibility: field.visibility,
width: field.width,
type_option_json,
};
Ok(grid.create_field(field_meta, start_field_id)?) 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 // 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. // 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); let builder = type_option_builder_from_bytes(type_option_data, &self.0);
Ok(type_option_json) Ok(builder.entry().json_str())
} }
} }

View File

@ -8,25 +8,25 @@ pub trait CellDataSerde {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn serialize_cell_data(data: &str, field: &FieldMeta) -> Result<String, FlowyError> { pub fn serialize_cell_data(data: &str, field_meta: &FieldMeta) -> Result<String, FlowyError> {
match field.field_type { match field_meta.field_type {
FieldType::RichText => RichTextTypeOption::from(field).serialize_cell_data(data), FieldType::RichText => RichTextTypeOption::from(field_meta).serialize_cell_data(data),
FieldType::Number => NumberTypeOption::from(field).serialize_cell_data(data), FieldType::Number => NumberTypeOption::from(field_meta).serialize_cell_data(data),
FieldType::DateTime => DateTypeOption::from(field).serialize_cell_data(data), FieldType::DateTime => DateTypeOption::from(field_meta).serialize_cell_data(data),
FieldType::SingleSelect => SingleSelectTypeOption::from(field).serialize_cell_data(data), FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).serialize_cell_data(data),
FieldType::MultiSelect => MultiSelectTypeOption::from(field).serialize_cell_data(data), FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).serialize_cell_data(data),
FieldType::Checkbox => CheckboxTypeOption::from(field).serialize_cell_data(data), FieldType::Checkbox => CheckboxTypeOption::from(field_meta).serialize_cell_data(data),
} }
} }
pub fn deserialize_cell_data(data: String, field: &FieldMeta) -> Result<String, FlowyError> { pub fn deserialize_cell_data(data: String, field_meta: &FieldMeta) -> Result<String, FlowyError> {
let s = match field.field_type { let s = match field_meta.field_type {
FieldType::RichText => RichTextTypeOption::from(field).deserialize_cell_data(data), FieldType::RichText => RichTextTypeOption::from(field_meta).deserialize_cell_data(data),
FieldType::Number => NumberTypeOption::from(field).deserialize_cell_data(data), FieldType::Number => NumberTypeOption::from(field_meta).deserialize_cell_data(data),
FieldType::DateTime => DateTypeOption::from(field).deserialize_cell_data(data), FieldType::DateTime => DateTypeOption::from(field_meta).deserialize_cell_data(data),
FieldType::SingleSelect => SingleSelectTypeOption::from(field).deserialize_cell_data(data), FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).deserialize_cell_data(data),
FieldType::MultiSelect => MultiSelectTypeOption::from(field).deserialize_cell_data(data), FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).deserialize_cell_data(data),
FieldType::Checkbox => CheckboxTypeOption::from(field).deserialize_cell_data(data), FieldType::Checkbox => CheckboxTypeOption::from(field_meta).deserialize_cell_data(data),
}; };
Ok(s) Ok(s)
} }

View File

@ -3,7 +3,7 @@ use flowy_grid::services::field::*;
use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
use flowy_grid::services::row::CreateRowMetaPayload; use flowy_grid::services::row::CreateRowMetaPayload;
use flowy_grid_data_model::entities::{ 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, GridBlockMetaChangeset, RowMeta, RowMetaChangeset, RowOrder,
}; };
use flowy_grid_data_model::parser::CreateFieldParams; use flowy_grid_data_model::parser::CreateFieldParams;

View File

@ -1,8 +1,11 @@
use crate::parser::NotEmptyUuid; use crate::parser::NotEmptyUuid;
use bytes::Bytes;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error_code::ErrorCode; use flowy_error_code::ErrorCode;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::Deref;
use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
pub const DEFAULT_ROW_HEIGHT: i32 = 36; pub const DEFAULT_ROW_HEIGHT: i32 = 36;
@ -76,7 +79,7 @@ pub struct GridBlockMetaSerde {
pub row_metas: Vec<RowMeta>, pub row_metas: Vec<RowMeta>,
} }
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf, PartialEq, Eq)] #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
pub struct FieldMeta { pub struct FieldMeta {
#[pb(index = 1)] #[pb(index = 1)]
pub id: String, pub id: String,
@ -100,7 +103,7 @@ pub struct FieldMeta {
pub width: i32, pub width: i32,
#[pb(index = 8)] #[pb(index = 8)]
pub type_option_json: String, pub type_option_by_field_type_id: TypeOptionDataByFieldTypeId,
} }
impl FieldMeta { impl FieldMeta {
@ -113,7 +116,55 @@ impl FieldMeta {
frozen: false, frozen: false,
visibility: true, visibility: true,
width: DEFAULT_FIELD_WIDTH, 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<String> {
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<String, String>,
}
impl TypeOptionDataByFieldTypeId {
pub fn insert_entry<T: TypeOptionDataEntry + ?Sized>(&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<T: TypeOptionDataFrom>(&self, field_type: &FieldType) -> Option<T> {
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<String> {
match self.map.get(&field_type.type_id()) {
None => None,
Some(s) => Some(s.to_owned()),
} }
} }
} }

View File

@ -727,7 +727,7 @@ pub struct FieldMeta {
pub frozen: bool, pub frozen: bool,
pub visibility: bool, pub visibility: bool,
pub width: i32, pub width: i32,
pub type_option_json: ::std::string::String, pub type_option_by_field_type_id: ::protobuf::SingularPtrField<TypeOptionDataByFieldTypeId>,
// special fields // special fields
pub unknown_fields: ::protobuf::UnknownFields, pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize, pub cached_size: ::protobuf::CachedSize,
@ -882,35 +882,47 @@ impl FieldMeta {
self.width = v; self.width = v;
} }
// string type_option_json = 8; // .TypeOptionDataByFieldTypeId type_option_by_field_type_id = 8;
pub fn get_type_option_json(&self) -> &str { pub fn get_type_option_by_field_type_id(&self) -> &TypeOptionDataByFieldTypeId {
&self.type_option_json self.type_option_by_field_type_id.as_ref().unwrap_or_else(|| <TypeOptionDataByFieldTypeId as ::protobuf::Message>::default_instance())
} }
pub fn clear_type_option_json(&mut self) { pub fn clear_type_option_by_field_type_id(&mut self) {
self.type_option_json.clear(); 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 // Param is passed by value, moved
pub fn set_type_option_json(&mut self, v: ::std::string::String) { pub fn set_type_option_by_field_type_id(&mut self, v: TypeOptionDataByFieldTypeId) {
self.type_option_json = v; self.type_option_by_field_type_id = ::protobuf::SingularPtrField::some(v);
} }
// Mutable pointer to the field. // Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first. // If field is not initialized, it is initialized with default value first.
pub fn mut_type_option_json(&mut self) -> &mut ::std::string::String { pub fn mut_type_option_by_field_type_id(&mut self) -> &mut TypeOptionDataByFieldTypeId {
&mut self.type_option_json 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 // Take field
pub fn take_type_option_json(&mut self) -> ::std::string::String { pub fn take_type_option_by_field_type_id(&mut self) -> TypeOptionDataByFieldTypeId {
::std::mem::replace(&mut self.type_option_json, ::std::string::String::new()) self.type_option_by_field_type_id.take().unwrap_or_else(|| TypeOptionDataByFieldTypeId::new())
} }
} }
impl ::protobuf::Message for FieldMeta { impl ::protobuf::Message for FieldMeta {
fn is_initialized(&self) -> bool { fn is_initialized(&self) -> bool {
for v in &self.type_option_by_field_type_id {
if !v.is_initialized() {
return false;
}
};
true true
} }
@ -952,7 +964,7 @@ impl ::protobuf::Message for FieldMeta {
self.width = tmp; self.width = tmp;
}, },
8 => { 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())?; ::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 { if self.width != 0 {
my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint); my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint);
} }
if !self.type_option_json.is_empty() { if let Some(ref v) = self.type_option_by_field_type_id.as_ref() {
my_size += ::protobuf::rt::string_size(8, &self.type_option_json); 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()); my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size); self.cached_size.set(my_size);
@ -1017,8 +1030,10 @@ impl ::protobuf::Message for FieldMeta {
if self.width != 0 { if self.width != 0 {
os.write_int32(7, self.width)?; os.write_int32(7, self.width)?;
} }
if !self.type_option_json.is_empty() { if let Some(ref v) = self.type_option_by_field_type_id.as_ref() {
os.write_string(8, &self.type_option_json)?; 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())?; os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
@ -1093,10 +1108,10 @@ impl ::protobuf::Message for FieldMeta {
|m: &FieldMeta| { &m.width }, |m: &FieldMeta| { &m.width },
|m: &mut FieldMeta| { &mut m.width }, |m: &mut FieldMeta| { &mut m.width },
)); ));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<TypeOptionDataByFieldTypeId>>(
"type_option_json", "type_option_by_field_type_id",
|m: &FieldMeta| { &m.type_option_json }, |m: &FieldMeta| { &m.type_option_by_field_type_id },
|m: &mut FieldMeta| { &mut m.type_option_json }, |m: &mut FieldMeta| { &mut m.type_option_by_field_type_id },
)); ));
::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldMeta>( ::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldMeta>(
"FieldMeta", "FieldMeta",
@ -1121,7 +1136,7 @@ impl ::protobuf::Clear for FieldMeta {
self.frozen = false; self.frozen = false;
self.visibility = false; self.visibility = false;
self.width = 0; self.width = 0;
self.type_option_json.clear(); self.type_option_by_field_type_id.clear();
self.unknown_fields.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 {
<TypeOptionDataByFieldTypeId as ::protobuf::Message>::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<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
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>(
"TypeOptionDataByFieldTypeId",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static TypeOptionDataByFieldTypeId {
static instance: ::protobuf::rt::LazyV2<TypeOptionDataByFieldTypeId> = ::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)] #[derive(PartialEq,Clone,Default)]
pub struct FieldChangesetPayload { pub struct FieldChangesetPayload {
// message fields // 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\ 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\ \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_\ 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\ 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)\ \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\ \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\ \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\ \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\"\ idth\x12[\n\x1ctype_option_by_field_type_id\x18\x08\x20\x01(\x0b2\x1c.Ty\
\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\x20\ peOptionDataByFieldTypeIdR\x17typeOptionByFieldTypeId\"\x8e\x01\n\x1bTyp\
\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\ eOptionDataByFieldTypeId\x127\n\x03map\x18\x01\x20\x03(\x0b2%.TypeOption\
\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\ DataByFieldTypeId.MapEntryR\x03map\x1a6\n\x08MapEntry\x12\x10\n\x03key\
\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n\ \x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05va\
.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\ lue:\x028\x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\
\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibi\ \x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\
lity\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\x10ty\ \x06gridId\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\
pe_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\r\n\x0bone_of\ \x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\
_nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_fro\ \x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\
zenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x19\n\x17one_of_\ \x01(\x08H\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\
type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\t\ \x04R\nvisibility\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\
R\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\ \x12*\n\x10type_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\
\n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08blo\ \r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\
ck_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\ \n\rone_of_frozenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\
\x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\ \x19\n\x17one_of_type_option_data\"8\n\x07AnyData\x12\x17\n\x07type_id\
\x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\ \x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\
\x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\ \x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02\
\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.C\ id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_b\
ellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\ y_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellBy\
\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\ FieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nv\
\x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\ isibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\
\nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaCh\
angeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\
\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\ \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\ \x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChan\
\n\x11one_of_visibility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\ geset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06heig\
\x20\x01(\tR\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\ ht\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\
\x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ \x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\
\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\ \x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rcellByFieldId\x1aK\n\x12Cel\
\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\ lByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\
\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridCont\ \x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\ro\
ext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\ ne_of_heightB\x13\n\x11one_of_visibility\"9\n\x08CellMeta\x12\x19\n\x08f\
\x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMe\ ield_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x12\n\x04data\x18\x02\x20\x01\
tas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSer\ (\tR\x04data\"\x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\
deR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\ \x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05ro\
\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSele\ wId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04da\
ct\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\ ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10Bui\
\x05b\x06proto3\ 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; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -22,7 +22,10 @@ message FieldMeta {
bool frozen = 5; bool frozen = 5;
bool visibility = 6; bool visibility = 6;
int32 width = 7; int32 width = 7;
string type_option_json = 8; TypeOptionDataByFieldTypeId type_option_by_field_type_id = 8;
}
message TypeOptionDataByFieldTypeId {
map<string, string> map = 1;
} }
message FieldChangesetPayload { message FieldChangesetPayload {
string field_id = 1; string field_id = 1;

View File

@ -129,8 +129,8 @@ impl GridMetaPad {
if let Some(type_option_data) = changeset.type_option_data { if let Some(type_option_data) = changeset.type_option_data {
match deserializer.deserialize(type_option_data) { match deserializer.deserialize(type_option_data) {
Ok(type_option_json) => { Ok(json_str) => {
field.type_option_json = type_option_json; field.type_option_by_field_type_id.insert(&field.field_type, json_str);
is_changed = Some(()) is_changed = Some(())
} }
Err(err) => { Err(err) => {