Browse Source

chore: update test (#1584)

Nathan.fooo 2 years ago
parent
commit
9f7f86a49a
23 changed files with 198 additions and 147 deletions
  1. 1 0
      frontend/rust-lib/flowy-error/src/errors.rs
  2. 2 2
      frontend/rust-lib/flowy-grid/src/entities/cell_entities.rs
  3. 7 7
      frontend/rust-lib/flowy-grid/src/event_handler.rs
  4. 19 13
      frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs
  5. 1 1
      frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs
  6. 3 8
      frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs
  7. 1 1
      frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_tests.rs
  8. 3 10
      frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs
  9. 1 1
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_tests.rs
  10. 6 8
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs
  11. 30 18
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs
  12. 26 24
      frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/type_option_transform.rs
  13. 2 2
      frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs
  14. 10 10
      frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs
  15. 25 12
      frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option.rs
  16. 1 1
      frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_tests.rs
  17. 3 9
      frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs
  18. 6 0
      frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option_entities.rs
  19. 0 6
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  20. 1 1
      frontend/rust-lib/flowy-grid/tests/grid/block_test/script.rs
  21. 26 1
      frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs
  22. 22 12
      frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs
  23. 2 0
      shared-lib/flowy-error-code/src/code.rs

+ 1 - 0
frontend/rust-lib/flowy-error/src/errors.rs

@@ -68,6 +68,7 @@ impl FlowyError {
     static_flowy_error!(invalid_data, ErrorCode::InvalidData);
     static_flowy_error!(invalid_data, ErrorCode::InvalidData);
     static_flowy_error!(out_of_bounds, ErrorCode::OutOfBounds);
     static_flowy_error!(out_of_bounds, ErrorCode::OutOfBounds);
     static_flowy_error!(serde, ErrorCode::Serde);
     static_flowy_error!(serde, ErrorCode::Serde);
+    static_flowy_error!(field_record_not_found, ErrorCode::FieldRecordNotFound);
 }
 }
 
 
 impl std::convert::From<ErrorCode> for FlowyError {
 impl std::convert::From<ErrorCode> for FlowyError {

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

@@ -51,7 +51,7 @@ pub struct CellPathPB {
 }
 }
 
 
 pub struct CellPathParams {
 pub struct CellPathParams {
-    pub grid_id: String,
+    pub view_id: String,
     pub field_id: String,
     pub field_id: String,
     pub row_id: String,
     pub row_id: String,
 }
 }
@@ -64,7 +64,7 @@ impl TryInto<CellPathParams> for CellPathPB {
         let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
         let field_id = NotEmptyStr::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
         let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
         let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
         Ok(CellPathParams {
         Ok(CellPathParams {
-            grid_id: grid_id.0,
+            view_id: grid_id.0,
             field_id: field_id.0,
             field_id: field_id.0,
             row_id: row_id.0,
             row_id: row_id.0,
         })
         })

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

@@ -303,7 +303,7 @@ pub(crate) async fn get_cell_handler(
     manager: AFPluginState<Arc<GridManager>>,
     manager: AFPluginState<Arc<GridManager>>,
 ) -> DataResult<CellPB, FlowyError> {
 ) -> DataResult<CellPB, FlowyError> {
     let params: CellPathParams = data.into_inner().try_into()?;
     let params: CellPathParams = data.into_inner().try_into()?;
-    let editor = manager.get_grid_editor(&params.grid_id).await?;
+    let editor = manager.get_grid_editor(&params.view_id).await?;
     match editor.get_cell(&params).await {
     match editor.get_cell(&params).await {
         None => data_result(CellPB::empty(&params.field_id)),
         None => data_result(CellPB::empty(&params.field_id)),
         Some(cell) => data_result(cell),
         Some(cell) => data_result(cell),
@@ -344,7 +344,7 @@ pub(crate) async fn update_select_option_handler(
     manager: AFPluginState<Arc<GridManager>>,
     manager: AFPluginState<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
 ) -> Result<(), FlowyError> {
     let changeset: SelectOptionChangeset = data.into_inner().try_into()?;
     let changeset: SelectOptionChangeset = data.into_inner().try_into()?;
-    let editor = manager.get_grid_editor(&changeset.cell_identifier.grid_id).await?;
+    let editor = manager.get_grid_editor(&changeset.cell_identifier.view_id).await?;
 
 
     let _ = editor
     let _ = editor
         .modify_field_rev(&changeset.cell_identifier.field_id, |field_rev| {
         .modify_field_rev(&changeset.cell_identifier.field_id, |field_rev| {
@@ -375,7 +375,7 @@ pub(crate) async fn update_select_option_handler(
 
 
             if let Some(cell_content_changeset) = cell_content_changeset {
             if let Some(cell_content_changeset) = cell_content_changeset {
                 let changeset = CellChangesetPB {
                 let changeset = CellChangesetPB {
-                    grid_id: changeset.cell_identifier.grid_id,
+                    grid_id: changeset.cell_identifier.view_id,
                     row_id: changeset.cell_identifier.row_id,
                     row_id: changeset.cell_identifier.row_id,
                     field_id: changeset.cell_identifier.field_id.clone(),
                     field_id: changeset.cell_identifier.field_id.clone(),
                     content: cell_content_changeset,
                     content: cell_content_changeset,
@@ -401,7 +401,7 @@ pub(crate) async fn get_select_option_handler(
     manager: AFPluginState<Arc<GridManager>>,
     manager: AFPluginState<Arc<GridManager>>,
 ) -> DataResult<SelectOptionCellDataPB, FlowyError> {
 ) -> DataResult<SelectOptionCellDataPB, FlowyError> {
     let params: CellPathParams = data.into_inner().try_into()?;
     let params: CellPathParams = data.into_inner().try_into()?;
-    let editor = manager.get_grid_editor(&params.grid_id).await?;
+    let editor = manager.get_grid_editor(&params.view_id).await?;
     match editor.get_field_rev(&params.field_id).await {
     match editor.get_field_rev(&params.field_id).await {
         None => {
         None => {
             tracing::error!("Can't find the select option field with id: {}", params.field_id);
             tracing::error!("Can't find the select option field with id: {}", params.field_id);
@@ -431,7 +431,7 @@ pub(crate) async fn update_select_option_cell_handler(
     manager: AFPluginState<Arc<GridManager>>,
     manager: AFPluginState<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
 ) -> Result<(), FlowyError> {
     let params: SelectOptionCellChangesetParams = data.into_inner().try_into()?;
     let params: SelectOptionCellChangesetParams = data.into_inner().try_into()?;
-    let editor = manager.get_grid_editor(&params.cell_identifier.grid_id).await?;
+    let editor = manager.get_grid_editor(&params.cell_identifier.view_id).await?;
     let _ = editor.update_cell_with_changeset(params.into()).await?;
     let _ = editor.update_cell_with_changeset(params.into()).await?;
     Ok(())
     Ok(())
 }
 }
@@ -449,9 +449,9 @@ pub(crate) async fn update_date_cell_handler(
         is_utc: data.is_utc,
         is_utc: data.is_utc,
     };
     };
 
 
-    let editor = manager.get_grid_editor(&cell_path.grid_id).await?;
+    let editor = manager.get_grid_editor(&cell_path.view_id).await?;
     let _ = editor
     let _ = editor
-        .update_cell(cell_path.grid_id, cell_path.row_id, cell_path.field_id, content)
+        .update_cell(cell_path.view_id, cell_path.row_id, cell_path.field_id, content)
         .await?;
         .await?;
     Ok(())
     Ok(())
 }
 }

+ 19 - 13
frontend/rust-lib/flowy-grid/src/services/cell/cell_operation.rs

@@ -35,7 +35,7 @@ pub trait CellDataDecoder: TypeOption {
     /// data that can be parsed by the current field type. One approach is to transform the cell data
     /// data that can be parsed by the current field type. One approach is to transform the cell data
     /// when it get read. For the moment, the cell data is a string, `Yes` or `No`. It needs to compare
     /// when it get read. For the moment, the cell data is a string, `Yes` or `No`. It needs to compare
     /// with the option's name, if match return the id of the option.
     /// with the option's name, if match return the id of the option.
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
@@ -43,12 +43,9 @@ pub trait CellDataDecoder: TypeOption {
     ) -> FlowyResult<<Self as TypeOption>::CellData>;
     ) -> FlowyResult<<Self as TypeOption>::CellData>;
 
 
     /// Same as `decode_cell_data` does but Decode the cell data to readable `String`
     /// Same as `decode_cell_data` does but Decode the cell data to readable `String`
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        decoded_field_type: &FieldType,
-        field_rev: &FieldRevision,
-    ) -> FlowyResult<String>;
+    /// For example, The string of the Multi-Select cell will be a list of the option's name
+    /// separated by a comma.
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String;
 }
 }
 
 
 pub trait CellDataChangeset: TypeOption {
 pub trait CellDataChangeset: TypeOption {
@@ -119,10 +116,10 @@ pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debu
     }
     }
 }
 }
 
 
-/// Decode the opaque cell data from one field type to another using the corresponding type option builder
+/// Decode the opaque cell data from one field type to another using the corresponding `TypeOption`
 ///
 ///
-/// The cell data might become an empty string depends on these two fields' `TypeOptionBuilder`
-/// support transform or not.
+/// The cell data might become an empty string depends on the to_field_type's `TypeOption`   
+/// support transform the from_field_type's cell data or not.
 ///
 ///
 /// # Arguments
 /// # Arguments
 ///
 ///
@@ -147,10 +144,19 @@ pub fn try_decode_cell_data(
     }
     }
 }
 }
 
 
-pub fn stringify_cell_data(cell_data: String, field_type: &FieldType, field_rev: &FieldRevision) -> String {
-    match FieldRevisionExt::new(field_rev).get_type_option_handler(field_type) {
+/// Returns a string that represents the current field_type's cell data.
+/// If the cell data of the `FieldType` doesn't support displaying in String then will return an
+/// empty string. For example, The string of the Multi-Select cell will be a list of the option's name
+/// separated by a comma.
+pub fn stringify_cell_data(
+    cell_data: String,
+    from_field_type: &FieldType,
+    to_field_type: &FieldType,
+    field_rev: &FieldRevision,
+) -> String {
+    match FieldRevisionExt::new(field_rev).get_type_option_handler(to_field_type) {
         None => "".to_string(),
         None => "".to_string(),
-        Some(handler) => handler.stringify_cell_data(cell_data, field_type, field_rev),
+        Some(handler) => handler.stringify_cell_data(cell_data, from_field_type, field_rev),
     }
     }
 }
 }
 
 

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

@@ -36,7 +36,7 @@ mod tests {
     ) {
     ) {
         assert_eq!(
         assert_eq!(
             type_option
             type_option
-                .try_decode_cell_data(input_str.to_owned(), field_type, field_rev)
+                .decode_cell_data(input_str.to_owned(), field_type, field_rev)
                 .unwrap()
                 .unwrap()
                 .to_string(),
                 .to_string(),
             expected_str.to_owned()
             expected_str.to_owned()

+ 3 - 8
frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_type_option.rs

@@ -64,7 +64,7 @@ impl TypeOptionCellData for CheckboxTypeOptionPB {
 }
 }
 
 
 impl CellDataDecoder for CheckboxTypeOptionPB {
 impl CellDataDecoder for CheckboxTypeOptionPB {
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
@@ -77,13 +77,8 @@ impl CellDataDecoder for CheckboxTypeOptionPB {
         self.decode_type_option_cell_data(cell_data)
         self.decode_type_option_cell_data(cell_data)
     }
     }
 
 
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        _decoded_field_type: &FieldType,
-        _field_rev: &FieldRevision,
-    ) -> FlowyResult<String> {
-        Ok(cell_data)
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
+        cell_data.to_string()
     }
     }
 }
 }
 
 

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

@@ -163,7 +163,7 @@ mod tests {
 
 
     fn decode_cell_data(encoded_data: String, type_option: &DateTypeOptionPB, field_rev: &FieldRevision) -> String {
     fn decode_cell_data(encoded_data: String, type_option: &DateTypeOptionPB, field_rev: &FieldRevision) -> String {
         let decoded_data = type_option
         let decoded_data = type_option
-            .try_decode_cell_data(encoded_data, &FieldType::DateTime, field_rev)
+            .decode_cell_data(encoded_data, &FieldType::DateTime, field_rev)
             .unwrap();
             .unwrap();
         let decoded_data = type_option.convert_to_protobuf(decoded_data);
         let decoded_data = type_option.convert_to_protobuf(decoded_data);
         if type_option.include_time {
         if type_option.include_time {

+ 3 - 10
frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option/date_type_option.rs

@@ -131,7 +131,7 @@ impl DateTypeOptionPB {
 impl TypeOptionTransform for DateTypeOptionPB {}
 impl TypeOptionTransform for DateTypeOptionPB {}
 
 
 impl CellDataDecoder for DateTypeOptionPB {
 impl CellDataDecoder for DateTypeOptionPB {
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
@@ -148,15 +148,8 @@ impl CellDataDecoder for DateTypeOptionPB {
         self.decode_type_option_cell_data(cell_data)
         self.decode_type_option_cell_data(cell_data)
     }
     }
 
 
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        _decoded_field_type: &FieldType,
-        _field_rev: &FieldRevision,
-    ) -> FlowyResult<String> {
-        let cell_data = self.decode_type_option_cell_data(cell_data)?;
-        let cell_data_pb = self.today_desc_from_timestamp(cell_data);
-        Ok(cell_data_pb.date)
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
+        self.today_desc_from_timestamp(cell_data).date
     }
     }
 }
 }
 
 

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

@@ -439,7 +439,7 @@ mod tests {
     ) {
     ) {
         assert_eq!(
         assert_eq!(
             type_option
             type_option
-                .try_decode_cell_data(input_str.to_owned(), field_type, field_rev)
+                .decode_cell_data(input_str.to_owned(), field_type, field_rev)
                 .unwrap()
                 .unwrap()
                 .to_string(),
                 .to_string(),
             expected_str.to_owned()
             expected_str.to_owned()

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

@@ -128,7 +128,7 @@ pub(crate) fn strip_currency_symbol<T: ToString>(s: T) -> String {
 impl TypeOptionTransform for NumberTypeOptionPB {}
 impl TypeOptionTransform for NumberTypeOptionPB {}
 
 
 impl CellDataDecoder for NumberTypeOptionPB {
 impl CellDataDecoder for NumberTypeOptionPB {
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
@@ -143,13 +143,11 @@ impl CellDataDecoder for NumberTypeOptionPB {
         Ok(s.into())
         Ok(s.into())
     }
     }
 
 
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        _decoded_field_type: &FieldType,
-        _field_rev: &FieldRevision,
-    ) -> FlowyResult<String> {
-        Ok(cell_data)
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
+        match self.format_cell_data(&cell_data) {
+            Ok(cell_data) => cell_data.to_string(),
+            Err(_) => "".to_string(),
+        }
     }
     }
 }
 }
 
 

+ 30 - 18
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/select_type_option.rs

@@ -6,8 +6,8 @@ use crate::services::cell::{
 
 
 use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformHelper;
 use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformHelper;
 use crate::services::field::{
 use crate::services::field::{
-    ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB, TypeOption, TypeOptionCellData,
-    TypeOptionTransform,
+    CheckboxCellData, ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB, TypeOption,
+    TypeOptionCellData, TypeOptionTransform,
 };
 };
 use bytes::Bytes;
 use bytes::Bytes;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
@@ -131,7 +131,10 @@ pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
 
 
 impl<T> TypeOptionTransform for T
 impl<T> TypeOptionTransform for T
 where
 where
-    T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + TypeOptionDataSerializer,
+    T: SelectTypeOptionSharedAction
+        + TypeOption<CellData = SelectOptionIds>
+        + TypeOptionDataSerializer
+        + CellDataDecoder,
 {
 {
     fn transformable(&self) -> bool {
     fn transformable(&self) -> bool {
         true
         true
@@ -147,10 +150,26 @@ where
 
 
     fn transform_type_option_cell_data(
     fn transform_type_option_cell_data(
         &self,
         &self,
-        cell_data: <Self as TypeOption>::CellData,
+        cell_data: &str,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
-    ) -> <Self as TypeOption>::CellData {
-        SelectOptionTypeOptionTransformHelper::transform_type_option_cell_data(self, cell_data, decoded_field_type)
+        _field_rev: &FieldRevision,
+    ) -> Option<<Self as TypeOption>::CellData> {
+        match decoded_field_type {
+            FieldType::SingleSelect | FieldType::MultiSelect | FieldType::Checklist => None,
+            FieldType::Checkbox => match CheckboxCellData::from_cell_str(cell_data) {
+                Ok(checkbox_cell_data) => {
+                    let cell_content = checkbox_cell_data.to_string();
+                    let mut transformed_ids = Vec::new();
+                    let options = self.options();
+                    if let Some(option) = options.iter().find(|option| option.name == cell_content) {
+                        transformed_ids.push(option.id.clone());
+                    }
+                    Some(SelectOptionIds::from(transformed_ids))
+                }
+                Err(_) => None,
+            },
+            _ => Some(SelectOptionIds::from(vec![])),
+        }
     }
     }
 }
 }
 
 
@@ -158,7 +177,7 @@ impl<T> CellDataDecoder for T
 where
 where
     T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + TypeOptionCellData,
     T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + TypeOptionCellData,
 {
 {
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         _decoded_field_type: &FieldType,
         _decoded_field_type: &FieldType,
@@ -167,20 +186,13 @@ where
         self.decode_type_option_cell_data(cell_data)
         self.decode_type_option_cell_data(cell_data)
     }
     }
 
 
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        _decoded_field_type: &FieldType,
-        _field_rev: &FieldRevision,
-    ) -> FlowyResult<String> {
-        let ids = self.decode_type_option_cell_data(cell_data)?;
-        Ok(self
-            .get_selected_options(ids)
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
+        self.get_selected_options(cell_data)
             .select_options
             .select_options
             .into_iter()
             .into_iter()
             .map(|option| option.name)
             .map(|option| option.name)
             .collect::<Vec<String>>()
             .collect::<Vec<String>>()
-            .join(SELECTION_IDS_SEPARATOR))
+            .join(SELECTION_IDS_SEPARATOR)
     }
     }
 }
 }
 
 
@@ -375,7 +387,7 @@ impl std::convert::From<SelectOptionCellChangesetParams> for CellChangesetPB {
         };
         };
         let content = serde_json::to_string(&changeset).unwrap();
         let content = serde_json::to_string(&changeset).unwrap();
         CellChangesetPB {
         CellChangesetPB {
-            grid_id: params.cell_identifier.grid_id,
+            grid_id: params.cell_identifier.view_id,
             row_id: params.cell_identifier.row_id,
             row_id: params.cell_identifier.row_id,
             field_id: params.cell_identifier.field_id,
             field_id: params.cell_identifier.field_id,
             content,
             content,

+ 26 - 24
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/type_option_transform.rs

@@ -53,28 +53,30 @@ impl SelectOptionTypeOptionTransformHelper {
         }
         }
     }
     }
 
 
-    pub fn transform_type_option_cell_data<T>(
-        shared: &T,
-        cell_data: <T as TypeOption>::CellData,
-        decoded_field_type: &FieldType,
-    ) -> <T as TypeOption>::CellData
-    where
-        T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds>,
-    {
-        match decoded_field_type {
-            FieldType::SingleSelect | FieldType::MultiSelect | FieldType::Checklist => cell_data,
-            FieldType::Checkbox => {
-                // transform the cell data to the option id
-                let mut transformed_ids = Vec::new();
-                let options = shared.options();
-                cell_data.iter().for_each(|name| {
-                    if let Some(option) = options.iter().find(|option| &option.name == name) {
-                        transformed_ids.push(option.id.clone());
-                    }
-                });
-                SelectOptionIds::from(transformed_ids)
-            }
-            _ => SelectOptionIds::from(vec![]),
-        }
-    }
+    // pub fn transform_e_option_cell_data<T>(
+    //     //     shared: &T,
+    //     //     cell_data: String,
+    //     //     decoded_field_type: &FieldType,
+    //     // ) -> <T as TypeOption>::CellData
+    //     // where
+    //     //     T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + CellDataDecoder,
+    //     // {
+    //     //     match decoded_field_type {
+    //     //         FieldType::SingleSelect | FieldType::MultiSelect | FieldType::Checklist => {
+    //     //             self.try_decode_cell_data(cell_data)
+    //     //         }
+    //     //         FieldType::Checkbox => {
+    //     //             // transform the cell data to the option id
+    //     //             let mut transformed_ids = Vec::new();
+    //     //             let options = shared.options();
+    //     //             cell_data.iter().for_each(|name| {
+    //     //                 if let Some(option) = options.iter().find(|option| &option.name == name) {
+    //     //                     transformed_ids.push(option.id.clone());
+    //     //                 }
+    //     //             });
+    //     //             SelectOptionIds::from(transformed_ids)
+    //     //         }
+    //     //         _ => SelectOptionIds::from(vec![]),
+    //     //     }
+    //     // }typ
 }
 }

+ 2 - 2
frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_tests.rs

@@ -16,7 +16,7 @@ mod tests {
 
 
         assert_eq!(
         assert_eq!(
             type_option
             type_option
-                .try_decode_cell_data(1647251762.to_string(), &field_type, &field_rev)
+                .decode_cell_data(1647251762.to_string(), &field_type, &field_rev)
                 .unwrap()
                 .unwrap()
                 .as_str(),
                 .as_str(),
             "Mar 14,2022"
             "Mar 14,2022"
@@ -37,7 +37,7 @@ mod tests {
 
 
         assert_eq!(
         assert_eq!(
             type_option
             type_option
-                .try_decode_cell_data(option_id, &field_type, &field_rev)
+                .decode_cell_data(option_id, &field_type, &field_rev)
                 .unwrap()
                 .unwrap()
                 .to_string(),
                 .to_string(),
             done_option.name,
             done_option.name,

+ 10 - 10
frontend/rust-lib/flowy-grid/src/services/field/type_options/text_type_option/text_type_option.rs

@@ -64,7 +64,7 @@ impl TypeOptionCellData for RichTextTypeOptionPB {
 }
 }
 
 
 impl CellDataDecoder for RichTextTypeOptionPB {
 impl CellDataDecoder for RichTextTypeOptionPB {
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
@@ -76,20 +76,14 @@ impl CellDataDecoder for RichTextTypeOptionPB {
             || decoded_field_type.is_number()
             || decoded_field_type.is_number()
             || decoded_field_type.is_url()
             || decoded_field_type.is_url()
         {
         {
-            Ok(stringify_cell_data(cell_data, decoded_field_type, field_rev).into())
+            Ok(stringify_cell_data(cell_data, decoded_field_type, decoded_field_type, field_rev).into())
         } else {
         } else {
             StrCellData::from_cell_str(&cell_data)
             StrCellData::from_cell_str(&cell_data)
         }
         }
     }
     }
 
 
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        _decoded_field_type: &FieldType,
-        _field_rev: &FieldRevision,
-    ) -> FlowyResult<String> {
-        let cell_str = StrCellData::from_cell_str(&cell_data)?;
-        Ok(cell_str.into())
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
+        cell_data.to_string()
     }
     }
 }
 }
 
 
@@ -193,6 +187,12 @@ impl std::convert::From<String> for StrCellData {
     }
     }
 }
 }
 
 
+impl ToString for StrCellData {
+    fn to_string(&self) -> String {
+        self.0.clone()
+    }
+}
+
 impl std::convert::From<StrCellData> for String {
 impl std::convert::From<StrCellData> for String {
     fn from(value: StrCellData) -> Self {
     fn from(value: StrCellData) -> Self {
         value.0
         value.0

+ 25 - 12
frontend/rust-lib/flowy-grid/src/services/field/type_options/type_option.rs

@@ -79,15 +79,16 @@ pub trait TypeOptionTransform: TypeOption {
     /// # Arguments
     /// # Arguments
     ///
     ///
     /// * `cell_data`: the cell data of the current field type
     /// * `cell_data`: the cell data of the current field type
-    /// * `decoded_field_type`: the field type of the cell data that's going to be transformed into.
+    /// * `decoded_field_type`: the field type of the cell data that's going to be transformed into
+    /// current `TypeOption` field type.
     ///
     ///
     fn transform_type_option_cell_data(
     fn transform_type_option_cell_data(
         &self,
         &self,
-        cell_data: <Self as TypeOption>::CellData,
+        _cell_data: &str,
         _decoded_field_type: &FieldType,
         _decoded_field_type: &FieldType,
-    ) -> <Self as TypeOption>::CellData {
-        // Do nothing, just return the passed-in cell data
-        cell_data
+        _field_rev: &FieldRevision,
+    ) -> Option<<Self as TypeOption>::CellData> {
+        None
     }
     }
 }
 }
 
 
@@ -130,13 +131,17 @@ where
     fn handle_cell_data(
     fn handle_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
-        field_type: &FieldType,
+        decoded_field_type: &FieldType,
         field_rev: &FieldRevision,
         field_rev: &FieldRevision,
     ) -> FlowyResult<CellProtobufBlob> {
     ) -> FlowyResult<CellProtobufBlob> {
-        let mut cell_data = self.try_decode_cell_data(cell_data, field_type, field_rev)?;
-        if self.transformable() {
-            cell_data = self.transform_type_option_cell_data(cell_data, field_type);
-        }
+        let cell_data = if self.transformable() {
+            match self.transform_type_option_cell_data(&cell_data, decoded_field_type, field_rev) {
+                None => self.decode_cell_data(cell_data, decoded_field_type, field_rev)?,
+                Some(new_cell_data) => new_cell_data,
+            }
+        } else {
+            self.decode_cell_data(cell_data, decoded_field_type, field_rev)?
+        };
         CellProtobufBlob::from(self.convert_to_protobuf(cell_data))
         CellProtobufBlob::from(self.convert_to_protobuf(cell_data))
     }
     }
 
 
@@ -146,8 +151,16 @@ where
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
         field_rev: &FieldRevision,
         field_rev: &FieldRevision,
     ) -> String {
     ) -> String {
-        self.decode_cell_data_to_str(cell_data, decoded_field_type, field_rev)
-            .unwrap_or_default()
+        if self.transformable() {
+            let cell_data = self.transform_type_option_cell_data(&cell_data, decoded_field_type, field_rev);
+            if let Some(cell_data) = cell_data {
+                return self.decode_cell_data_to_str(cell_data);
+            }
+        }
+        match <Self as TypeOption>::CellData::from_cell_str(&cell_data) {
+            Ok(cell_data) => self.decode_cell_data_to_str(cell_data),
+            Err(_) => "".to_string(),
+        }
     }
     }
 }
 }
 
 

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

@@ -183,7 +183,7 @@ mod tests {
         field_type: &FieldType,
         field_type: &FieldType,
     ) -> URLCellData {
     ) -> URLCellData {
         type_option
         type_option
-            .try_decode_cell_data(encoded_data, field_type, field_rev)
+            .decode_cell_data(encoded_data, field_type, field_rev)
             .unwrap()
             .unwrap()
     }
     }
 }
 }

