mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: improve type option filter logic (#4652)
This commit is contained in:
parent
6f173c2ada
commit
c500cd1287
@ -43,9 +43,8 @@ impl FromStr for DateFilterContentPB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
|
#[derive(Debug, Clone, Default, PartialEq, Eq, ProtoBuf_Enum)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default)]
|
|
||||||
pub enum DateFilterConditionPB {
|
pub enum DateFilterConditionPB {
|
||||||
#[default]
|
#[default]
|
||||||
DateIs = 0,
|
DateIs = 0,
|
||||||
|
@ -12,9 +12,8 @@ pub struct NumberFilterPB {
|
|||||||
pub content: String,
|
pub content: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
|
#[derive(Debug, Clone, Default, PartialEq, Eq, ProtoBuf_Enum)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default)]
|
|
||||||
pub enum NumberFilterConditionPB {
|
pub enum NumberFilterConditionPB {
|
||||||
#[default]
|
#[default]
|
||||||
Equal = 0,
|
Equal = 0,
|
||||||
|
@ -1,65 +1,108 @@
|
|||||||
use crate::entities::{DateFilterConditionPB, DateFilterPB};
|
use crate::entities::{DateFilterConditionPB, DateFilterPB};
|
||||||
use chrono::NaiveDateTime;
|
|
||||||
|
use chrono::{NaiveDate, NaiveDateTime};
|
||||||
|
|
||||||
|
use super::DateCellData;
|
||||||
|
|
||||||
impl DateFilterPB {
|
impl DateFilterPB {
|
||||||
pub fn is_visible<T: Into<Option<i64>>>(&self, cell_timestamp: T) -> bool {
|
/// Returns `None` if the DateFilterPB doesn't have the necessary data for
|
||||||
match cell_timestamp.into() {
|
/// the condition. For example, `start` and `end` timestamps for
|
||||||
None => DateFilterConditionPB::DateIsEmpty == self.condition,
|
/// `DateFilterConditionPB::DateWithin`.
|
||||||
Some(timestamp) => {
|
pub fn is_visible(&self, cell_data: &DateCellData) -> Option<bool> {
|
||||||
match self.condition {
|
let strategy = match self.condition {
|
||||||
DateFilterConditionPB::DateIsNotEmpty => {
|
DateFilterConditionPB::DateIs => DateFilterStrategy::On(self.timestamp?),
|
||||||
return true;
|
DateFilterConditionPB::DateBefore => DateFilterStrategy::Before(self.timestamp?),
|
||||||
},
|
DateFilterConditionPB::DateAfter => DateFilterStrategy::After(self.timestamp?),
|
||||||
DateFilterConditionPB::DateIsEmpty => {
|
DateFilterConditionPB::DateOnOrBefore => DateFilterStrategy::OnOrBefore(self.timestamp?),
|
||||||
return false;
|
DateFilterConditionPB::DateOnOrAfter => DateFilterStrategy::OnOrAfter(self.timestamp?),
|
||||||
},
|
DateFilterConditionPB::DateWithIn => DateFilterStrategy::DateWithin {
|
||||||
_ => {},
|
start: self.start?,
|
||||||
}
|
end: self.end?,
|
||||||
|
|
||||||
let cell_time = NaiveDateTime::from_timestamp_opt(timestamp, 0);
|
|
||||||
let cell_date = cell_time.map(|time| time.date());
|
|
||||||
match self.timestamp {
|
|
||||||
None => {
|
|
||||||
if self.start.is_none() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.end.is_none() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let start_time = NaiveDateTime::from_timestamp_opt(*self.start.as_ref().unwrap(), 0);
|
|
||||||
let start_date = start_time.map(|time| time.date());
|
|
||||||
|
|
||||||
let end_time = NaiveDateTime::from_timestamp_opt(*self.end.as_ref().unwrap(), 0);
|
|
||||||
let end_date = end_time.map(|time| time.date());
|
|
||||||
|
|
||||||
cell_date >= start_date && cell_date <= end_date
|
|
||||||
},
|
|
||||||
Some(timestamp) => {
|
|
||||||
let expected_timestamp = NaiveDateTime::from_timestamp_opt(timestamp, 0);
|
|
||||||
let expected_date = expected_timestamp.map(|time| time.date());
|
|
||||||
|
|
||||||
// We assume that the cell_timestamp doesn't contain hours, just day.
|
|
||||||
match self.condition {
|
|
||||||
DateFilterConditionPB::DateIs => cell_date == expected_date,
|
|
||||||
DateFilterConditionPB::DateBefore => cell_date < expected_date,
|
|
||||||
DateFilterConditionPB::DateAfter => cell_date > expected_date,
|
|
||||||
DateFilterConditionPB::DateOnOrBefore => cell_date <= expected_date,
|
|
||||||
DateFilterConditionPB::DateOnOrAfter => cell_date >= expected_date,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
DateFilterConditionPB::DateIsEmpty => DateFilterStrategy::Empty,
|
||||||
|
DateFilterConditionPB::DateIsNotEmpty => DateFilterStrategy::NotEmpty,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(strategy.filter(cell_data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn naive_date_from_timestamp(timestamp: i64) -> Option<NaiveDate> {
|
||||||
|
NaiveDateTime::from_timestamp_opt(timestamp, 0).map(|date_time: NaiveDateTime| date_time.date())
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DateFilterStrategy {
|
||||||
|
On(i64),
|
||||||
|
Before(i64),
|
||||||
|
After(i64),
|
||||||
|
OnOrBefore(i64),
|
||||||
|
OnOrAfter(i64),
|
||||||
|
DateWithin { start: i64, end: i64 },
|
||||||
|
Empty,
|
||||||
|
NotEmpty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DateFilterStrategy {
|
||||||
|
fn filter(self, cell_data: &DateCellData) -> bool {
|
||||||
|
match self {
|
||||||
|
DateFilterStrategy::On(expected_timestamp) => cell_data.timestamp.is_some_and(|timestamp| {
|
||||||
|
let cell_date = naive_date_from_timestamp(timestamp);
|
||||||
|
let expected_date = naive_date_from_timestamp(expected_timestamp);
|
||||||
|
cell_date == expected_date
|
||||||
|
}),
|
||||||
|
DateFilterStrategy::Before(expected_timestamp) => {
|
||||||
|
cell_data.timestamp.is_some_and(|timestamp| {
|
||||||
|
let cell_date = naive_date_from_timestamp(timestamp);
|
||||||
|
let expected_date = naive_date_from_timestamp(expected_timestamp);
|
||||||
|
cell_date < expected_date
|
||||||
|
})
|
||||||
|
},
|
||||||
|
DateFilterStrategy::After(expected_timestamp) => {
|
||||||
|
cell_data.timestamp.is_some_and(|timestamp| {
|
||||||
|
let cell_date = naive_date_from_timestamp(timestamp);
|
||||||
|
let expected_date = naive_date_from_timestamp(expected_timestamp);
|
||||||
|
cell_date > expected_date
|
||||||
|
})
|
||||||
|
},
|
||||||
|
DateFilterStrategy::OnOrBefore(expected_timestamp) => {
|
||||||
|
cell_data.timestamp.is_some_and(|timestamp| {
|
||||||
|
let cell_date = naive_date_from_timestamp(timestamp);
|
||||||
|
let expected_date = naive_date_from_timestamp(expected_timestamp);
|
||||||
|
cell_date <= expected_date
|
||||||
|
})
|
||||||
|
},
|
||||||
|
DateFilterStrategy::OnOrAfter(expected_timestamp) => {
|
||||||
|
cell_data.timestamp.is_some_and(|timestamp| {
|
||||||
|
let cell_date = naive_date_from_timestamp(timestamp);
|
||||||
|
let expected_date = naive_date_from_timestamp(expected_timestamp);
|
||||||
|
cell_date >= expected_date
|
||||||
|
})
|
||||||
|
},
|
||||||
|
DateFilterStrategy::DateWithin { start, end } => {
|
||||||
|
cell_data.timestamp.is_some_and(|timestamp| {
|
||||||
|
let cell_date = naive_date_from_timestamp(timestamp);
|
||||||
|
let expected_start_date = naive_date_from_timestamp(start);
|
||||||
|
let expected_end_date = naive_date_from_timestamp(end);
|
||||||
|
cell_date >= expected_start_date && cell_date <= expected_end_date
|
||||||
|
})
|
||||||
|
},
|
||||||
|
DateFilterStrategy::Empty => {
|
||||||
|
cell_data.timestamp.is_none() && cell_data.end_timestamp.is_none()
|
||||||
|
},
|
||||||
|
DateFilterStrategy::NotEmpty => cell_data.timestamp.is_some(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::all)]
|
|
||||||
use crate::entities::{DateFilterConditionPB, DateFilterPB};
|
use crate::entities::{DateFilterConditionPB, DateFilterPB};
|
||||||
|
use crate::services::field::DateCellData;
|
||||||
|
|
||||||
|
fn to_cell_data(timestamp: i32) -> DateCellData {
|
||||||
|
DateCellData::new(timestamp as i64, false, false, "".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn date_filter_is_test() {
|
fn date_filter_is_test() {
|
||||||
@ -70,10 +113,11 @@ mod tests {
|
|||||||
start: None,
|
start: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (val, visible) in vec![(1668387885, true), (1647251762, false)] {
|
for (val, visible) in [(1668387885, true), (1647251762, false)] {
|
||||||
assert_eq!(filter.is_visible(val as i64), visible);
|
assert_eq!(filter.is_visible(&to_cell_data(val)).unwrap(), visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn date_filter_before_test() {
|
fn date_filter_before_test() {
|
||||||
let filter = DateFilterPB {
|
let filter = DateFilterPB {
|
||||||
@ -83,8 +127,13 @@ mod tests {
|
|||||||
end: None,
|
end: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (val, visible, msg) in vec![(1668387884, false, "1"), (1647251762, true, "2")] {
|
for (val, visible, msg) in [(1668387884, false, "1"), (1647251762, true, "2")] {
|
||||||
assert_eq!(filter.is_visible(val as i64), visible, "{}", msg);
|
assert_eq!(
|
||||||
|
filter.is_visible(&to_cell_data(val)).unwrap(),
|
||||||
|
visible,
|
||||||
|
"{}",
|
||||||
|
msg
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,8 +146,8 @@ mod tests {
|
|||||||
end: None,
|
end: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (val, visible) in vec![(1668387884, true), (1668387885, true)] {
|
for (val, visible) in [(1668387884, true), (1668387885, true)] {
|
||||||
assert_eq!(filter.is_visible(val as i64), visible);
|
assert_eq!(filter.is_visible(&to_cell_data(val)).unwrap(), visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
@ -110,8 +159,8 @@ mod tests {
|
|||||||
end: None,
|
end: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (val, visible) in vec![(1668387888, false), (1668531885, true), (0, false)] {
|
for (val, visible) in [(1668387888, false), (1668531885, true), (0, false)] {
|
||||||
assert_eq!(filter.is_visible(val as i64), visible);
|
assert_eq!(filter.is_visible(&to_cell_data(val)).unwrap(), visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,12 +173,12 @@ mod tests {
|
|||||||
timestamp: None,
|
timestamp: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (val, visible, _msg) in vec![
|
for (val, visible, _msg) in [
|
||||||
(1668272685, true, "11/13"),
|
(1668272685, true, "11/13"),
|
||||||
(1668359085, true, "11/14"),
|
(1668359085, true, "11/14"),
|
||||||
(1668704685, false, "11/18"),
|
(1668704685, false, "11/18"),
|
||||||
] {
|
] {
|
||||||
assert_eq!(filter.is_visible(val as i64), visible);
|
assert_eq!(filter.is_visible(&to_cell_data(val)).unwrap(), visible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +191,16 @@ mod tests {
|
|||||||
timestamp: None,
|
timestamp: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (val, visible) in vec![(None, true), (Some(123), false)] {
|
for (val, visible) in [(None, true), (Some(123), false)] {
|
||||||
assert_eq!(filter.is_visible(val), visible);
|
assert_eq!(
|
||||||
|
filter
|
||||||
|
.is_visible(&DateCellData {
|
||||||
|
timestamp: val,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
visible
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@ use crate::services::field::{
|
|||||||
};
|
};
|
||||||
use crate::services::sort::SortCondition;
|
use crate::services::sort::SortCondition;
|
||||||
|
|
||||||
/// The [DateTypeOption] is used by [FieldType::Date], [FieldType::LastEditedTime], and [FieldType::CreatedTime].
|
|
||||||
/// So, storing the field type is necessary to distinguish the field type.
|
|
||||||
/// Most of the cases, each [FieldType] has its own [TypeOption] implementation.
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||||
pub struct DateTypeOption {
|
pub struct DateTypeOption {
|
||||||
pub date_format: DateFormat,
|
pub date_format: DateFormat,
|
||||||
@ -351,8 +348,7 @@ impl TypeOptionCellDataFilter for DateTypeOption {
|
|||||||
if !field_type.is_date() {
|
if !field_type.is_date() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
filter.is_visible(cell_data).unwrap_or(true)
|
||||||
filter.is_visible(cell_data.timestamp)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,32 +5,62 @@ use rust_decimal::Decimal;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
impl NumberFilterPB {
|
impl NumberFilterPB {
|
||||||
pub fn is_visible(&self, num_cell_data: &NumberCellFormat) -> bool {
|
pub fn is_visible(&self, cell_data: &NumberCellFormat) -> Option<bool> {
|
||||||
if self.content.is_empty() {
|
let expected_decimal = Decimal::from_str(&self.content).unwrap_or_else(|_| Decimal::zero());
|
||||||
match self.condition {
|
|
||||||
NumberFilterConditionPB::NumberIsEmpty => {
|
let strategy = match self.condition {
|
||||||
return num_cell_data.is_empty();
|
NumberFilterConditionPB::Equal => NumberFilterStrategy::Equal(expected_decimal),
|
||||||
},
|
NumberFilterConditionPB::NotEqual => NumberFilterStrategy::NotEqual(expected_decimal),
|
||||||
NumberFilterConditionPB::NumberIsNotEmpty => {
|
NumberFilterConditionPB::GreaterThan => NumberFilterStrategy::GreaterThan(expected_decimal),
|
||||||
return !num_cell_data.is_empty();
|
NumberFilterConditionPB::LessThan => NumberFilterStrategy::LessThan(expected_decimal),
|
||||||
},
|
NumberFilterConditionPB::GreaterThanOrEqualTo => {
|
||||||
_ => {},
|
NumberFilterStrategy::GreaterThanOrEqualTo(expected_decimal)
|
||||||
}
|
|
||||||
}
|
|
||||||
match num_cell_data.decimal().as_ref() {
|
|
||||||
None => false,
|
|
||||||
Some(cell_decimal) => {
|
|
||||||
let decimal = Decimal::from_str(&self.content).unwrap_or_else(|_| Decimal::zero());
|
|
||||||
match self.condition {
|
|
||||||
NumberFilterConditionPB::Equal => cell_decimal == &decimal,
|
|
||||||
NumberFilterConditionPB::NotEqual => cell_decimal != &decimal,
|
|
||||||
NumberFilterConditionPB::GreaterThan => cell_decimal > &decimal,
|
|
||||||
NumberFilterConditionPB::LessThan => cell_decimal < &decimal,
|
|
||||||
NumberFilterConditionPB::GreaterThanOrEqualTo => cell_decimal >= &decimal,
|
|
||||||
NumberFilterConditionPB::LessThanOrEqualTo => cell_decimal <= &decimal,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
NumberFilterConditionPB::LessThanOrEqualTo => {
|
||||||
|
NumberFilterStrategy::LessThanOrEqualTo(expected_decimal)
|
||||||
|
},
|
||||||
|
NumberFilterConditionPB::NumberIsEmpty => NumberFilterStrategy::Empty,
|
||||||
|
NumberFilterConditionPB::NumberIsNotEmpty => NumberFilterStrategy::NotEmpty,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(strategy.filter(cell_data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NumberFilterStrategy {
|
||||||
|
Equal(Decimal),
|
||||||
|
NotEqual(Decimal),
|
||||||
|
GreaterThan(Decimal),
|
||||||
|
LessThan(Decimal),
|
||||||
|
GreaterThanOrEqualTo(Decimal),
|
||||||
|
LessThanOrEqualTo(Decimal),
|
||||||
|
Empty,
|
||||||
|
NotEmpty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NumberFilterStrategy {
|
||||||
|
fn filter(self, cell_data: &NumberCellFormat) -> bool {
|
||||||
|
match self {
|
||||||
|
NumberFilterStrategy::Equal(expected_value) => cell_data
|
||||||
|
.decimal()
|
||||||
|
.is_some_and(|decimal| decimal == expected_value),
|
||||||
|
NumberFilterStrategy::NotEqual(expected_value) => cell_data
|
||||||
|
.decimal()
|
||||||
|
.is_some_and(|decimal| decimal != expected_value),
|
||||||
|
NumberFilterStrategy::GreaterThan(expected_value) => cell_data
|
||||||
|
.decimal()
|
||||||
|
.is_some_and(|decimal| decimal > expected_value),
|
||||||
|
NumberFilterStrategy::LessThan(expected_value) => cell_data
|
||||||
|
.decimal()
|
||||||
|
.is_some_and(|decimal| decimal < expected_value),
|
||||||
|
NumberFilterStrategy::GreaterThanOrEqualTo(expected_value) => cell_data
|
||||||
|
.decimal()
|
||||||
|
.is_some_and(|decimal| decimal >= expected_value),
|
||||||
|
NumberFilterStrategy::LessThanOrEqualTo(expected_value) => cell_data
|
||||||
|
.decimal()
|
||||||
|
.is_some_and(|decimal| decimal <= expected_value),
|
||||||
|
NumberFilterStrategy::Empty => cell_data.is_empty(),
|
||||||
|
NumberFilterStrategy::NotEmpty => !cell_data.is_empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,6 +69,7 @@ impl NumberFilterPB {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::entities::{NumberFilterConditionPB, NumberFilterPB};
|
use crate::entities::{NumberFilterConditionPB, NumberFilterPB};
|
||||||
use crate::services::field::{NumberCellFormat, NumberFormat};
|
use crate::services::field::{NumberCellFormat, NumberFormat};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn number_filter_equal_test() {
|
fn number_filter_equal_test() {
|
||||||
let number_filter = NumberFilterPB {
|
let number_filter = NumberFilterPB {
|
||||||
@ -48,15 +79,16 @@ mod tests {
|
|||||||
|
|
||||||
for (num_str, visible) in [("123", true), ("1234", false), ("", false)] {
|
for (num_str, visible) in [("123", true), ("1234", false), ("", false)] {
|
||||||
let data = NumberCellFormat::from_format_str(num_str, &NumberFormat::Num).unwrap_or_default();
|
let data = NumberCellFormat::from_format_str(num_str, &NumberFormat::Num).unwrap_or_default();
|
||||||
assert_eq!(number_filter.is_visible(&data), visible);
|
assert_eq!(number_filter.is_visible(&data), Some(visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
let format = NumberFormat::USD;
|
let format = NumberFormat::USD;
|
||||||
for (num_str, visible) in [("$123", true), ("1234", false), ("", false)] {
|
for (num_str, visible) in [("$123", true), ("1234", false), ("", false)] {
|
||||||
let data = NumberCellFormat::from_format_str(num_str, &format).unwrap();
|
let data = NumberCellFormat::from_format_str(num_str, &format).unwrap();
|
||||||
assert_eq!(number_filter.is_visible(&data), visible);
|
assert_eq!(number_filter.is_visible(&data), Some(visible));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn number_filter_greater_than_test() {
|
fn number_filter_greater_than_test() {
|
||||||
let number_filter = NumberFilterPB {
|
let number_filter = NumberFilterPB {
|
||||||
@ -65,7 +97,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
for (num_str, visible) in [("123", true), ("10", false), ("30", true), ("", false)] {
|
for (num_str, visible) in [("123", true), ("10", false), ("30", true), ("", false)] {
|
||||||
let data = NumberCellFormat::from_format_str(num_str, &NumberFormat::Num).unwrap_or_default();
|
let data = NumberCellFormat::from_format_str(num_str, &NumberFormat::Num).unwrap_or_default();
|
||||||
assert_eq!(number_filter.is_visible(&data), visible);
|
assert_eq!(number_filter.is_visible(&data), Some(visible));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +109,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
for (num_str, visible) in [("12", true), ("1234", false), ("30", true), ("", false)] {
|
for (num_str, visible) in [("12", true), ("1234", false), ("30", true), ("", false)] {
|
||||||
let data = NumberCellFormat::from_format_str(num_str, &NumberFormat::Num).unwrap_or_default();
|
let data = NumberCellFormat::from_format_str(num_str, &NumberFormat::Num).unwrap_or_default();
|
||||||
assert_eq!(number_filter.is_visible(&data), visible);
|
assert_eq!(number_filter.is_visible(&data), Some(visible));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,10 +120,7 @@ impl NumberTypeOption {
|
|||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn format_cell_data(
|
fn format_cell_data(&self, num_cell_data: &NumberCellData) -> FlowyResult<NumberCellFormat> {
|
||||||
&self,
|
|
||||||
num_cell_data: &NumberCellData,
|
|
||||||
) -> FlowyResult<NumberCellFormat> {
|
|
||||||
match self.format {
|
match self.format {
|
||||||
NumberFormat::Num => {
|
NumberFormat::Num => {
|
||||||
if SCIENTIFIC_NOTATION_REGEX
|
if SCIENTIFIC_NOTATION_REGEX
|
||||||
@ -252,7 +249,7 @@ impl TypeOptionCellDataFilter for NumberTypeOption {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
match self.format_cell_data(cell_data) {
|
match self.format_cell_data(cell_data) {
|
||||||
Ok(cell_data) => filter.is_visible(&cell_data),
|
Ok(cell_data) => filter.is_visible(&cell_data).unwrap_or(true),
|
||||||
Err(_) => true,
|
Err(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,15 +174,14 @@ impl CellDataChangeset for TimestampTypeOption {
|
|||||||
impl TypeOptionCellDataFilter for TimestampTypeOption {
|
impl TypeOptionCellDataFilter for TimestampTypeOption {
|
||||||
fn apply_filter(
|
fn apply_filter(
|
||||||
&self,
|
&self,
|
||||||
filter: &<Self as TypeOption>::CellFilter,
|
_filter: &<Self as TypeOption>::CellFilter,
|
||||||
field_type: &FieldType,
|
field_type: &FieldType,
|
||||||
cell_data: &<Self as TypeOption>::CellData,
|
_cell_data: &<Self as TypeOption>::CellData,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if !field_type.is_last_edited_time() && !field_type.is_created_time() {
|
if !field_type.is_last_edited_time() && !field_type.is_created_time() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
false
|
||||||
filter.is_visible(cell_data.timestamp)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user