瀏覽代碼

chore: display time

appflowy 3 年之前
父節點
當前提交
76079d8ce0
共有 25 個文件被更改,包括 533 次插入153 次删除
  1. 5 5
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart
  2. 30 2
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_loader.dart
  3. 16 10
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_persistence.dart
  4. 10 7
      frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart
  5. 21 10
      frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart
  6. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart
  7. 13 15
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart
  8. 4 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart
  9. 22 5
      frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart
  10. 61 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pb.dart
  11. 11 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbjson.dart
  12. 4 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart
  13. 3 2
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbjson.dart
  14. 13 13
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart
  15. 5 5
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart
  16. 24 15
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  17. 7 3
      frontend/rust-lib/flowy-grid/src/event_map.rs
  18. 210 7
      frontend/rust-lib/flowy-grid/src/protobuf/model/date_type_option.rs
  19. 10 7
      frontend/rust-lib/flowy-grid/src/protobuf/model/event_map.rs
  20. 25 25
      frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs
  21. 4 0
      frontend/rust-lib/flowy-grid/src/protobuf/proto/date_type_option.proto
  22. 2 1
      frontend/rust-lib/flowy-grid/src/protobuf/proto/event_map.proto
  23. 1 1
      frontend/rust-lib/flowy-grid/src/protobuf/proto/selection_type_option.proto
  24. 24 9
      frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs
  25. 6 6
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs

+ 5 - 5
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart

@@ -1,8 +1,8 @@
 part of 'cell_service.dart';
 
 typedef GridCellContext = _GridCellContext<Cell, String>;
