Browse Source

Refactor/selection option transform (#1294)

* chore: support unnamed struct in AST parser progress

* chore: handle select option type option data transform in one place
Nathan.fooo 2 years ago
parent
commit
825725df7d

+ 1 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/mod.rs

@@ -1,6 +1,7 @@
 mod multi_select_type_option;
 mod select_type_option;
 mod single_select_type_option;
+mod type_option_transform;
 
 pub use multi_select_type_option::*;
 pub use select_type_option::*;

+ 2 - 1
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/multi_select_type_option.rs

@@ -1,6 +1,7 @@
 use crate::entities::FieldType;
 use crate::impl_type_option;
 use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
+use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
 use crate::services::field::type_options::util::get_cell_data;
 use crate::services::field::{
     BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction,
@@ -110,7 +111,7 @@ impl TypeOptionBuilder for MultiSelectTypeOptionBuilder {
     }
 
     fn transform(&mut self, field_type: &FieldType, type_option_data: String) {
-        self.0.transform_type_option(field_type, type_option_data);
+        SelectOptionTypeOptionTransformer::transform_type_option(&mut self.0, field_type, type_option_data)
     }
 }
 #[cfg(test)]

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

@@ -2,7 +2,8 @@ use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams
 use crate::services::cell::{
     CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString,
 };
-use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB, CHECK, UNCHECK};
+use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
+use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
 use bytes::Bytes;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::{internal_error, ErrorCode, FlowyResult};
@@ -119,25 +120,6 @@ pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
         }
     }
 
