From 6a01a44cc26d0877a31a00931e8110877720b895 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 8 Jul 2022 16:08:39 +0800 Subject: [PATCH] refactor: rm filter login from eneities mod --- .../filter_entities/checkbox_filter.rs | 27 ------ .../entities/filter_entities/number_filter.rs | 74 ---------------- .../filter_entities/select_option_filter.rs | 63 -------------- .../entities/filter_entities/text_filter.rs | 86 ------------------ .../src/services/filter/checkbox_filter.rs | 29 +++++++ .../src/services/filter/date_filter.rs | 3 + .../flowy-grid/src/services/filter/mod.rs | 5 ++ .../src/services/filter/number_filter.rs | 78 +++++++++++++++++ .../services/filter/select_option_filter.rs | 64 ++++++++++++++ .../src/services/filter/text_filter.rs | 87 +++++++++++++++++++ 10 files changed, 266 insertions(+), 250 deletions(-) create mode 100644 frontend/rust-lib/flowy-grid/src/services/filter/checkbox_filter.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/filter/date_filter.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/filter/number_filter.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/filter/select_option_filter.rs create mode 100644 frontend/rust-lib/flowy-grid/src/services/filter/text_filter.rs diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs index c13cad33e8..42b0bfe1cc 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs @@ -10,16 +10,6 @@ pub struct GridCheckboxFilter { pub condition: CheckboxCondition, } -impl GridCheckboxFilter { - pub fn apply(&self, cell_data: &CheckboxCellData) -> bool { - let is_check = cell_data.is_check(); - match self.condition { - CheckboxCondition::IsChecked => is_check, - CheckboxCondition::IsUnChecked => !is_check, - } - } -} - #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)] #[repr(u8)] pub enum CheckboxCondition { @@ -58,20 +48,3 @@ impl std::convert::From> for GridCheckboxFilter { } } } - -#[cfg(test)] -mod tests { - use crate::entities::{CheckboxCondition, GridCheckboxFilter}; - use crate::services::field::CheckboxCellData; - - #[test] - fn checkbox_filter_is_check_test() { - let checkbox_filter = GridCheckboxFilter { - condition: CheckboxCondition::IsChecked, - }; - for (value, r) in [("true", true), ("yes", true), ("false", false), ("no", false)] { - let data = CheckboxCellData(value.to_owned()); - assert_eq!(checkbox_filter.apply(&data), r); - } - } -} diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs index b54f94972d..2db980de04 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs @@ -16,31 +16,6 @@ pub struct GridNumberFilter { pub content: Option, } -impl GridNumberFilter { - pub fn apply(&self, num_cell_data: &NumberCellData) -> bool { - if self.content.is_none() { - return false; - } - - let content = self.content.as_ref().unwrap(); - let zero_decimal = Decimal::zero(); - let cell_decimal = num_cell_data.decimal().as_ref().unwrap_or(&zero_decimal); - match Decimal::from_str(content) { - Ok(decimal) => match self.condition { - NumberFilterCondition::Equal => cell_decimal == &decimal, - NumberFilterCondition::NotEqual => cell_decimal != &decimal, - NumberFilterCondition::GreaterThan => cell_decimal > &decimal, - NumberFilterCondition::LessThan => cell_decimal < &decimal, - NumberFilterCondition::GreaterThanOrEqualTo => cell_decimal >= &decimal, - NumberFilterCondition::LessThanOrEqualTo => cell_decimal <= &decimal, - NumberFilterCondition::NumberIsEmpty => num_cell_data.is_empty(), - NumberFilterCondition::NumberIsNotEmpty => !num_cell_data.is_empty(), - }, - Err(_) => false, - } - } -} - #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)] #[repr(u8)] pub enum NumberFilterCondition { @@ -91,52 +66,3 @@ impl std::convert::From> for GridNumberFilter { } } } - -#[cfg(test)] -mod tests { - use crate::entities::{GridNumberFilter, NumberFilterCondition}; - - use crate::services::field::{NumberCellData, NumberFormat}; - use std::str::FromStr; - #[test] - fn number_filter_equal_test() { - let number_filter = GridNumberFilter { - condition: NumberFilterCondition::Equal, - content: Some("123".to_owned()), - }; - - for (num_str, r) in [("123", true), ("1234", false), ("", false)] { - let data = NumberCellData::from_str(num_str).unwrap(); - assert_eq!(number_filter.apply(&data), r); - } - - let format = NumberFormat::USD; - for (num_str, r) in [("$123", true), ("1234", false), ("", false)] { - let data = NumberCellData::from_format_str(num_str, true, &format).unwrap(); - assert_eq!(number_filter.apply(&data), r); - } - } - #[test] - fn number_filter_greater_than_test() { - let number_filter = GridNumberFilter { - condition: NumberFilterCondition::GreaterThan, - content: Some("12".to_owned()), - }; - for (num_str, r) in [("123", true), ("10", false), ("30", true), ("", false)] { - let data = NumberCellData::from_str(num_str).unwrap(); - assert_eq!(number_filter.apply(&data), r); - } - } - - #[test] - fn number_filter_less_than_test() { - let number_filter = GridNumberFilter { - condition: NumberFilterCondition::LessThan, - content: Some("100".to_owned()), - }; - for (num_str, r) in [("12", true), ("1234", false), ("30", true), ("", true)] { - let data = NumberCellData::from_str(num_str).unwrap(); - assert_eq!(number_filter.apply(&data), r); - } - } -} diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs index 15edec0707..ad215dfd45 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs @@ -1,4 +1,3 @@ -#![allow(clippy::needless_collect)] use crate::services::field::select_option::{SelectOptionIds, SelectedSelectOptions}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; @@ -13,36 +12,6 @@ pub struct GridSelectOptionFilter { #[pb(index = 2)] pub option_ids: Vec, } - -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 selected options equal to filter's options, then the required_options will be empty. - let required_options = self - .option_ids - .iter() - .filter(|id| !selected_option_ids.contains(id)) - .collect::>(); - - // https://stackoverflow.com/questions/69413164/how-to-fix-this-clippy-warning-needless-collect - !required_options.is_empty() - } - SelectOptionCondition::OptionIsNot => { - for option_id in selected_option_ids { - if self.option_ids.contains(option_id) { - return true; - } - } - false - } - SelectOptionCondition::OptionIsEmpty => selected_option_ids.is_empty(), - SelectOptionCondition::OptionIsNotEmpty => !selected_option_ids.is_empty(), - } - } -} - #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)] #[repr(u8)] pub enum SelectOptionCondition { @@ -87,35 +56,3 @@ impl std::convert::From> for GridSelectOptionFilter { } } } - -#[cfg(test)] -mod tests { - #![allow(clippy::all)] - use crate::entities::{GridSelectOptionFilter, SelectOptionCondition}; - use crate::services::field::select_option::{SelectOption, SelectedSelectOptions}; - - #[test] - fn select_option_filter_is_test() { - let option_1 = SelectOption::new("A"); - let option_2 = SelectOption::new("B"); - - let filter_1 = GridSelectOptionFilter { - condition: SelectOptionCondition::OptionIs, - option_ids: vec![option_1.id.clone(), option_2.id.clone()], - }; - - assert_eq!( - filter_1.apply(&SelectedSelectOptions { - options: vec![option_1.clone(), option_2.clone()], - }), - false - ); - - assert_eq!( - filter_1.apply(&SelectedSelectOptions { - options: vec![option_1.clone()], - }), - true, - ); - } -} diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs index 65253d2faa..7335e89129 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs @@ -12,27 +12,6 @@ pub struct GridTextFilter { pub content: Option, } -impl GridTextFilter { - pub fn apply>(&self, cell_data: T) -> bool { - let cell_data = cell_data.as_ref(); - let s = cell_data.to_lowercase(); - if let Some(content) = self.content.as_ref() { - match self.condition { - TextFilterCondition::Is => &s == content, - TextFilterCondition::IsNot => &s != content, - TextFilterCondition::Contains => s.contains(content), - TextFilterCondition::DoesNotContain => !s.contains(content), - TextFilterCondition::StartsWith => s.starts_with(content), - TextFilterCondition::EndsWith => s.ends_with(content), - TextFilterCondition::TextIsEmpty => s.is_empty(), - TextFilterCondition::TextIsNotEmpty => !s.is_empty(), - } - } else { - false - } - } -} - #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)] #[repr(u8)] pub enum TextFilterCondition { @@ -83,68 +62,3 @@ impl std::convert::From> for GridTextFilter { } } } - -#[cfg(test)] -mod tests { - #![allow(clippy::all)] - use crate::entities::{GridTextFilter, TextFilterCondition}; - - #[test] - fn text_filter_equal_test() { - let text_filter = GridTextFilter { - condition: TextFilterCondition::Is, - content: Some("appflowy".to_owned()), - }; - - assert!(text_filter.apply("AppFlowy")); - assert_eq!(text_filter.apply("appflowy"), true); - assert_eq!(text_filter.apply("Appflowy"), true); - assert_eq!(text_filter.apply("AppFlowy.io"), false); - } - #[test] - fn text_filter_start_with_test() { - let text_filter = GridTextFilter { - condition: TextFilterCondition::StartsWith, - content: Some("appflowy".to_owned()), - }; - - assert_eq!(text_filter.apply("AppFlowy.io"), true); - assert_eq!(text_filter.apply(""), false); - assert_eq!(text_filter.apply("https"), false); - } - - #[test] - fn text_filter_end_with_test() { - let text_filter = GridTextFilter { - condition: TextFilterCondition::EndsWith, - content: Some("appflowy".to_owned()), - }; - - assert_eq!(text_filter.apply("https://github.com/appflowy"), true); - assert_eq!(text_filter.apply("App"), false); - assert_eq!(text_filter.apply("appflowy.io"), false); - } - #[test] - fn text_filter_empty_test() { - let text_filter = GridTextFilter { - condition: TextFilterCondition::TextIsEmpty, - content: Some("appflowy".to_owned()), - }; - - assert_eq!(text_filter.apply(""), true); - assert_eq!(text_filter.apply("App"), false); - } - #[test] - fn text_filter_contain_test() { - let text_filter = GridTextFilter { - condition: TextFilterCondition::Contains, - content: Some("appflowy".to_owned()), - }; - - assert_eq!(text_filter.apply("https://github.com/appflowy"), true); - assert_eq!(text_filter.apply("AppFlowy"), true); - assert_eq!(text_filter.apply("App"), false); - assert_eq!(text_filter.apply(""), false); - assert_eq!(text_filter.apply("github"), false); - } -} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/checkbox_filter.rs b/frontend/rust-lib/flowy-grid/src/services/filter/checkbox_filter.rs new file mode 100644 index 0000000000..ee2a352b65 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/filter/checkbox_filter.rs @@ -0,0 +1,29 @@ +use crate::entities::{CheckboxCondition, GridCheckboxFilter}; +use crate::services::field::CheckboxCellData; + +impl GridCheckboxFilter { + pub fn apply(&self, cell_data: &CheckboxCellData) -> bool { + let is_check = cell_data.is_check(); + match self.condition { + CheckboxCondition::IsChecked => is_check, + CheckboxCondition::IsUnChecked => !is_check, + } + } +} + +#[cfg(test)] +mod tests { + use crate::entities::{CheckboxCondition, GridCheckboxFilter}; + use crate::services::field::CheckboxCellData; + + #[test] + fn checkbox_filter_is_check_test() { + let checkbox_filter = GridCheckboxFilter { + condition: CheckboxCondition::IsChecked, + }; + for (value, r) in [("true", true), ("yes", true), ("false", false), ("no", false)] { + let data = CheckboxCellData(value.to_owned()); + assert_eq!(checkbox_filter.apply(&data), r); + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/date_filter.rs b/frontend/rust-lib/flowy-grid/src/services/filter/date_filter.rs new file mode 100644 index 0000000000..e1dc1d6b47 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/filter/date_filter.rs @@ -0,0 +1,3 @@ +use crate::entities::GridDateFilter; + +impl GridDateFilter {} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs b/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs index 39ae6ba462..336e045249 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/mod.rs @@ -1,4 +1,9 @@ +mod checkbox_filter; +mod date_filter; mod filter_cache; mod filter_service; +mod number_filter; +mod select_option_filter; +mod text_filter; pub(crate) use filter_service::*; diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/number_filter.rs b/frontend/rust-lib/flowy-grid/src/services/filter/number_filter.rs new file mode 100644 index 0000000000..67e39bfa0d --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/filter/number_filter.rs @@ -0,0 +1,78 @@ +use crate::entities::{GridNumberFilter, NumberFilterCondition}; +use crate::services::field::NumberCellData; +use rust_decimal::prelude::Zero; +use rust_decimal::Decimal; +use std::str::FromStr; + +impl GridNumberFilter { + pub fn apply(&self, num_cell_data: &NumberCellData) -> bool { + if self.content.is_none() { + return false; + } + + let content = self.content.as_ref().unwrap(); + let zero_decimal = Decimal::zero(); + let cell_decimal = num_cell_data.decimal().as_ref().unwrap_or(&zero_decimal); + match Decimal::from_str(content) { + Ok(decimal) => match self.condition { + NumberFilterCondition::Equal => cell_decimal == &decimal, + NumberFilterCondition::NotEqual => cell_decimal != &decimal, + NumberFilterCondition::GreaterThan => cell_decimal > &decimal, + NumberFilterCondition::LessThan => cell_decimal < &decimal, + NumberFilterCondition::GreaterThanOrEqualTo => cell_decimal >= &decimal, + NumberFilterCondition::LessThanOrEqualTo => cell_decimal <= &decimal, + NumberFilterCondition::NumberIsEmpty => num_cell_data.is_empty(), + NumberFilterCondition::NumberIsNotEmpty => !num_cell_data.is_empty(), + }, + Err(_) => false, + } + } +} +#[cfg(test)] +mod tests { + use crate::entities::{GridNumberFilter, NumberFilterCondition}; + + use crate::services::field::{NumberCellData, NumberFormat}; + use std::str::FromStr; + #[test] + fn number_filter_equal_test() { + let number_filter = GridNumberFilter { + condition: NumberFilterCondition::Equal, + content: Some("123".to_owned()), + }; + + for (num_str, r) in [("123", true), ("1234", false), ("", false)] { + let data = NumberCellData::from_str(num_str).unwrap(); + assert_eq!(number_filter.apply(&data), r); + } + + let format = NumberFormat::USD; + for (num_str, r) in [("$123", true), ("1234", false), ("", false)] { + let data = NumberCellData::from_format_str(num_str, true, &format).unwrap(); + assert_eq!(number_filter.apply(&data), r); + } + } + #[test] + fn number_filter_greater_than_test() { + let number_filter = GridNumberFilter { + condition: NumberFilterCondition::GreaterThan, + content: Some("12".to_owned()), + }; + for (num_str, r) in [("123", true), ("10", false), ("30", true), ("", false)] { + let data = NumberCellData::from_str(num_str).unwrap(); + assert_eq!(number_filter.apply(&data), r); + } + } + + #[test] + fn number_filter_less_than_test() { + let number_filter = GridNumberFilter { + condition: NumberFilterCondition::LessThan, + content: Some("100".to_owned()), + }; + for (num_str, r) in [("12", true), ("1234", false), ("30", true), ("", true)] { + let data = NumberCellData::from_str(num_str).unwrap(); + assert_eq!(number_filter.apply(&data), r); + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/select_option_filter.rs b/frontend/rust-lib/flowy-grid/src/services/filter/select_option_filter.rs new file mode 100644 index 0000000000..2195463524 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/filter/select_option_filter.rs @@ -0,0 +1,64 @@ +#![allow(clippy::needless_collect)] +use crate::entities::{GridSelectOptionFilter, SelectOptionCondition}; +use crate::services::field::select_option::SelectedSelectOptions; + +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 selected options equal to filter's options, then the required_options will be empty. + let required_options = self + .option_ids + .iter() + .filter(|id| !selected_option_ids.contains(id)) + .collect::>(); + + // https://stackoverflow.com/questions/69413164/how-to-fix-this-clippy-warning-needless-collect + !required_options.is_empty() + } + SelectOptionCondition::OptionIsNot => { + for option_id in selected_option_ids { + if self.option_ids.contains(option_id) { + return true; + } + } + false + } + SelectOptionCondition::OptionIsEmpty => selected_option_ids.is_empty(), + SelectOptionCondition::OptionIsNotEmpty => !selected_option_ids.is_empty(), + } + } +} + +#[cfg(test)] +mod tests { + #![allow(clippy::all)] + use crate::entities::{GridSelectOptionFilter, SelectOptionCondition}; + use crate::services::field::select_option::{SelectOption, SelectedSelectOptions}; + + #[test] + fn select_option_filter_is_test() { + let option_1 = SelectOption::new("A"); + let option_2 = SelectOption::new("B"); + + let filter_1 = GridSelectOptionFilter { + condition: SelectOptionCondition::OptionIs, + option_ids: vec![option_1.id.clone(), option_2.id.clone()], + }; + + assert_eq!( + filter_1.apply(&SelectedSelectOptions { + options: vec![option_1.clone(), option_2.clone()], + }), + false + ); + + assert_eq!( + filter_1.apply(&SelectedSelectOptions { + options: vec![option_1.clone()], + }), + true, + ); + } +} diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/text_filter.rs b/frontend/rust-lib/flowy-grid/src/services/filter/text_filter.rs new file mode 100644 index 0000000000..a0ed6b6976 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/services/filter/text_filter.rs @@ -0,0 +1,87 @@ +use crate::entities::{GridTextFilter, TextFilterCondition}; + +impl GridTextFilter { + pub fn apply>(&self, cell_data: T) -> bool { + let cell_data = cell_data.as_ref(); + let s = cell_data.to_lowercase(); + if let Some(content) = self.content.as_ref() { + match self.condition { + TextFilterCondition::Is => &s == content, + TextFilterCondition::IsNot => &s != content, + TextFilterCondition::Contains => s.contains(content), + TextFilterCondition::DoesNotContain => !s.contains(content), + TextFilterCondition::StartsWith => s.starts_with(content), + TextFilterCondition::EndsWith => s.ends_with(content), + TextFilterCondition::TextIsEmpty => s.is_empty(), + TextFilterCondition::TextIsNotEmpty => !s.is_empty(), + } + } else { + false + } + } +} + +#[cfg(test)] +mod tests { + #![allow(clippy::all)] + use crate::entities::{GridTextFilter, TextFilterCondition}; + + #[test] + fn text_filter_equal_test() { + let text_filter = GridTextFilter { + condition: TextFilterCondition::Is, + content: Some("appflowy".to_owned()), + }; + + assert!(text_filter.apply("AppFlowy")); + assert_eq!(text_filter.apply("appflowy"), true); + assert_eq!(text_filter.apply("Appflowy"), true); + assert_eq!(text_filter.apply("AppFlowy.io"), false); + } + #[test] + fn text_filter_start_with_test() { + let text_filter = GridTextFilter { + condition: TextFilterCondition::StartsWith, + content: Some("appflowy".to_owned()), + }; + + assert_eq!(text_filter.apply("AppFlowy.io"), true); + assert_eq!(text_filter.apply(""), false); + assert_eq!(text_filter.apply("https"), false); + } + + #[test] + fn text_filter_end_with_test() { + let text_filter = GridTextFilter { + condition: TextFilterCondition::EndsWith, + content: Some("appflowy".to_owned()), + }; + + assert_eq!(text_filter.apply("https://github.com/appflowy"), true); + assert_eq!(text_filter.apply("App"), false); + assert_eq!(text_filter.apply("appflowy.io"), false); + } + #[test] + fn text_filter_empty_test() { + let text_filter = GridTextFilter { + condition: TextFilterCondition::TextIsEmpty, + content: Some("appflowy".to_owned()), + }; + + assert_eq!(text_filter.apply(""), true); + assert_eq!(text_filter.apply("App"), false); + } + #[test] + fn text_filter_contain_test() { + let text_filter = GridTextFilter { + condition: TextFilterCondition::Contains, + content: Some("appflowy".to_owned()), + }; + + assert_eq!(text_filter.apply("https://github.com/appflowy"), true); + assert_eq!(text_filter.apply("AppFlowy"), true); + assert_eq!(text_filter.apply("App"), false); + assert_eq!(text_filter.apply(""), false); + assert_eq!(text_filter.apply("github"), false); + } +}