فهرست منبع

chore: delete field

appflowy 3 سال پیش
والد
کامیت
c7bba01fe5
28فایلهای تغییر یافته به همراه540 افزوده شده و 397 حذف شده
  1. 6 1
      frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart
  2. 2 0
      frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart
  3. 38 1
      frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
  4. 3 3
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart
  5. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart
  6. 17 0
      frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
  7. 4 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart
  8. 3 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart
  9. 58 58
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart
  10. 7 7
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart
  11. 3 1
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
  12. 3 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
  13. 14 10
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  14. 5 1
      frontend/rust-lib/flowy-grid/src/event_map.rs
  15. 10 6
      frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
  16. 2 1
      frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
  17. 15 4
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  18. 2 2
      frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs
  19. 5 2
      shared-lib/flowy-error-code/src/code.rs
  20. 9 6
      shared-lib/flowy-error-code/src/protobuf/model/code.rs
  21. 2 1
      shared-lib/flowy-error-code/src/protobuf/proto/code.proto
  22. 108 0
      shared-lib/flowy-grid-data-model/src/entities/grid.rs
  23. 44 2
      shared-lib/flowy-grid-data-model/src/entities/meta.rs
  24. 0 112
      shared-lib/flowy-grid-data-model/src/parser/grid_params.rs
  25. 0 2
      shared-lib/flowy-grid-data-model/src/parser/mod.rs
  26. 163 162
      shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs
  27. 2 2
      shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto
  28. 13 5
      shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs

+ 6 - 1
frontend/app_flowy/lib/workspace/application/grid/field/create_field_bloc.dart

@@ -44,7 +44,12 @@ class CreateFieldBloc extends Bloc<CreateFieldEvent, CreateFieldState> {
     await state.field.fold(
       () async => null,
       (field) async {
-        final result = await service.createField(field: field, typeOptionData: state.typeOptionData);
+        field.name = state.fieldName;
+
+        final result = await service.createField(
+          field: field,
+          typeOptionData: state.typeOptionData,
+        );
         result.fold((l) => null, (r) => null);
       },
     );

+ 2 - 0
frontend/app_flowy/lib/workspace/application/grid/field/edit_field_bloc.dart

@@ -21,6 +21,7 @@ class EditFieldBloc extends Bloc<EditFieldEvent, EditFieldState> {
           hideField: (_HideField value) {},
           deleteField: (_DeleteField value) {},
           duplicateField: (_DuplicateField value) {},
+          saveField: (_SaveField value) {},
         );
       },
     );
@@ -39,6 +40,7 @@ class EditFieldEvent with _$EditFieldEvent {
   const factory EditFieldEvent.hideField() = _HideField;
   const factory EditFieldEvent.duplicateField() = _DuplicateField;
   const factory EditFieldEvent.deleteField() = _DeleteField;
+  const factory EditFieldEvent.saveField() = _SaveField;
 }
 
 @freezed

+ 38 - 1
frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart

