Browse Source

Merge branch 'AppFlowy-IO:main' into dev

Zaki Mubarok 2 years ago
parent
commit
7c5c6f2faa
26 changed files with 620 additions and 346 deletions
  1. 75 3
      frontend/app_flowy/assets/translations/es-VE.json
  2. 1 1
      frontend/app_flowy/assets/translations/fr-FR.json
  3. 218 0
      frontend/app_flowy/assets/translations/zh-TW.json
  4. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart
  5. 1 1
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart
  6. 4 4
      frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart
  7. 5 5
      frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
  8. 2 5
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
  9. 4 4
      frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart
  10. 3 3
      frontend/app_flowy/pubspec.lock
  11. 3 0
      frontend/app_flowy/pubspec.yaml
  12. 16 17
      frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs
  13. 97 9
      frontend/rust-lib/flowy-grid/src/entities/field_entities.rs
  14. 7 12
      frontend/rust-lib/flowy-grid/src/entities/row_entities.rs
  15. 17 17
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  16. 9 9
      frontend/rust-lib/flowy-grid/src/event_map.rs
  17. 32 18
      frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs
  18. 5 5
      frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs
  19. 43 166
      frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_tests.rs
  20. 4 4
      frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option_entities.rs
  21. 39 32
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_tests.rs
  22. 6 6
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_option.rs
  23. 19 15
      frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_tests.rs
  24. 3 3
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  25. 2 2
      frontend/rust-lib/flowy-grid/tests/grid/block_test/row_test.rs
  26. 3 3
      frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs

+ 75 - 3
frontend/app_flowy/assets/translations/es-VE.json

@@ -96,6 +96,12 @@
     "lightMode": "Cambiar a modo Claro",
     "darkMode": "Cambiar a modo Oscuro"
   },
+  "notifications": {
+    "export": {
+      "markdown": "Nota exportada a Markdown",
+      "path": "Documentos/flowy"
+    }
+  },
   "contactsPage": {
     "title": "Contactos",
     "whatsHappening": "¿Qué está pasando esta semana?",
@@ -120,13 +126,13 @@
   "oAuth": {
     "err": {
       "failedTitle": "Imposible conectarse con sus credenciales.",
-      "failedMsg": "Por favor asegurese haber completado el proceso de ingreso en su buscador."
+      "failedMsg": "Por favor asegurese haber completado el proceso de ingreso en su navegador."
     },
     "google": {
       "title": "Ingresar con Google",
-      "instruction1": "Para importar sus contactos de Google, debe autorizar esta aplicación usando su buscador web.",
+      "instruction1": "Para importar sus contactos de Google, debe autorizar esta aplicación usando su navegador web.",
       "instruction2": "Copie este código al presionar el icono o al seleccionar el texto:",
-      "instruction3": "Navege al siguiente enlace en su buscador web, e ingrese el código anterior:",
+      "instruction3": "Navege al siguiente enlace en su navegador web, e ingrese el código anterior:",
       "instruction4": "Presione el botón de abajo cuando haya completado su registro:"
     }
   },
@@ -141,5 +147,71 @@
       "lightLabel": "Modo Claro",
       "darkLabel": "Modo Oscuro"
     }
+  },
+  "grid": {
+    "settings": {
+      "filter": "Filtrar",
+      "sortBy": "Ordenar por",
+      "Properties": "Propiedades"
+    },
+    "field": {
+      "hide": "Ocultar",
+      "insertLeft": "Insertar a la Izquierda",
+      "insertRight": "Insertar a la Derecha",
+      "duplicate": "Duplicar",
+      "delete": "Eliminar",
+      "textFieldName": "Texto",
+      "checkboxFieldName": "Casilla de verificación",
+      "dateFieldName": "Fecha",
+      "numberFieldName": "Números",
+      "singleSelectFieldName": "Seleccionar",
+      "multiSelectFieldName": "Selección múltiple",
+      "urlFieldName": "URL",
+      "numberFormat": " Formato numérico",
+      "dateFormat": " Formato de fecha",
+      "includeTime": " Incluir tiempo",
+      "dateFormatFriendly": "Mes Día, Año",
+      "dateFormatISO": "Año-Mes-Día",
+      "dateFormatLocal": "Año/Mes/Día",
+      "dateFormatUS": "Año/Mes/Día",
+      "timeFormat": " Time format",
+      "invalidTimeFormat": "Formato de tiempo",
+      "timeFormatTwelveHour": "12 horas",
+      "timeFormatTwentyFourHour": "24 horas",
+      "addSelectOption": "Añadir una opción",
+      "optionTitle": "Opciones",
+      "addOption": "Añadir opción",
+      "editProperty": "Editar propiedad"
+    },
+    "row": {
+      "duplicate": "Duplicar",
+      "delete": "Eliminar",
+      "textPlaceholder": "Vacío",
+      "copyProperty": "Propiedad copiada al portapapeles"
+    },
+    "selectOption": {
+      "create": "Crear",
+      "purpleColor": "Morado",
+      "pinkColor": "Rosa",
+      "lightPinkColor": "Rosa Claro",
+      "orangeColor": "Naranja",
+      "yellowColor": "Amarillo",
+      "limeColor": "Lima",
+      "greenColor": "Verde",
+      "aquaColor": "Agua",
+      "blueColor": "Azul",
+      "deleteTag": "Borrar etiqueta",
+      "colorPannelTitle": "Colores",
+      "pannelTitle": "Selecciona una opción o crea una",
+      "searchOption": "Buscar una opción"
+    },
+    "menuName": "Grid"
+  },
+  "document": {
+    "menuName": "Doc",
+    "date": {
+      "timeHintTextInTwelveHour": "12:00 AM",
+      "timeHintTextInTwentyFourHour": "12:00"
+    }
   }
 }

+ 1 - 1
frontend/app_flowy/assets/translations/fr-FR.json

@@ -68,7 +68,7 @@
     "help": "Aide et Support",
     "debug": {
       "name": "Informations de Débogage",
-      "success": "Informations de Débogage copiées dans le presse-papiers!",
+      "success": "Informations de Débogage copiées dans le presse-papiers !",
       "fail": "Impossible de copier les informations de Débogage dans le presse-papiers"
     }
   },

+ 218 - 0
frontend/app_flowy/assets/translations/zh-TW.json

