refactor: separate filter operation from filter_entities mod

This commit is contained in:
appflowy 2022-07-08 16:32:11 +08:00
parent 6a01a44cc2
commit 4f30f8e2cd
15 changed files with 133 additions and 96 deletions

View File

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

View File

@ -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)]

View File

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

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

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

View File

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

View File

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

View File

@ -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()],

View File

@ -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)]

View File

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