refactor: rm filter login from eneities mod

This commit is contained in:
appflowy 2022-07-08 16:08:39 +08:00
parent bb6a670d26
commit 6a01a44cc2
10 changed files with 266 additions and 250 deletions

View File

@ -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<Arc<GridFilterRevision>> 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);
}
}
}

View File

@ -16,31 +16,6 @@ pub struct GridNumberFilter {
pub content: Option<String>,
}
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<Arc<GridFilterRevision>> 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);
}
}
}

View File

@ -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<String>,
}
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::<Vec<_>>();
// 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<Arc<GridFilterRevision>> 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,
);
}
}

View File

@ -12,27 +12,6 @@ pub struct GridTextFilter {
pub content: Option<String>,
}
impl GridTextFilter {
pub fn apply<T: AsRef<str>>(&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<Arc<GridFilterRevision>> 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);
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,3 @@
use crate::entities::GridDateFilter;
impl GridDateFilter {}

View File

@ -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::*;

View File

@ -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);
}
}
}

View File

@ -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::<Vec<_>>();
// 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,
);
}
}

View File

@ -0,0 +1,87 @@
use crate::entities::{GridTextFilter, TextFilterCondition};
impl GridTextFilter {
pub fn apply<T: AsRef<str>>(&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);
}
}