瀏覽代碼

refactor: separate filter operation from filter_entities mod

appflowy 2 年之前
父節點
當前提交
4f30f8e2cd

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

@@ -1,4 +1,3 @@
-use crate::services::field::CheckboxCellData;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::revision::GridFilterRevision;

+ 1 - 4
frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs

@@ -1,10 +1,7 @@
-use crate::services::field::NumberCellData;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::revision::GridFilterRevision;
-use rust_decimal::prelude::Zero;
-use rust_decimal::Decimal;
-use std::str::FromStr;
+
 use std::sync::Arc;
 
 #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]

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

@@ -1,4 +1,4 @@
-use crate::services::field::select_option::{SelectOptionIds, SelectedSelectOptions};
+use crate::services::field::select_option::SelectOptionIds;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::revision::GridFilterRevision;

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

@@ -1,8 +1,6 @@
-use crate::entities::{FieldType, GridCheckboxFilter};
+use crate::entities::FieldType;
 use crate::impl_type_option;
-use crate::services::cell::{
-    AnyCellData, CellData, CellDataChangeset, CellDataOperation, CellFilterOperation, DecodedCellData,
-};
+use crate::services::cell::{AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData};
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use bytes::Bytes;
 use flowy_derive::ProtoBuf;
@@ -42,16 +40,6 @@ impl_type_option!(CheckboxTypeOption, FieldType::Checkbox);
 const YES: &str = "Yes";
 const NO: &str = "No";
 
-impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption {
-    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridCheckboxFilter) -> FlowyResult<bool> {
-        if !any_cell_data.is_checkbox() {
-            return Ok(true);
-        }
-        let checkbox_cell_data: CheckboxCellData = any_cell_data.try_into()?;
-        Ok(filter.apply(&checkbox_cell_data))
-    }
-}
-
 impl CellDataOperation<String, String> for CheckboxTypeOption {
     fn decode_cell_data(
         &self,

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

@@ -1,12 +1,10 @@
-use crate::entities::{FieldType, GridSelectOptionFilter};
+use crate::entities::FieldType;
 
 use crate::impl_type_option;
-use crate::services::cell::{
-    AnyCellData, CellData, CellDataChangeset, CellDataOperation, CellFilterOperation, DecodedCellData,
-};
+use crate::services::cell::{AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData};
 use crate::services::field::select_option::{
     make_selected_select_options, SelectOption, SelectOptionCellChangeset, SelectOptionCellData, SelectOptionIds,
-    SelectOptionOperation, SelectedSelectOptions, SELECTION_IDS_SEPARATOR,
+    SelectOptionOperation, SELECTION_IDS_SEPARATOR,
 };
 use crate::services::field::type_options::util::get_cell_data;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
@@ -46,16 +44,7 @@ impl SelectOptionOperation for MultiSelectTypeOption {
         &mut self.options
     }
 }
-impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOption {
-    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
-        if !any_cell_data.is_multi_select() {
-            return Ok(true);
-        }
 
-        let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data));
-        Ok(filter.apply(&selected_options))
-    }
-}
 impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSelectTypeOption {
     fn decode_cell_data(
         &self,

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

@@ -1,9 +1,7 @@
 use crate::impl_type_option;
 
-use crate::entities::{FieldType, GridNumberFilter};
-use crate::services::cell::{
-    AnyCellData, CellData, CellDataChangeset, CellDataOperation, CellFilterOperation, DecodedCellData,
-};
+use crate::entities::FieldType;
+use crate::services::cell::{CellData, CellDataChangeset, CellDataOperation, DecodedCellData};
 use crate::services::field::number_currency::Currency;
 use crate::services::field::type_options::number_type_option::format::*;
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
@@ -79,7 +77,7 @@ impl NumberTypeOption {
         Self::default()
     }
 
-    fn format_cell_data(&self, s: &str) -> FlowyResult<NumberCellData> {
+    pub(crate) fn format_cell_data(&self, s: &str) -> FlowyResult<NumberCellData> {
         match self.format {
             NumberFormat::Num | NumberFormat::Percent => match Decimal::from_str(s) {
                 Ok(value, ..) => Ok(NumberCellData::from_decimal(value)),
@@ -105,18 +103,6 @@ pub(crate) fn strip_currency_symbol<T: ToString>(s: T) -> String {
     }
     s
 }
-impl CellFilterOperation<GridNumberFilter> for NumberTypeOption {
-    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridNumberFilter) -> FlowyResult<bool> {
-        if !any_cell_data.is_number() {
-            return Ok(true);
-        }
-
-        let cell_data = any_cell_data.cell_data;
-        let num_cell_data = self.format_cell_data(&cell_data)?;
-
-        Ok(filter.apply(&num_cell_data))
-    }
-}
 
 impl CellDataOperation<String, String> for NumberTypeOption {
     fn decode_cell_data(

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

@@ -1,8 +1,6 @@
-use crate::entities::{FieldType, GridSelectOptionFilter};
+use crate::entities::FieldType;
 use crate::impl_type_option;
-use crate::services::cell::{
-    AnyCellData, CellData, CellDataChangeset, CellDataOperation, CellFilterOperation, DecodedCellData,
-};
+use crate::services::cell::{AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData};
 use crate::services::field::select_option::{
     make_selected_select_options, SelectOption, SelectOptionCellChangeset, SelectOptionCellData, SelectOptionIds,
     SelectOptionOperation,
@@ -43,16 +41,6 @@ impl SelectOptionOperation for SingleSelectTypeOption {
     }
 }
 
-impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOption {
-    fn apply_filter(&self, any_cell_data: AnyCellData, _filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
-        if !any_cell_data.is_single_select() {
-            return Ok(true);
-        }
-        let _ids: SelectOptionIds = any_cell_data.try_into()?;
-        Ok(false)
-    }
-}
-
 impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSelectTypeOption {
     fn decode_cell_data(
         &self,

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

@@ -1,8 +1,7 @@
-use crate::entities::{FieldType, GridTextFilter};
+use crate::entities::FieldType;
 use crate::impl_type_option;
 use crate::services::cell::{
-    try_decode_cell_data, AnyCellData, CellData, CellDataChangeset, CellDataOperation, CellFilterOperation,
-    DecodedCellData,
+    try_decode_cell_data, AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData,
 };
 use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use bytes::Bytes;
@@ -33,17 +32,6 @@ pub struct RichTextTypeOption {
 }
 impl_type_option!(RichTextTypeOption, FieldType::RichText);
 
-impl CellFilterOperation<GridTextFilter> for RichTextTypeOption {
-    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> {
-        if !any_cell_data.is_text() {
-            return Ok(true);
-        }
-
-        let text_cell_data: TextCellData = any_cell_data.try_into()?;
-        Ok(filter.apply(text_cell_data))
-    }
-}
-
 impl CellDataOperation<String, String> for RichTextTypeOption {
     fn decode_cell_data(
         &self,

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

@@ -1,9 +1,9 @@
-use crate::entities::{FieldType, GridTextFilter};
+use crate::entities::FieldType;
 use crate::impl_type_option;
 use crate::services::cell::{
-    AnyCellData, CellData, CellDataChangeset, CellDataOperation, CellFilterOperation, DecodedCellData, FromCellString,
+    AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData, FromCellString,
 };
-use crate::services::field::{BoxTypeOptionBuilder, TextCellData, TypeOptionBuilder};
+use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
 use bytes::Bytes;
 use fancy_regex::Regex;
 use flowy_derive::ProtoBuf;
@@ -34,17 +34,6 @@ pub struct URLTypeOption {
 }
 impl_type_option!(URLTypeOption, FieldType::URL);
 
-impl CellFilterOperation<GridTextFilter> for URLTypeOption {
-    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> {
-        if !any_cell_data.is_url() {
-            return Ok(true);
-        }
-
-        let text_cell_data: TextCellData = any_cell_data.try_into()?;
-        Ok(filter.apply(&text_cell_data))
-    }
-}
-
 impl CellDataOperation<URLCellData, String> for URLTypeOption {
     fn decode_cell_data(
         &self,

+ 24 - 1
frontend/rust-lib/flowy-grid/src/services/filter/checkbox_filter.rs

@@ -1,5 +1,7 @@
 use crate::entities::{CheckboxCondition, GridCheckboxFilter};
-use crate::services::field::CheckboxCellData;
+use crate::services::cell::{AnyCellData, CellFilterOperation};
+use crate::services::field::{CheckboxCellData, CheckboxTypeOption};
+use flowy_error::FlowyResult;
 
 impl GridCheckboxFilter {
     pub fn apply(&self, cell_data: &CheckboxCellData) -> bool {
@@ -11,6 +13,16 @@ impl GridCheckboxFilter {
     }
 }
 
+impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption {
+    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridCheckboxFilter) -> FlowyResult<bool> {
+        if !any_cell_data.is_checkbox() {
+            return Ok(true);
+        }
+        let checkbox_cell_data: CheckboxCellData = any_cell_data.try_into()?;
+        Ok(filter.apply(&checkbox_cell_data))
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::entities::{CheckboxCondition, GridCheckboxFilter};
@@ -26,4 +38,15 @@ mod tests {
             assert_eq!(checkbox_filter.apply(&data), r);
         }
     }
+
+    #[test]
+    fn checkbox_filter_is_uncheck_test() {
+        let checkbox_filter = GridCheckboxFilter {
+            condition: CheckboxCondition::IsUnChecked,
+        };
+        for (value, r) in [("false", true), ("no", true), ("true", false), ("yes", false)] {
+            let data = CheckboxCellData(value.to_owned());
+            assert_eq!(checkbox_filter.apply(&data), r);
+        }
+    }
 }

+ 1 - 0
frontend/rust-lib/flowy-grid/src/services/filter/mod.rs

@@ -5,5 +5,6 @@ mod filter_service;
 mod number_filter;
 mod select_option_filter;
 mod text_filter;
+mod url_filter;
 
 pub(crate) use filter_service::*;

+ 17 - 1
frontend/rust-lib/flowy-grid/src/services/filter/number_filter.rs

@@ -1,5 +1,7 @@
 use crate::entities::{GridNumberFilter, NumberFilterCondition};
-use crate::services::field::NumberCellData;
+use crate::services::cell::{AnyCellData, CellFilterOperation};
+use crate::services::field::{NumberCellData, NumberTypeOption};
+use flowy_error::FlowyResult;
 use rust_decimal::prelude::Zero;
 use rust_decimal::Decimal;
 use std::str::FromStr;
@@ -28,6 +30,20 @@ impl GridNumberFilter {
         }
     }
 }
+
+impl CellFilterOperation<GridNumberFilter> for NumberTypeOption {
+    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridNumberFilter) -> FlowyResult<bool> {
+        if !any_cell_data.is_number() {
+            return Ok(true);
+        }
+
+        let cell_data = any_cell_data.cell_data;
+        let num_cell_data = self.format_cell_data(&cell_data)?;
+
+        Ok(filter.apply(&num_cell_data))
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::entities::{GridNumberFilter, NumberFilterCondition};

+ 46 - 1
frontend/rust-lib/flowy-grid/src/services/filter/select_option_filter.rs

@@ -1,12 +1,20 @@
 #![allow(clippy::needless_collect)]
+
 use crate::entities::{GridSelectOptionFilter, SelectOptionCondition};
-use crate::services::field::select_option::SelectedSelectOptions;
+use crate::services::cell::{AnyCellData, CellFilterOperation};
+use crate::services::field::select_option::{SelectOptionOperation, SelectedSelectOptions};
+use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption};
+use flowy_error::FlowyResult;
 
 impl GridSelectOptionFilter {
     pub fn apply(&self, selected_options: &SelectedSelectOptions) -> bool {
         let selected_option_ids: Vec<&String> = selected_options.options.iter().map(|option| &option.id).collect();
         match self.condition {
             SelectOptionCondition::OptionIs => {
+                if self.option_ids.len() != selected_option_ids.len() {
+                    return true;
+                }
+
                 // if selected options equal to filter's options, then the required_options will be empty.
                 let required_options = self
                     .option_ids
@@ -31,6 +39,27 @@ impl GridSelectOptionFilter {
     }
 }
 
+impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOption {
+    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
+        if !any_cell_data.is_multi_select() {
+            return Ok(true);
+        }
+
+        let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data));
+        Ok(filter.apply(&selected_options))
+    }
+}
+
+impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOption {
+    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
+        if !any_cell_data.is_single_select() {
+            return Ok(true);
+        }
+        let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data));
+        Ok(filter.apply(&selected_options))
+    }
+}
+
 #[cfg(test)]
 mod tests {
     #![allow(clippy::all)]
@@ -41,6 +70,7 @@ mod tests {
     fn select_option_filter_is_test() {
         let option_1 = SelectOption::new("A");
         let option_2 = SelectOption::new("B");
+        let option_3 = SelectOption::new("C");
 
         let filter_1 = GridSelectOptionFilter {
             condition: SelectOptionCondition::OptionIs,
@@ -54,6 +84,21 @@ mod tests {
             false
         );
 
+        assert_eq!(
+            filter_1.apply(&SelectedSelectOptions {
+                options: vec![option_1.clone(), option_2.clone(), option_3.clone()],
+            }),
+            true
+        );
+
+        assert_eq!(
+            filter_1.apply(&SelectedSelectOptions {
+                options: vec![option_1.clone(), option_3.clone()],
+            }),
+            true
+        );
+
+        assert_eq!(filter_1.apply(&SelectedSelectOptions { options: vec![] }), true);
         assert_eq!(
             filter_1.apply(&SelectedSelectOptions {
                 options: vec![option_1.clone()],

+ 13 - 0
frontend/rust-lib/flowy-grid/src/services/filter/text_filter.rs

@@ -1,4 +1,7 @@
 use crate::entities::{GridTextFilter, TextFilterCondition};
+use crate::services::cell::{AnyCellData, CellFilterOperation};
+use crate::services::field::{RichTextTypeOption, TextCellData};
+use flowy_error::FlowyResult;
 
 impl GridTextFilter {
     pub fn apply<T: AsRef<str>>(&self, cell_data: T) -> bool {
@@ -21,6 +24,16 @@ impl GridTextFilter {
     }
 }
 
+impl CellFilterOperation<GridTextFilter> for RichTextTypeOption {
+    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> {
+        if !any_cell_data.is_text() {
+            return Ok(true);
+        }
+
+        let text_cell_data: TextCellData = any_cell_data.try_into()?;
+        Ok(filter.apply(text_cell_data))
+    }
+}
 #[cfg(test)]
 mod tests {
     #![allow(clippy::all)]

+ 15 - 0
frontend/rust-lib/flowy-grid/src/services/filter/url_filter.rs

@@ -0,0 +1,15 @@
+use crate::entities::GridTextFilter;
+use crate::services::cell::{AnyCellData, CellFilterOperation};
+use crate::services::field::{TextCellData, URLTypeOption};
+use flowy_error::FlowyResult;
+
+impl CellFilterOperation<GridTextFilter> for URLTypeOption {
+    fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> {
+        if !any_cell_data.is_url() {
+            return Ok(true);
+        }
+
+        let text_cell_data: TextCellData = any_cell_data.try_into()?;
+        Ok(filter.apply(&text_cell_data))
+    }
+}