mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: separate filter operation from filter_entities mod
This commit is contained in:
parent
6a01a44cc2
commit
4f30f8e2cd
@ -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,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,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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
@ -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};
|
||||
|
@ -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()],
|
||||
|
@ -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)]
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user