@@ -0,0 +1,218 @@
+{
+  "appName": "AppFlowy",
+  "defaultUsername": "我",
+  "welcomeText": "歡迎使用 @:appName",
+  "githubStarText": "在 GitHub 點星",
+  "subscribeNewsletterText": "訂閱電子報",
+  "letsGoButtonText": "出發吧",
+  "title": "標題",
+  "signUp": {
+    "buttonText": "註冊",
+    "title": "註冊 @:appName",
+    "getStartedText": "開始使用",
+    "emptyPasswordError": "密碼不能為空",
+    "repeatPasswordEmptyError": "確認密碼不能為空",
+    "unmatchedPasswordError": "確認密碼與密碼不符",
+    "alreadyHaveAnAccount": "已經有帳號了嗎?",
+    "emailHint": "電子郵件地址",
+    "passwordHint": "密碼",
+    "repeatPasswordHint": "確認密碼"
+  },
+  "signIn": {
+    "loginTitle": "登入 @:appName",
+    "loginButtonText": "登入",
+    "buttonText": "登入",
+    "forgotPassword": "忘記密碼?",
+    "emailHint": "電子郵件地址",
+    "passwordHint": "密碼",
+    "dontHaveAnAccount": "沒有帳號?",
+    "repeatPasswordEmptyError": "確認密碼不能為空",
+    "unmatchedPasswordError": "確認密碼與密碼不符"
+  },
+  "workspace": {
+    "create": "建立工作區",
+    "hint": "工作區",
+    "notFoundError": "找不到工作區"
+  },
+  "shareAction": {
+    "buttonText": "分享",
+    "workInProgress": "即將推出",
+    "markdown": "Markdown",
+    "copyLink": "複製連結"
+  },
+  "disclosureAction": {
+    "rename": "重新命名",
+    "delete": "刪除",
+    "duplicate": "複製"
+  },
+  "blankPageTitle": "空白頁面",
+  "newPageText": "新頁面",
+  "trash": {
+    "text": "垃圾筒",
+    "restoreAll": "全部復原",
+    "deleteAll": "全部刪除",
+    "pageHeader": {
+      "fileName": "檔案名稱",
+      "lastModified": "最後修改時間",
+      "created": "建立時間"
+    }
+  },
+  "deletePagePrompt": {
+    "text": "此頁面在垃圾筒中",
+    "restore": "復原頁面",
+    "deletePermanent": "永久刪除"
+  },
+  "dialogCreatePageNameHint": "頁面名稱",
+  "questionBubble": {
+    "whatsNew": "新功能",
+    "help": "幫助 & 支援",
+    "debug": {
+      "name": "除錯資訊",
+      "success": "已將除錯資訊複製至剪貼簿!",
+      "fail": "無法將除錯資訊複製至剪貼簿"
+    }
+  },
+  "menuAppHeader": {
+    "addPageTooltip": "快速新增頁面",
+    "defaultNewPageName": "未命名",
+    "renameDialog": "重新命名"
+  },
+  "toolbar": {
+    "undo": "復原",
+    "redo": "取消復原",
+    "bold": "粗體",
+    "italic": "斜體",
+    "underline": "底線",
+    "strike": "刪除線",
+    "numList": "有序清單",
+    "bulletList": "無序清單",
+    "checkList": "核取清單",
+    "inlineCode": "程式碼",
+    "quote": "區塊引言",
+    "header": "標題",
+    "highlight": "反白"
+  },
+  "tooltip": {
+    "lightMode": "切換至亮色模式",
+    "darkMode": "切換至暗色模式"
+  },
+  "notifications": {
+    "export": {
+      "markdown": "已將筆記匯出成 Markdown",
+      "path": "Documents/flowy"
+    }
+  },
+  "contactsPage": {
+    "title": "聯絡人",
+    "whatsHappening": "這周有甚麼新鮮事?",
+    "addContact": "新增聯絡人",
+    "editContact": "編輯聯絡人"
+  },
+  "button": {
+    "OK": "OK",
+    "Cancel": "取消",
+    "signIn": "登入",
+    "signOut": "登出",
+    "complete": "完成",
+    "save": "儲存"
+  },
+  "label": {
+    "welcome": "歡迎!",
+    "firstName": "名",
+    "middleName": "中間名",
+    "lastName": "姓",
+    "stepX": "步驟 {X}"
+  },
+  "oAuth": {
+    "err": {
+      "failedTitle": "無法連接至您的帳號。",
+      "failedMsg": "請確認您已在瀏覽器中完成登入程序:"
+    },
+    "google": {
+      "title": "GOOGLE 登入",
+      "instruction1": "若要匯入您的 Google 聯絡人,您必須透過瀏覽器授權此應用程式:",
+      "instruction2": "點擊圖示或選取文字以複製代碼:",
+      "instruction3": "前往下列網址,並輸入上述代碼:",
+      "instruction4": "完成註冊後,請點擊下方按鈕:"
+    }
+  },
+  "settings": {
+    "title": "設定",
+    "menu": {
+      "appearance": "外觀",
+      "language": "語言",
+      "user": "使用者",
+      "open": "開啟設定"
+    },
+    "appearance": {
+      "lightLabel": "亮色模式",
+      "darkLabel": "暗色模式"
+    }
+  },
+  "grid": {
+    "settings": {
+      "filter": "篩選",
+      "sortBy": "排序方式",
+      "Properties": "內容"
+    },
+    "field": {
+      "hide": "隱藏",
+      "insertLeft": "插入左方欄",
+      "insertRight": "插入右方欄",
+      "duplicate": "複製",
+      "delete": "刪除",
+      "textFieldName": "文字",
+      "checkboxFieldName": "核取方塊",
+      "dateFieldName": "日期",
+      "numberFieldName": "數字",
+      "singleSelectFieldName": "單選",
+      "multiSelectFieldName": "多選",
+      "urlFieldName": "網址",
+      "numberFormat": " 數字格式",
+      "dateFormat": " 日期格式",
+      "includeTime": " 包含時間",
+      "dateFormatFriendly": "月 日,年",
+      "dateFormatISO": "年-月-日",
+      "dateFormatLocal": "年/月/日",
+      "dateFormatUS": "年/月/日",
+      "timeFormat": " 時間格式",
+      "invalidTimeFormat": "格式無效",
+      "timeFormatTwelveHour": "12 小時",
+      "timeFormatTwentyFourHour": "24 小時",
+      "addSelectOption": "新增選項",
+      "optionTitle": "選項",
+      "addOption": "新增選項",
+      "editProperty": "編輯內容"
+    },
+    "row": {
+      "duplicate": "複製",
+      "delete": "刪除",
+      "textPlaceholder": "空",
+      "copyProperty": "已將內容複製至剪貼簿"
+    },
+    "selectOption": {
+      "create": "建立",
+      "purpleColor": "紫色",
+      "pinkColor": "粉色",
+      "lightPinkColor": "淡粉色",
+      "orangeColor": "橘色",
+      "yellowColor": "黃色",
+      "limeColor": "萊姆色",
+      "greenColor": "綠色",
+      "aquaColor": "水藍色",
+      "blueColor": "藍色",
+      "deleteTag": "刪除標籤",
+      "colorPannelTitle": "顏色",
+      "pannelTitle": "搜尋或建立選項",
+      "searchOption": "搜尋選項"
+    },
+    "menuName": "網格"
+  },
+  "document": {
+    "menuName": "檔案",
+    "date": {
+      "timeHintTextInTwelveHour": "12:00 AM",
+      "timeHintTextInTwentyFourHour": "12:00"
+    }
+  }
+}

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

@@ -58,8 +58,8 @@ class DateCellDataPersistence implements IGridCellDataPersistence<CalendarData>
   }
 }
 