-    fn transform_type_option(&mut self, field_type: &FieldType, _type_option_data: String) {
-        match field_type {
-            FieldType::Checkbox => {
-                //add Yes and No options if it does not exist.
-                if !self.options().iter().any(|option| option.name == CHECK) {
-                    let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
-                    self.mut_options().push(check_option);
-                }
-
-                if !self.options().iter().any(|option| option.name == UNCHECK) {
-                    let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
-                    self.mut_options().push(uncheck_option);
-                }
-            }
-            FieldType::MultiSelect => {}
-            _ => {}
-        }
-    }
-
     fn transform_cell_data(
         &self,
         cell_data: CellData<SelectOptionIds>,
@@ -189,7 +171,12 @@ where
         decoded_field_type: &FieldType,
         field_rev: &FieldRevision,
     ) -> FlowyResult<CellBytes> {
-        self.transform_cell_data(cell_data, decoded_field_type, field_rev)
+        SelectOptionTypeOptionTransformer::transform_type_option_cell_data(
+            self,
+            cell_data,
+            decoded_field_type,
+            field_rev,
+        )
     }
 
     fn displayed_cell_string(

+ 2 - 1
frontend/rust-lib/flowy-grid/src/services/field/type_options/selection_type_option/single_select_type_option.rs

@@ -1,6 +1,7 @@
 use crate::entities::FieldType;
 use crate::impl_type_option;
 use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
+use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use crate::services::field::{
     SelectOptionCellChangeset, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction,
@@ -96,7 +97,7 @@ impl TypeOptionBuilder for SingleSelectTypeOptionBuilder {
     }
 
     fn transform(&mut self, field_type: &FieldType, type_option_data: String) {
-        self.0.transform_type_option(field_type, type_option_data);
+        SelectOptionTypeOptionTransformer::transform_type_option(&mut self.0, field_type, type_option_data)
     }
 }
 

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

@@ -0,0 +1,63 @@
+use crate::entities::FieldType;
+use crate::services::cell::{CellBytes, CellData};
+use crate::services::field::{
+    SelectOptionColorPB, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction, CHECK, UNCHECK,
+};
+use flowy_error::FlowyResult;
+use flowy_grid_data_model::revision::FieldRevision;
+
+/// Handles how to transform the cell data when switching between different field types
+pub struct SelectOptionTypeOptionTransformer();
+impl SelectOptionTypeOptionTransformer {
+    pub fn transform_type_option<T>(shared: &mut T, field_type: &FieldType, _type_option_data: String)
+    where
+        T: SelectTypeOptionSharedAction,
+    {
+        match field_type {
+            FieldType::Checkbox => {
+                //add Yes and No options if it does not exist.
+                if !shared.options().iter().any(|option| option.name == CHECK) {
+                    let check_option = SelectOptionPB::with_color(CHECK, SelectOptionColorPB::Green);
+                    shared.mut_options().push(check_option);
+                }
+
+                if !shared.options().iter().any(|option| option.name == UNCHECK) {
+                    let uncheck_option = SelectOptionPB::with_color(UNCHECK, SelectOptionColorPB::Yellow);
+                    shared.mut_options().push(uncheck_option);
+                }
+            }
+            FieldType::MultiSelect => {}
+            _ => {}
+        }
+    }
+
+    pub fn transform_type_option_cell_data<T>(
+        shared: &T,
+        cell_data: CellData<SelectOptionIds>,
+        decoded_field_type: &FieldType,
+        _field_rev: &FieldRevision,
+    ) -> FlowyResult<CellBytes>
+    where
+        T: SelectTypeOptionSharedAction,
+    {
+        match decoded_field_type {
+            FieldType::SingleSelect | FieldType::MultiSelect => {
+                //
+                CellBytes::from(shared.get_selected_options(cell_data))
+            }
+            FieldType::Checkbox => {
+                // transform the cell data to the option id
+                let mut transformed_ids = Vec::new();
+                let options = shared.options();
+                cell_data.try_into_inner()?.iter().for_each(|name| {
+                    if let Some(option) = options.iter().find(|option| &option.name == name) {
+                        transformed_ids.push(option.id.clone());
+                    }
+                });
+                let transformed_cell_data = CellData::from(SelectOptionIds::from(transformed_ids));
+                CellBytes::from(shared.get_selected_options(transformed_cell_data))
+            }
+            _ => Ok(CellBytes::default()),
+        }
+    }
+}

+ 7 - 6
shared-lib/flowy-ast/src/ast.rs

@@ -112,7 +112,7 @@ pub struct ASTField<'a> {
 }
 
 impl<'a> ASTField<'a> {
-    pub fn new(cx: &Ctxt, field: &'a syn::Field, index: usize) -> Self {
+    pub fn new(cx: &Ctxt, field: &'a syn::Field, index: usize) -> Result<Self, String> {
         let mut bracket_inner_ty = None;
         let mut bracket_ty = None;
         let mut bracket_category = Some(BracketCategory::Other);
@@ -144,15 +144,16 @@ impl<'a> ASTField<'a> {
                 }
             }
             Ok(None) => {
-                cx.error_spanned_by(&field.ty, "fail to get the ty inner type");
+                let msg = format!("Fail to get the ty inner type: {:?}", field);
+                return Err(msg);
             }
             Err(e) => {
                 eprintln!("ASTField parser failed: {:?} with error: {}", field, e);
-                panic!()
+                return Err(e);
             }
         }
 
-        ASTField {
+        Ok(ASTField {
             member: match &field.ident {
                 Some(ident) => syn::Member::Named(ident.clone()),
                 None => syn::Member::Unnamed(index.into()),
@@ -163,7 +164,7 @@ impl<'a> ASTField<'a> {
             bracket_ty,
             bracket_inner_ty,
             bracket_category,
-        }
+        })
     }
 
     pub fn ty_as_str(&self) -> String {
@@ -235,6 +236,6 @@ fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a Punctuated<syn::Field, Token![,]>)
     fields
         .iter()
         .enumerate()
-        .map(|(index, field)| ASTField::new(cx, field, index))
+        .flat_map(|(index, field)| ASTField::new(cx, field, index).ok())
         .collect()
 }

+ 1 - 2
shared-lib/flowy-ast/src/ty_ext.rs

@@ -74,8 +74,7 @@ pub fn parse_ty<'a>(ctxt: &Ctxt, ty: &'a syn::Type) -> Result<Option<TyInfo<'a>>
             }));
         };
     }
-    ctxt.error_spanned_by(ty, "Unsupported inner type, get inner type fail".to_string());
-    Ok(None)
+    Err("Unsupported inner type, get inner type fail".to_string())
 }
 
 fn parse_bracketed(bracketed: &AngleBracketedGenericArguments) -> Vec<&syn::Type> {