Sfoglia il codice sorgente

refactor: cell data operation

appflowy 3 anni fa
parent
commit
5b2b50dc9c

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

@@ -43,14 +43,15 @@ impl_type_option!(CheckboxTypeOption, FieldType::Checkbox);
 const YES: &str = "Yes";
 const NO: &str = "No";
 
-impl CellDataOperation for CheckboxTypeOption {
+impl CellDataOperation<String> for CheckboxTypeOption {
     fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
         type_option_cell_data: T,
+        decoded_field_type: &FieldType,
         _field_meta: &FieldMeta,
     ) -> DecodedCellData {
         let type_option_cell_data = type_option_cell_data.into();
-        if !type_option_cell_data.is_checkbox() {
+        if !decoded_field_type.is_checkbox() {
             return DecodedCellData::default();
         }
         let cell_data = type_option_cell_data.data;
@@ -61,11 +62,10 @@ impl CellDataOperation for CheckboxTypeOption {
         DecodedCellData::default()
     }
 
-    fn apply_changeset<T: Into<CellContentChangeset>>(
-        &self,
-        changeset: T,
-        _cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError> {
+    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
+    where
+        C: Into<CellContentChangeset>,
+    {
         let changeset = changeset.into();
         let s = match string_to_bool(&changeset) {
             true => YES,

+ 14 - 12
frontend/rust-lib/flowy-grid/src/services/field/type_options/date_type_option.rs

@@ -135,10 +135,11 @@ impl DateTypeOption {
     }
 }
 
-impl CellDataOperation for DateTypeOption {
+impl CellDataOperation<DateCellDataSerde> for DateTypeOption {
     fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
         type_option_cell_data: T,
+        decoded_field_type: &FieldType,
         _field_meta: &FieldMeta,
     ) -> DecodedCellData {
         let type_option_cell_data = type_option_cell_data.into();
@@ -146,7 +147,7 @@ impl CellDataOperation for DateTypeOption {
         // It happens when switching from one field to another.
         // For example:
         // FieldType::RichText -> FieldType::DateTime, it will display empty content on the screen.
-        if !type_option_cell_data.is_date() {
+        if !decoded_field_type.is_date() {
             return DecodedCellData::default();
         }
         match DateCellDataSerde::from_str(&type_option_cell_data.data) {
@@ -155,11 +156,10 @@ impl CellDataOperation for DateTypeOption {
         }
     }
 
-    fn apply_changeset<T: Into<CellContentChangeset>>(
-        &self,
-        changeset: T,
-        _cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError> {
+    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<DateCellDataSerde, FlowyError>
+    where
+        C: Into<CellContentChangeset>,
+    {
         let content_changeset: DateCellContentChangeset = serde_json::from_str(&changeset.into())?;
         let cell_data = match content_changeset.date_timestamp() {
             None => DateCellDataSerde::default(),
@@ -174,7 +174,7 @@ impl CellDataOperation for DateTypeOption {
             },
         };
 
-        Ok(cell_data.to_string())
+        Ok(cell_data)
     }
 }
 
@@ -316,15 +316,17 @@ impl DateCellDataSerde {
         Self { timestamp, time }
     }
 
-    fn to_string(self) -> String {
-        serde_json::to_string(&self).unwrap_or("".to_string())
-    }
-
     fn from_str(s: &str) -> FlowyResult<Self> {
         serde_json::from_str::<DateCellDataSerde>(s).map_err(internal_error)
     }
 }
 
+impl ToString for DateCellDataSerde {
+    fn to_string(&self) -> String {
+        serde_json::to_string(&self).unwrap_or("".to_string())
+    }
+}
+
 fn default_time_str(time_format: &TimeFormat) -> String {
     match time_format {
         TimeFormat::TwelveHour => "12:00 AM".to_string(),

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

@@ -76,14 +76,15 @@ pub struct NumberTypeOption {
 }
 impl_type_option!(NumberTypeOption, FieldType::Number);
 
-impl CellDataOperation for NumberTypeOption {
+impl CellDataOperation<String> for NumberTypeOption {
     fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
         type_option_cell_data: T,
+        decoded_field_type: &FieldType,
         _field_meta: &FieldMeta,
     ) -> DecodedCellData {
         let type_option_cell_data = type_option_cell_data.into();
-        if type_option_cell_data.is_date() {
+        if decoded_field_type.is_date() {
             return DecodedCellData::default();
         }
 
@@ -111,11 +112,10 @@ impl CellDataOperation for NumberTypeOption {
         }
     }
 
-    fn apply_changeset<T: Into<CellContentChangeset>>(
-        &self,
-        changeset: T,
-        _cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError> {
+    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
+    where
+        C: Into<CellContentChangeset>,
+    {
         let changeset = changeset.into();
         let mut data = changeset.trim().to_string();
 

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

@@ -95,14 +95,15 @@ impl SelectOptionOperation for SingleSelectTypeOption {
     }
 }
 
-impl CellDataOperation for SingleSelectTypeOption {
+impl CellDataOperation<String> for SingleSelectTypeOption {
     fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
         type_option_cell_data: T,
+        decoded_field_type: &FieldType,
         _field_meta: &FieldMeta,
     ) -> DecodedCellData {
         let type_option_cell_data = type_option_cell_data.into();
-        if !type_option_cell_data.is_select_option() {
+        if !decoded_field_type.is_select_option() {
             return DecodedCellData::default();
         }
 
@@ -116,11 +117,10 @@ impl CellDataOperation for SingleSelectTypeOption {
         DecodedCellData::default()
     }
 
-    fn apply_changeset<T: Into<CellContentChangeset>>(
-        &self,
-        changeset: T,
-        _cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError> {
+    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
+    where
+        C: Into<CellContentChangeset>,
+    {
         let changeset = changeset.into();
         let select_option_changeset: SelectOptionCellContentChangeset = serde_json::from_str(&changeset)?;
         let new_cell_data: String;
@@ -187,14 +187,15 @@ impl SelectOptionOperation for MultiSelectTypeOption {
     }
 }
 
-impl CellDataOperation for MultiSelectTypeOption {
+impl CellDataOperation<String> for MultiSelectTypeOption {
     fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
         type_option_cell_data: T,
+        decoded_field_type: &FieldType,
         _field_meta: &FieldMeta,
     ) -> DecodedCellData {
         let type_option_cell_data = type_option_cell_data.into();
-        if !type_option_cell_data.is_select_option() {
+        if !decoded_field_type.is_select_option() {
             return DecodedCellData::default();
         }
 
@@ -210,11 +211,10 @@ impl CellDataOperation for MultiSelectTypeOption {
         DecodedCellData::from_content(content)
     }
 
-    fn apply_changeset<T: Into<CellContentChangeset>>(
-        &self,
-        changeset: T,
-        cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError> {
+    fn apply_changeset<T>(&self, changeset: T, cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
+    where
+        T: Into<CellContentChangeset>,
+    {
         let content_changeset: SelectOptionCellContentChangeset = serde_json::from_str(&changeset.into())?;
         let new_cell_data: String;
         match cell_meta {

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

@@ -34,17 +34,18 @@ pub struct RichTextTypeOption {
 }
 impl_type_option!(RichTextTypeOption, FieldType::RichText);
 
-impl CellDataOperation for RichTextTypeOption {
+impl CellDataOperation<String> for RichTextTypeOption {
     fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
         type_option_cell_data: T,
+        decoded_field_type: &FieldType,
         field_meta: &FieldMeta,
     ) -> DecodedCellData {
         let type_option_cell_data = type_option_cell_data.into();
-        if type_option_cell_data.is_date()
-            || type_option_cell_data.is_single_select()
-            || type_option_cell_data.is_multi_select()
-            || type_option_cell_data.is_number()
+        if decoded_field_type.is_date()
+            || decoded_field_type.is_single_select()
+            || decoded_field_type.is_multi_select()
+            || decoded_field_type.is_number()
         {
             let field_type = type_option_cell_data.field_type.clone();
             decode_cell_data(type_option_cell_data, field_meta, &field_type).unwrap_or_default()
@@ -53,16 +54,15 @@ impl CellDataOperation for RichTextTypeOption {
         }
     }
 
-    fn apply_changeset<T: Into<CellContentChangeset>>(
-        &self,
-        changeset: T,
-        _cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError> {
+    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
+    where
+        C: Into<CellContentChangeset>,
+    {
         let data = changeset.into();
         if data.len() > 10000 {
             Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000"))
         } else {
-            Ok(data.to_string())
+            Ok(data.0)
         }
     }
 }

+ 27 - 13
frontend/rust-lib/flowy-grid/src/services/row/cell_data_operation.rs

@@ -5,17 +5,22 @@ use serde::{Deserialize, Serialize};
 use std::fmt::Formatter;
 use std::str::FromStr;
 
-pub trait CellDataOperation {
-    fn decode_cell_data<T: Into<TypeOptionCellData>>(&self, data: T, field_meta: &FieldMeta) -> DecodedCellData;
-    fn apply_changeset<T: Into<CellContentChangeset>>(
+pub trait CellDataOperation<D, CO: ToString> {
+    fn decode_cell_data<T: Into<TypeOptionCellData>>(
         &self,
-        changeset: T,
+        data: T,
+        decoded_field_type: &FieldType,
+        field_meta: &FieldMeta,
+    ) -> DecodedCellData;
+    fn apply_changeset<C: Into<CellContentChangeset>>(
+        &self,
+        changeset: C,
         cell_meta: Option<CellMeta>,
-    ) -> Result<String, FlowyError>;
+    ) -> Result<CO, FlowyError>;
 }
 
 #[derive(Debug)]
-pub struct CellContentChangeset(String);
+pub struct CellContentChangeset(pub String);
 
 impl std::fmt::Display for CellContentChangeset {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@@ -44,6 +49,12 @@ pub struct TypeOptionCellData {
     pub field_type: FieldType,
 }
 
+impl TypeOptionCellData {
+    pub fn split(self) -> (String, FieldType) {
+        (self.data, self.field_type)
+    }
+}
+
 impl std::str::FromStr for TypeOptionCellData {
     type Err = FlowyError;
 
@@ -120,7 +131,9 @@ pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
     let s = match field_meta.field_type {
         FieldType::RichText => RichTextTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
         FieldType::Number => NumberTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
-        FieldType::DateTime => DateTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
+        FieldType::DateTime => DateTypeOption::from(field_meta)
+            .apply_changeset(changeset, cell_meta)
+            .map(|data| data.to_string()),
         FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
         FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
         FieldType::Checkbox => CheckboxTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
@@ -135,25 +148,26 @@ pub fn decode_cell_data<T: TryInto<TypeOptionCellData>>(
     field_type: &FieldType,
 ) -> Option<DecodedCellData> {
     if let Ok(type_option_cell_data) = data.try_into() {
+        let (decoded_field_type, data) = &type_option_cell_data.split();
         let s = match field_type {
             FieldType::RichText => field_meta
                 .get_type_option_entry::<RichTextTypeOption>(field_type)?
-                .decode_cell_data(type_option_cell_data, field_meta),
+                .decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
             FieldType::Number => field_meta
                 .get_type_option_entry::<NumberTypeOption>(field_type)?
-                .decode_cell_data(type_option_cell_data, field_meta),
+                .decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
             FieldType::DateTime => field_meta
                 .get_type_option_entry::<DateTypeOption>(field_type)?
-                .decode_cell_data(type_option_cell_data, field_meta),
+                .decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
             FieldType::SingleSelect => field_meta
                 .get_type_option_entry::<SingleSelectTypeOption>(field_type)?
-                .decode_cell_data(type_option_cell_data, field_meta),
+                .decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
             FieldType::MultiSelect => field_meta
                 .get_type_option_entry::<MultiSelectTypeOption>(field_type)?
-                .decode_cell_data(type_option_cell_data, field_meta),
+                .decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
             FieldType::Checkbox => field_meta
                 .get_type_option_entry::<CheckboxTypeOption>(field_type)?
-                .decode_cell_data(type_option_cell_data, field_meta),
+                .decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
         };
         tracing::Span::current().record(
             "content",