+ 3 - 9
frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option.rs

@@ -58,7 +58,7 @@ impl TypeOptionCellData for URLTypeOptionPB {
 }
 }
 
 
 impl CellDataDecoder for URLTypeOptionPB {
 impl CellDataDecoder for URLTypeOptionPB {
-    fn try_decode_cell_data(
+    fn decode_cell_data(
         &self,
         &self,
         cell_data: String,
         cell_data: String,
         decoded_field_type: &FieldType,
         decoded_field_type: &FieldType,
@@ -71,14 +71,8 @@ impl CellDataDecoder for URLTypeOptionPB {
         self.decode_type_option_cell_data(cell_data)
         self.decode_type_option_cell_data(cell_data)
     }
     }
 
 
-    fn decode_cell_data_to_str(
-        &self,
-        cell_data: String,
-        _decoded_field_type: &FieldType,
-        _field_rev: &FieldRevision,
-    ) -> FlowyResult<String> {
-        let cell_data = self.decode_type_option_cell_data(cell_data)?;
-        Ok(cell_data.content)
+    fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
+        cell_data.content
     }
     }
 }
 }
 
 

+ 6 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/url_type_option/url_type_option_entities.rs

@@ -77,3 +77,9 @@ impl FromCellString for URLCellData {
         serde_json::from_str::<URLCellData>(s).map_err(internal_error)
         serde_json::from_str::<URLCellData>(s).map_err(internal_error)
     }
     }
 }
 }