@@ -6,7 +6,6 @@ import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 
 class FieldService {
   final String gridId;
@@ -21,6 +20,44 @@ class FieldService {
     return GridEventCreateEditFieldContext(payload).send();
   }
 
+  Future<Either<Unit, FlowyError>> updateField({
+    required Field field,
+    String? name,
+    FieldType? fieldType,
+    bool? frozen,
+    bool? visibility,
+    double? width,
+    List<int>? typeOptionData,
+  }) {
+    var payload = FieldChangesetPayload.create()..gridId = gridId;
+
+    if (name != null) {
+      payload.name = name;
+    }
+
+    if (fieldType != null) {
+      payload.fieldType = fieldType;
+    }
+
+    if (frozen != null) {
+      payload.frozen = frozen;
+    }
+
+    if (visibility != null) {
+      payload.visibility = visibility;
+    }
+
+    if (width != null) {
+      payload.width = width.toInt();
+    }
+
+    if (typeOptionData != null) {
+      payload.typeOptionData = typeOptionData;
+    }
+
+    return GridEventUpdateField(payload).send();
+  }
+
   Future<Either<Unit, FlowyError>> createField({
     required Field field,
     List<int>? typeOptionData,

+ 3 - 3
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart → frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/edit_field_pannel.dart

@@ -10,12 +10,12 @@ import 'field_name_input.dart';
 import 'field_operation_list.dart';
 import 'field_tyep_switcher.dart';
 
-class FieldEditor extends StatelessWidget {
+class EditFieldPannel extends StatelessWidget {
   final GridFieldData fieldData;
-  const FieldEditor({required this.fieldData, Key? key}) : super(key: key);
+  const EditFieldPannel({required this.fieldData, Key? key}) : super(key: key);
 
   static void show(BuildContext context, GridFieldData fieldData) {
-    final editor = FieldEditor(fieldData: fieldData);
+    final editor = EditFieldPannel(fieldData: fieldData);
     FlowyOverlay.of(context).insertWithAnchor(
       widget: OverlayContainer(
         child: editor,

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart

@@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
-import 'field_editor.dart';
+import 'edit_field_pannel.dart';
 
 class HeaderCell extends StatelessWidget {
   final GridFieldData fieldData;
@@ -18,7 +18,7 @@ class HeaderCell extends StatelessWidget {
     final theme = context.watch<AppTheme>();
     final button = FlowyButton(
       hoverColor: theme.hover,
-      onTap: () => FieldEditor.show(context, fieldData),
+      onTap: () => EditFieldPannel.show(context, fieldData),
       rightIcon: svg("editor/details", color: theme.iconColor),
       text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)),
     );

+ 17 - 0
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart

@@ -86,6 +86,23 @@ class GridEventCreateField {
     }
 }
 
+class GridEventDeleteField {
+     FieldOrder request;
+     GridEventDeleteField(this.request);
+
+    Future<Either<Unit, FlowyError>> send() {
+    final request = FFIRequest.create()
+          ..event = GridEvent.DeleteField.toString()
+          ..payload = requestToBytes(this.request);
+
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+           (bytes) => left(unit),
+           (errBytes) => right(FlowyError.fromBuffer(errBytes)),
+        ));
+    }
+}
+
 class GridEventCreateEditFieldContext {
      CreateEditFieldContextParams request;
      GridEventCreateEditFieldContext(this.request);

+ 4 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbenum.dart

@@ -46,7 +46,8 @@ class ErrorCode extends $pb.ProtobufEnum {
   static const ErrorCode BlockIdIsEmpty = ErrorCode._(420, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'BlockIdIsEmpty');
   static const ErrorCode RowIdIsEmpty = ErrorCode._(430, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RowIdIsEmpty');
   static const ErrorCode FieldIdIsEmpty = ErrorCode._(440, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldIdIsEmpty');
-  static const ErrorCode TypeOptionIsEmpty = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionIsEmpty');
+  static const ErrorCode FieldDoesNotExist = ErrorCode._(441, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'FieldDoesNotExist');
+  static const ErrorCode TypeOptionDataIsEmpty = ErrorCode._(450, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TypeOptionDataIsEmpty');
   static const ErrorCode InvalidData = ErrorCode._(500, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InvalidData');
 
   static const $core.List<ErrorCode> values = <ErrorCode> [
@@ -86,7 +87,8 @@ class ErrorCode extends $pb.ProtobufEnum {
     BlockIdIsEmpty,
     RowIdIsEmpty,
     FieldIdIsEmpty,
-    TypeOptionIsEmpty,
+    FieldDoesNotExist,
+    TypeOptionDataIsEmpty,
     InvalidData,
   ];
 

+ 3 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error-code/code.pbjson.dart

@@ -48,10 +48,11 @@ const ErrorCode$json = const {
     const {'1': 'BlockIdIsEmpty', '2': 420},
     const {'1': 'RowIdIsEmpty', '2': 430},
     const {'1': 'FieldIdIsEmpty', '2': 440},
-    const {'1': 'TypeOptionIsEmpty', '2': 441},
+    const {'1': 'FieldDoesNotExist', '2': 441},
+    const {'1': 'TypeOptionDataIsEmpty', '2': 450},
     const {'1': 'InvalidData', '2': 500},
   ],
 };
 
 /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFUeXBlT3B0aW9uSXNFbXB0eRC5AxIQCgtJbnZhbGlkRGF0YRD0Aw==');
+final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIRCg1Vc2VySWRJc0VtcHR5EAQSGAoUV29ya3NwYWNlTmFtZUludmFsaWQQZBIWChJXb3Jrc3BhY2VJZEludmFsaWQQZRIYChRBcHBDb2xvclN0eWxlSW52YWxpZBBmEhgKFFdvcmtzcGFjZURlc2NUb29Mb25nEGcSGAoUV29ya3NwYWNlTmFtZVRvb0xvbmcQaBIQCgxBcHBJZEludmFsaWQQbhISCg5BcHBOYW1lSW52YWxpZBBvEhMKD1ZpZXdOYW1lSW52YWxpZBB4EhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEHkSEQoNVmlld0lkSW52YWxpZBB6EhMKD1ZpZXdEZXNjVG9vTG9uZxB7EhMKD1ZpZXdEYXRhSW52YWxpZBB8EhMKD1ZpZXdOYW1lVG9vTG9uZxB9EhEKDENvbm5lY3RFcnJvchDIARIRCgxFbWFpbElzRW1wdHkQrAISFwoSRW1haWxGb3JtYXRJbnZhbGlkEK0CEhcKEkVtYWlsQWxyZWFkeUV4aXN0cxCuAhIUCg9QYXNzd29yZElzRW1wdHkQrwISFAoPUGFzc3dvcmRUb29Mb25nELACEiUKIFBhc3N3b3JkQ29udGFpbnNGb3JiaWRDaGFyYWN0ZXJzELECEhoKFVBhc3N3b3JkRm9ybWF0SW52YWxpZBCyAhIVChBQYXNzd29yZE5vdE1hdGNoELMCEhQKD1VzZXJOYW1lVG9vTG9uZxC0AhInCiJVc2VyTmFtZUNvbnRhaW5Gb3JiaWRkZW5DaGFyYWN0ZXJzELUCEhQKD1VzZXJOYW1lSXNFbXB0eRC2AhISCg1Vc2VySWRJbnZhbGlkELcCEhEKDFVzZXJOb3RFeGlzdBC4AhIQCgtUZXh0VG9vTG9uZxCQAxISCg1HcmlkSWRJc0VtcHR5EJoDEhMKDkJsb2NrSWRJc0VtcHR5EKQDEhEKDFJvd0lkSXNFbXB0eRCuAxITCg5GaWVsZElkSXNFbXB0eRC4AxIWChFGaWVsZERvZXNOb3RFeGlzdBC5AxIaChVUeXBlT3B0aW9uRGF0YUlzRW1wdHkQwgMSEAoLSW52YWxpZERhdGEQ9AM=');

+ 58 - 58
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart

@@ -351,71 +351,71 @@ class FieldMeta extends $pb.GeneratedMessage {
   void clearTypeOptionJson() => clearField(8);
 }
 
-enum FieldChangeset_OneOfName {
+enum FieldChangesetPayload_OneOfName {
   name, 
   notSet
 }
 
-enum FieldChangeset_OneOfDesc {
+enum FieldChangesetPayload_OneOfDesc {
   desc, 
   notSet
 }
 
-enum FieldChangeset_OneOfFieldType {
+enum FieldChangesetPayload_OneOfFieldType {
   fieldType, 
   notSet
 }
 
-enum FieldChangeset_OneOfFrozen {
+enum FieldChangesetPayload_OneOfFrozen {
   frozen, 
   notSet
 }
 
-enum FieldChangeset_OneOfVisibility {
+enum FieldChangesetPayload_OneOfVisibility {
   visibility, 
   notSet
 }
 
-enum FieldChangeset_OneOfWidth {
+enum FieldChangesetPayload_OneOfWidth {
   width, 
   notSet
 }
 
-enum FieldChangeset_OneOfTypeOptions {
-  typeOptions, 
+enum FieldChangesetPayload_OneOfTypeOptionData {
+  typeOptionData, 
   notSet
 }
 
-class FieldChangeset extends $pb.GeneratedMessage {
-  static const $core.Map<$core.int, FieldChangeset_OneOfName> _FieldChangeset_OneOfNameByTag = {
-    3 : FieldChangeset_OneOfName.name,
-    0 : FieldChangeset_OneOfName.notSet
+class FieldChangesetPayload extends $pb.GeneratedMessage {
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfName> _FieldChangesetPayload_OneOfNameByTag = {
+    3 : FieldChangesetPayload_OneOfName.name,
+    0 : FieldChangesetPayload_OneOfName.notSet
   };
-  static const $core.Map<$core.int, FieldChangeset_OneOfDesc> _FieldChangeset_OneOfDescByTag = {
-    4 : FieldChangeset_OneOfDesc.desc,
-    0 : FieldChangeset_OneOfDesc.notSet
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfDesc> _FieldChangesetPayload_OneOfDescByTag = {
+    4 : FieldChangesetPayload_OneOfDesc.desc,
+    0 : FieldChangesetPayload_OneOfDesc.notSet
   };
-  static const $core.Map<$core.int, FieldChangeset_OneOfFieldType> _FieldChangeset_OneOfFieldTypeByTag = {
-    5 : FieldChangeset_OneOfFieldType.fieldType,
-    0 : FieldChangeset_OneOfFieldType.notSet
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfFieldType> _FieldChangesetPayload_OneOfFieldTypeByTag = {
+    5 : FieldChangesetPayload_OneOfFieldType.fieldType,
+    0 : FieldChangesetPayload_OneOfFieldType.notSet
   };
-  static const $core.Map<$core.int, FieldChangeset_OneOfFrozen> _FieldChangeset_OneOfFrozenByTag = {
-    6 : FieldChangeset_OneOfFrozen.frozen,
-    0 : FieldChangeset_OneOfFrozen.notSet
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfFrozen> _FieldChangesetPayload_OneOfFrozenByTag = {
+    6 : FieldChangesetPayload_OneOfFrozen.frozen,
+    0 : FieldChangesetPayload_OneOfFrozen.notSet
   };
-  static const $core.Map<$core.int, FieldChangeset_OneOfVisibility> _FieldChangeset_OneOfVisibilityByTag = {
-    7 : FieldChangeset_OneOfVisibility.visibility,
-    0 : FieldChangeset_OneOfVisibility.notSet
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfVisibility> _FieldChangesetPayload_OneOfVisibilityByTag = {
+    7 : FieldChangesetPayload_OneOfVisibility.visibility,
+    0 : FieldChangesetPayload_OneOfVisibility.notSet
   };
-  static const $core.Map<$core.int, FieldChangeset_OneOfWidth> _FieldChangeset_OneOfWidthByTag = {
-    8 : FieldChangeset_OneOfWidth.width,
-    0 : FieldChangeset_OneOfWidth.notSet
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfWidth> _FieldChangesetPayload_OneOfWidthByTag = {
+    8 : FieldChangesetPayload_OneOfWidth.width,
+    0 : FieldChangesetPayload_OneOfWidth.notSet
   };
-  static const $core.Map<$core.int, FieldChangeset_OneOfTypeOptions> _FieldChangeset_OneOfTypeOptionsByTag = {
-    9 : FieldChangeset_OneOfTypeOptions.typeOptions,
-    0 : FieldChangeset_OneOfTypeOptions.notSet
+  static const $core.Map<$core.int, FieldChangesetPayload_OneOfTypeOptionData> _FieldChangesetPayload_OneOfTypeOptionDataByTag = {
+    9 : FieldChangesetPayload_OneOfTypeOptionData.typeOptionData,
+    0 : FieldChangesetPayload_OneOfTypeOptionData.notSet
   };
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldChangeset', createEmptyInstance: create)
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldChangesetPayload', createEmptyInstance: create)
     ..oo(0, [3])
     ..oo(1, [4])
     ..oo(2, [5])
@@ -431,12 +431,12 @@ class FieldChangeset extends $pb.GeneratedMessage {
     ..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen')
     ..aOB(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility')
     ..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3)
-    ..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions')
+    ..a<$core.List<$core.int>>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptionData', $pb.PbFieldType.OY)
     ..hasRequiredFields = false
   ;
 
-  FieldChangeset._() : super();
-  factory FieldChangeset({
+  FieldChangesetPayload._() : super();
+  factory FieldChangesetPayload({
     $core.String? fieldId,
     $core.String? gridId,
     $core.String? name,
@@ -445,7 +445,7 @@ class FieldChangeset extends $pb.GeneratedMessage {
     $core.bool? frozen,
     $core.bool? visibility,
     $core.int? width,
-    $core.String? typeOptions,
+    $core.List<$core.int>? typeOptionData,
   }) {
     final _result = create();
     if (fieldId != null) {
@@ -472,52 +472,52 @@ class FieldChangeset extends $pb.GeneratedMessage {
     if (width != null) {
       _result.width = width;
     }
-    if (typeOptions != null) {
-      _result.typeOptions = typeOptions;
+    if (typeOptionData != null) {
+      _result.typeOptionData = typeOptionData;
     }
     return _result;
   }
-  factory FieldChangeset.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory FieldChangeset.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory FieldChangesetPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory FieldChangesetPayload.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')
-  FieldChangeset clone() => FieldChangeset()..mergeFromMessage(this);
+  FieldChangesetPayload clone() => FieldChangesetPayload()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  FieldChangeset copyWith(void Function(FieldChangeset) updates) => super.copyWith((message) => updates(message as FieldChangeset)) as FieldChangeset; // ignore: deprecated_member_use
+  FieldChangesetPayload copyWith(void Function(FieldChangesetPayload) updates) => super.copyWith((message) => updates(message as FieldChangesetPayload)) as FieldChangesetPayload; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static FieldChangeset create() => FieldChangeset._();
-  FieldChangeset createEmptyInstance() => create();
-  static $pb.PbList<FieldChangeset> createRepeated() => $pb.PbList<FieldChangeset>();
+  static FieldChangesetPayload create() => FieldChangesetPayload._();
+  FieldChangesetPayload createEmptyInstance() => create();
+  static $pb.PbList<FieldChangesetPayload> createRepeated() => $pb.PbList<FieldChangesetPayload>();
   @$core.pragma('dart2js:noInline')
-  static FieldChangeset getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldChangeset>(create);
-  static FieldChangeset? _defaultInstance;
+  static FieldChangesetPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldChangesetPayload>(create);
+  static FieldChangesetPayload? _defaultInstance;
 
-  FieldChangeset_OneOfName whichOneOfName() => _FieldChangeset_OneOfNameByTag[$_whichOneof(0)]!;
+  FieldChangesetPayload_OneOfName whichOneOfName() => _FieldChangesetPayload_OneOfNameByTag[$_whichOneof(0)]!;
   void clearOneOfName() => clearField($_whichOneof(0));
 
-  FieldChangeset_OneOfDesc whichOneOfDesc() => _FieldChangeset_OneOfDescByTag[$_whichOneof(1)]!;
+  FieldChangesetPayload_OneOfDesc whichOneOfDesc() => _FieldChangesetPayload_OneOfDescByTag[$_whichOneof(1)]!;
   void clearOneOfDesc() => clearField($_whichOneof(1));
 
-  FieldChangeset_OneOfFieldType whichOneOfFieldType() => _FieldChangeset_OneOfFieldTypeByTag[$_whichOneof(2)]!;
+  FieldChangesetPayload_OneOfFieldType whichOneOfFieldType() => _FieldChangesetPayload_OneOfFieldTypeByTag[$_whichOneof(2)]!;
   void clearOneOfFieldType() => clearField($_whichOneof(2));
 
-  FieldChangeset_OneOfFrozen whichOneOfFrozen() => _FieldChangeset_OneOfFrozenByTag[$_whichOneof(3)]!;
+  FieldChangesetPayload_OneOfFrozen whichOneOfFrozen() => _FieldChangesetPayload_OneOfFrozenByTag[$_whichOneof(3)]!;
   void clearOneOfFrozen() => clearField($_whichOneof(3));
 
-  FieldChangeset_OneOfVisibility whichOneOfVisibility() => _FieldChangeset_OneOfVisibilityByTag[$_whichOneof(4)]!;
+  FieldChangesetPayload_OneOfVisibility whichOneOfVisibility() => _FieldChangesetPayload_OneOfVisibilityByTag[$_whichOneof(4)]!;
   void clearOneOfVisibility() => clearField($_whichOneof(4));
 
-  FieldChangeset_OneOfWidth whichOneOfWidth() => _FieldChangeset_OneOfWidthByTag[$_whichOneof(5)]!;
+  FieldChangesetPayload_OneOfWidth whichOneOfWidth() => _FieldChangesetPayload_OneOfWidthByTag[$_whichOneof(5)]!;
   void clearOneOfWidth() => clearField($_whichOneof(5));
 
-  FieldChangeset_OneOfTypeOptions whichOneOfTypeOptions() => _FieldChangeset_OneOfTypeOptionsByTag[$_whichOneof(6)]!;
-  void clearOneOfTypeOptions() => clearField($_whichOneof(6));
+  FieldChangesetPayload_OneOfTypeOptionData whichOneOfTypeOptionData() => _FieldChangesetPayload_OneOfTypeOptionDataByTag[$_whichOneof(6)]!;
+  void clearOneOfTypeOptionData() => clearField($_whichOneof(6));
 
   @$pb.TagNumber(1)
   $core.String get fieldId => $_getSZ(0);
@@ -592,13 +592,13 @@ class FieldChangeset extends $pb.GeneratedMessage {
   void clearWidth() => clearField(8);
 
   @$pb.TagNumber(9)
-  $core.String get typeOptions => $_getSZ(8);
+  $core.List<$core.int> get typeOptionData => $_getN(8);
   @$pb.TagNumber(9)
-  set typeOptions($core.String v) { $_setString(8, v); }
+  set typeOptionData($core.List<$core.int> v) { $_setBytes(8, v); }
   @$pb.TagNumber(9)
-  $core.bool hasTypeOptions() => $_has(8);
+  $core.bool hasTypeOptionData() => $_has(8);
   @$pb.TagNumber(9)
-  void clearTypeOptions() => clearField(9);
+  void clearTypeOptionData() => clearField(9);
 }
 
 class AnyData extends $pb.GeneratedMessage {

+ 7 - 7
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart

@@ -75,9 +75,9 @@ const FieldMeta$json = const {
 
 /// Descriptor for `FieldMeta`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List fieldMetaDescriptor = $convert.base64Decode('CglGaWVsZE1ldGESDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIpCgpmaWVsZF90eXBlGAQgASgOMgouRmllbGRUeXBlUglmaWVsZFR5cGUSFgoGZnJvemVuGAUgASgIUgZmcm96ZW4SHgoKdmlzaWJpbGl0eRgGIAEoCFIKdmlzaWJpbGl0eRIUCgV3aWR0aBgHIAEoBVIFd2lkdGgSKAoQdHlwZV9vcHRpb25fanNvbhgIIAEoCVIOdHlwZU9wdGlvbkpzb24=');
-@$core.Deprecated('Use fieldChangesetDescriptor instead')
-const FieldChangeset$json = const {
-  '1': 'FieldChangeset',
+@$core.Deprecated('Use fieldChangesetPayloadDescriptor instead')
+const FieldChangesetPayload$json = const {
+  '1': 'FieldChangesetPayload',
   '2': const [
     const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'},
     const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'},
@@ -87,7 +87,7 @@ const FieldChangeset$json = const {
     const {'1': 'frozen', '3': 6, '4': 1, '5': 8, '9': 3, '10': 'frozen'},
     const {'1': 'visibility', '3': 7, '4': 1, '5': 8, '9': 4, '10': 'visibility'},
     const {'1': 'width', '3': 8, '4': 1, '5': 5, '9': 5, '10': 'width'},
-    const {'1': 'type_options', '3': 9, '4': 1, '5': 9, '9': 6, '10': 'typeOptions'},
+    const {'1': 'type_option_data', '3': 9, '4': 1, '5': 12, '9': 6, '10': 'typeOptionData'},
   ],
   '8': const [
     const {'1': 'one_of_name'},
@@ -96,12 +96,12 @@ const FieldChangeset$json = const {
     const {'1': 'one_of_frozen'},
     const {'1': 'one_of_visibility'},
     const {'1': 'one_of_width'},
-    const {'1': 'one_of_type_options'},
+    const {'1': 'one_of_type_option_data'},
   ],
 };
 
-/// Descriptor for `FieldChangeset`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List fieldChangesetDescriptor = $convert.base64Decode('Cg5GaWVsZENoYW5nZXNldBIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBIXCgdncmlkX2lkGAIgASgJUgZncmlkSWQSFAoEbmFtZRgDIAEoCUgAUgRuYW1lEhQKBGRlc2MYBCABKAlIAVIEZGVzYxIrCgpmaWVsZF90eXBlGAUgASgOMgouRmllbGRUeXBlSAJSCWZpZWxkVHlwZRIYCgZmcm96ZW4YBiABKAhIA1IGZnJvemVuEiAKCnZpc2liaWxpdHkYByABKAhIBFIKdmlzaWJpbGl0eRIWCgV3aWR0aBgIIAEoBUgFUgV3aWR0aBIjCgx0eXBlX29wdGlvbnMYCSABKAlIBlILdHlwZU9wdGlvbnNCDQoLb25lX29mX25hbWVCDQoLb25lX29mX2Rlc2NCEwoRb25lX29mX2ZpZWxkX3R5cGVCDwoNb25lX29mX2Zyb3plbkITChFvbmVfb2ZfdmlzaWJpbGl0eUIOCgxvbmVfb2Zfd2lkdGhCFQoTb25lX29mX3R5cGVfb3B0aW9ucw==');
+/// Descriptor for `FieldChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List fieldChangesetPayloadDescriptor = $convert.base64Decode('ChVGaWVsZENoYW5nZXNldFBheWxvYWQSGQoIZmllbGRfaWQYASABKAlSB2ZpZWxkSWQSFwoHZ3JpZF9pZBgCIAEoCVIGZ3JpZElkEhQKBG5hbWUYAyABKAlIAFIEbmFtZRIUCgRkZXNjGAQgASgJSAFSBGRlc2MSKwoKZmllbGRfdHlwZRgFIAEoDjIKLkZpZWxkVHlwZUgCUglmaWVsZFR5cGUSGAoGZnJvemVuGAYgASgISANSBmZyb3plbhIgCgp2aXNpYmlsaXR5GAcgASgISARSCnZpc2liaWxpdHkSFgoFd2lkdGgYCCABKAVIBVIFd2lkdGgSKgoQdHlwZV9vcHRpb25fZGF0YRgJIAEoDEgGUg50eXBlT3B0aW9uRGF0YUINCgtvbmVfb2ZfbmFtZUINCgtvbmVfb2ZfZGVzY0ITChFvbmVfb2ZfZmllbGRfdHlwZUIPCg1vbmVfb2ZfZnJvemVuQhMKEW9uZV9vZl92aXNpYmlsaXR5Qg4KDG9uZV9vZl93aWR0aEIZChdvbmVfb2ZfdHlwZV9vcHRpb25fZGF0YQ==');
 @$core.Deprecated('Use anyDataDescriptor instead')
 const AnyData$json = const {
   '1': 'AnyData',

+ 3 - 1
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart

@@ -15,7 +15,8 @@ class GridEvent extends $pb.ProtobufEnum {
   static const GridEvent GetFields = GridEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFields');
   static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField');
   static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField');
-  static const GridEvent CreateEditFieldContext = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext');
+  static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField');
+  static const GridEvent CreateEditFieldContext = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext');
   static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
   static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
   static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
@@ -26,6 +27,7 @@ class GridEvent extends $pb.ProtobufEnum {
     GetFields,
     UpdateField,
     CreateField,
+    DeleteField,
     CreateEditFieldContext,
     CreateRow,
     GetRow,

+ 3 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart

@@ -17,7 +17,8 @@ const GridEvent$json = const {
     const {'1': 'GetFields', '2': 10},
     const {'1': 'UpdateField', '2': 11},
     const {'1': 'CreateField', '2': 12},
-    const {'1': 'CreateEditFieldContext', '2': 13},
+    const {'1': 'DeleteField', '2': 13},
+    const {'1': 'CreateEditFieldContext', '2': 14},
     const {'1': 'CreateRow', '2': 21},
     const {'1': 'GetRow', '2': 22},
     const {'1': 'UpdateCell', '2': 30},
@@ -25,4 +26,4 @@ const GridEvent$json = const {
 };
 
 /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEhoKFkNyZWF0ZUVkaXRGaWVsZENvbnRleHQQDRINCglDcmVhdGVSb3cQFRIKCgZHZXRSb3cQFhIOCgpVcGRhdGVDZWxsEB4=');
+final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SGgoWQ3JlYXRlRWRpdEZpZWxkQ29udGV4dBAOEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg==');

+ 14 - 10
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -1,14 +1,7 @@
 use crate::manager::GridManager;
 use crate::services::field::type_option_data_from_str;
 use flowy_error::FlowyError;
-use flowy_grid_data_model::entities::{
-    CellMetaChangeset, CreateEditFieldContextParams, CreateFieldPayload, CreateRowPayload, EditFieldContext, Field,
-    FieldChangeset, Grid, GridId, QueryFieldPayload, QueryGridBlocksPayload, QueryRowPayload, RepeatedField,
-    RepeatedGridBlock, Row,
-};
-use flowy_grid_data_model::parser::{
-    CreateFieldParams, CreateRowParams, QueryFieldParams, QueryGridBlocksParams, QueryRowParams,
-};
+use flowy_grid_data_model::entities::*;
 use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
 use std::sync::Arc;
 
@@ -53,10 +46,10 @@ pub(crate) async fn get_fields_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn update_field_handler(
-    data: Data<FieldChangeset>,
+    data: Data<FieldChangesetPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let changeset: FieldChangeset = data.into_inner();
+    let changeset: FieldChangesetParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&changeset.grid_id)?;
     let _ = editor.update_field(changeset).await?;
     Ok(())
@@ -73,6 +66,17 @@ pub(crate) async fn create_field_handler(
     Ok(())
 }
 
+#[tracing::instrument(level = "debug", skip(data, manager), err)]
+pub(crate) async fn delete_field_handler(
+    data: Data<FieldOrder>,
+    manager: AppData<Arc<GridManager>>,
+) -> Result<(), FlowyError> {
+    let field_order: FieldOrder = data.into_inner();
+    let editor = manager.get_grid_editor(&params.grid_id)?;
+    let _ = editor.delete_field(&field_order.field_id).await?;
+    Ok(())
+}
+
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn create_edit_field_context_handler(
     data: Data<CreateEditFieldContextParams>,

+ 5 - 1
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -13,6 +13,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
         .event(GridEvent::GetFields, get_fields_handler)
         .event(GridEvent::UpdateField, update_field_handler)
         .event(GridEvent::CreateField, create_field_handler)
+        .event(GridEvent::DeleteField, create_field_handler)
         .event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler)
         .event(GridEvent::CreateRow, create_row_handler)
         .event(GridEvent::GetRow, get_row_handler)
@@ -39,8 +40,11 @@ pub enum GridEvent {
     #[event(input = "CreateFieldPayload")]
     CreateField = 12,
 
+    #[event(input = "FieldOrder")]
+    DeleteField = 13,
+
     #[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")]
-    CreateEditFieldContext = 13,
+    CreateEditFieldContext = 14,
 
     #[event(input = "CreateRowPayload", output = "Row")]
     CreateRow = 21,

+ 10 - 6
frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs

@@ -30,7 +30,8 @@ pub enum GridEvent {
     GetFields = 10,
     UpdateField = 11,
     CreateField = 12,
-    CreateEditFieldContext = 13,
+    DeleteField = 13,
+    CreateEditFieldContext = 14,
     CreateRow = 21,
     GetRow = 22,
     UpdateCell = 30,
@@ -48,7 +49,8 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             10 => ::std::option::Option::Some(GridEvent::GetFields),
             11 => ::std::option::Option::Some(GridEvent::UpdateField),
             12 => ::std::option::Option::Some(GridEvent::CreateField),
-            13 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext),
+            13 => ::std::option::Option::Some(GridEvent::DeleteField),
+            14 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext),
             21 => ::std::option::Option::Some(GridEvent::CreateRow),
             22 => ::std::option::Option::Some(GridEvent::GetRow),
             30 => ::std::option::Option::Some(GridEvent::UpdateCell),
@@ -63,6 +65,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             GridEvent::GetFields,
             GridEvent::UpdateField,
             GridEvent::CreateField,
+            GridEvent::DeleteField,
             GridEvent::CreateEditFieldContext,
             GridEvent::CreateRow,
             GridEvent::GetRow,
@@ -95,11 +98,12 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0fevent_map.proto*\xa7\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
+    \n\x0fevent_map.proto*\xb8\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
     \0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\
-    \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x1a\n\x16Cr\
-    eateEditFieldContext\x10\r\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\
-    \x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\
+    \x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\
+    leteField\x10\r\x12\x1a\n\x16CreateEditFieldContext\x10\x0e\x12\r\n\tCre\
+    ateRow\x10\x15\x12\n\n\x06GetRow\x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\
+    \x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 2 - 1
frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto

@@ -6,7 +6,8 @@ enum GridEvent {
     GetFields = 10;
     UpdateField = 11;
     CreateField = 12;
-    CreateEditFieldContext = 13;
+    DeleteField = 13;
+    CreateEditFieldContext = 14;
     CreateRow = 21;
     GetRow = 22;
     UpdateCell = 30;

+ 15 - 4
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -4,9 +4,8 @@ use crate::services::block_meta_editor::GridBlockMetaEditorManager;
 use crate::services::field::{type_option_json_str_from_bytes, FieldBuilder};
 use crate::services::row::*;
 use bytes::Bytes;
-use flowy_error::{FlowyError, FlowyResult};
+use flowy_error::{ErrorCode, FlowyError, FlowyResult};
 use flowy_grid_data_model::entities::*;
-use flowy_grid_data_model::parser::CreateFieldParams;
 use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
 use flowy_sync::client_grid::{GridChangeset, GridMetaPad};
 use flowy_sync::entities::revision::Revision;
@@ -87,8 +86,20 @@ impl ClientGridEditor {
         self.pad.read().await.contain_field(field_id)
     }
 
-    pub async fn update_field(&self, change: FieldChangeset) -> FlowyResult<()> {
-        let _ = self.modify(|grid| Ok(grid.update_field(change)?)).await?;
+    pub async fn update_field(&self, mut params: FieldChangesetParams) -> FlowyResult<()> {
+        if let Some(type_option_data) = params.type_option_data {
+            match self.pad.read().await.get_field(&params.field_id) {
+                None => return Err(ErrorCode::FieldDoesNotExist.into()),
+                Some(field_meta) => {
+                    // The type_option_data is serialized by protobuf. But the type_option_data should be
+                    // serialized by utf-8 encoding. So we must transform the data here.
+                    let type_option_json = type_option_json_str_from_bytes(type_option_data, &field_meta.field_type);
+                    params.type_option_data = Some(type_option_json.as_bytes().to_vec());
+                }
+            }
+        }
+
+        let _ = self.modify(|grid| Ok(grid.update_field(params)?)).await?;
         let _ = self.notify_did_update_fields().await?;
         Ok(())
     }

+ 2 - 2
frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs

@@ -64,7 +64,7 @@ async fn grid_update_field_with_empty_change() {
         frozen: None,
         visibility: None,
         width: None,
-        type_options: None,
+        type_option_data: None,
     };
 
     let scripts = vec![
@@ -95,7 +95,7 @@ async fn grid_update_field() {
         frozen: Some(true),
         visibility: None,
         width: Some(1000),
-        type_options: Some(single_select_type_options.clone().into()),
+        type_option_data: Some(single_select_type_options.clone().into()),
     };
 
     cloned_field.frozen = true;

+ 5 - 2
shared-lib/flowy-error-code/src/code.rs

@@ -97,8 +97,11 @@ pub enum ErrorCode {
     RowIdIsEmpty = 430,
     #[display(fmt = "Field id is empty")]
     FieldIdIsEmpty = 440,
-    #[display(fmt = "Field's type option should not be empty")]
-    TypeOptionIsEmpty = 441,
+    #[display(fmt = "Field doesn't exist")]
+    FieldDoesNotExist = 441,
+
+    #[display(fmt = "Field's type option data should not be empty")]
+    TypeOptionDataIsEmpty = 450,
 
     #[display(fmt = "Invalid data")]
     InvalidData = 500,

+ 9 - 6
shared-lib/flowy-error-code/src/protobuf/model/code.rs

@@ -61,7 +61,8 @@ pub enum ErrorCode {
     BlockIdIsEmpty = 420,
     RowIdIsEmpty = 430,
     FieldIdIsEmpty = 440,
-    TypeOptionIsEmpty = 441,
+    FieldDoesNotExist = 441,
+    TypeOptionDataIsEmpty = 450,
     InvalidData = 500,
 }
 
@@ -108,7 +109,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
             420 => ::std::option::Option::Some(ErrorCode::BlockIdIsEmpty),
             430 => ::std::option::Option::Some(ErrorCode::RowIdIsEmpty),
             440 => ::std::option::Option::Some(ErrorCode::FieldIdIsEmpty),
-            441 => ::std::option::Option::Some(ErrorCode::TypeOptionIsEmpty),
+            441 => ::std::option::Option::Some(ErrorCode::FieldDoesNotExist),
+            450 => ::std::option::Option::Some(ErrorCode::TypeOptionDataIsEmpty),
             500 => ::std::option::Option::Some(ErrorCode::InvalidData),
             _ => ::std::option::Option::None
         }
@@ -152,7 +154,8 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
             ErrorCode::BlockIdIsEmpty,
             ErrorCode::RowIdIsEmpty,
             ErrorCode::FieldIdIsEmpty,
-            ErrorCode::TypeOptionIsEmpty,
+            ErrorCode::FieldDoesNotExist,
+            ErrorCode::TypeOptionDataIsEmpty,
             ErrorCode::InvalidData,
         ];
         values
@@ -182,7 +185,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\ncode.proto*\xe4\x06\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\
+    \n\ncode.proto*\x80\x07\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\x12\x14\
     \n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\x03\x12\
     \x11\n\rUserIdIsEmpty\x10\x04\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\
     \x16\n\x12WorkspaceIdInvalid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\
@@ -202,8 +205,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     erNotExist\x10\xb8\x02\x12\x10\n\x0bTextTooLong\x10\x90\x03\x12\x12\n\rG\
     ridIdIsEmpty\x10\x9a\x03\x12\x13\n\x0eBlockIdIsEmpty\x10\xa4\x03\x12\x11\
     \n\x0cRowIdIsEmpty\x10\xae\x03\x12\x13\n\x0eFieldIdIsEmpty\x10\xb8\x03\
-    \x12\x16\n\x11TypeOptionIsEmpty\x10\xb9\x03\x12\x10\n\x0bInvalidData\x10\
-    \xf4\x03b\x06proto3\
+    \x12\x16\n\x11FieldDoesNotExist\x10\xb9\x03\x12\x1a\n\x15TypeOptionDataI\
+    sEmpty\x10\xc2\x03\x12\x10\n\x0bInvalidData\x10\xf4\x03b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 2 - 1
shared-lib/flowy-error-code/src/protobuf/proto/code.proto

@@ -37,6 +37,7 @@ enum ErrorCode {
     BlockIdIsEmpty = 420;
     RowIdIsEmpty = 430;
     FieldIdIsEmpty = 440;
-    TypeOptionIsEmpty = 441;
+    FieldDoesNotExist = 441;
+    TypeOptionDataIsEmpty = 450;
     InvalidData = 500;
 }

+ 108 - 0
shared-lib/flowy-grid-data-model/src/entities/grid.rs

@@ -1,5 +1,7 @@
 use crate::entities::{FieldMeta, FieldType, RowMeta};
+use crate::parser::NotEmptyUuid;
 use flowy_derive::ProtoBuf;
+use flowy_error_code::ErrorCode;
 use std::collections::HashMap;
 use std::sync::Arc;
 
@@ -311,6 +313,24 @@ pub struct CreateRowPayload {
     pub start_row_id: Option<String>,
 }
 
+#[derive(Default)]
+pub struct CreateRowParams {
+    pub grid_id: String,
+    pub start_row_id: Option<String>,
+}
+
+impl TryInto<CreateRowParams> for CreateRowPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateRowParams, Self::Error> {
+        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        Ok(CreateRowParams {
+            grid_id: grid_id.0,
+            start_row_id: self.start_row_id,
+        })
+    }
+}
+
 #[derive(ProtoBuf, Default)]
 pub struct CreateFieldPayload {
     #[pb(index = 1)]
@@ -326,6 +346,35 @@ pub struct CreateFieldPayload {
     pub start_field_id: Option<String>,
 }
 
+#[derive(Default, Clone)]
+pub struct CreateFieldParams {
+    pub grid_id: String,
+    pub field: Field,
+    pub type_option_data: Vec<u8>,
+    pub start_field_id: Option<String>,
+}
+
+impl TryInto<CreateFieldParams> for CreateFieldPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
+        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let _ = NotEmptyUuid::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+
+        let start_field_id = match self.start_field_id {
+            None => None,
+            Some(id) => Some(NotEmptyUuid::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
+        };
+
+        Ok(CreateFieldParams {
+            grid_id: grid_id.0,
+            field: self.field,
+            type_option_data: self.type_option_data,
+            start_field_id,
+        })
+    }
+}
+
 #[derive(ProtoBuf, Default)]
 pub struct QueryFieldPayload {
     #[pb(index = 1)]
@@ -335,6 +384,24 @@ pub struct QueryFieldPayload {
     pub field_orders: RepeatedFieldOrder,
 }
 
+#[derive(Default)]
+pub struct QueryFieldParams {
+    pub grid_id: String,
+    pub field_orders: RepeatedFieldOrder,
+}
+
+impl TryInto<QueryFieldParams> for QueryFieldPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<QueryFieldParams, Self::Error> {
+        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        Ok(QueryFieldParams {
+            grid_id: grid_id.0,
+            field_orders: self.field_orders,
+        })
+    }
+}
+
 #[derive(ProtoBuf, Default)]
 pub struct QueryGridBlocksPayload {
     #[pb(index = 1)]
@@ -344,6 +411,24 @@ pub struct QueryGridBlocksPayload {
     pub block_orders: Vec<GridBlockOrder>,
 }
 
+#[derive(Default)]
+pub struct QueryGridBlocksParams {
+    pub grid_id: String,
+    pub block_orders: Vec<GridBlockOrder>,
+}
+
+impl TryInto<QueryGridBlocksParams> for QueryGridBlocksPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<QueryGridBlocksParams, Self::Error> {
+        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        Ok(QueryGridBlocksParams {
+            grid_id: grid_id.0,
+            block_orders: self.block_orders,
+        })
+    }
+}
+
 #[derive(ProtoBuf, Default)]
 pub struct QueryRowPayload {
     #[pb(index = 1)]
@@ -355,3 +440,26 @@ pub struct QueryRowPayload {
     #[pb(index = 3)]
     pub row_id: String,
 }
+
+#[derive(Default)]
+pub struct QueryRowParams {
+    pub grid_id: String,
+    pub block_id: String,
+    pub row_id: String,
+}
+
+impl TryInto<QueryRowParams> for QueryRowPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<QueryRowParams, Self::Error> {
+        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let block_id = NotEmptyUuid::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
+        let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
+
+        Ok(QueryRowParams {
+            grid_id: grid_id.0,
+            block_id: block_id.0,
+            row_id: row_id.0,
+        })
+    }
+}

+ 44 - 2
shared-lib/flowy-grid-data-model/src/entities/meta.rs

@@ -1,4 +1,6 @@
+use crate::parser::NotEmptyUuid;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
+use flowy_error_code::ErrorCode;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
@@ -117,7 +119,7 @@ impl FieldMeta {
 }
 
 #[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct FieldChangeset {
+pub struct FieldChangesetPayload {
     #[pb(index = 1)]
     pub field_id: String,
 
@@ -143,7 +145,47 @@ pub struct FieldChangeset {
     pub width: Option<i32>,
 
     #[pb(index = 9, one_of)]
-    pub type_options: Option<String>,
+    pub type_option_data: Option<Vec<u8>>,
+}
+
+#[derive(Debug, Clone, Default)]
+pub struct FieldChangesetParams {
+    pub field_id: String,
+    pub grid_id: String,
+    pub name: Option<String>,
+    pub desc: Option<String>,
+    pub field_type: Option<FieldType>,
+    pub frozen: Option<bool>,
+    pub visibility: Option<bool>,
+    pub width: Option<i32>,
+    pub type_option_data: Option<Vec<u8>>,
+}
+
+impl TryInto<FieldChangesetParams> for FieldChangesetPayload {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<FieldChangesetParams, Self::Error> {
+        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+
+        if let Some(type_option_data) = self.type_option_data.as_ref() {
+            if type_option_data.is_empty() {
+                return Err(ErrorCode::TypeOptionDataIsEmpty);
+            }
+        }
+
+        Ok(FieldChangesetParams {
+            field_id: field_id.0,
+            grid_id: grid_id.0,
+            name: self.name,
+            desc: self.desc,
+            field_type: self.field_type,
+            frozen: self.frozen,
+            visibility: self.visibility,
+            width: self.width,
+            type_option_data: self.type_option_data,
+        })
+    }
 }
 
 #[derive(

+ 0 - 112
shared-lib/flowy-grid-data-model/src/parser/grid_params.rs

@@ -1,112 +0,0 @@
-use crate::entities::{
-    CreateFieldPayload, CreateRowPayload, Field, GridBlockOrder, QueryFieldPayload, QueryGridBlocksPayload,
-    QueryRowPayload, RepeatedFieldOrder,
-};
-use crate::parser::NotEmptyUuid;
-use flowy_error_code::ErrorCode;
-
-#[derive(Default)]
-pub struct CreateRowParams {
-    pub grid_id: String,
-    pub start_row_id: Option<String>,
-}
-
-impl TryInto<CreateRowParams> for CreateRowPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<CreateRowParams, Self::Error> {
-        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        Ok(CreateRowParams {
-            grid_id: grid_id.0,
-            start_row_id: self.start_row_id,
-        })
-    }
-}
-
-#[derive(Default)]
-pub struct QueryFieldParams {
-    pub grid_id: String,
-    pub field_orders: RepeatedFieldOrder,
-}
-
-impl TryInto<QueryFieldParams> for QueryFieldPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<QueryFieldParams, Self::Error> {
-        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        Ok(QueryFieldParams {
-            grid_id: grid_id.0,
-            field_orders: self.field_orders,
-        })
-    }
-}
-
-#[derive(Default)]
-pub struct QueryGridBlocksParams {
-    pub grid_id: String,
-    pub block_orders: Vec<GridBlockOrder>,
-}
-
-impl TryInto<QueryGridBlocksParams> for QueryGridBlocksPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<QueryGridBlocksParams, Self::Error> {
-        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        Ok(QueryGridBlocksParams {
-            grid_id: grid_id.0,
-            block_orders: self.block_orders,
-        })
-    }
-}
-
-#[derive(Default)]
-pub struct QueryRowParams {
-    pub grid_id: String,
-    pub block_id: String,
-    pub row_id: String,
-}
-
-impl TryInto<QueryRowParams> for QueryRowPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<QueryRowParams, Self::Error> {
-        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let block_id = NotEmptyUuid::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
-        let row_id = NotEmptyUuid::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
-
-        Ok(QueryRowParams {
-            grid_id: grid_id.0,
-            block_id: block_id.0,
-            row_id: row_id.0,
-        })
-    }
-}
-
-#[derive(Default, Clone)]
-pub struct CreateFieldParams {
-    pub grid_id: String,
-    pub field: Field,
-    pub type_option_data: Vec<u8>,
-    pub start_field_id: Option<String>,
-}
-
-impl TryInto<CreateFieldParams> for CreateFieldPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
-        let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let _ = NotEmptyUuid::parse(self.field.id.clone()).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
-
-        let start_field_id = match self.start_field_id {
-            None => None,
-            Some(id) => Some(NotEmptyUuid::parse(id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
-        };
-
-        Ok(CreateFieldParams {
-            grid_id: grid_id.0,
-            field: self.field,
-            type_option_data: self.type_option_data,
-            start_field_id,
-        })
-    }
-}

+ 0 - 2
shared-lib/flowy-grid-data-model/src/parser/mod.rs

@@ -1,5 +1,3 @@
-mod grid_params;
 mod id_parser;
 
-pub use grid_params::*;
 pub use id_parser::*;

+ 163 - 162
shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs

@@ -1139,66 +1139,66 @@ impl ::protobuf::reflect::ProtobufValue for FieldMeta {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct FieldChangeset {
+pub struct FieldChangesetPayload {
     // message fields
     pub field_id: ::std::string::String,
     pub grid_id: ::std::string::String,
     // message oneof groups
-    pub one_of_name: ::std::option::Option<FieldChangeset_oneof_one_of_name>,
-    pub one_of_desc: ::std::option::Option<FieldChangeset_oneof_one_of_desc>,
-    pub one_of_field_type: ::std::option::Option<FieldChangeset_oneof_one_of_field_type>,
-    pub one_of_frozen: ::std::option::Option<FieldChangeset_oneof_one_of_frozen>,
-    pub one_of_visibility: ::std::option::Option<FieldChangeset_oneof_one_of_visibility>,
-    pub one_of_width: ::std::option::Option<FieldChangeset_oneof_one_of_width>,
-    pub one_of_type_options: ::std::option::Option<FieldChangeset_oneof_one_of_type_options>,
+    pub one_of_name: ::std::option::Option<FieldChangesetPayload_oneof_one_of_name>,
+    pub one_of_desc: ::std::option::Option<FieldChangesetPayload_oneof_one_of_desc>,
+    pub one_of_field_type: ::std::option::Option<FieldChangesetPayload_oneof_one_of_field_type>,
+    pub one_of_frozen: ::std::option::Option<FieldChangesetPayload_oneof_one_of_frozen>,
+    pub one_of_visibility: ::std::option::Option<FieldChangesetPayload_oneof_one_of_visibility>,
+    pub one_of_width: ::std::option::Option<FieldChangesetPayload_oneof_one_of_width>,
+    pub one_of_type_option_data: ::std::option::Option<FieldChangesetPayload_oneof_one_of_type_option_data>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a FieldChangeset {
-    fn default() -> &'a FieldChangeset {
-        <FieldChangeset as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a FieldChangesetPayload {
+    fn default() -> &'a FieldChangesetPayload {
+        <FieldChangesetPayload as ::protobuf::Message>::default_instance()
     }
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_name {
+pub enum FieldChangesetPayload_oneof_one_of_name {
     name(::std::string::String),
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_desc {
+pub enum FieldChangesetPayload_oneof_one_of_desc {
     desc(::std::string::String),
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_field_type {
+pub enum FieldChangesetPayload_oneof_one_of_field_type {
     field_type(FieldType),
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_frozen {
+pub enum FieldChangesetPayload_oneof_one_of_frozen {
     frozen(bool),
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_visibility {
+pub enum FieldChangesetPayload_oneof_one_of_visibility {
     visibility(bool),
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_width {
+pub enum FieldChangesetPayload_oneof_one_of_width {
     width(i32),
 }
 
 #[derive(Clone,PartialEq,Debug)]
-pub enum FieldChangeset_oneof_one_of_type_options {
-    type_options(::std::string::String),
+pub enum FieldChangesetPayload_oneof_one_of_type_option_data {
+    type_option_data(::std::vec::Vec<u8>),
 }
 
-impl FieldChangeset {
-    pub fn new() -> FieldChangeset {
+impl FieldChangesetPayload {
+    pub fn new() -> FieldChangesetPayload {
         ::std::default::Default::default()
     }
 
@@ -1259,7 +1259,7 @@ impl FieldChangeset {
 
     pub fn get_name(&self) -> &str {
         match self.one_of_name {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(ref v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(ref v)) => v,
             _ => "",
         }
     }
@@ -1269,24 +1269,24 @@ impl FieldChangeset {
 
     pub fn has_name(&self) -> bool {
         match self.one_of_name {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(..)) => true,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
     pub fn set_name(&mut self, v: ::std::string::String) {
-        self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(v))
+        self.one_of_name = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(v))
     }
 
     // Mutable pointer to the field.
     pub fn mut_name(&mut self) -> &mut ::std::string::String {
-        if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(_)) = self.one_of_name {
+        if let ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(_)) = self.one_of_name {
         } else {
-            self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(::std::string::String::new()));
+            self.one_of_name = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(::std::string::String::new()));
         }
         match self.one_of_name {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(ref mut v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(ref mut v)) => v,
             _ => panic!(),
         }
     }
@@ -1295,7 +1295,7 @@ impl FieldChangeset {
     pub fn take_name(&mut self) -> ::std::string::String {
         if self.has_name() {
             match self.one_of_name.take() {
-                ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(v)) => v,
+                ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(v)) => v,
                 _ => panic!(),
             }
         } else {
@@ -1308,7 +1308,7 @@ impl FieldChangeset {
 
     pub fn get_desc(&self) -> &str {
         match self.one_of_desc {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(ref v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(ref v)) => v,
             _ => "",
         }
     }
@@ -1318,24 +1318,24 @@ impl FieldChangeset {
 
     pub fn has_desc(&self) -> bool {
         match self.one_of_desc {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(..)) => true,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
     pub fn set_desc(&mut self, v: ::std::string::String) {
-        self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(v))
+        self.one_of_desc = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(v))
     }
 
     // Mutable pointer to the field.
     pub fn mut_desc(&mut self) -> &mut ::std::string::String {
-        if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(_)) = self.one_of_desc {
+        if let ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(_)) = self.one_of_desc {
         } else {
-            self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(::std::string::String::new()));
+            self.one_of_desc = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(::std::string::String::new()));
         }
         match self.one_of_desc {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(ref mut v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(ref mut v)) => v,
             _ => panic!(),
         }
     }
@@ -1344,7 +1344,7 @@ impl FieldChangeset {
     pub fn take_desc(&mut self) -> ::std::string::String {
         if self.has_desc() {
             match self.one_of_desc.take() {
-                ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(v)) => v,
+                ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(v)) => v,
                 _ => panic!(),
             }
         } else {
@@ -1357,7 +1357,7 @@ impl FieldChangeset {
 
     pub fn get_field_type(&self) -> FieldType {
         match self.one_of_field_type {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(v)) => v,
             _ => FieldType::RichText,
         }
     }
@@ -1367,14 +1367,14 @@ impl FieldChangeset {
 
     pub fn has_field_type(&self) -> bool {
         match self.one_of_field_type {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(..)) => true,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
     pub fn set_field_type(&mut self, v: FieldType) {
-        self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v))
+        self.one_of_field_type = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(v))
     }
 
     // bool frozen = 6;
@@ -1382,7 +1382,7 @@ impl FieldChangeset {
 
     pub fn get_frozen(&self) -> bool {
         match self.one_of_frozen {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(v)) => v,
             _ => false,
         }
     }
@@ -1392,14 +1392,14 @@ impl FieldChangeset {
 
     pub fn has_frozen(&self) -> bool {
         match self.one_of_frozen {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(..)) => true,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
     pub fn set_frozen(&mut self, v: bool) {
-        self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v))
+        self.one_of_frozen = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(v))
     }
 
     // bool visibility = 7;
@@ -1407,7 +1407,7 @@ impl FieldChangeset {
 
     pub fn get_visibility(&self) -> bool {
         match self.one_of_visibility {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(v)) => v,
             _ => false,
         }
     }
@@ -1417,14 +1417,14 @@ impl FieldChangeset {
 
     pub fn has_visibility(&self) -> bool {
         match self.one_of_visibility {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(..)) => true,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
     pub fn set_visibility(&mut self, v: bool) {
-        self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v))
+        self.one_of_visibility = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(v))
     }
 
     // int32 width = 8;
@@ -1432,7 +1432,7 @@ impl FieldChangeset {
 
     pub fn get_width(&self) -> i32 {
         match self.one_of_width {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v)) => v,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(v)) => v,
             _ => 0,
         }
     }
@@ -1442,67 +1442,67 @@ impl FieldChangeset {
 
     pub fn has_width(&self) -> bool {
         match self.one_of_width {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(..)) => true,
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
     pub fn set_width(&mut self, v: i32) {
-        self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v))
+        self.one_of_width = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(v))
     }
 
-    // string type_options = 9;
+    // bytes type_option_data = 9;
 
 
-    pub fn get_type_options(&self) -> &str {
-        match self.one_of_type_options {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(ref v)) => v,
-            _ => "",
+    pub fn get_type_option_data(&self) -> &[u8] {
+        match self.one_of_type_option_data {
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref v)) => v,
+            _ => &[],
         }
     }
-    pub fn clear_type_options(&mut self) {
-        self.one_of_type_options = ::std::option::Option::None;
+    pub fn clear_type_option_data(&mut self) {
+        self.one_of_type_option_data = ::std::option::Option::None;
     }
 
-    pub fn has_type_options(&self) -> bool {
-        match self.one_of_type_options {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(..)) => true,
+    pub fn has_type_option_data(&self) -> bool {
+        match self.one_of_type_option_data {
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(..)) => true,
             _ => false,
         }
     }
 
     // Param is passed by value, moved
-    pub fn set_type_options(&mut self, v: ::std::string::String) {
-        self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(v))
+    pub fn set_type_option_data(&mut self, v: ::std::vec::Vec<u8>) {
+        self.one_of_type_option_data = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(v))
     }
 
     // Mutable pointer to the field.
-    pub fn mut_type_options(&mut self) -> &mut ::std::string::String {
-        if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(_)) = self.one_of_type_options {
+    pub fn mut_type_option_data(&mut self) -> &mut ::std::vec::Vec<u8> {
+        if let ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(_)) = self.one_of_type_option_data {
         } else {
-            self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(::std::string::String::new()));
+            self.one_of_type_option_data = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(::std::vec::Vec::new()));
         }
-        match self.one_of_type_options {
-            ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(ref mut v)) => v,
+        match self.one_of_type_option_data {
+            ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref mut v)) => v,
             _ => panic!(),
         }
     }
 
     // Take field
-    pub fn take_type_options(&mut self) -> ::std::string::String {
-        if self.has_type_options() {
-            match self.one_of_type_options.take() {
-                ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(v)) => v,
+    pub fn take_type_option_data(&mut self) -> ::std::vec::Vec<u8> {
+        if self.has_type_option_data() {
+            match self.one_of_type_option_data.take() {
+                ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(v)) => v,
                 _ => panic!(),
             }
         } else {
-            ::std::string::String::new()
+            ::std::vec::Vec::new()
         }
     }
 }
 
-impl ::protobuf::Message for FieldChangeset {
+impl ::protobuf::Message for FieldChangesetPayload {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -1521,43 +1521,43 @@ impl ::protobuf::Message for FieldChangeset {
                     if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(is.read_string()?));
+                    self.one_of_name = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_name::name(is.read_string()?));
                 },
                 4 => {
                     if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(is.read_string()?));
+                    self.one_of_desc = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_desc::desc(is.read_string()?));
                 },
                 5 => {
                     if wire_type != ::protobuf::wire_format::WireTypeVarint {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(is.read_enum()?));
+                    self.one_of_field_type = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_field_type::field_type(is.read_enum()?));
                 },
                 6 => {
                     if wire_type != ::protobuf::wire_format::WireTypeVarint {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(is.read_bool()?));
+                    self.one_of_frozen = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_frozen::frozen(is.read_bool()?));
                 },
                 7 => {
                     if wire_type != ::protobuf::wire_format::WireTypeVarint {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(is.read_bool()?));
+                    self.one_of_visibility = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_visibility::visibility(is.read_bool()?));
                 },
                 8 => {
                     if wire_type != ::protobuf::wire_format::WireTypeVarint {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(is.read_int32()?));
+                    self.one_of_width = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_width::width(is.read_int32()?));
                 },
                 9 => {
                     if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
                         return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
                     }
-                    self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(is.read_string()?));
+                    self.one_of_type_option_data = ::std::option::Option::Some(FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(is.read_bytes()?));
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -1579,50 +1579,50 @@ impl ::protobuf::Message for FieldChangeset {
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_name {
             match v {
-                &FieldChangeset_oneof_one_of_name::name(ref v) => {
+                &FieldChangesetPayload_oneof_one_of_name::name(ref v) => {
                     my_size += ::protobuf::rt::string_size(3, &v);
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_desc {
             match v {
-                &FieldChangeset_oneof_one_of_desc::desc(ref v) => {
+                &FieldChangesetPayload_oneof_one_of_desc::desc(ref v) => {
                     my_size += ::protobuf::rt::string_size(4, &v);
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_field_type {
             match v {
-                &FieldChangeset_oneof_one_of_field_type::field_type(v) => {
+                &FieldChangesetPayload_oneof_one_of_field_type::field_type(v) => {
                     my_size += ::protobuf::rt::enum_size(5, v);
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_frozen {
             match v {
-                &FieldChangeset_oneof_one_of_frozen::frozen(v) => {
+                &FieldChangesetPayload_oneof_one_of_frozen::frozen(v) => {
                     my_size += 2;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_visibility {
             match v {
-                &FieldChangeset_oneof_one_of_visibility::visibility(v) => {
+                &FieldChangesetPayload_oneof_one_of_visibility::visibility(v) => {
                     my_size += 2;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_width {
             match v {
-                &FieldChangeset_oneof_one_of_width::width(v) => {
+                &FieldChangesetPayload_oneof_one_of_width::width(v) => {
                     my_size += ::protobuf::rt::value_size(8, v, ::protobuf::wire_format::WireTypeVarint);
                 },
             };
         }
-        if let ::std::option::Option::Some(ref v) = self.one_of_type_options {
+        if let ::std::option::Option::Some(ref v) = self.one_of_type_option_data {
             match v {
-                &FieldChangeset_oneof_one_of_type_options::type_options(ref v) => {
-                    my_size += ::protobuf::rt::string_size(9, &v);
+                &FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref v) => {
+                    my_size += ::protobuf::rt::bytes_size(9, &v);
                 },
             };
         }
@@ -1640,50 +1640,50 @@ impl ::protobuf::Message for FieldChangeset {
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_name {
             match v {
-                &FieldChangeset_oneof_one_of_name::name(ref v) => {
+                &FieldChangesetPayload_oneof_one_of_name::name(ref v) => {
                     os.write_string(3, v)?;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_desc {
             match v {
-                &FieldChangeset_oneof_one_of_desc::desc(ref v) => {
+                &FieldChangesetPayload_oneof_one_of_desc::desc(ref v) => {
                     os.write_string(4, v)?;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_field_type {
             match v {
-                &FieldChangeset_oneof_one_of_field_type::field_type(v) => {
+                &FieldChangesetPayload_oneof_one_of_field_type::field_type(v) => {
                     os.write_enum(5, ::protobuf::ProtobufEnum::value(&v))?;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_frozen {
             match v {
-                &FieldChangeset_oneof_one_of_frozen::frozen(v) => {
+                &FieldChangesetPayload_oneof_one_of_frozen::frozen(v) => {
                     os.write_bool(6, v)?;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_visibility {
             match v {
-                &FieldChangeset_oneof_one_of_visibility::visibility(v) => {
+                &FieldChangesetPayload_oneof_one_of_visibility::visibility(v) => {
                     os.write_bool(7, v)?;
                 },
             };
         }
         if let ::std::option::Option::Some(ref v) = self.one_of_width {
             match v {
-                &FieldChangeset_oneof_one_of_width::width(v) => {
+                &FieldChangesetPayload_oneof_one_of_width::width(v) => {
                     os.write_int32(8, v)?;
                 },
             };
         }
-        if let ::std::option::Option::Some(ref v) = self.one_of_type_options {
+        if let ::std::option::Option::Some(ref v) = self.one_of_type_option_data {
             match v {
-                &FieldChangeset_oneof_one_of_type_options::type_options(ref v) => {
-                    os.write_string(9, v)?;
+                &FieldChangesetPayload_oneof_one_of_type_option_data::type_option_data(ref v) => {
+                    os.write_bytes(9, v)?;
                 },
             };
         }
@@ -1717,8 +1717,8 @@ impl ::protobuf::Message for FieldChangeset {
         Self::descriptor_static()
     }
 
-    fn new() -> FieldChangeset {
-        FieldChangeset::new()
+    fn new() -> FieldChangesetPayload {
+        FieldChangesetPayload::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -1727,64 +1727,64 @@ impl ::protobuf::Message for FieldChangeset {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "field_id",
-                |m: &FieldChangeset| { &m.field_id },
-                |m: &mut FieldChangeset| { &mut m.field_id },
+                |m: &FieldChangesetPayload| { &m.field_id },
+                |m: &mut FieldChangesetPayload| { &mut m.field_id },
             ));
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "grid_id",
-                |m: &FieldChangeset| { &m.grid_id },
-                |m: &mut FieldChangeset| { &mut m.grid_id },
+                |m: &FieldChangesetPayload| { &m.grid_id },
+                |m: &mut FieldChangesetPayload| { &mut m.grid_id },
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
                 "name",
-                FieldChangeset::has_name,
-                FieldChangeset::get_name,
+                FieldChangesetPayload::has_name,
+                FieldChangesetPayload::get_name,
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
                 "desc",
-                FieldChangeset::has_desc,
-                FieldChangeset::get_desc,
+                FieldChangesetPayload::has_desc,
+                FieldChangesetPayload::get_desc,
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_enum_accessor::<_, FieldType>(
                 "field_type",
-                FieldChangeset::has_field_type,
-                FieldChangeset::get_field_type,
+                FieldChangesetPayload::has_field_type,
+                FieldChangesetPayload::get_field_type,
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>(
                 "frozen",
-                FieldChangeset::has_frozen,
-                FieldChangeset::get_frozen,
+                FieldChangesetPayload::has_frozen,
+                FieldChangesetPayload::get_frozen,
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>(
                 "visibility",
-                FieldChangeset::has_visibility,
-                FieldChangeset::get_visibility,
+                FieldChangesetPayload::has_visibility,
+                FieldChangesetPayload::get_visibility,
             ));
             fields.push(::protobuf::reflect::accessor::make_singular_i32_accessor::<_>(
                 "width",
-                FieldChangeset::has_width,
-                FieldChangeset::get_width,
+                FieldChangesetPayload::has_width,
+                FieldChangesetPayload::get_width,
             ));
-            fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
-                "type_options",
-                FieldChangeset::has_type_options,
-                FieldChangeset::get_type_options,
+            fields.push(::protobuf::reflect::accessor::make_singular_bytes_accessor::<_>(
+                "type_option_data",
+                FieldChangesetPayload::has_type_option_data,
+                FieldChangesetPayload::get_type_option_data,
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldChangeset>(
-                "FieldChangeset",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldChangesetPayload>(
+                "FieldChangesetPayload",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static FieldChangeset {
-        static instance: ::protobuf::rt::LazyV2<FieldChangeset> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(FieldChangeset::new)
+    fn default_instance() -> &'static FieldChangesetPayload {
+        static instance: ::protobuf::rt::LazyV2<FieldChangesetPayload> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(FieldChangesetPayload::new)
     }
 }
 
-impl ::protobuf::Clear for FieldChangeset {
+impl ::protobuf::Clear for FieldChangesetPayload {
     fn clear(&mut self) {
         self.field_id.clear();
         self.grid_id.clear();
@@ -1794,18 +1794,18 @@ impl ::protobuf::Clear for FieldChangeset {
         self.one_of_frozen = ::std::option::Option::None;
         self.one_of_visibility = ::std::option::Option::None;
         self.one_of_width = ::std::option::Option::None;
-        self.one_of_type_options = ::std::option::Option::None;
+        self.one_of_type_option_data = ::std::option::Option::None;
         self.unknown_fields.clear();
     }
 }
 
-impl ::std::fmt::Debug for FieldChangeset {
+impl ::std::fmt::Debug for FieldChangesetPayload {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for FieldChangeset {
+impl ::protobuf::reflect::ProtobufValue for FieldChangesetPayload {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
@@ -3514,43 +3514,44 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \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\"\
-    \x96\x03\n\x0eFieldChangeset\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.FieldTy\
-    peH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06fr\
-    ozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\
-    \x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12#\n\x0ctype_optio\
-    ns\x18\t\x20\x01(\tH\x06R\x0btypeOptionsB\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\x15\n\x13one_of_type_options\"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\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01\
-    (\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.Row\
-    Meta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\
-    \x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibi\
-    lity\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\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\x06he\
-    ight\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\
-    \x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByField\
-    IdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\
+    \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\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visib\
-    ility\"9\n\x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fiel\
-    dId\x12\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"\x83\x01\n\x11CellMet\
-    aChangeset\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\x04data\
-    B\r\n\x0bone_of_data\"\xad\x01\n\x10BuildGridContext\x12+\n\x0bfield_met\
-    as\x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12/\n\x0bblock_metas\
-    \x18\x02\x20\x01(\x0b2\x0e.GridBlockMetaR\nblockMetas\x12;\n\x0fblock_me\
-    ta_data\x18\x03\x20\x01(\x0b2\x13.GridBlockMetaSerdeR\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\x0cSingleSelect\x10\x03\x12\x0f\n\
-    \x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\
+    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\
+    \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\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 2 - 2
shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto

@@ -24,7 +24,7 @@ message FieldMeta {
     int32 width = 7;
     string type_option_json = 8;
 }
-message FieldChangeset {
+message FieldChangesetPayload {
     string field_id = 1;
     string grid_id = 2;
     oneof one_of_name { string name = 3; };
@@ -33,7 +33,7 @@ message FieldChangeset {
     oneof one_of_frozen { bool frozen = 6; };
     oneof one_of_visibility { bool visibility = 7; };
     oneof one_of_width { int32 width = 8; };
-    oneof one_of_type_options { string type_options = 9; };
+    oneof one_of_type_option_data { bytes type_option_data = 9; };
 }
 message AnyData {
     string type_id = 1;

+ 13 - 5
shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs

@@ -3,12 +3,13 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult};
 use crate::util::{cal_diff, make_delta_from_revisions};
 use bytes::Bytes;
 use flowy_grid_data_model::entities::{
-    FieldChangeset, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder,
+    FieldChangesetParams, FieldMeta, FieldOrder, GridBlockMeta, GridBlockMetaChangeset, GridMeta, RepeatedFieldOrder,
 };
 
 use lib_infra::uuid;
 use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
 use std::collections::HashMap;
+use std::string::FromUtf8Error;
 use std::sync::Arc;
 
 pub type GridMetaDelta = PlainTextDelta;
@@ -109,7 +110,7 @@ impl GridMetaPad {
         }
     }
 
-    pub fn update_field(&mut self, changeset: FieldChangeset) -> CollaborateResult<Option<GridChangeset>> {
+    pub fn update_field(&mut self, changeset: FieldChangesetParams) -> CollaborateResult<Option<GridChangeset>> {
         let field_id = changeset.field_id.clone();
         self.modify_field(&field_id, |field| {
             let mut is_changed = None;
@@ -143,9 +144,16 @@ impl GridMetaPad {
                 is_changed = Some(())
             }
 
-            if let Some(type_options) = changeset.type_options {
-                field.type_option_json = type_options;
-                is_changed = Some(())
+            if let Some(type_option_data) = changeset.type_option_data {
+                match String::from_utf8(type_option_data) {
+                    Ok(type_option_json) => {
+                        field.type_option_json = type_option_json;
+                        is_changed = Some(())
+                    }
+                    Err(err) => {
+                        tracing::error!("Deserialize data to type option json failed: {}", err);
+                    }
+                }
             }
 
             Ok(is_changed)