nathan пре 2 година
родитељ
комит
6846bbf103

+ 1 - 0
frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs

@@ -36,6 +36,7 @@ impl std::default::Default for TextFilterCondition {
         TextFilterCondition::Is
     }
 }
+
 impl std::convert::TryFrom<u8> for TextFilterCondition {
     type Error = ErrorCode;
 

+ 10 - 1
frontend/rust-lib/flowy-grid/src/services/cell/any_cell_data.rs

@@ -15,6 +15,15 @@ pub struct AnyCellData {
     pub field_type: FieldType,
 }
 
+impl AnyCellData {
+    pub fn from_field_type(field_type: &FieldType) -> AnyCellData {
+        Self {
+            data: "".to_string(),
+            field_type: field_type.clone(),
+        }
+    }
+}
+
 impl std::str::FromStr for AnyCellData {
     type Err = FlowyError;
 
@@ -68,7 +77,7 @@ impl AnyCellData {
         }
     }
 
-    pub fn json(&self) -> String {
+    pub fn to_json(&self) -> String {
         serde_json::to_string(self).unwrap_or_else(|_| "".to_owned())
     }
 

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

@@ -126,7 +126,7 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
         FieldType::URL => URLTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
     }?;
 
-    Ok(AnyCellData::new(s, field_type).json())
+    Ok(AnyCellData::new(s, field_type).to_json())
 }
 
 pub fn decode_any_cell_data<T: TryInto<AnyCellData, Error = FlowyError> + Debug>(

+ 4 - 0
frontend/rust-lib/flowy-grid/src/services/filter/cache.rs

@@ -84,6 +84,10 @@ pub(crate) struct FilterResult {
 
 impl FilterResult {
     pub(crate) fn is_visible(&self) -> bool {
+        if self.visible_by_filter_id.is_empty() {
+            return false;
+        }
+
         for visible in self.visible_by_filter_id.values() {
             if visible == &false {
                 return false;

+ 9 - 5
frontend/rust-lib/flowy-grid/src/services/filter/controller.rs

@@ -232,10 +232,9 @@ fn filter_row(
         .or_insert_with(FilterResult::default);
 
     // Iterate each cell of the row to check its visibility
-    for (field_id, cell_rev) in row_rev.cells.iter() {
-        let field_rev = field_rev_by_field_id.get(field_id)?;
+    for (field_id, field_rev) in field_rev_by_field_id {
         let filter_type = FilterType::from(field_rev);
-
+        let cell_rev = row_rev.cells.get(field_id);
         // if the visibility of the cell_rew is changed, which means the visibility of the
         // row is changed too.
         if let Some(is_visible) = filter_cell(&filter_type, field_rev, filter_map, cell_rev) {
@@ -255,6 +254,7 @@ fn filter_row(
             }
         }
     }
+
     None
 }
 
@@ -263,9 +263,13 @@ fn filter_cell(
     filter_id: &FilterType,
     field_rev: &Arc<FieldRevision>,
     filter_map: &FilterMap,
-    cell_rev: &CellRevision,
+    cell_rev: Option<&CellRevision>,
 ) -> Option<bool> {
-    let any_cell_data = AnyCellData::try_from(cell_rev).ok()?;
+    let any_cell_data = match cell_rev {
+        None => AnyCellData::from_field_type(&filter_id.field_type),
+        Some(cell_rev) => AnyCellData::try_from(cell_rev).ok()?,
+    };
+
     let is_visible = match &filter_id.field_type {
         FieldType::RichText => filter_map.text_filter.get(filter_id).and_then(|filter| {
             Some(

+ 12 - 0
frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs

@@ -36,6 +36,10 @@ pub enum FilterScript {
         condition: SelectOptionCondition,
         option_ids: Vec<String>,
     },
+    CreateSingleSelectFilter {
+        condition: SelectOptionCondition,
+        option_ids: Vec<String>,
+    },
     AssertFilterCount {
         count: i32,
     },
@@ -118,6 +122,14 @@ impl GridFilterTest {
                     CreateFilterPayloadPB::new(field_rev, condition, content);
                 self.insert_filter(payload).await;
             }
+            FilterScript::CreateSingleSelectFilter { condition, option_ids} => {
+                let field_rev = self.get_field_rev(FieldType::SingleSelect);
+                let content =
+                    SelectOptionIds::from(option_ids).to_string();
+                let payload =
+                    CreateFilterPayloadPB::new(field_rev, condition, content);
+                self.insert_filter(payload).await;
+            }
             FilterScript::AssertFilterCount { count } => {
                 let filters = self.editor.get_all_filters().await.unwrap();
                 assert_eq!(count as usize, filters.len());

+ 56 - 1
frontend/rust-lib/flowy-grid/tests/grid/filter_test/select_option_filter_test.rs

@@ -1,6 +1,6 @@
 use crate::grid::filter_test::script::FilterScript::*;
 use crate::grid::filter_test::script::GridFilterTest;
-use flowy_grid::entities::{NumberFilterCondition, SelectOptionCondition};
+use flowy_grid::entities::SelectOptionCondition;
 
 #[tokio::test]
 async fn grid_filter_multi_select_is_empty_test() {
@@ -27,3 +27,58 @@ async fn grid_filter_multi_select_is_not_empty_test() {
     ];
     test.run_scripts(scripts).await;
 }
+
+#[tokio::test]
+async fn grid_filter_multi_select_is_test() {
+    let mut test = GridFilterTest::new().await;
+    let mut options = test.get_multi_select_type_option();
+    let scripts = vec![
+        CreateMultiSelectFilter {
+            condition: SelectOptionCondition::OptionIs,
+            option_ids: vec![options.remove(0).id, options.remove(0).id],
+        },
+        AssertNumberOfRows { expected: 2 },
+    ];
+    test.run_scripts(scripts).await;
+}
+
+#[tokio::test]
+async fn grid_filter_multi_select_is_test2() {
+    let mut test = GridFilterTest::new().await;
+    let mut options = test.get_multi_select_type_option();
+    let scripts = vec![
+        CreateMultiSelectFilter {
+            condition: SelectOptionCondition::OptionIs,
+            option_ids: vec![options.remove(1).id],
+        },
+        AssertNumberOfRows { expected: 1 },
+    ];
+    test.run_scripts(scripts).await;
+}
+
+#[tokio::test]
+async fn grid_filter_single_select_is_empty_test() {
+    let mut test = GridFilterTest::new().await;
+    let scripts = vec![
+        CreateSingleSelectFilter {
+            condition: SelectOptionCondition::OptionIsEmpty,
+            option_ids: vec![],
+        },
+        AssertNumberOfRows { expected: 2 },
+    ];
+    test.run_scripts(scripts).await;
+}
+
+#[tokio::test]
+async fn grid_filter_single_select_is_test() {
+    let mut test = GridFilterTest::new().await;
+    let mut options = test.get_single_select_type_option();
+    let scripts = vec![
+        CreateSingleSelectFilter {
+            condition: SelectOptionCondition::OptionIs,
+            option_ids: vec![options.remove(0).id],
+        },
+        AssertNumberOfRows { expected: 2 },
+    ];
+    test.run_scripts(scripts).await;
+}

+ 181 - 6
frontend/rust-lib/flowy-grid/tests/grid/grid_editor.rs

@@ -45,12 +45,17 @@ impl GridEditorTest {
     pub async fn new(layout: GridLayout) -> Self {
         let sdk = FlowySDKTest::default();
         let _ = sdk.init_user().await;
-        let build_context = make_test_grid();
-        let view_data: Bytes = build_context.into();
-
         let test = match layout {
-            GridLayout::Table => ViewTest::new_grid_view(&sdk, view_data.to_vec()).await,
-            GridLayout::Board => ViewTest::new_board_view(&sdk, view_data.to_vec()).await,
+            GridLayout::Table => {
+                let build_context = make_test_grid();
+                let view_data: Bytes = build_context.into();
+                ViewTest::new_grid_view(&sdk, view_data.to_vec()).await
+            }
+            GridLayout::Board => {
+                let build_context = make_test_board();
+                let view_data: Bytes = build_context.into();
+                ViewTest::new_board_view(&sdk, view_data.to_vec()).await
+            }
         };
 
         let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
@@ -96,6 +101,23 @@ impl GridEditorTest {
             .unwrap()
     }
 
+    pub fn get_multi_select_type_option(&self) -> Vec<SelectOptionPB> {
+        let field_type = FieldType::MultiSelect;
+        let field_rev = self.get_field_rev(field_type.clone());
+        let type_option = field_rev
+            .get_type_option::<MultiSelectTypeOptionPB>(field_type.into())
+            .unwrap();
+        type_option.options
+    }
+
+    pub fn get_single_select_type_option(&self) -> Vec<SelectOptionPB> {
+        let field_type = FieldType::SingleSelect;
+        let field_rev = self.get_field_rev(field_type.clone());
+        let type_option = field_rev
+            .get_type_option::<SingleSelectTypeOptionPB>(field_type.into())
+            .unwrap();
+        type_option.options
+    }
     pub fn block_id(&self) -> &str {
         &self.block_meta_revs.last().unwrap().block_id
     }
@@ -176,6 +198,159 @@ fn make_test_grid() -> BuildGridContext {
         }
     }
 
+    // We have many assumptions base on the number of the rows, so do not change the number of the loop.
+    for i in 0..5 {
+        let block_id = grid_builder.block_id().to_owned();
+        let field_revs = grid_builder.field_revs();
+        let mut row_builder = GridRowTestBuilder::new(&block_id, field_revs);
+        match i {
+            0 => {
+                for field_type in FieldType::iter() {
+                    match field_type {
+                        FieldType::RichText => row_builder.insert_text_cell("A"),
+                        FieldType::Number => row_builder.insert_number_cell("1"),
+                        FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
+                        FieldType::MultiSelect => row_builder
+                            .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]),
+                        FieldType::Checkbox => row_builder.insert_checkbox_cell("true"),
+                        _ => "".to_owned(),
+                    };
+                }
+            }
+            1 => {
+                for field_type in FieldType::iter() {
+                    match field_type {
+                        FieldType::RichText => row_builder.insert_text_cell("B"),
+                        FieldType::Number => row_builder.insert_number_cell("2"),
+                        FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
+                        FieldType::MultiSelect => row_builder
+                            .insert_multi_select_cell(|mut options| vec![options.remove(0), options.remove(0)]),
+                        FieldType::Checkbox => row_builder.insert_checkbox_cell("true"),
+                        _ => "".to_owned(),
+                    };
+                }
+            }
+            2 => {
+                for field_type in FieldType::iter() {
+                    match field_type {
+                        FieldType::RichText => row_builder.insert_text_cell("C"),
+                        FieldType::Number => row_builder.insert_number_cell("3"),
+                        FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
+                        FieldType::SingleSelect => {
+                            row_builder.insert_single_select_cell(|mut options| options.remove(0))
+                        }
+                        FieldType::MultiSelect => {
+                            row_builder.insert_multi_select_cell(|mut options| vec![options.remove(1)])
+                        }
+                        FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
+                        _ => "".to_owned(),
+                    };
+                }
+            }
+            3 => {
+                for field_type in FieldType::iter() {
+                    match field_type {
+                        FieldType::RichText => row_builder.insert_text_cell("DA"),
+                        FieldType::Number => row_builder.insert_number_cell("4"),
+                        FieldType::DateTime => row_builder.insert_date_cell("1668704685"),
+                        FieldType::SingleSelect => {
+                            row_builder.insert_single_select_cell(|mut options| options.remove(0))
+                        }
+                        FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
+                        _ => "".to_owned(),
+                    };
+                }
+            }
+            4 => {
+                for field_type in FieldType::iter() {
+                    match field_type {
+                        FieldType::RichText => row_builder.insert_text_cell("AE"),
+                        FieldType::Number => row_builder.insert_number_cell(""),
+                        FieldType::DateTime => row_builder.insert_date_cell("1668359085"),
+                        FieldType::SingleSelect => {
+                            row_builder.insert_single_select_cell(|mut options| options.remove(1))
+                        }
+
+                        FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
+                        _ => "".to_owned(),
+                    };
+                }
+            }
+            _ => {}
+        }
+
+        let row_rev = row_builder.build();
+        grid_builder.add_row(row_rev);
+    }
+    grid_builder.build()
+}
+
+fn make_test_board() -> BuildGridContext {
+    let mut grid_builder = GridBuilder::new();
+    // Iterate through the FieldType to create the corresponding Field.
+    for field_type in FieldType::iter() {
+        let field_type: FieldType = field_type;
+
+        // The
+        match field_type {
+            FieldType::RichText => {
+                let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
+                    .name("Name")
+                    .visibility(true)
+                    .primary(true)
+                    .build();
+                grid_builder.add_field(text_field);
+            }
+            FieldType::Number => {
+                // Number
+                let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
+                let number_field = FieldBuilder::new(number).name("Price").visibility(true).build();
+                grid_builder.add_field(number_field);
+            }
+            FieldType::DateTime => {
+                // Date
+                let date = DateTypeOptionBuilder::default()
+                    .date_format(DateFormat::US)
+                    .time_format(TimeFormat::TwentyFourHour);
+                let date_field = FieldBuilder::new(date).name("Time").visibility(true).build();
+                grid_builder.add_field(date_field);
+            }
+            FieldType::SingleSelect => {
+                // Single Select
+                let single_select = SingleSelectTypeOptionBuilder::default()
+                    .add_option(SelectOptionPB::new(COMPLETED))
+                    .add_option(SelectOptionPB::new(PLANNED))
+                    .add_option(SelectOptionPB::new(PAUSED));
+                let single_select_field = FieldBuilder::new(single_select).name("Status").visibility(true).build();
+                grid_builder.add_field(single_select_field);
+            }
+            FieldType::MultiSelect => {
+                // MultiSelect
+                let multi_select = MultiSelectTypeOptionBuilder::default()
+                    .add_option(SelectOptionPB::new(GOOGLE))
+                    .add_option(SelectOptionPB::new(FACEBOOK))
+                    .add_option(SelectOptionPB::new(TWITTER));
+                let multi_select_field = FieldBuilder::new(multi_select)
+                    .name("Platform")
+                    .visibility(true)
+                    .build();
+                grid_builder.add_field(multi_select_field);
+            }
+            FieldType::Checkbox => {
+                // Checkbox
+                let checkbox = CheckboxTypeOptionBuilder::default();
+                let checkbox_field = FieldBuilder::new(checkbox).name("is urgent").visibility(true).build();
+                grid_builder.add_field(checkbox_field);
+            }
+            FieldType::URL => {
+                // URL
+                let url = URLTypeOptionBuilder::default();
+                let url_field = FieldBuilder::new(url).name("link").visibility(true).build();
+                grid_builder.add_field(url_field);
+            }
+        }
+    }
+
     // We have many assumptions base on the number of the rows, so do not change the number of the loop.
     for i in 0..5 {
         let block_id = grid_builder.block_id().to_owned();
@@ -224,7 +399,7 @@ fn make_test_grid() -> BuildGridContext {
                             row_builder.insert_single_select_cell(|mut options| options.remove(1))
                         }
                         FieldType::MultiSelect => {
-                            row_builder.insert_multi_select_cell(|mut options| vec![options.remove(1)])
+                            row_builder.insert_multi_select_cell(|mut options| vec![options.remove(0)])
                         }
                         FieldType::Checkbox => row_builder.insert_checkbox_cell("false"),
                         _ => "".to_owned(),

+ 1 - 1
shared-lib/grid-rev-model/src/grid_block.rs

@@ -64,7 +64,7 @@ impl RowChangeset {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
 pub struct CellRevision {
     pub data: String,
 }