+
+impl ToString for URLCellData {
+    fn to_string(&self) -> String {
+        self.content.clone()
+    }
+}

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

@@ -279,12 +279,6 @@ impl GridRevisionEditor {
         let type_option_transform =
         let type_option_transform =
             |old_field_type: FieldTypeRevision, old_type_option: Option<String>, new_type_option: String| {
             |old_field_type: FieldTypeRevision, old_type_option: Option<String>, new_type_option: String| {
                 let old_field_type: FieldType = old_field_type.into();
                 let old_field_type: FieldType = old_field_type.into();
-                // let mut type_option_builder = type_option_builder_from_json_str(&new_type_option, new_field_type);
-                // if let Some(old_type_option) = old_type_option {
-                //     type_option_builder.transform(&old_field_type, old_type_option)
-                // }
-                // type_option_builder.serializer().json_str()
-
                 transform_type_option(&new_type_option, new_field_type, old_type_option, old_field_type)
                 transform_type_option(&new_type_option, new_field_type, old_type_option, old_field_type)
             };
             };
 
 

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

@@ -113,7 +113,7 @@ impl GridRowTest {
                 expected,
                 expected,
             } => {
             } => {
                 let id = CellPathParams {
                 let id = CellPathParams {
-                    grid_id: self.grid_id.clone(),
+                    view_id: self.grid_id.clone(),
                     field_id,
                     field_id,
                     row_id,
                     row_id,
                 };
                 };

+ 26 - 1
frontend/rust-lib/flowy-grid/tests/grid/field_test/script.rs

@@ -1,5 +1,6 @@
 use crate::grid::grid_editor::GridEditorTest;
 use crate::grid::grid_editor::GridEditorTest;
 use flowy_grid::entities::{CreateFieldParams, FieldChangesetParams, FieldType};
 use flowy_grid::entities::{CreateFieldParams, FieldChangesetParams, FieldType};
+use flowy_grid::services::cell::{stringify_cell_data, TypeCellData};
 use grid_rev_model::FieldRevision;
 use grid_rev_model::FieldRevision;
 
 
 pub enum FieldScript {
 pub enum FieldScript {
@@ -29,6 +30,12 @@ pub enum FieldScript {
         field_index: usize,
         field_index: usize,
         expected_type_option_data: String,
         expected_type_option_data: String,
     },
     },
+    AssertCellContent {
+        field_id: String,
+        row_index: usize,
+        from_field_type: FieldType,
+        expected_content: String,
+    },
 }
 }
 
 
 pub struct GridFieldTest {
 pub struct GridFieldTest {
@@ -41,7 +48,7 @@ impl GridFieldTest {
         Self { inner: editor_test }
         Self { inner: editor_test }
     }
     }
 
 
-    pub fn grid_id(&self) -> String {
+    pub fn view_id(&self) -> String {
         self.grid_id.clone()
         self.grid_id.clone()
     }
     }
 
 
@@ -115,6 +122,24 @@ impl GridFieldTest {
                 let type_option_data = field_rev.get_type_option_str(field_rev.ty).unwrap();
                 let type_option_data = field_rev.get_type_option_str(field_rev.ty).unwrap();
                 assert_eq!(type_option_data, expected_type_option_data);
                 assert_eq!(type_option_data, expected_type_option_data);
             }
             }
+            FieldScript::AssertCellContent {
+                field_id,
+                row_index,
+                from_field_type,
+                expected_content,
+            } => {
+                let field_rev = self.editor.get_field_rev(&field_id).await.unwrap();
+                let field_type: FieldType = field_rev.ty.into();
+
+                let rows = self.editor.get_grid(&self.view_id()).await.unwrap().rows;
+                let row = rows.get(row_index).unwrap();
+                let row_rev = self.editor.get_row_rev(&row.id).await.unwrap().unwrap();
+
+                let cell_rev = row_rev.cells.get(&field_id).unwrap().clone();
+                let type_cell_data: TypeCellData = cell_rev.try_into().unwrap();
+                let content = stringify_cell_data(type_cell_data.data, &from_field_type, &field_type, &field_rev);
+                assert_eq!(content, expected_content);
+            }
         }
         }
     }
     }
 }
 }