-GridCellIdentifierPayloadPB _makeCellIdPayload(GridCellIdentifier cellId) {
-  return GridCellIdentifierPayloadPB.create()
+GridCellIdPB _makeCellIdPayload(GridCellIdentifier cellId) {
+  return GridCellIdPB.create()
     ..gridId = cellId.gridId
     ..fieldId = cellId.fieldId
     ..rowId = cellId.rowId;

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

@@ -46,7 +46,7 @@ class CellService {
   Future<Either<GridCellPB, FlowyError>> getCell({
     required GridCellIdentifier cellId,
   }) {
-    final payload = GridCellIdentifierPayloadPB.create()
+    final payload = GridCellIdPB.create()
       ..gridId = cellId.gridId
       ..fieldId = cellId.fieldId
       ..rowId = cellId.rowId;

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

@@ -19,7 +19,7 @@ class SelectOptionService {
       (result) {
         return result.fold(
           (option) {
-            final cellIdentifier = GridCellIdentifierPayloadPB.create()
+            final cellIdentifier = GridCellIdPB.create()
               ..gridId = gridId
               ..fieldId = fieldId
               ..rowId = rowId;
@@ -54,7 +54,7 @@ class SelectOptionService {
   }
 
   Future<Either<SelectOptionCellDataPB, FlowyError>> getOpitonContext() {
-    final payload = GridCellIdentifierPayloadPB.create()
+    final payload = GridCellIdPB.create()
       ..gridId = gridId
       ..fieldId = fieldId
       ..rowId = rowId;
@@ -76,8 +76,8 @@ class SelectOptionService {
     return GridEventUpdateSelectOptionCell(payload).send();
   }
 
-  GridCellIdentifierPayloadPB _cellIdentifier() {
-    return GridCellIdentifierPayloadPB.create()
+  GridCellIdPB _cellIdentifier() {
+    return GridCellIdPB.create()
       ..gridId = gridId
       ..fieldId = fieldId
       ..rowId = rowId;

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

@@ -103,7 +103,7 @@ class FieldService {
   }
 
   Future<Either<Unit, FlowyError>> deleteField() {
-    final payload = GridFieldIdentifierPayloadPB.create()
+    final payload = DeleteFieldPayloadPB.create()
       ..gridId = gridId
       ..fieldId = fieldId;
 
@@ -111,7 +111,7 @@ class FieldService {
   }
 
   Future<Either<Unit, FlowyError>> duplicateField() {
-    final payload = GridFieldIdentifierPayloadPB.create()
+    final payload = DuplicateFieldPayloadPB.create()
       ..gridId = gridId
       ..fieldId = fieldId;
 
@@ -121,7 +121,7 @@ class FieldService {
   Future<Either<FieldTypeOptionDataPB, FlowyError>> getFieldTypeOptionData({
     required FieldType fieldType,
   }) {
-    final payload = EditFieldPayloadPB.create()
+    final payload = GridFieldTypeOptionIdPB.create()
       ..gridId = gridId
       ..fieldId = fieldId
       ..fieldType = fieldType;
@@ -165,7 +165,7 @@ class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader {
 
   @override
   Future<Either<FieldTypeOptionDataPB, FlowyError>> load() {
-    final payload = EditFieldPayloadPB.create()
+    final payload = CreateFieldPayloadPB.create()
       ..gridId = gridId
       ..fieldType = FieldType.RichText;
 
@@ -185,7 +185,7 @@ class FieldTypeOptionLoader extends IFieldTypeOptionLoader {
 
   @override
   Future<Either<FieldTypeOptionDataPB, FlowyError>> load() {
-    final payload = EditFieldPayloadPB.create()
+    final payload = GridFieldTypeOptionIdPB.create()
       ..gridId = gridId
       ..fieldId = field.id
       ..fieldType = field.fieldType;

+ 2 - 5
frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart

@@ -21,13 +21,10 @@ class TypeOptionService {
   Future<Either<SelectOptionPB, FlowyError>> newOption({
     required String name,
   }) {
-    final fieldIdentifier = GridFieldIdentifierPayloadPB.create()
-      ..gridId = gridId
-      ..fieldId = fieldId;
-
     final payload = CreateSelectOptionPayloadPB.create()
       ..optionName = name
-      ..fieldIdentifier = fieldIdentifier;
+      ..gridId = gridId
+      ..fieldId = fieldId;
 
     return GridEventNewSelectOption(payload).send();
   }

+ 4 - 4
frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart

@@ -191,7 +191,7 @@ class GridRowCache {
   }
 
   Future<void> _loadRow(String rowId) async {
-    final payload = GridRowIdPayloadPB.create()
+    final payload = GridRowIdPB.create()
       ..gridId = gridId
       ..blockId = block.id
       ..rowId = rowId;
@@ -297,7 +297,7 @@ class RowService {
   }
 
   Future<Either<OptionalRowPB, FlowyError>> getRow() {
-    final payload = GridRowIdPayloadPB.create()
+    final payload = GridRowIdPB.create()
       ..gridId = gridId
       ..blockId = blockId
       ..rowId = rowId;
@@ -306,7 +306,7 @@ class RowService {
   }
 
   Future<Either<Unit, FlowyError>> deleteRow() {
-    final payload = GridRowIdPayloadPB.create()
+    final payload = GridRowIdPB.create()
       ..gridId = gridId
       ..blockId = blockId
       ..rowId = rowId;
@@ -315,7 +315,7 @@ class RowService {
   }
 
   Future<Either<Unit, FlowyError>> duplicateRow() {
-    final payload = GridRowIdPayloadPB.create()
+    final payload = GridRowIdPB.create()
       ..gridId = gridId
       ..blockId = blockId
       ..rowId = rowId;

+ 3 - 3
frontend/app_flowy/pubspec.lock

@@ -7,14 +7,14 @@ packages:
       name: _fe_analyzer_shared
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "38.0.0"
+    version: "42.0.0"
   analyzer:
-    dependency: transitive
+    dependency: "direct overridden"
     description:
       name: analyzer
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.4.1"
+    version: "4.3.0"
   animations:
     dependency: transitive
     description:

+ 3 - 0
frontend/app_flowy/pubspec.yaml

@@ -85,6 +85,9 @@ dev_dependencies:
   freezed:
   bloc_test: ^9.0.2
 
+dependency_overrides:
+  analyzer: ">=4.2.0 <5.0.0"
+
   # The "flutter_lints" package below contains a set of recommended lints to
   # encourage good coding practices. The lint set provided by the package is
   # activated in the `analysis_options.yaml` file located at the root of your

+ 16 - 17
frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs

@@ -1,4 +1,4 @@
-use crate::entities::{FieldIdentifierParams, GridFieldIdentifierPayloadPB};
+
 use flowy_derive::ProtoBuf;
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
@@ -8,23 +8,20 @@ use std::collections::HashMap;
 #[derive(ProtoBuf, Default)]
 pub struct CreateSelectOptionPayloadPB {
     #[pb(index = 1)]
-    pub field_identifier: GridFieldIdentifierPayloadPB,
+    pub field_id: String,
 
     #[pb(index = 2)]
+    pub grid_id: String,
+
+    #[pb(index = 3)]
     pub option_name: String,
 }
 
 pub struct CreateSelectOptionParams {
-    pub field_identifier: FieldIdentifierParams,
+    pub field_id: String,
+    pub grid_id: String,
     pub option_name: String,
-}
 
-impl std::ops::Deref for CreateSelectOptionParams {
-    type Target = FieldIdentifierParams;
-
-    fn deref(&self) -> &Self::Target {
-        &self.field_identifier
-    }
 }
 
 impl TryInto<CreateSelectOptionParams> for CreateSelectOptionPayloadPB {
@@ -32,16 +29,18 @@ impl TryInto<CreateSelectOptionParams> for CreateSelectOptionPayloadPB {
 
     fn try_into(self) -> Result<CreateSelectOptionParams, Self::Error> {
         let option_name = NotEmptyStr::parse(self.option_name).map_err(|_| ErrorCode::SelectOptionNameIsEmpty)?;
-        let field_identifier = self.field_identifier.try_into()?;
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
         Ok(CreateSelectOptionParams {
-            field_identifier,
+            field_id: field_id.0,
             option_name: option_name.0,
+            grid_id: grid_id.0,
         })
     }
 }
 
 #[derive(Debug, Clone, Default, ProtoBuf)]
-pub struct GridCellIdentifierPayloadPB {
+pub struct GridCellIdPB {
     #[pb(index = 1)]
     pub grid_id: String,
 
@@ -52,20 +51,20 @@ pub struct GridCellIdentifierPayloadPB {
     pub row_id: String,
 }
 
-pub struct CellIdentifierParams {
+pub struct GridCellIdParams {
     pub grid_id: String,
     pub field_id: String,
     pub row_id: String,
 }
 
-impl TryInto<CellIdentifierParams> for GridCellIdentifierPayloadPB {
+impl TryInto<GridCellIdParams> for GridCellIdPB {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<CellIdentifierParams, Self::Error> {
+    fn try_into(self) -> Result<GridCellIdParams, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
         let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
         let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
-        Ok(CellIdentifierParams {
+        Ok(GridCellIdParams {
             grid_id: grid_id.0,
             field_id: field_id.0,
             row_id: row_id.0,

+ 97 - 9
frontend/rust-lib/flowy-grid/src/entities/field_entities.rs

@@ -155,6 +155,45 @@ pub struct GetEditFieldContextPayloadPB {
     pub field_type: FieldType,
 }
 
+
+
+#[derive(Debug, Default, ProtoBuf)]
+pub struct CreateFieldPayloadPB {
+    #[pb(index = 1)]
+    pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field_id: String,
+
+    #[pb(index = 3)]
+    pub field_type: FieldType,
+
+    #[pb(index = 4)]
+    pub create_if_not_exist: bool,
+}
+
+pub struct CreateFieldParams {
+    pub grid_id: String,
+    pub field_id: String,
+    pub field_type: FieldType,
+}
+
+impl TryInto<CreateFieldParams> for CreateFieldPayloadPB {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+        Ok(CreateFieldParams {
+            grid_id: grid_id.0,
+            field_id: field_id.0,
+            field_type: self.field_type,
+        })
+    }
+}
+
+
+
 #[derive(Debug, Default, ProtoBuf)]
 pub struct EditFieldPayloadPB {
     #[pb(index = 1)]
@@ -190,19 +229,34 @@ impl TryInto<EditFieldParams> for EditFieldPayloadPB {
     }
 }
 
-pub struct CreateFieldParams {
+#[derive(Debug, Default, ProtoBuf)]
+pub struct GridFieldTypeOptionIdPB {
+    #[pb(index = 1)]
     pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub field_id: String,
+
+    #[pb(index = 3)]
     pub field_type: FieldType,
 }
 
-impl TryInto<CreateFieldParams> for EditFieldPayloadPB {
+
+pub struct GridFieldTypeOptionIdParams {
+    pub grid_id: String,
+    pub field_id: String,
+    pub field_type: FieldType,
+}
+
+impl TryInto<GridFieldTypeOptionIdParams> for GridFieldTypeOptionIdPB {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<CreateFieldParams, Self::Error> {
+    fn try_into(self) -> Result<GridFieldTypeOptionIdParams, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-
-        Ok(CreateFieldParams {
+        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+        Ok(GridFieldTypeOptionIdParams {
             grid_id: grid_id.0,
+            field_id: field_id.0,
             field_type: self.field_type,
         })
     }
@@ -556,6 +610,16 @@ impl std::convert::From<FieldTypeRevision> for FieldType {
         }
     }
 }
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct DuplicateFieldPayloadPB {
+    #[pb(index = 1)]
+    pub field_id: String,
+
+    #[pb(index = 2)]
+    pub grid_id: String,
+}
+
+
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct GridFieldIdentifierPayloadPB {
     #[pb(index = 1)]
@@ -565,20 +629,44 @@ pub struct GridFieldIdentifierPayloadPB {
     pub grid_id: String,
 }
 
-pub struct FieldIdentifierParams {
+impl TryInto<GridFieldIdParams> for DuplicateFieldPayloadPB {
+    type Error = ErrorCode;
+
+    fn try_into(self) -> Result<GridFieldIdParams, Self::Error> {
+        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
+        Ok(GridFieldIdParams {
+            grid_id: grid_id.0,
+            field_id: field_id.0,
+        })
+    }
+}
+
+#[derive(Debug, Clone, Default, ProtoBuf)]
+pub struct DeleteFieldPayloadPB {
+    #[pb(index = 1)]
     pub field_id: String,
+
+    #[pb(index = 2)]
     pub grid_id: String,
 }
 
-impl TryInto<FieldIdentifierParams> for GridFieldIdentifierPayloadPB {
+impl TryInto<GridFieldIdParams> for DeleteFieldPayloadPB {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<FieldIdentifierParams, Self::Error> {
+    fn try_into(self) -> Result<GridFieldIdParams, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
         let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
-        Ok(FieldIdentifierParams {
+        Ok(GridFieldIdParams {
             grid_id: grid_id.0,
             field_id: field_id.0,
         })
     }
 }
+
+pub struct GridFieldIdParams {
+    pub field_id: String,
+    pub grid_id: String,
+}
+
+

+ 7 - 12
frontend/rust-lib/flowy-grid/src/entities/row_entities.rs

@@ -2,8 +2,9 @@ use flowy_derive::ProtoBuf;
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
 
-#[derive(ProtoBuf, Default)]
-pub struct GridRowIdPayloadPB {
+
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct GridRowIdPB {
     #[pb(index = 1)]
     pub grid_id: String,
 
@@ -14,27 +15,21 @@ pub struct GridRowIdPayloadPB {
     pub row_id: String,
 }
 
-#[derive(Debug, Default, Clone, ProtoBuf)]
-pub struct GridRowIdPB {
-    #[pb(index = 1)]
+pub struct GridRowIdParams {
     pub grid_id: String,
-
-    #[pb(index = 2)]
     pub block_id: String,
-
-    #[pb(index = 3)]
     pub row_id: String,
 }
 
-impl TryInto<GridRowIdPB> for GridRowIdPayloadPB {
+impl TryInto<GridRowIdParams> for GridRowIdPB {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<GridRowIdPB, Self::Error> {
+    fn try_into(self) -> Result<GridRowIdParams, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
         let block_id = NotEmptyStr::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
         let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
 
-        Ok(GridRowIdPB {
+        Ok(GridRowIdParams {
             grid_id: grid_id.0,
             block_id: block_id.0,
             row_id: row_id.0,

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

@@ -113,10 +113,10 @@ pub(crate) async fn update_field_type_option_handler(
 
 #[tracing::instrument(level = "trace", skip(data, manager), err)]
 pub(crate) async fn delete_field_handler(
-    data: Data<GridFieldIdentifierPayloadPB>,
+    data: Data<DeleteFieldPayloadPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: FieldIdentifierParams = data.into_inner().try_into()?;
+    let params: GridFieldIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.delete_field(&params.field_id).await?;
     Ok(())
@@ -151,10 +151,10 @@ pub(crate) async fn switch_to_field_handler(
 
 #[tracing::instrument(level = "trace", skip(data, manager), err)]
 pub(crate) async fn duplicate_field_handler(
-    data: Data<GridFieldIdentifierPayloadPB>,
+    data: Data<DuplicateFieldPayloadPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: FieldIdentifierParams = data.into_inner().try_into()?;
+    let params: GridFieldIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.duplicate_field(&params.field_id).await?;
     Ok(())
@@ -163,10 +163,10 @@ pub(crate) async fn duplicate_field_handler(
 /// Return the FieldTypeOptionData if the Field exists otherwise return record not found error.
 #[tracing::instrument(level = "trace", skip(data, manager), err)]
 pub(crate) async fn get_field_type_option_data_handler(
-    data: Data<EditFieldPayloadPB>,
+    data: Data<GridFieldTypeOptionIdPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<FieldTypeOptionDataPB, FlowyError> {
-    let params: EditFieldParams = data.into_inner().try_into()?;
+    let params: GridFieldTypeOptionIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     match editor.get_field_rev(&params.field_id).await {
         None => Err(FlowyError::record_not_found()),
@@ -186,7 +186,7 @@ pub(crate) async fn get_field_type_option_data_handler(
 /// Create FieldMeta and save it. Return the FieldTypeOptionData.
 #[tracing::instrument(level = "trace", skip(data, manager), err)]
 pub(crate) async fn create_field_type_option_data_handler(
-    data: Data<EditFieldPayloadPB>,
+    data: Data<CreateFieldPayloadPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<FieldTypeOptionDataPB, FlowyError> {
     let params: CreateFieldParams = data.into_inner().try_into()?;
@@ -227,10 +227,10 @@ async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType)
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn get_row_handler(
-    data: Data<GridRowIdPayloadPB>,
+    data: Data<GridRowIdPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<OptionalRowPB, FlowyError> {
-    let params: GridRowIdPB = data.into_inner().try_into()?;
+    let params: GridRowIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let row = editor
         .get_row_rev(&params.row_id)
@@ -242,10 +242,10 @@ pub(crate) async fn get_row_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn delete_row_handler(
-    data: Data<GridRowIdPayloadPB>,
+    data: Data<GridRowIdPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: GridRowIdPB = data.into_inner().try_into()?;
+    let params: GridRowIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.delete_row(&params.row_id).await?;
     Ok(())
@@ -253,10 +253,10 @@ pub(crate) async fn delete_row_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn duplicate_row_handler(
-    data: Data<GridRowIdPayloadPB>,
+    data: Data<GridRowIdPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: GridRowIdPB = data.into_inner().try_into()?;
+    let params: GridRowIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.duplicate_row(&params.row_id).await?;
     Ok(())
@@ -275,10 +275,10 @@ pub(crate) async fn create_row_handler(
 
 // #[tracing::instrument(level = "debug", skip_all, err)]
 pub(crate) async fn get_cell_handler(
-    data: Data<GridCellIdentifierPayloadPB>,
+    data: Data<GridCellIdPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<GridCellPB, FlowyError> {
-    let params: CellIdentifierParams = data.into_inner().try_into()?;
+    let params: GridCellIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     match editor.get_cell(&params).await {
         None => data_result(GridCellPB::empty(&params.field_id)),
@@ -357,10 +357,10 @@ pub(crate) async fn update_select_option_handler(
 
 #[tracing::instrument(level = "trace", skip(data, manager), err)]
 pub(crate) async fn get_select_option_handler(
-    data: Data<GridCellIdentifierPayloadPB>,
+    data: Data<GridCellIdPB>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<SelectOptionCellDataPB, FlowyError> {
-    let params: CellIdentifierParams = data.into_inner().try_into()?;
+    let params: GridCellIdParams = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     match editor.get_field_rev(&params.field_id).await {
         None => {

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

@@ -69,28 +69,28 @@ pub enum GridEvent {
     #[event(input = "InsertFieldPayloadPB")]
     InsertField = 13,
 
-    #[event(input = "GridFieldIdentifierPayloadPB")]
+    #[event(input = "DeleteFieldPayloadPB")]
     DeleteField = 14,
 
     #[event(input = "EditFieldPayloadPB", output = "FieldTypeOptionDataPB")]
     SwitchToField = 20,
 
-    #[event(input = "GridFieldIdentifierPayloadPB")]
+    #[event(input = "DuplicateFieldPayloadPB")]
     DuplicateField = 21,
 
     #[event(input = "MoveItemPayloadPB")]
     MoveItem = 22,
 
-    #[event(input = "EditFieldPayloadPB", output = "FieldTypeOptionDataPB")]
+    #[event(input = "GridFieldTypeOptionIdPB", output = "FieldTypeOptionDataPB")]
     GetFieldTypeOption = 23,
 
-    #[event(input = "EditFieldPayloadPB", output = "FieldTypeOptionDataPB")]
+    #[event(input = "CreateFieldPayloadPB", output = "FieldTypeOptionDataPB")]
     CreateFieldTypeOption = 24,
 
     #[event(input = "CreateSelectOptionPayloadPB", output = "SelectOptionPB")]
     NewSelectOption = 30,
 
-    #[event(input = "GridCellIdentifierPayloadPB", output = "SelectOptionCellDataPB")]
+    #[event(input = "GridCellIdPB", output = "SelectOptionCellDataPB")]
     GetSelectOptionCellData = 31,
 
     #[event(input = "SelectOptionChangesetPayloadPB")]
@@ -99,16 +99,16 @@ pub enum GridEvent {
     #[event(input = "CreateRowPayloadPB", output = "GridRowPB")]
     CreateRow = 50,
 
-    #[event(input = "GridRowIdPayloadPB", output = "OptionalRowPB")]
+    #[event(input = "GridRowIdPB", output = "OptionalRowPB")]
     GetRow = 51,
 
-    #[event(input = "GridRowIdPayloadPB")]
+    #[event(input = "GridRowIdPB")]
     DeleteRow = 52,
 
-    #[event(input = "GridRowIdPayloadPB")]
+    #[event(input = "GridRowIdPB")]
     DuplicateRow = 53,
 
-    #[event(input = "GridCellIdentifierPayloadPB", output = "GridCellPB")]
+    #[event(input = "GridCellIdPB", output = "GridCellPB")]
     GetCell = 70,
 
     #[event(input = "CellChangesetPB")]

+ 32 - 18
frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs

@@ -1,30 +1,44 @@
 #[cfg(test)]
 mod tests {
-    use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data};
-    use crate::services::field::type_options::checkbox_type_option::{NO, YES};
-    use crate::services::field::FieldBuilder;
-
     use crate::entities::FieldType;
+    use crate::services::cell::{CellDataOperation};
+    use crate::services::field::type_options::checkbox_type_option::*;
+    use crate::services::field::FieldBuilder;
+    use flowy_grid_data_model::revision::FieldRevision;
 
     #[test]
     fn checkout_box_description_test() {
-        let field_rev = FieldBuilder::from_field_type(&FieldType::Checkbox).build();
-        let data = apply_cell_data_changeset("true", None, &field_rev).unwrap();
-        assert_eq!(decode_any_cell_data(data, &field_rev).to_string(), YES);
+        let type_option = CheckboxTypeOption::default();
+        let field_type = FieldType::Checkbox;
+        let field_rev = FieldBuilder::from_field_type(&field_type).build();
 
-        let data = apply_cell_data_changeset("1", None, &field_rev).unwrap();
-        assert_eq!(decode_any_cell_data(data, &field_rev,).to_string(), YES);
+        // the checkout value will be checked if the value is "1", "true" or "yes"
+        assert_checkbox(&type_option, "1", CHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "true", CHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "yes", CHECK, &field_type, &field_rev);
 
-        let data = apply_cell_data_changeset("yes", None, &field_rev).unwrap();
-        assert_eq!(decode_any_cell_data(data, &field_rev,).to_string(), YES);
+        // the checkout value will be uncheck if the value is "false" or "No"
+        assert_checkbox(&type_option, "false", UNCHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "No", UNCHECK, &field_type, &field_rev);
 
-        let data = apply_cell_data_changeset("false", None, &field_rev).unwrap();
-        assert_eq!(decode_any_cell_data(data, &field_rev,).to_string(), NO);
-
-        let data = apply_cell_data_changeset("no", None, &field_rev).unwrap();
-        assert_eq!(decode_any_cell_data(data, &field_rev,).to_string(), NO);
+        // the checkout value will be empty if the value is letters or empty string
+        assert_checkbox(&type_option, "abc", "", &field_type, &field_rev);
+        assert_checkbox(&type_option, "", "", &field_type, &field_rev);
+    }
 
-        let data = apply_cell_data_changeset("12", None, &field_rev).unwrap();
-        assert_eq!(decode_any_cell_data(data, &field_rev,).to_string(), "");
+    fn assert_checkbox(
+        type_option: &CheckboxTypeOption,
+        input_str: &str,
+        expected_str: &str,
+        field_type: &FieldType,
+        field_rev: &FieldRevision,
+    ) {
+        assert_eq!(
+            type_option
+                .decode_cell_data(input_str.to_owned().into(), field_type, field_rev)
+                .unwrap()
+                .to_string(),
+            expected_str.to_owned()
+        );
     }
 }

+ 5 - 5
frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option_entities.rs

@@ -3,14 +3,14 @@ use bytes::Bytes;
 use flowy_error::{FlowyError, FlowyResult};
 use std::str::FromStr;
 
-pub const YES: &str = "Yes";
-pub const NO: &str = "No";
+pub const CHECK: &str = "Yes";
+pub const UNCHECK: &str = "No";
 
 pub struct CheckboxCellData(String);
 
 impl CheckboxCellData {
     pub fn is_check(&self) -> bool {
-        self.0 == YES
+        self.0 == CHECK
     }
 }
 
@@ -36,8 +36,8 @@ impl FromStr for CheckboxCellData {
         };
 
         match val {
-            Some(true) => Ok(Self(YES.to_string())),
-            Some(false) => Ok(Self(NO.to_string())),
+            Some(true) => Ok(Self(CHECK.to_string())),
+            Some(false) => Ok(Self(UNCHECK.to_string())),
             None => Ok(Self("".to_string())),
         }
     }

+ 43 - 166
frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_tests.rs

@@ -1,29 +1,12 @@
 #[cfg(test)]
 mod tests {
     use crate::entities::FieldType;
-    use crate::services::cell::{CellDataChangeset, CellDataOperation};
+    use crate::services::cell::{CellDataOperation};
     use crate::services::field::*;
     // use crate::services::field::{DateCellChangeset, DateCellData, DateFormat, DateTypeOption, TimeFormat};
     use flowy_grid_data_model::revision::FieldRevision;
     use strum::IntoEnumIterator;
 
-    #[test]
-    fn date_type_option_invalid_input_test() {
-        let type_option = DateTypeOption::default();
-        let field_type = FieldType::DateTime;
-        let field_rev = FieldBuilder::from_field_type(&field_type).build();
-        assert_changeset_result(
-            &type_option,
-            DateCellChangesetPB {
-                date: Some("1e".to_string()),
-                time: Some("23:00".to_owned()),
-            },
-            &field_type,
-            &field_rev,
-            "",
-        );
-    }
-
     #[test]
     fn date_type_option_date_format_test() {
         let mut type_option = DateTypeOption::default();
@@ -32,23 +15,23 @@ mod tests {
             type_option.date_format = date_format;
             match date_format {
                 DateFormat::Friendly => {
-                    assert_decode_timestamp(1647251762, &type_option, &field_rev, "Mar 14,2022");
+                    assert_date(&type_option, 1647251762, None, "Mar 14,2022", &field_rev);
                 }
                 DateFormat::US => {
-                    assert_decode_timestamp(1647251762, &type_option, &field_rev, "2022/03/14");
+                    assert_date(&type_option, 1647251762, None, "2022/03/14", &field_rev);
                 }
                 DateFormat::ISO => {
-                    assert_decode_timestamp(1647251762, &type_option, &field_rev, "2022-03-14");
+                    assert_date(&type_option, 1647251762, None, "2022-03-14", &field_rev);
                 }
                 DateFormat::Local => {
-                    assert_decode_timestamp(1647251762, &type_option, &field_rev, "2022/03/14");
+                    assert_date(&type_option, 1647251762, None, "2022/03/14", &field_rev);
                 }
             }
         }
     }
 
     #[test]
-    fn date_type_option_time_format_test() {
+    fn date_type_option_different_time_format_test() {
         let mut type_option = DateTypeOption::default();
         let field_type = FieldType::DateTime;
         let field_rev = FieldBuilder::from_field_type(&field_type).build();
@@ -58,59 +41,23 @@ mod tests {
             type_option.include_time = true;
             match time_format {
                 TimeFormat::TwentyFourHour => {
-                    assert_changeset_result(
-                        &type_option,
-                        DateCellChangesetPB {
-                            date: Some(1653609600.to_string()),
-                            time: None,
-                        },
-                        &field_type,
-                        &field_rev,
-                        "May 27,2022",
-                    );
-                    assert_changeset_result(
+                    assert_date(&type_option, 1653609600, None, "May 27,2022", &field_rev);
+                    assert_date(
                         &type_option,
-                        DateCellChangesetPB {
-                            date: Some(1653609600.to_string()),
-                            time: Some("23:00".to_owned()),
-                        },
-                        &field_type,
-                        &field_rev,
+                        1653609600,
+                        Some("23:00".to_owned()),
                         "May 27,2022 23:00",
+                        &field_rev,
                     );
                 }
                 TimeFormat::TwelveHour => {
-                    assert_changeset_result(
+                    assert_date(&type_option, 1653609600, None, "May 27,2022", &field_rev);
+                    assert_date(
                         &type_option,
-                        DateCellChangesetPB {
-                            date: Some(1653609600.to_string()),
-                            time: None,
-                        },
-                        &field_type,
-                        &field_rev,
-                        "May 27,2022",
-                    );
-                    //
-                    assert_changeset_result(
-                        &type_option,
-                        DateCellChangesetPB {
-                            date: Some(1653609600.to_string()),
-                            time: Some("".to_owned()),
-                        },
-                        &field_type,
-                        &field_rev,
-                        "May 27,2022",
-                    );
-
-                    assert_changeset_result(
-                        &type_option,
-                        DateCellChangesetPB {
-                            date: Some(1653609600.to_string()),
-                            time: Some("11:23 pm".to_owned()),
-                        },
-                        &field_type,
-                        &field_rev,
+                        1653609600,
+                        Some("11:23 pm".to_owned()),
                         "May 27,2022 11:23 PM",
+                        &field_rev,
                     );
                 }
             }
@@ -118,141 +65,71 @@ mod tests {
     }
 
     #[test]
-    fn date_type_option_apply_changeset_test() {
-        let mut type_option = DateTypeOption::new();
+    fn date_type_option_invalid_date_str_test() {
+        let type_option = DateTypeOption::default();
         let field_type = FieldType::DateTime;
         let field_rev = FieldBuilder::from_field_type(&field_type).build();
-        let date_timestamp = "1653609600".to_owned();
-
-        assert_changeset_result(
-            &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp.clone()),
-                time: None,
-            },
-            &field_type,
-            &field_rev,
-            "May 27,2022",
-        );
+        assert_date(&type_option, "abc", None, "", &field_rev);
+    }
 
+    #[test]
+    #[should_panic]
+    fn date_type_option_invalid_include_time_str_test() {
+        let mut type_option = DateTypeOption::new();
         type_option.include_time = true;
-        assert_changeset_result(
-            &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp.clone()),
-                time: None,
-            },
-            &field_type,
-            &field_rev,
-            "May 27,2022",
-        );
+        let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
 
-        assert_changeset_result(
+        assert_date(
             &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp.clone()),
-                time: Some("1:00".to_owned()),
-            },
-            &field_type,
-            &field_rev,
+            1653609600,
+            Some("1:".to_owned()),
             "May 27,2022 01:00",
-        );
-
-        type_option.time_format = TimeFormat::TwelveHour;
-        assert_changeset_result(
-            &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp),
-                time: Some("1:00 am".to_owned()),
-            },
-            &field_type,
             &field_rev,
-            "May 27,2022 01:00 AM",
         );
     }
 
     #[test]
-    #[should_panic]
-    fn date_type_option_apply_changeset_error_test() {
+    fn date_type_option_empty_include_time_str_test() {
         let mut type_option = DateTypeOption::new();
         type_option.include_time = true;
         let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
-        let date_timestamp = "1653609600".to_owned();
 
-        assert_changeset_result(
-            &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp.clone()),
-                time: Some("1:".to_owned()),
-            },
-            &FieldType::DateTime,
-            &field_rev,
-            "May 27,2022 01:00",
-        );
-
-        assert_changeset_result(
-            &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp),
-                time: Some("1:00".to_owned()),
-            },
-            &FieldType::DateTime,
-            &field_rev,
-            "May 27,2022 01:00",
-        );
+        assert_date(&type_option, 1653609600, Some("".to_owned()), "May 27,2022", &field_rev);
     }
 
+    /// The default time format is TwentyFourHour, so the include_time_str  in twelve_hours_format will cause parser error.
     #[test]
     #[should_panic]
-    fn date_type_option_twelve_hours_to_twenty_four_hours() {
+    fn date_type_option_twelve_hours_include_time_str_in_twenty_four_hours_format() {
         let mut type_option = DateTypeOption::new();
         type_option.include_time = true;
         let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
-        let date_timestamp = "1653609600".to_owned();
 
-        assert_changeset_result(
+        assert_date(
             &type_option,
-            DateCellChangesetPB {
-                date: Some(date_timestamp),
-                time: Some("1:00 am".to_owned()),
-            },
-            &FieldType::DateTime,
+            1653609600,
+            Some("1:00 am".to_owned()),
+            "May 27,2022 01:00 AM",
             &field_rev,
-            "May 27,2022 01:00",
         );
     }
-
-    fn assert_changeset_result(
-        type_option: &DateTypeOption,
-        changeset: DateCellChangesetPB,
-        _field_type: &FieldType,
-        field_rev: &FieldRevision,
-        expected: &str,
-    ) {
-        let changeset = CellDataChangeset(Some(changeset));
-        let encoded_data = type_option.apply_changeset(changeset, None).unwrap();
-        assert_eq!(
-            expected.to_owned(),
-            decode_cell_data(encoded_data, type_option, field_rev)
-        );
-    }
-
-    fn assert_decode_timestamp(
-        timestamp: i64,
+    fn assert_date<T: ToString>(
         type_option: &DateTypeOption,
+        timestamp: T,
+        include_time_str: Option<String>,
+        expected_str: &str,
         field_rev: &FieldRevision,
-        expected: &str,
     ) {
         let s = serde_json::to_string(&DateCellChangesetPB {
             date: Some(timestamp.to_string()),
-            time: None,
+            time: include_time_str,
         })
         .unwrap();
         let encoded_data = type_option.apply_changeset(s.into(), None).unwrap();
 
         assert_eq!(
-            expected.to_owned(),
-            decode_cell_data(encoded_data, type_option, field_rev)
+            decode_cell_data(encoded_data, type_option, field_rev),
+            expected_str.to_owned(),
         );
     }
 

+ 4 - 4
frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option_entities.rs

@@ -1,5 +1,5 @@
 use crate::entities::CellChangesetPB;
-use crate::entities::{CellIdentifierParams, GridCellIdentifierPayloadPB};
+use crate::entities::{GridCellIdParams, GridCellIdPB};
 use crate::services::cell::{CellBytesParser, FromCellChangeset, FromCellString};
 use bytes::Bytes;
 
@@ -24,7 +24,7 @@ pub struct DateCellDataPB {
 #[derive(Clone, Debug, Default, ProtoBuf)]
 pub struct DateChangesetPayloadPB {
     #[pb(index = 1)]
-    pub cell_identifier: GridCellIdentifierPayloadPB,
+    pub cell_identifier: GridCellIdPB,
 
     #[pb(index = 2, one_of)]
     pub date: Option<String>,
@@ -34,7 +34,7 @@ pub struct DateChangesetPayloadPB {
 }
 
 pub struct DateChangesetParams {
-    pub cell_identifier: CellIdentifierParams,
+    pub cell_identifier: GridCellIdParams,
     pub date: Option<String>,
     pub time: Option<String>,
 }
@@ -43,7 +43,7 @@ impl TryInto<DateChangesetParams> for DateChangesetPayloadPB {
     type Error = ErrorCode;
 
     fn try_into(self) -> Result<DateChangesetParams, Self::Error> {
-        let cell_identifier: CellIdentifierParams = self.cell_identifier.try_into()?;
+        let cell_identifier: GridCellIdParams = self.cell_identifier.try_into()?;
         Ok(DateChangesetParams {
             cell_identifier,
             date: self.date,

+ 39 - 32
frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_tests.rs

@@ -7,25 +7,30 @@ mod tests {
     use flowy_grid_data_model::revision::FieldRevision;
     use strum::IntoEnumIterator;
 
+    /// Testing when the input is not a number.
     #[test]
     fn number_type_option_invalid_input_test() {
         let type_option = NumberTypeOption::default();
         let field_type = FieldType::Number;
         let field_rev = FieldBuilder::from_field_type(&field_type).build();
-        assert_equal(&type_option, "", "", &field_type, &field_rev);
-        assert_equal(&type_option, "abc", "", &field_type, &field_rev);
+
+        // Input is empty String
+        assert_number(&type_option, "", "", &field_type, &field_rev);
+
+        // Input is letter
+        assert_number(&type_option, "abc", "", &field_type, &field_rev);
     }
 
+    /// Testing the strip_currency_symbol function. It should return the string without the input symbol.
     #[test]
     fn number_type_option_strip_symbol_test() {
-        let mut type_option = NumberTypeOption::new();
-        type_option.format = NumberFormat::USD;
+        // Remove the $ symbol
         assert_eq!(strip_currency_symbol("$18,443"), "18,443".to_owned());
-
-        type_option.format = NumberFormat::Yuan;
-        assert_eq!(strip_currency_symbol("$0.2"), "0.2".to_owned());
+        // Remove the ¥ symbol
+        assert_eq!(strip_currency_symbol("¥0.2"), "0.2".to_owned());
     }
 
+    /// Format the input number to the corresponding format string.
     #[test]
     fn number_type_option_format_number_test() {
         let mut type_option = NumberTypeOption::default();
@@ -36,25 +41,26 @@ mod tests {
             type_option.format = format;
             match format {
                 NumberFormat::Num => {
-                    assert_equal(&type_option, "18443", "18443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "18443", &field_type, &field_rev);
                 }
                 NumberFormat::USD => {
-                    assert_equal(&type_option, "18443", "$18,443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "$18,443", &field_type, &field_rev);
                 }
                 NumberFormat::Yen => {
-                    assert_equal(&type_option, "18443", "¥18,443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "¥18,443", &field_type, &field_rev);
                 }
                 NumberFormat::Yuan => {
-                    assert_equal(&type_option, "18443", "CN¥18,443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "CN¥18,443", &field_type, &field_rev);
                 }
                 NumberFormat::EUR => {
-                    assert_equal(&type_option, "18443", "€18.443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "€18.443", &field_type, &field_rev);
                 }
                 _ => {}
             }
         }
     }
 
+    /// Format the input String to the corresponding format string.
     #[test]
     fn number_type_option_format_str_test() {
         let mut type_option = NumberTypeOption::default();
@@ -65,33 +71,34 @@ mod tests {
             type_option.format = format;
             match format {
                 NumberFormat::Num => {
-                    assert_equal(&type_option, "18443", "18443", &field_type, &field_rev);
-                    assert_equal(&type_option, "0.2", "0.2", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "18443", &field_type, &field_rev);
+                    assert_number(&type_option, "0.2", "0.2", &field_type, &field_rev);
                 }
                 NumberFormat::USD => {
-                    assert_equal(&type_option, "$18,44", "$1,844", &field_type, &field_rev);
-                    assert_equal(&type_option, "$0.2", "$0.2", &field_type, &field_rev);
-                    assert_equal(&type_option, "", "", &field_type, &field_rev);
-                    assert_equal(&type_option, "abc", "", &field_type, &field_rev);
+                    assert_number(&type_option, "$18,44", "$1,844", &field_type, &field_rev);
+                    assert_number(&type_option, "$0.2", "$0.2", &field_type, &field_rev);
+                    assert_number(&type_option, "", "", &field_type, &field_rev);
+                    assert_number(&type_option, "abc", "", &field_type, &field_rev);
                 }
                 NumberFormat::Yen => {
-                    assert_equal(&type_option, "¥18,44", "¥1,844", &field_type, &field_rev);
-                    assert_equal(&type_option, "¥1844", "¥1,844", &field_type, &field_rev);
+                    assert_number(&type_option, "¥18,44", "¥1,844", &field_type, &field_rev);
+                    assert_number(&type_option, "¥1844", "¥1,844", &field_type, &field_rev);
                 }
                 NumberFormat::Yuan => {
-                    assert_equal(&type_option, "CN¥18,44", "CN¥1,844", &field_type, &field_rev);
-                    assert_equal(&type_option, "CN¥1844", "CN¥1,844", &field_type, &field_rev);
+                    assert_number(&type_option, "CN¥18,44", "CN¥1,844", &field_type, &field_rev);
+                    assert_number(&type_option, "CN¥1844", "CN¥1,844", &field_type, &field_rev);
                 }
                 NumberFormat::EUR => {
-                    assert_equal(&type_option, "€18.44", "€18,44", &field_type, &field_rev);
-                    assert_equal(&type_option, "€0.5", "€0,5", &field_type, &field_rev);
-                    assert_equal(&type_option, "€1844", "€1.844", &field_type, &field_rev);
+                    assert_number(&type_option, "€18.44", "€18,44", &field_type, &field_rev);
+                    assert_number(&type_option, "€0.5", "€0,5", &field_type, &field_rev);
+                    assert_number(&type_option, "€1844", "€1.844", &field_type, &field_rev);
                 }
                 _ => {}
             }
         }
     }
 
+    /// Carry out the sign positive to input number
     #[test]
     fn number_description_sign_test() {
         let mut type_option = NumberTypeOption {
@@ -105,32 +112,32 @@ mod tests {
             type_option.format = format;
             match format {
                 NumberFormat::Num => {
-                    assert_equal(&type_option, "18443", "18443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "18443", &field_type, &field_rev);
                 }
                 NumberFormat::USD => {
-                    assert_equal(&type_option, "18443", "-$18,443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "-$18,443", &field_type, &field_rev);
                 }
                 NumberFormat::Yen => {
-                    assert_equal(&type_option, "18443", "-¥18,443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "-¥18,443", &field_type, &field_rev);
                 }
                 NumberFormat::EUR => {
-                    assert_equal(&type_option, "18443", "-€18.443", &field_type, &field_rev);
+                    assert_number(&type_option, "18443", "-€18.443", &field_type, &field_rev);
                 }
                 _ => {}
             }
         }
     }
 
-    fn assert_equal(
+    fn assert_number(
         type_option: &NumberTypeOption,
-        cell_data: &str,
+        input_str: &str,
         expected_str: &str,
         field_type: &FieldType,
         field_rev: &FieldRevision,
     ) {
         assert_eq!(
             type_option
-                .decode_cell_data(cell_data.to_owned().into(), field_type, field_rev)
+                .decode_cell_data(input_str.to_owned().into(), field_type, field_rev)
                 .unwrap()
                 .to_string(),
             expected_str.to_owned()

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

@@ -1,4 +1,4 @@
-use crate::entities::{CellChangesetPB, CellIdentifierParams, FieldType, GridCellIdentifierPayloadPB};
+use crate::entities::{CellChangesetPB, GridCellIdParams, FieldType, GridCellIdPB};
 use crate::services::cell::{CellBytes, CellBytesParser, CellData, CellDisplayable, FromCellChangeset, FromCellString};
 use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB};
 use bytes::Bytes;
@@ -225,7 +225,7 @@ impl CellBytesParser for SelectOptionCellDataParser {
 #[derive(Clone, Debug, Default, ProtoBuf)]
 pub struct SelectOptionCellChangesetPayloadPB {
     #[pb(index = 1)]
-    pub cell_identifier: GridCellIdentifierPayloadPB,
+    pub cell_identifier: GridCellIdPB,
 
     #[pb(index = 2, one_of)]
     pub insert_option_id: Option<String>,
@@ -235,7 +235,7 @@ pub struct SelectOptionCellChangesetPayloadPB {
 }
 
 pub struct SelectOptionCellChangesetParams {
-    pub cell_identifier: CellIdentifierParams,
+    pub cell_identifier: GridCellIdParams,
     pub insert_option_id: Option<String>,
     pub delete_option_id: Option<String>,
 }
@@ -260,7 +260,7 @@ impl TryInto<SelectOptionCellChangesetParams> for SelectOptionCellChangesetPaylo
     type Error = ErrorCode;
 
     fn try_into(self) -> Result<SelectOptionCellChangesetParams, Self::Error> {
-        let cell_identifier: CellIdentifierParams = self.cell_identifier.try_into()?;
+        let cell_identifier: GridCellIdParams = self.cell_identifier.try_into()?;
         let insert_option_id = match self.insert_option_id {
             None => None,
             Some(insert_option_id) => Some(
@@ -334,7 +334,7 @@ pub struct SelectOptionCellDataPB {
 #[derive(Clone, Debug, Default, ProtoBuf)]
 pub struct SelectOptionChangesetPayloadPB {
     #[pb(index = 1)]
-    pub cell_identifier: GridCellIdentifierPayloadPB,
+    pub cell_identifier: GridCellIdPB,
 
     #[pb(index = 2, one_of)]
     pub insert_option: Option<SelectOptionPB>,
@@ -347,7 +347,7 @@ pub struct SelectOptionChangesetPayloadPB {
 }
 
 pub struct SelectOptionChangeset {
-    pub cell_identifier: CellIdentifierParams,
+    pub cell_identifier: GridCellIdParams,
     pub insert_option: Option<SelectOptionPB>,
     pub update_option: Option<SelectOptionPB>,
     pub delete_option: Option<SelectOptionPB>,

+ 19 - 15
frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_tests.rs

@@ -6,49 +6,53 @@ mod tests {
     use crate::services::field::{URLCellDataPB, URLTypeOption};
     use flowy_grid_data_model::revision::FieldRevision;
 
+    /// The expected_str will equal to the input string, but the expected_url will be empty if there's no
+    /// http url in the input string.
     #[test]
-    fn url_type_option_test_no_url() {
+    fn url_type_option_does_not_contain_url_test() {
         let type_option = URLTypeOption::default();
         let field_type = FieldType::URL;
         let field_rev = FieldBuilder::from_field_type(&field_type).build();
-        assert_changeset(&type_option, "123", &field_type, &field_rev, "123", "");
+        assert_url(&type_option, "123", "123", "", &field_type, &field_rev);
     }
 
+    /// The expected_str will equal to the input string, but the expected_url will not be empty
+    /// if there's a http url in the input string.
     #[test]
-    fn url_type_option_test_contains_url() {
+    fn url_type_option_contains_url_test() {
         let type_option = URLTypeOption::default();
         let field_type = FieldType::URL;
         let field_rev = FieldBuilder::from_field_type(&field_type).build();
-        assert_changeset(
+        assert_url(
             &type_option,
             "AppFlowy website - https://www.appflowy.io",
-            &field_type,
-            &field_rev,
             "AppFlowy website - https://www.appflowy.io",
             "https://www.appflowy.io/",
+            &field_type,
+            &field_rev,
         );
 
-        assert_changeset(
+        assert_url(
             &type_option,
             "AppFlowy website appflowy.io",
-            &field_type,
-            &field_rev,
             "AppFlowy website appflowy.io",
             "https://appflowy.io",
+            &field_type,
+            &field_rev,
         );
     }
 
-    fn assert_changeset(
+    fn assert_url(
         type_option: &URLTypeOption,
-        cell_data: &str,
+        input_str: &str,
+        expected_str: &str,
+        expected_url: &str,
         field_type: &FieldType,
         field_rev: &FieldRevision,
-        expected: &str,
-        expected_url: &str,
     ) {
-        let encoded_data = type_option.apply_changeset(cell_data.to_owned().into(), None).unwrap();
+        let encoded_data = type_option.apply_changeset(input_str.to_owned().into(), None).unwrap();
         let decode_cell_data = decode_cell_data(encoded_data, type_option, field_rev, field_type);
-        assert_eq!(expected.to_owned(), decode_cell_data.content);
+        assert_eq!(expected_str.to_owned(), decode_cell_data.content);
         assert_eq!(expected_url.to_owned(), decode_cell_data.url);
     }
 

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

@@ -1,5 +1,5 @@
 use crate::dart_notification::{send_dart_notification, GridNotification};
-use crate::entities::CellIdentifierParams;
+use crate::entities::GridCellIdParams;
 use crate::entities::*;
 use crate::manager::{GridTaskSchedulerRwLock, GridUser};
 use crate::services::block_manager::GridBlockManager;
@@ -339,12 +339,12 @@ impl GridRevisionEditor {
         Ok(())
     }
 
-    pub async fn get_cell(&self, params: &CellIdentifierParams) -> Option<GridCellPB> {
+    pub async fn get_cell(&self, params: &GridCellIdParams) -> Option<GridCellPB> {
         let cell_bytes = self.get_cell_bytes(params).await?;
         Some(GridCellPB::new(&params.field_id, cell_bytes.to_vec()))
     }
 
-    pub async fn get_cell_bytes(&self, params: &CellIdentifierParams) -> Option<CellBytes> {
+    pub async fn get_cell_bytes(&self, params: &GridCellIdParams) -> Option<CellBytes> {
         let field_rev = self.get_field_rev(&params.field_id).await?;
         let row_rev = self.block_manager.get_row_rev(&params.row_id).await.ok()??;
 

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

@@ -2,7 +2,7 @@ use crate::grid::block_test::script::RowScript::*;
 use crate::grid::block_test::script::{CreateRowScriptBuilder, GridRowTest};
 use crate::grid::grid_editor::{COMPLETED, FACEBOOK, GOOGLE, PAUSED, TWITTER};
 use flowy_grid::entities::FieldType;
-use flowy_grid::services::field::{NO, SELECTION_IDS_SEPARATOR};
+use flowy_grid::services::field::{SELECTION_IDS_SEPARATOR, UNCHECK};
 use flowy_grid_data_model::revision::RowMetaChangeset;
 
 #[tokio::test]
@@ -72,7 +72,7 @@ async fn grid_row_add_cells_test() {
     builder.insert(FieldType::RichText, "hello world", "hello world");
     builder.insert(FieldType::DateTime, "1647251762", "2022/03/14");
     builder.insert(FieldType::Number, "18,443", "$18,443.00");
-    builder.insert(FieldType::Checkbox, "false", NO);
+    builder.insert(FieldType::Checkbox, "false", UNCHECK);
     builder.insert(FieldType::URL, "https://appflowy.io", "https://appflowy.io");
     builder.insert_single_select_cell(|mut options| options.remove(0), COMPLETED);
     builder.insert_multi_select_cell(

+ 3 - 3
frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs

@@ -2,7 +2,7 @@ use crate::grid::block_test::script::RowScript::{AssertCell, CreateRow};
 use crate::grid::block_test::util::GridRowTestBuilder;
 use crate::grid::grid_editor::GridEditorTest;
 
-use flowy_grid::entities::{CellIdentifierParams, FieldType, GridRowPB};
+use flowy_grid::entities::{GridCellIdParams, FieldType, GridRowPB};
 use flowy_grid::services::field::*;
 use flowy_grid_data_model::revision::{
     GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowMetaChangeset, RowRevision,
@@ -109,7 +109,7 @@ impl GridRowTest {
                 field_type,
                 expected,
             } => {
-                let id = CellIdentifierParams {
+                let id = GridCellIdParams {
                     grid_id: self.grid_id.clone(),
                     field_id,
                     row_id,
@@ -154,7 +154,7 @@ impl GridRowTest {
         }
     }
 
-    async fn compare_cell_content(&self, cell_id: CellIdentifierParams, field_type: FieldType, expected: String) {
+    async fn compare_cell_content(&self, cell_id: GridCellIdParams, field_type: FieldType, expected: String) {
         match field_type {
             FieldType::RichText => {
                 let cell_data = self