-typedef GridSelectOptionCellContext = _GridCellContext<SelectOptionContext, String>;
-typedef GridDateCellContext = _GridCellContext<Cell, DateCellPersistenceData>;
+typedef GridSelectOptionCellContext = _GridCellContext<SelectOptionCellData, String>;
+typedef GridDateCellContext = _GridCellContext<DateCellData, DateCellPersistenceData>;
 
 class GridCellContextBuilder {
   final GridCellCache _cellCache;
@@ -26,7 +26,7 @@ class GridCellContextBuilder {
         return GridDateCellContext(
           gridCell: _gridCell,
           cellCache: _cellCache,
-          cellDataLoader: CellDataLoader(gridCell: _gridCell),
+          cellDataLoader: DateCellDataLoader(gridCell: _gridCell),
           cellDataPersistence: NumberCellDataPersistence(gridCell: _gridCell),
         );
       case FieldType.Number:
@@ -154,8 +154,8 @@ class _GridCellContext<T, D> extends Equatable {
     return _fieldService.getTypeOptionData(fieldType: fieldType);
   }
 
-  void saveCellData(D data) {
-    cellDataPersistence.save(data);
+  Future<Option<FlowyError>> saveCellData(D data) {
+    return cellDataPersistence.save(data);
   }
 
   void _loadData() {

+ 30 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_loader.dart

@@ -59,14 +59,42 @@ class CellDataLoader extends _GridCellDataLoader<Cell> {
   GridCellDataConfig get config => _config;
 }
 
-class SelectOptionCellDataLoader extends _GridCellDataLoader<SelectOptionContext> {
+class DateCellDataLoader extends _GridCellDataLoader<DateCellData> {
+  final GridCell gridCell;
+  DateCellDataLoader({
+    required this.gridCell,
+  });
+
+  @override
+  GridCellDataConfig get config => DefaultCellDataConfig();
+
+  @override
+  Future<DateCellData?> loadData() {
+    final payload = CellIdentifierPayload.create()
+      ..gridId = gridCell.gridId
+      ..fieldId = gridCell.field.id
+      ..rowId = gridCell.rowId;
+
+    return GridEventGetDateCellData(payload).send().then((result) {
+      return result.fold(
+        (data) => data,
+        (err) {
+          Log.error(err);
+          return null;
+        },
+      );
+    });
+  }
+}
+
+class SelectOptionCellDataLoader extends _GridCellDataLoader<SelectOptionCellData> {
   final SelectOptionService service;
   final GridCell gridCell;
   SelectOptionCellDataLoader({
     required this.gridCell,
   }) : service = SelectOptionService(gridCell: gridCell);
   @override
-  Future<SelectOptionContext?> loadData() async {
+  Future<SelectOptionCellData?> loadData() async {
     return service.getOpitonContext().then((result) {
       return result.fold(
         (data) => data,

+ 16 - 10
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/data_persistence.dart

@@ -1,7 +1,7 @@
 part of 'cell_service.dart';
 
 abstract class _GridCellDataPersistence<D> {
-  void save(D data);
+  Future<Option<FlowyError>> save(D data);
 }
 
 class CellDataPersistence implements _GridCellDataPersistence<String> {
@@ -13,16 +13,19 @@ class CellDataPersistence implements _GridCellDataPersistence<String> {
   final CellService _cellService = CellService();
 
   @override
-  void save(String data) {
-    _cellService
-        .updateCell(
+  Future<Option<FlowyError>> save(String data) async {
+    final fut = _cellService.updateCell(
       gridId: gridCell.gridId,
       fieldId: gridCell.field.id,
       rowId: gridCell.rowId,
       data: data,
-    )
-        .then((result) {
-      result.fold((l) => null, (err) => Log.error(err));
+    );
+
+    return fut.then((result) {
+      return result.fold(
+        (l) => none(),
+        (err) => Some(err),
+      );
     });
   }
 }
@@ -39,7 +42,7 @@ class NumberCellDataPersistence implements _GridCellDataPersistence<DateCellPers
   });
 
   @override
-  void save(DateCellPersistenceData data) {
+  Future<Option<FlowyError>> save(DateCellPersistenceData data) {
     var payload = DateChangesetPayload.create()..cellIdentifier = _cellIdentifier(gridCell);
 
     final date = (data.date.millisecondsSinceEpoch ~/ 1000).toString();
@@ -49,8 +52,11 @@ class NumberCellDataPersistence implements _GridCellDataPersistence<DateCellPers
       payload.time = data.time!;
     }
 
-    GridEventUpdateDateCell(payload).send().then((result) {
-      result.fold((l) => null, (err) => Log.error(err));
+    return GridEventUpdateDateCell(payload).send().then((result) {
+      return result.fold(
+        (l) => none(),
+        (err) => Some(err),
+      );
     });
   }
 }

+ 10 - 7
frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -10,6 +9,7 @@ import 'dart:async';
 import 'cell_service/cell_service.dart';
 import 'package:dartz/dartz.dart';
 import 'package:protobuf/protobuf.dart';
+import 'package:fixnum/fixnum.dart' as $fixnum;
 part 'date_cal_bloc.freezed.dart';
 
 class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
@@ -18,9 +18,9 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
 
   DateCalBloc({
     required DateTypeOption dateTypeOption,
-    required DateTime? selectedDay,
+    required DateCellData? cellData,
     required this.cellContext,
-  }) : super(DateCalState.initial(dateTypeOption, selectedDay)) {
+  }) : super(DateCalState.initial(dateTypeOption, cellData)) {
     on<DateCalEvent>(
       (event, emit) async {
         await event.when(
@@ -142,7 +142,7 @@ class DateCalEvent with _$DateCalEvent {
   const factory DateCalEvent.setDateFormat(DateFormat dateFormat) = _DateFormat;
   const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime;
   const factory DateCalEvent.setTime(String time) = _Time;
-  const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
+  const factory DateCalEvent.didReceiveCellUpdate(DateCellData data) = _DidReceiveCellUpdate;
 }
 
 @freezed
@@ -158,10 +158,13 @@ class DateCalState with _$DateCalState {
 
   factory DateCalState.initial(
     DateTypeOption dateTypeOption,
-    DateTime? selectedDay,
+    DateCellData? cellData,
   ) {
     Option<DateCellPersistenceData> dateData = none();
-    if (selectedDay != null) {
+    final time = cellData?.time ?? "";
+    if (cellData != null) {
+      final timestamp = $fixnum.Int64.parseInt(cellData.date).toInt();
+      final selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
       dateData = Some(DateCellPersistenceData(date: selectedDay));
     }
 
@@ -170,7 +173,7 @@ class DateCalState with _$DateCalState {
       format: CalendarFormat.month,
       focusedDay: DateTime.now(),
       dateData: dateData,
-      time: "",
+      time: time,
       inputTimeError: none(),
     );
   }

+ 21 - 10
frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart

@@ -1,8 +1,10 @@
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, Field;
+import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
+import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
 import 'cell_service/cell_service.dart';
+import 'package:dartz/dartz.dart';
 part 'date_cell_bloc.freezed.dart';
 
 class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
@@ -15,7 +17,7 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
         event.when(
           initial: () => _startListening(),
           selectDate: (DateCellPersistenceData value) => cellContext.saveCellData(value),
-          didReceiveCellUpdate: (Cell value) => emit(state.copyWith(content: value.content)),
+          didReceiveCellUpdate: (DateCellData value) => emit(state.copyWith(data: Some(value))),
           didReceiveFieldUpdate: (Field value) => emit(state.copyWith(field: value)),
         );
       },
@@ -34,9 +36,9 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
 
   void _startListening() {
     _onCellChangedFn = cellContext.startListening(
-      onCellChanged: ((cell) {
+      onCellChanged: ((data) {
         if (!isClosed) {
-          add(DateCellEvent.didReceiveCellUpdate(cell));
+          add(DateCellEvent.didReceiveCellUpdate(data));
         }
       }),
     );
@@ -47,19 +49,28 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
 class DateCellEvent with _$DateCellEvent {
   const factory DateCellEvent.initial() = _InitialCell;
   const factory DateCellEvent.selectDate(DateCellPersistenceData data) = _SelectDay;
-  const factory DateCellEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
+  const factory DateCellEvent.didReceiveCellUpdate(DateCellData data) = _DidReceiveCellUpdate;
   const factory DateCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
 }
 
 @freezed
 class DateCellState with _$DateCellState {
   const factory DateCellState({
-    required String content,
+    required Option<DateCellData> data,
     required Field field,
   }) = _DateCellState;
 
-  factory DateCellState.initial(GridDateCellContext context) => DateCellState(
-        field: context.field,
-        content: context.getCellData()?.content ?? "",
-      );
+  factory DateCellState.initial(GridDateCellContext context) {
+    final cellData = context.getCellData();
+    Option<DateCellData> data = none();
+
+    if (cellData != null) {
+      data = Some(cellData);
+    }
+
+    return DateCellState(
+      field: context.field,
+      data: data,
+    );
+  }
 }

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart

@@ -53,13 +53,13 @@ class SelectOptionService {
     return GridEventUpdateSelectOption(payload).send();
   }
 
-  Future<Either<SelectOptionContext, FlowyError>> getOpitonContext() {
+  Future<Either<SelectOptionCellData, FlowyError>> getOpitonContext() {
     final payload = CellIdentifierPayload.create()
       ..gridId = gridId
       ..fieldId = fieldId
       ..rowId = rowId;
 
-    return GridEventGetSelectOptionContext(payload).send();
+    return GridEventGetSelectOptionCellData(payload).send();
   }
 
   Future<Either<void, FlowyError>> select({required String optionId}) {

+ 13 - 15
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart

@@ -16,7 +16,6 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:table_calendar/table_calendar.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';
-import 'package:fixnum/fixnum.dart' as $fixnum;
 
 final kToday = DateTime.now();
 final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
@@ -41,19 +40,18 @@ class CellCalendar with FlowyOverlayDelegate {
     result.fold(
       (data) {
         final typeOptionData = DateTypeOption.fromBuffer(data);
-        DateTime? selectedDay;
-        final cellData = cellContext.getCellData()?.data;
+        // DateTime? selectedDay;
+        // final cellData = cellContext.getCellData();
 
-        if (cellData != null) {
-          final timestamp = $fixnum.Int64.parseInt(cellData).toInt();
-          selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
-        }
+        // if (cellData != null) {
+        //   final timestamp = $fixnum.Int64.parseInt(cellData).toInt();
+        //   selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
+        // }
 
         final calendar = _CellCalendarWidget(
           onSelected: onSelected,
           cellContext: cellContext,
           dateTypeOption: typeOptionData,
-          selectedDay: selectedDay,
         );
 
         FlowyOverlay.of(context).insertWithAnchor(
@@ -90,14 +88,12 @@ class CellCalendar with FlowyOverlayDelegate {
 class _CellCalendarWidget extends StatelessWidget {
   final GridDateCellContext cellContext;
   final DateTypeOption dateTypeOption;
-  final DateTime? selectedDay;
   final void Function(DateCellPersistenceData) onSelected;
 
   const _CellCalendarWidget({
     required this.onSelected,
     required this.cellContext,
     required this.dateTypeOption,
-    this.selectedDay,
     Key? key,
   }) : super(key: key);
 
@@ -105,11 +101,13 @@ class _CellCalendarWidget extends StatelessWidget {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     return BlocProvider(
-      create: (context) => DateCalBloc(
-        dateTypeOption: dateTypeOption,
-        selectedDay: selectedDay,
-        cellContext: cellContext,
-      )..add(const DateCalEvent.initial()),
+      create: (context) {
+        return DateCalBloc(
+          dateTypeOption: dateTypeOption,
+          cellData: cellContext.getCellData(),
+          cellContext: cellContext,
+        )..add(const DateCalEvent.initial());
+      },
       child: BlocConsumer<DateCalBloc, DateCalState>(
         listener: (context, state) {
           state.dateData.fold(

+ 4 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart

@@ -62,7 +62,10 @@ class _DateCellState extends State<DateCell> {
               child: MouseRegion(
                 opaque: false,
                 cursor: SystemMouseCursors.click,
-                child: Align(alignment: alignment, child: FlowyText.medium(state.content, fontSize: 12)),
+                child: Align(
+                  alignment: alignment,
+                  child: FlowyText.medium(state.data.foldRight("", (data, _) => data.date), fontSize: 12),
+                ),
               ),
             ),
           );

+ 22 - 5
frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dart_event/flowy-grid/dart_event.dart

@@ -222,18 +222,18 @@ class GridEventNewSelectOption {
     }
 }
 
-class GridEventGetSelectOptionContext {
+class GridEventGetSelectOptionCellData {
      CellIdentifierPayload request;
-     GridEventGetSelectOptionContext(this.request);
+     GridEventGetSelectOptionCellData(this.request);
 
-    Future<Either<SelectOptionContext, FlowyError>> send() {
+    Future<Either<SelectOptionCellData, FlowyError>> send() {
     final request = FFIRequest.create()
-          ..event = GridEvent.GetSelectOptionContext.toString()
+          ..event = GridEvent.GetSelectOptionCellData.toString()
           ..payload = requestToBytes(this.request);
 
     return Dispatch.asyncRequest(request)
         .then((bytesResult) => bytesResult.fold(
-           (okBytes) => left(SelectOptionContext.fromBuffer(okBytes)),
+           (okBytes) => left(SelectOptionCellData.fromBuffer(okBytes)),
            (errBytes) => right(FlowyError.fromBuffer(errBytes)),
         ));
     }
@@ -392,3 +392,20 @@ class GridEventUpdateDateCell {
     }
 }
 
+class GridEventGetDateCellData {
+     CellIdentifierPayload request;
+     GridEventGetDateCellData(this.request);
+
+    Future<Either<DateCellData, FlowyError>> send() {
+    final request = FFIRequest.create()
+          ..event = GridEvent.GetDateCellData.toString()
+          ..payload = requestToBytes(this.request);
+
+    return Dispatch.asyncRequest(request)
+        .then((bytesResult) => bytesResult.fold(
+           (okBytes) => left(DateCellData.fromBuffer(okBytes)),
+           (errBytes) => right(FlowyError.fromBuffer(errBytes)),
+        ));
+    }
+}
+

+ 61 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pb.dart

@@ -90,6 +90,67 @@ class DateTypeOption extends $pb.GeneratedMessage {
   void clearIncludeTime() => clearField(3);
 }
 
+class DateCellData extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DateCellData', createEmptyInstance: create)
+    ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'date')
+    ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'time')
+    ..hasRequiredFields = false
+  ;
+
+  DateCellData._() : super();
+  factory DateCellData({
+    $core.String? date,
+    $core.String? time,
+  }) {
+    final _result = create();
+    if (date != null) {
+      _result.date = date;
+    }
+    if (time != null) {
+      _result.time = time;
+    }
+    return _result;
+  }
+  factory DateCellData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory DateCellData.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')
+  DateCellData clone() => DateCellData()..mergeFromMessage(this);
+  @$core.Deprecated(
+  'Using this can add significant overhead to your binary. '
+  'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+  'Will be removed in next major version')
+  DateCellData copyWith(void Function(DateCellData) updates) => super.copyWith((message) => updates(message as DateCellData)) as DateCellData; // ignore: deprecated_member_use
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static DateCellData create() => DateCellData._();
+  DateCellData createEmptyInstance() => create();
+  static $pb.PbList<DateCellData> createRepeated() => $pb.PbList<DateCellData>();
+  @$core.pragma('dart2js:noInline')
+  static DateCellData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DateCellData>(create);
+  static DateCellData? _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.String get date => $_getSZ(0);
+  @$pb.TagNumber(1)
+  set date($core.String v) { $_setString(0, v); }
+  @$pb.TagNumber(1)
+  $core.bool hasDate() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearDate() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.String get time => $_getSZ(1);
+  @$pb.TagNumber(2)
+  set time($core.String v) { $_setString(1, v); }
+  @$pb.TagNumber(2)
+  $core.bool hasTime() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearTime() => clearField(2);
+}
+
 enum DateChangesetPayload_OneOfDate {
   date, 
   notSet

+ 11 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/date_type_option.pbjson.dart

@@ -44,6 +44,17 @@ const DateTypeOption$json = const {
 
 /// Descriptor for `DateTypeOption`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List dateTypeOptionDescriptor = $convert.base64Decode('Cg5EYXRlVHlwZU9wdGlvbhIsCgtkYXRlX2Zvcm1hdBgBIAEoDjILLkRhdGVGb3JtYXRSCmRhdGVGb3JtYXQSLAoLdGltZV9mb3JtYXQYAiABKA4yCy5UaW1lRm9ybWF0Ugp0aW1lRm9ybWF0EiEKDGluY2x1ZGVfdGltZRgDIAEoCFILaW5jbHVkZVRpbWU=');
+@$core.Deprecated('Use dateCellDataDescriptor instead')
+const DateCellData$json = const {
+  '1': 'DateCellData',
+  '2': const [
+    const {'1': 'date', '3': 1, '4': 1, '5': 9, '10': 'date'},
+    const {'1': 'time', '3': 2, '4': 1, '5': 9, '10': 'time'},
+  ],
+};
+
+/// Descriptor for `DateCellData`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List dateCellDataDescriptor = $convert.base64Decode('CgxEYXRlQ2VsbERhdGESEgoEZGF0ZRgBIAEoCVIEZGF0ZRISCgR0aW1lGAIgASgJUgR0aW1l');
 @$core.Deprecated('Use dateChangesetPayloadDescriptor instead')
 const DateChangesetPayload$json = const {
   '1': 'DateChangesetPayload',

+ 4 - 2
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/event_map.pbenum.dart

@@ -23,7 +23,7 @@ class GridEvent extends $pb.ProtobufEnum {
   static const GridEvent MoveItem = GridEvent._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MoveItem');
   static const GridEvent GetFieldTypeOption = GridEvent._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetFieldTypeOption');
   static const GridEvent NewSelectOption = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewSelectOption');
-  static const GridEvent GetSelectOptionContext = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptionContext');
+  static const GridEvent GetSelectOptionCellData = GridEvent._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetSelectOptionCellData');
   static const GridEvent UpdateSelectOption = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateSelectOption');
   static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
   static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
@@ -33,6 +33,7 @@ class GridEvent extends $pb.ProtobufEnum {
   static const GridEvent UpdateCell = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
   static const GridEvent UpdateSelectOptionCell = GridEvent._(72, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateSelectOptionCell');
   static const GridEvent UpdateDateCell = GridEvent._(80, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateDateCell');
+  static const GridEvent GetDateCellData = GridEvent._(90, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetDateCellData');
 
   static const $core.List<GridEvent> values = <GridEvent> [
     GetGridData,
@@ -48,7 +49,7 @@ class GridEvent extends $pb.ProtobufEnum {
     MoveItem,
     GetFieldTypeOption,
     NewSelectOption,
-    GetSelectOptionContext,
+    GetSelectOptionCellData,
     UpdateSelectOption,
     CreateRow,
     GetRow,
@@ -58,6 +59,7 @@ class GridEvent extends $pb.ProtobufEnum {
     UpdateCell,
     UpdateSelectOptionCell,
     UpdateDateCell,
+    GetDateCellData,
   ];
 
   static final $core.Map<$core.int, GridEvent> _byValue = $pb.ProtobufEnum.initByValue(values);

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

@@ -25,7 +25,7 @@ const GridEvent$json = const {
     const {'1': 'MoveItem', '2': 23},
     const {'1': 'GetFieldTypeOption', '2': 24},
     const {'1': 'NewSelectOption', '2': 30},
-    const {'1': 'GetSelectOptionContext', '2': 31},
+    const {'1': 'GetSelectOptionCellData', '2': 31},
     const {'1': 'UpdateSelectOption', '2': 32},
     const {'1': 'CreateRow', '2': 50},
     const {'1': 'GetRow', '2': 51},
@@ -35,8 +35,9 @@ const GridEvent$json = const {
     const {'1': 'UpdateCell', '2': 71},
     const {'1': 'UpdateSelectOptionCell', '2': 72},
     const {'1': 'UpdateDateCell', '2': 80},
+    const {'1': 'GetDateCellData', '2': 90},
   ],
 };
 
 /// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIZChVVcGRhdGVGaWVsZFR5cGVPcHRpb24QDBIPCgtJbnNlcnRGaWVsZBANEg8KC0RlbGV0ZUZpZWxkEA4SEQoNU3dpdGNoVG9GaWVsZBAUEhIKDkR1cGxpY2F0ZUZpZWxkEBUSFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAWEgwKCE1vdmVJdGVtEBcSFgoSR2V0RmllbGRUeXBlT3B0aW9uEBgSEwoPTmV3U2VsZWN0T3B0aW9uEB4SGgoWR2V0U2VsZWN0T3B0aW9uQ29udGV4dBAfEhYKElVwZGF0ZVNlbGVjdE9wdGlvbhAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg0KCURlbGV0ZVJvdxA0EhAKDER1cGxpY2F0ZVJvdxA1EgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSGgoWVXBkYXRlU2VsZWN0T3B0aW9uQ2VsbBBIEhIKDlVwZGF0ZURhdGVDZWxsEFA=');
+final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIZChVVcGRhdGVGaWVsZFR5cGVPcHRpb24QDBIPCgtJbnNlcnRGaWVsZBANEg8KC0RlbGV0ZUZpZWxkEA4SEQoNU3dpdGNoVG9GaWVsZBAUEhIKDkR1cGxpY2F0ZUZpZWxkEBUSFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAWEgwKCE1vdmVJdGVtEBcSFgoSR2V0RmllbGRUeXBlT3B0aW9uEBgSEwoPTmV3U2VsZWN0T3B0aW9uEB4SGwoXR2V0U2VsZWN0T3B0aW9uQ2VsbERhdGEQHxIWChJVcGRhdGVTZWxlY3RPcHRpb24QIBINCglDcmVhdGVSb3cQMhIKCgZHZXRSb3cQMxINCglEZWxldGVSb3cQNBIQCgxEdXBsaWNhdGVSb3cQNRILCgdHZXRDZWxsEEYSDgoKVXBkYXRlQ2VsbBBHEhoKFlVwZGF0ZVNlbGVjdE9wdGlvbkNlbGwQSBISCg5VcGRhdGVEYXRlQ2VsbBBQEhMKD0dldERhdGVDZWxsRGF0YRBa');

+ 13 - 13
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pb.dart

@@ -439,15 +439,15 @@ class SelectOptionCellChangesetPayload extends $pb.GeneratedMessage {
   void clearDeleteOptionId() => clearField(3);
 }
 
-class SelectOptionContext extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionContext', createEmptyInstance: create)
+class SelectOptionCellData extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOptionCellData', createEmptyInstance: create)
     ..pc<SelectOption>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create)
     ..pc<SelectOption>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'selectOptions', $pb.PbFieldType.PM, subBuilder: SelectOption.create)
     ..hasRequiredFields = false
   ;
 
-  SelectOptionContext._() : super();
-  factory SelectOptionContext({
+  SelectOptionCellData._() : super();
+  factory SelectOptionCellData({
     $core.Iterable<SelectOption>? options,
     $core.Iterable<SelectOption>? selectOptions,
   }) {
@@ -460,26 +460,26 @@ class SelectOptionContext extends $pb.GeneratedMessage {
     }
     return _result;
   }
-  factory SelectOptionContext.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory SelectOptionContext.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory SelectOptionCellData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory SelectOptionCellData.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')
-  SelectOptionContext clone() => SelectOptionContext()..mergeFromMessage(this);
+  SelectOptionCellData clone() => SelectOptionCellData()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  SelectOptionContext copyWith(void Function(SelectOptionContext) updates) => super.copyWith((message) => updates(message as SelectOptionContext)) as SelectOptionContext; // ignore: deprecated_member_use
+  SelectOptionCellData copyWith(void Function(SelectOptionCellData) updates) => super.copyWith((message) => updates(message as SelectOptionCellData)) as SelectOptionCellData; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static SelectOptionContext create() => SelectOptionContext._();
-  SelectOptionContext createEmptyInstance() => create();
-  static $pb.PbList<SelectOptionContext> createRepeated() => $pb.PbList<SelectOptionContext>();
+  static SelectOptionCellData create() => SelectOptionCellData._();
+  SelectOptionCellData createEmptyInstance() => create();
+  static $pb.PbList<SelectOptionCellData> createRepeated() => $pb.PbList<SelectOptionCellData>();
   @$core.pragma('dart2js:noInline')
-  static SelectOptionContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SelectOptionContext>(create);
-  static SelectOptionContext? _defaultInstance;
+  static SelectOptionCellData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SelectOptionCellData>(create);
+  static SelectOptionCellData? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.List<SelectOption> get options => $_getList(0);

+ 5 - 5
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/selection_type_option.pbjson.dart

@@ -94,14 +94,14 @@ const SelectOptionCellChangesetPayload$json = const {
 
 /// Descriptor for `SelectOptionCellChangesetPayload`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List selectOptionCellChangesetPayloadDescriptor = $convert.base64Decode('CiBTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0UGF5bG9hZBI/Cg9jZWxsX2lkZW50aWZpZXIYASABKAsyFi5DZWxsSWRlbnRpZmllclBheWxvYWRSDmNlbGxJZGVudGlmaWVyEioKEGluc2VydF9vcHRpb25faWQYAiABKAlIAFIOaW5zZXJ0T3B0aW9uSWQSKgoQZGVsZXRlX29wdGlvbl9pZBgDIAEoCUgBUg5kZWxldGVPcHRpb25JZEIZChdvbmVfb2ZfaW5zZXJ0X29wdGlvbl9pZEIZChdvbmVfb2ZfZGVsZXRlX29wdGlvbl9pZA==');
-@$core.Deprecated('Use selectOptionContextDescriptor instead')
-const SelectOptionContext$json = const {
-  '1': 'SelectOptionContext',
+@$core.Deprecated('Use selectOptionCellDataDescriptor instead')
+const SelectOptionCellData$json = const {
+  '1': 'SelectOptionCellData',
   '2': const [
     const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'},
     const {'1': 'select_options', '3': 2, '4': 3, '5': 11, '6': '.SelectOption', '10': 'selectOptions'},
   ],
 };
 
-/// Descriptor for `SelectOptionContext`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List selectOptionContextDescriptor = $convert.base64Decode('ChNTZWxlY3RPcHRpb25Db250ZXh0EicKB29wdGlvbnMYASADKAsyDS5TZWxlY3RPcHRpb25SB29wdGlvbnMSNAoOc2VsZWN0X29wdGlvbnMYAiADKAsyDS5TZWxlY3RPcHRpb25SDXNlbGVjdE9wdGlvbnM=');
+/// Descriptor for `SelectOptionCellData`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List selectOptionCellDataDescriptor = $convert.base64Decode('ChRTZWxlY3RPcHRpb25DZWxsRGF0YRInCgdvcHRpb25zGAEgAygLMg0uU2VsZWN0T3B0aW9uUgdvcHRpb25zEjQKDnNlbGVjdF9vcHRpb25zGAIgAygLMg0uU2VsZWN0T3B0aW9uUg1zZWxlY3RPcHRpb25z');

+ 24 - 15
frontend/rust-lib/flowy-grid/src/event_handler.rs

@@ -274,6 +274,27 @@ pub(crate) async fn update_cell_handler(
     Ok(())
 }
 
+#[tracing::instrument(level = "debug", skip(data, manager), err)]
+pub(crate) async fn get_date_cell_data_handler(
+    data: Data<CellIdentifierPayload>,
+    manager: AppData<Arc<GridManager>>,
+) -> DataResult<DateCellData, FlowyError> {
+    let params: CellIdentifier = data.into_inner().try_into()?;
+    let editor = manager.get_grid_editor(&params.grid_id)?;
+    match editor.get_field_meta(&params.field_id).await {
+        None => {
+            tracing::error!("Can't find the corresponding field with id: {}", params.field_id);
+            data_result(DateCellData::default())
+        }
+        Some(field_meta) => {
+            let cell_meta = editor.get_cell_meta(&params.row_id, &params.field_id).await?;
+            let type_option = DateTypeOption::from(&field_meta);
+            let date_cell_data = type_option.date_cell_data(&cell_meta)?;
+            data_result(date_cell_data)
+        }
+    }
+}
+
 #[tracing::instrument(level = "debug", skip_all, err)]
 pub(crate) async fn new_select_option_handler(
     data: Data<CreateSelectOptionPayload>,
@@ -330,35 +351,23 @@ pub(crate) async fn update_select_option_handler(
     }
     Ok(())
 }
-//
-// #[tracing::instrument(level = "debug", skip_all, err)]
-// pub(crate) async fn update_date_option_handler(
-//     data: Data<SelectOptionCellChangesetPayload>,
-//     manager: AppData<Arc<GridManager>>,
-// ) -> Result<(), FlowyError> {
-//     let params: SelectOptionCellChangesetParams = data.into_inner().try_into()?;
-//     let editor = manager.get_grid_editor(&params.grid_id)?;
-//     let changeset: CellChangeset = params.into();
-//     let _ = editor.update_cell(changeset).await?;
-//     Ok(())
-// }
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn get_select_option_handler(
     data: Data<CellIdentifierPayload>,
     manager: AppData<Arc<GridManager>>,
-) -> DataResult<SelectOptionContext, FlowyError> {
+) -> DataResult<SelectOptionCellData, FlowyError> {
     let params: CellIdentifier = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     match editor.get_field_meta(&params.field_id).await {
         None => {
             tracing::error!("Can't find the corresponding field with id: {}", params.field_id);
-            data_result(SelectOptionContext::default())
+            data_result(SelectOptionCellData::default())
         }
         Some(field_meta) => {
             let cell_meta = editor.get_cell_meta(&params.row_id, &params.field_id).await?;
             let type_option = select_option_operation(&field_meta)?;
-            let option_context = type_option.option_context(&cell_meta);
+            let option_context = type_option.select_option_cell_data(&cell_meta);
             data_result(option_context)
         }
     }

+ 7 - 3
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -29,10 +29,11 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
         // Cell
         .event(GridEvent::GetCell, get_cell_handler)
         .event(GridEvent::UpdateCell, update_cell_handler)
+        .event(GridEvent::GetDateCellData, get_date_cell_data_handler)
         // SelectOption
         .event(GridEvent::NewSelectOption, new_select_option_handler)
         .event(GridEvent::UpdateSelectOption, update_select_option_handler)
-        .event(GridEvent::GetSelectOptionContext, get_select_option_handler)
+        .event(GridEvent::GetSelectOptionCellData, get_select_option_handler)
         .event(GridEvent::UpdateSelectOptionCell, update_select_option_cell_handler)
         // Date
         .event(GridEvent::UpdateDateCell, update_date_cell_handler);
@@ -82,8 +83,8 @@ pub enum GridEvent {
     #[event(input = "CreateSelectOptionPayload", output = "SelectOption")]
     NewSelectOption = 30,
 
-    #[event(input = "CellIdentifierPayload", output = "SelectOptionContext")]
-    GetSelectOptionContext = 31,
+    #[event(input = "CellIdentifierPayload", output = "SelectOptionCellData")]
+    GetSelectOptionCellData = 31,
 
     #[event(input = "SelectOptionChangesetPayload")]
     UpdateSelectOption = 32,
@@ -111,4 +112,7 @@ pub enum GridEvent {
 
     #[event(input = "DateChangesetPayload")]
     UpdateDateCell = 80,
+
+    #[event(input = "CellIdentifierPayload", output = "DateCellData")]
+    GetDateCellData = 90,
 }

+ 210 - 7
frontend/rust-lib/flowy-grid/src/protobuf/model/date_type_option.rs

@@ -237,6 +237,207 @@ impl ::protobuf::reflect::ProtobufValue for DateTypeOption {
     }
 }
 
+#[derive(PartialEq,Clone,Default)]
+pub struct DateCellData {
+    // message fields
+    pub date: ::std::string::String,
+    pub time: ::std::string::String,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a DateCellData {
+    fn default() -> &'a DateCellData {
+        <DateCellData as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl DateCellData {
+    pub fn new() -> DateCellData {
+        ::std::default::Default::default()
+    }
+
+    // string date = 1;
+
+
+    pub fn get_date(&self) -> &str {
+        &self.date
+    }
+    pub fn clear_date(&mut self) {
+        self.date.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_date(&mut self, v: ::std::string::String) {
+        self.date = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_date(&mut self) -> &mut ::std::string::String {
+        &mut self.date
+    }
+
+    // Take field
+    pub fn take_date(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.date, ::std::string::String::new())
+    }
+
+    // string time = 2;
+
+
+    pub fn get_time(&self) -> &str {
+        &self.time
+    }
+    pub fn clear_time(&mut self) {
+        self.time.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_time(&mut self, v: ::std::string::String) {
+        self.time = v;
+    }
+
+    // Mutable pointer to the field.
+    // If field is not initialized, it is initialized with default value first.
+    pub fn mut_time(&mut self) -> &mut ::std::string::String {
+        &mut self.time
+    }
+
+    // Take field
+    pub fn take_time(&mut self) -> ::std::string::String {
+        ::std::mem::replace(&mut self.time, ::std::string::String::new())
+    }
+}
+
+impl ::protobuf::Message for DateCellData {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.date)?;
+                },
+                2 => {
+                    ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.time)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if !self.date.is_empty() {
+            my_size += ::protobuf::rt::string_size(1, &self.date);
+        }
+        if !self.time.is_empty() {
+            my_size += ::protobuf::rt::string_size(2, &self.time);
+        }
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if !self.date.is_empty() {
+            os.write_string(1, &self.date)?;
+        }
+        if !self.time.is_empty() {
+            os.write_string(2, &self.time)?;
+        }
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> DateCellData {
+        DateCellData::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "date",
+                |m: &DateCellData| { &m.date },
+                |m: &mut DateCellData| { &mut m.date },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
+                "time",
+                |m: &DateCellData| { &m.time },
+                |m: &mut DateCellData| { &mut m.time },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<DateCellData>(
+                "DateCellData",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static DateCellData {
+        static instance: ::protobuf::rt::LazyV2<DateCellData> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(DateCellData::new)
+    }
+}
+
+impl ::protobuf::Clear for DateCellData {
+    fn clear(&mut self) {
+        self.date.clear();
+        self.time.clear();
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for DateCellData {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for DateCellData {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
 #[derive(PartialEq,Clone,Default)]
 pub struct DateChangesetPayload {
     // message fields
@@ -685,13 +886,15 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     ateTypeOption\x12,\n\x0bdate_format\x18\x01\x20\x01(\x0e2\x0b.DateFormat\
     R\ndateFormat\x12,\n\x0btime_format\x18\x02\x20\x01(\x0e2\x0b.TimeFormat\
     R\ntimeFormat\x12!\n\x0cinclude_time\x18\x03\x20\x01(\x08R\x0bincludeTim\
-    e\"\xa1\x01\n\x14DateChangesetPayload\x12?\n\x0fcell_identifier\x18\x01\
-    \x20\x01(\x0b2\x16.CellIdentifierPayloadR\x0ecellIdentifier\x12\x14\n\
-    \x04date\x18\x02\x20\x01(\tH\0R\x04date\x12\x14\n\x04time\x18\x03\x20\
-    \x01(\tH\x01R\x04timeB\r\n\x0bone_of_dateB\r\n\x0bone_of_time*6\n\nDateF\
-    ormat\x12\t\n\x05Local\x10\0\x12\x06\n\x02US\x10\x01\x12\x07\n\x03ISO\
-    \x10\x02\x12\x0c\n\x08Friendly\x10\x03*0\n\nTimeFormat\x12\x0e\n\nTwelve\
-    Hour\x10\0\x12\x12\n\x0eTwentyFourHour\x10\x01b\x06proto3\
+    e\"6\n\x0cDateCellData\x12\x12\n\x04date\x18\x01\x20\x01(\tR\x04date\x12\
+    \x12\n\x04time\x18\x02\x20\x01(\tR\x04time\"\xa1\x01\n\x14DateChangesetP\
+    ayload\x12?\n\x0fcell_identifier\x18\x01\x20\x01(\x0b2\x16.CellIdentifie\
+    rPayloadR\x0ecellIdentifier\x12\x14\n\x04date\x18\x02\x20\x01(\tH\0R\x04\
+    date\x12\x14\n\x04time\x18\x03\x20\x01(\tH\x01R\x04timeB\r\n\x0bone_of_d\
+    ateB\r\n\x0bone_of_time*6\n\nDateFormat\x12\t\n\x05Local\x10\0\x12\x06\n\
+    \x02US\x10\x01\x12\x07\n\x03ISO\x10\x02\x12\x0c\n\x08Friendly\x10\x03*0\
+    \n\nTimeFormat\x12\x0e\n\nTwelveHour\x10\0\x12\x12\n\x0eTwentyFourHour\
+    \x10\x01b\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

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

@@ -38,7 +38,7 @@ pub enum GridEvent {
     MoveItem = 23,
     GetFieldTypeOption = 24,
     NewSelectOption = 30,
-    GetSelectOptionContext = 31,
+    GetSelectOptionCellData = 31,
     UpdateSelectOption = 32,
     CreateRow = 50,
     GetRow = 51,
@@ -48,6 +48,7 @@ pub enum GridEvent {
     UpdateCell = 71,
     UpdateSelectOptionCell = 72,
     UpdateDateCell = 80,
+    GetDateCellData = 90,
 }
 
 impl ::protobuf::ProtobufEnum for GridEvent {
@@ -70,7 +71,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             23 => ::std::option::Option::Some(GridEvent::MoveItem),
             24 => ::std::option::Option::Some(GridEvent::GetFieldTypeOption),
             30 => ::std::option::Option::Some(GridEvent::NewSelectOption),
-            31 => ::std::option::Option::Some(GridEvent::GetSelectOptionContext),
+            31 => ::std::option::Option::Some(GridEvent::GetSelectOptionCellData),
             32 => ::std::option::Option::Some(GridEvent::UpdateSelectOption),
             50 => ::std::option::Option::Some(GridEvent::CreateRow),
             51 => ::std::option::Option::Some(GridEvent::GetRow),
@@ -80,6 +81,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             71 => ::std::option::Option::Some(GridEvent::UpdateCell),
             72 => ::std::option::Option::Some(GridEvent::UpdateSelectOptionCell),
             80 => ::std::option::Option::Some(GridEvent::UpdateDateCell),
+            90 => ::std::option::Option::Some(GridEvent::GetDateCellData),
             _ => ::std::option::Option::None
         }
     }
@@ -99,7 +101,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             GridEvent::MoveItem,
             GridEvent::GetFieldTypeOption,
             GridEvent::NewSelectOption,
-            GridEvent::GetSelectOptionContext,
+            GridEvent::GetSelectOptionCellData,
             GridEvent::UpdateSelectOption,
             GridEvent::CreateRow,
             GridEvent::GetRow,
@@ -109,6 +111,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
             GridEvent::UpdateCell,
             GridEvent::UpdateSelectOptionCell,
             GridEvent::UpdateDateCell,
+            GridEvent::GetDateCellData,
         ];
         values
     }
@@ -137,18 +140,18 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x0fevent_map.proto*\xc4\x03\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
+    \n\x0fevent_map.proto*\xda\x03\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\x19\n\x15UpdateFieldTypeOption\x10\x0c\x12\
     \x0f\n\x0bInsertField\x10\r\x12\x0f\n\x0bDeleteField\x10\x0e\x12\x11\n\r\
     SwitchToField\x10\x14\x12\x12\n\x0eDuplicateField\x10\x15\x12\x17\n\x13G\
     etEditFieldContext\x10\x16\x12\x0c\n\x08MoveItem\x10\x17\x12\x16\n\x12Ge\
-    tFieldTypeOption\x10\x18\x12\x13\n\x0fNewSelectOption\x10\x1e\x12\x1a\n\
-    \x16GetSelectOptionContext\x10\x1f\x12\x16\n\x12UpdateSelectOption\x10\
+    tFieldTypeOption\x10\x18\x12\x13\n\x0fNewSelectOption\x10\x1e\x12\x1b\n\
+    \x17GetSelectOptionCellData\x10\x1f\x12\x16\n\x12UpdateSelectOption\x10\
     \x20\x12\r\n\tCreateRow\x102\x12\n\n\x06GetRow\x103\x12\r\n\tDeleteRow\
     \x104\x12\x10\n\x0cDuplicateRow\x105\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\
     \nUpdateCell\x10G\x12\x1a\n\x16UpdateSelectOptionCell\x10H\x12\x12\n\x0e\
-    UpdateDateCell\x10Pb\x06proto3\
+    UpdateDateCell\x10P\x12\x13\n\x0fGetDateCellData\x10Zb\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 25 - 25
frontend/rust-lib/flowy-grid/src/protobuf/model/selection_type_option.rs

@@ -1437,7 +1437,7 @@ impl ::protobuf::reflect::ProtobufValue for SelectOptionCellChangesetPayload {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct SelectOptionContext {
+pub struct SelectOptionCellData {
     // message fields
     pub options: ::protobuf::RepeatedField<SelectOption>,
     pub select_options: ::protobuf::RepeatedField<SelectOption>,
@@ -1446,14 +1446,14 @@ pub struct SelectOptionContext {
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a SelectOptionContext {
-    fn default() -> &'a SelectOptionContext {
-        <SelectOptionContext as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a SelectOptionCellData {
+    fn default() -> &'a SelectOptionCellData {
+        <SelectOptionCellData as ::protobuf::Message>::default_instance()
     }
 }
 
-impl SelectOptionContext {
-    pub fn new() -> SelectOptionContext {
+impl SelectOptionCellData {
+    pub fn new() -> SelectOptionCellData {
         ::std::default::Default::default()
     }
 
@@ -1508,7 +1508,7 @@ impl SelectOptionContext {
     }
 }
 
-impl ::protobuf::Message for SelectOptionContext {
+impl ::protobuf::Message for SelectOptionCellData {
     fn is_initialized(&self) -> bool {
         for v in &self.options {
             if !v.is_initialized() {
@@ -1599,8 +1599,8 @@ impl ::protobuf::Message for SelectOptionContext {
         Self::descriptor_static()
     }
 
-    fn new() -> SelectOptionContext {
-        SelectOptionContext::new()
+    fn new() -> SelectOptionCellData {
+        SelectOptionCellData::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -1609,29 +1609,29 @@ impl ::protobuf::Message for SelectOptionContext {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<SelectOption>>(
                 "options",
-                |m: &SelectOptionContext| { &m.options },
-                |m: &mut SelectOptionContext| { &mut m.options },
+                |m: &SelectOptionCellData| { &m.options },
+                |m: &mut SelectOptionCellData| { &mut m.options },
             ));
             fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<SelectOption>>(
                 "select_options",
-                |m: &SelectOptionContext| { &m.select_options },
-                |m: &mut SelectOptionContext| { &mut m.select_options },
+                |m: &SelectOptionCellData| { &m.select_options },
+                |m: &mut SelectOptionCellData| { &mut m.select_options },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<SelectOptionContext>(
-                "SelectOptionContext",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<SelectOptionCellData>(
+                "SelectOptionCellData",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static SelectOptionContext {
-        static instance: ::protobuf::rt::LazyV2<SelectOptionContext> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(SelectOptionContext::new)
+    fn default_instance() -> &'static SelectOptionCellData {
+        static instance: ::protobuf::rt::LazyV2<SelectOptionCellData> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(SelectOptionCellData::new)
     }
 }
 
-impl ::protobuf::Clear for SelectOptionContext {
+impl ::protobuf::Clear for SelectOptionCellData {
     fn clear(&mut self) {
         self.options.clear();
         self.select_options.clear();
@@ -1639,13 +1639,13 @@ impl ::protobuf::Clear for SelectOptionContext {
     }
 }
 
-impl ::std::fmt::Debug for SelectOptionContext {
+impl ::std::fmt::Debug for SelectOptionCellData {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for SelectOptionContext {
+impl ::protobuf::reflect::ProtobufValue for SelectOptionCellData {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
@@ -1742,10 +1742,10 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     loadR\x0ecellIdentifier\x12*\n\x10insert_option_id\x18\x02\x20\x01(\tH\0\
     R\x0einsertOptionId\x12*\n\x10delete_option_id\x18\x03\x20\x01(\tH\x01R\
     \x0edeleteOptionIdB\x19\n\x17one_of_insert_option_idB\x19\n\x17one_of_de\
-    lete_option_id\"t\n\x13SelectOptionContext\x12'\n\x07options\x18\x01\x20\
-    \x03(\x0b2\r.SelectOptionR\x07options\x124\n\x0eselect_options\x18\x02\
-    \x20\x03(\x0b2\r.SelectOptionR\rselectOptions*y\n\x11SelectOptionColor\
-    \x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightPink\
+    lete_option_id\"u\n\x14SelectOptionCellData\x12'\n\x07options\x18\x01\
+    \x20\x03(\x0b2\r.SelectOptionR\x07options\x124\n\x0eselect_options\x18\
+    \x02\x20\x03(\x0b2\r.SelectOptionR\rselectOptions*y\n\x11SelectOptionCol\
+    or\x12\n\n\x06Purple\x10\0\x12\x08\n\x04Pink\x10\x01\x12\r\n\tLightPink\
     \x10\x02\x12\n\n\x06Orange\x10\x03\x12\n\n\x06Yellow\x10\x04\x12\x08\n\
     \x04Lime\x10\x05\x12\t\n\x05Green\x10\x06\x12\x08\n\x04Aqua\x10\x07\x12\
     \x08\n\x04Blue\x10\x08b\x06proto3\

+ 4 - 0
frontend/rust-lib/flowy-grid/src/protobuf/proto/date_type_option.proto

@@ -6,6 +6,10 @@ message DateTypeOption {
     TimeFormat time_format = 2;
     bool include_time = 3;
 }
+message DateCellData {
+    string date = 1;
+    string time = 2;
+}
 message DateChangesetPayload {
     CellIdentifierPayload cell_identifier = 1;
     oneof one_of_date { string date = 2; };

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

@@ -14,7 +14,7 @@ enum GridEvent {
     MoveItem = 23;
     GetFieldTypeOption = 24;
     NewSelectOption = 30;
-    GetSelectOptionContext = 31;
+    GetSelectOptionCellData = 31;
     UpdateSelectOption = 32;
     CreateRow = 50;
     GetRow = 51;
@@ -24,4 +24,5 @@ enum GridEvent {
     UpdateCell = 71;
     UpdateSelectOptionCell = 72;
     UpdateDateCell = 80;
+    GetDateCellData = 90;
 }

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

@@ -25,7 +25,7 @@ message SelectOptionCellChangesetPayload {
     oneof one_of_insert_option_id { string insert_option_id = 2; };
     oneof one_of_delete_option_id { string delete_option_id = 3; };
 }
-message SelectOptionContext {
+message SelectOptionCellData {
     repeated SelectOption options = 1;
     repeated SelectOption select_options = 2;
 }

+ 24 - 9
frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs

@@ -77,6 +77,21 @@ impl DateTypeOption {
             self.date_format.format_str().to_string()
         }
     }
+
+    pub fn date_cell_data(&self, cell_meta: &Option<CellMeta>) -> FlowyResult<DateCellData> {
+        if cell_meta.is_none() {
+            return Ok(DateCellData::default());
+        }
+
+        let json = &cell_meta.as_ref().unwrap().data;
+        let result = TypeOptionCellData::from_str(json);
+        if result.is_err() {
+            return Ok(DateCellData::default());
+        }
+
+        let data: DateCellData = serde_json::from_str(&result.unwrap().data)?;
+        Ok(data)
+    }
 }
 
 impl CellDataOperation for DateTypeOption {
@@ -235,6 +250,15 @@ impl std::default::Default for TimeFormat {
     }
 }
 
+#[derive(Clone, Debug, Default, ProtoBuf, Serialize, Deserialize)]
+pub struct DateCellData {
+    #[pb(index = 1)]
+    pub date: String,
+
+    #[pb(index = 2)]
+    pub time: String,
+}
+
 #[derive(Clone, Debug, Default, ProtoBuf)]
 pub struct DateChangesetPayload {
     #[pb(index = 1)]
@@ -461,15 +485,6 @@ mod tests {
             time: Some("1:".to_owned()),
         };
         let _ = type_option.apply_changeset(changeset, None).unwrap();
-
-        // let changeset = DateCellContentChangeset {
-        //     date: Some(date_timestamp),
-        //     time: Some("1:00 am".to_owned()),
-        // };
-        // type_option.time_format = TimeFormat::TwelveHour;
-        // let result = type_option.apply_changeset(changeset, None).unwrap();
-        // let content = type_option.decode_cell_data(result, &field_meta).content;
-        // assert_eq!(content, "May 27,2022 01:00 AM".to_owned());
     }
 
     #[test]

+ 6 - 6
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option.rs

@@ -42,7 +42,7 @@ pub trait SelectOptionOperation: TypeOptionDataEntry + Send + Sync {
         SelectOption::with_color(name, color)
     }
 
-    fn option_context(&self, cell_meta: &Option<CellMeta>) -> SelectOptionContext;
+    fn select_option_cell_data(&self, cell_meta: &Option<CellMeta>) -> SelectOptionCellData;
 
     fn options(&self) -> &Vec<SelectOption>;
 
@@ -78,9 +78,9 @@ pub struct SingleSelectTypeOption {
 impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect);
 
 impl SelectOptionOperation for SingleSelectTypeOption {
-    fn option_context(&self, cell_meta: &Option<CellMeta>) -> SelectOptionContext {
+    fn select_option_cell_data(&self, cell_meta: &Option<CellMeta>) -> SelectOptionCellData {
         let select_options = make_select_context_from(cell_meta, &self.options);
-        SelectOptionContext {
+        SelectOptionCellData {
             options: self.options.clone(),
             select_options,
         }
@@ -167,9 +167,9 @@ pub struct MultiSelectTypeOption {
 impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect);
 
 impl SelectOptionOperation for MultiSelectTypeOption {
-    fn option_context(&self, cell_meta: &Option<CellMeta>) -> SelectOptionContext {
+    fn select_option_cell_data(&self, cell_meta: &Option<CellMeta>) -> SelectOptionCellData {
         let select_options = make_select_context_from(cell_meta, &self.options);
-        SelectOptionContext {
+        SelectOptionCellData {
             options: self.options.clone(),
             select_options,
         }
@@ -426,7 +426,7 @@ impl SelectOptionCellContentChangeset {
 }
 
 #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
-pub struct SelectOptionContext {
+pub struct SelectOptionCellData {
     #[pb(index = 1)]
     pub options: Vec<SelectOption>,