+ 22 - 12
frontend/rust-lib/flowy-grid/tests/grid/field_test/test.rs

@@ -9,7 +9,7 @@ use flowy_grid::services::field::{gen_option_id, SingleSelectTypeOptionPB, CHECK
 #[tokio::test]
 #[tokio::test]
 async fn grid_create_field() {
 async fn grid_create_field() {
     let mut test = GridFieldTest::new().await;
     let mut test = GridFieldTest::new().await;
-    let (params, field_rev) = create_text_field(&test.grid_id());
+    let (params, field_rev) = create_text_field(&test.view_id());
 
 
     let scripts = vec![
     let scripts = vec![
         CreateField { params },
         CreateField { params },
@@ -20,7 +20,7 @@ async fn grid_create_field() {
     ];
     ];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
 
 
-    let (params, field_rev) = create_single_select_field(&test.grid_id());
+    let (params, field_rev) = create_single_select_field(&test.view_id());
     let scripts = vec![
     let scripts = vec![
         CreateField { params },
         CreateField { params },
         AssertFieldTypeOptionEqual {
         AssertFieldTypeOptionEqual {
@@ -34,7 +34,7 @@ async fn grid_create_field() {
 #[tokio::test]
 #[tokio::test]
 async fn grid_create_duplicate_field() {
 async fn grid_create_duplicate_field() {
     let mut test = GridFieldTest::new().await;
     let mut test = GridFieldTest::new().await;
-    let (params, _) = create_text_field(&test.grid_id());
+    let (params, _) = create_text_field(&test.view_id());
     let field_count = test.field_count();
     let field_count = test.field_count();
     let expected_field_count = field_count + 1;
     let expected_field_count = field_count + 1;
     let scripts = vec![
     let scripts = vec![
@@ -47,7 +47,7 @@ async fn grid_create_duplicate_field() {
 #[tokio::test]
 #[tokio::test]
 async fn grid_update_field_with_empty_change() {
 async fn grid_update_field_with_empty_change() {
     let mut test = GridFieldTest::new().await;
     let mut test = GridFieldTest::new().await;
-    let (params, _) = create_single_select_field(&test.grid_id());
+    let (params, _) = create_single_select_field(&test.view_id());
     let create_field_index = test.field_count();
     let create_field_index = test.field_count();
     let scripts = vec![CreateField { params }];
     let scripts = vec![CreateField { params }];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
@@ -55,7 +55,7 @@ async fn grid_update_field_with_empty_change() {
     let field_rev = (&*test.field_revs.clone().pop().unwrap()).clone();
     let field_rev = (&*test.field_revs.clone().pop().unwrap()).clone();
     let changeset = FieldChangesetParams {
     let changeset = FieldChangesetParams {
         field_id: field_rev.id.clone(),
         field_id: field_rev.id.clone(),
-        grid_id: test.grid_id(),
+        grid_id: test.view_id(),
         ..Default::default()
         ..Default::default()
     };
     };
 
 
@@ -72,7 +72,7 @@ async fn grid_update_field_with_empty_change() {
 #[tokio::test]
 #[tokio::test]
 async fn grid_update_field() {
 async fn grid_update_field() {
     let mut test = GridFieldTest::new().await;
     let mut test = GridFieldTest::new().await;
-    let (params, _) = create_single_select_field(&test.grid_id());
+    let (params, _) = create_single_select_field(&test.view_id());
     let scripts = vec![CreateField { params }];
     let scripts = vec![CreateField { params }];
     let create_field_index = test.field_count();
     let create_field_index = test.field_count();
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
@@ -83,7 +83,7 @@ async fn grid_update_field() {
 
 
     let changeset = FieldChangesetParams {
     let changeset = FieldChangesetParams {
         field_id: single_select_field.id.clone(),
         field_id: single_select_field.id.clone(),
-        grid_id: test.grid_id(),
+        grid_id: test.view_id(),
         frozen: Some(true),
         frozen: Some(true),
         width: Some(1000),
         width: Some(1000),
         ..Default::default()
         ..Default::default()
@@ -109,7 +109,7 @@ async fn grid_update_field() {
 async fn grid_delete_field() {
 async fn grid_delete_field() {
     let mut test = GridFieldTest::new().await;
     let mut test = GridFieldTest::new().await;
     let original_field_count = test.field_count();
     let original_field_count = test.field_count();
-    let (params, _) = create_text_field(&test.grid_id());
+    let (params, _) = create_text_field(&test.view_id());
     let scripts = vec![CreateField { params }];
     let scripts = vec![CreateField { params }];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
 
 
@@ -162,10 +162,20 @@ async fn grid_switch_from_select_option_to_checkbox_test() {
 async fn grid_switch_from_checkbox_to_select_option_test() {
 async fn grid_switch_from_checkbox_to_select_option_test() {
     let mut test = GridFieldTest::new().await;
     let mut test = GridFieldTest::new().await;
     let field_rev = test.get_first_field_rev(FieldType::Checkbox).clone();
     let field_rev = test.get_first_field_rev(FieldType::Checkbox).clone();
-    let scripts = vec![SwitchToField {
-        field_id: field_rev.id.clone(),
-        new_field_type: FieldType::SingleSelect,
-    }];
+    let scripts = vec![
+        SwitchToField {
+            field_id: field_rev.id.clone(),
+            new_field_type: FieldType::SingleSelect,
+        },
+        AssertCellContent {
+            field_id: field_rev.id.clone(),
+            // the mock data of the checkbox with row_index one is "true"
+            row_index: 1,
+            from_field_type: FieldType::Checkbox,
+            // The content of the checkbox should transform to the corresponding option name.
+            expected_content: CHECK.to_string(),
+        },
+    ];
     test.run_scripts(scripts).await;
     test.run_scripts(scripts).await;
 
 
     let single_select_type_option = test.get_single_select_type_option(&field_rev.id);
     let single_select_type_option = test.get_single_select_type_option(&field_rev.id);

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

@@ -112,6 +112,8 @@ pub enum ErrorCode {
     FieldInvalidOperation = 444,
     FieldInvalidOperation = 444,
     #[display(fmt = "Filter id is empty")]
     #[display(fmt = "Filter id is empty")]
     FilterIdIsEmpty = 445,
     FilterIdIsEmpty = 445,
+    #[display(fmt = "Field is not exist")]
+    FieldRecordNotFound = 446,
 
 
     #[display(fmt = "Field's type-option data should not be empty")]
     #[display(fmt = "Field's type-option data should not be empty")]
     TypeOptionDataIsEmpty = 450,
     TypeOptionDataIsEmpty = 450,