refactor: type option impl trait

This commit is contained in:
nathan
2022-12-12 17:36:36 +08:00
parent e141e7ee63
commit 9ba17e004e
37 changed files with 268 additions and 226 deletions

View File

@ -1,10 +1,10 @@
use crate::entities::parser::NotEmptyStr; use crate::entities::parser::NotEmptyStr;
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::sort::SortType; use crate::services::sort::SortType;
use bytes::Bytes;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use grid_rev_model::{FieldRevision, FieldTypeRevision}; use grid_rev_model::FieldTypeRevision;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridSortPB { pub struct GridSortPB {

View File

@ -411,14 +411,14 @@ pub(crate) async fn get_select_option_handler(
// //
let cell_rev = editor.get_cell_rev(&params.row_id, &params.field_id).await?; let cell_rev = editor.get_cell_rev(&params.row_id, &params.field_id).await?;
let type_option = select_type_option_from_field_rev(&field_rev)?; let type_option = select_type_option_from_field_rev(&field_rev)?;
let any_cell_data: TypeCellData = match cell_rev { let type_cell_data: TypeCellData = match cell_rev {
None => TypeCellData { None => TypeCellData {
data: "".to_string(), data: "".to_string(),
field_type: field_rev.ty.into(), field_type: field_rev.ty.into(),
}, },
Some(cell_rev) => cell_rev.try_into()?, Some(cell_rev) => cell_rev.try_into()?,
}; };
let selected_options = type_option.get_selected_options(any_cell_data.into()); let selected_options = type_option.get_selected_options(type_cell_data.into());
data_result(selected_options) data_result(selected_options)
} }
} }

View File

@ -7,19 +7,25 @@ use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use grid_rev_model::{CellRevision, FieldRevision, FieldTypeRevision}; use grid_rev_model::{CellRevision, FieldRevision, FieldTypeRevision};
/// This trait is used when doing filter/search on the grid. /// This trait is used when doing filter/search on the grid.
pub trait CellFilterOperation<T> { pub trait CellFilterable<T> {
/// Return true if any_cell_data match the filter condition. /// Return true if type_cell_data match the filter condition.
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &T) -> FlowyResult<bool>; fn apply_filter(&self, type_cell_data: TypeCellData, filter: &T) -> FlowyResult<bool>;
} }
pub trait CellGroupOperation { pub trait CellComparable {
fn apply_group(&self, any_cell_data: TypeCellData, group_content: &str) -> FlowyResult<bool>; fn apply_cmp(&self, type_cell_data: &TypeCellData, other_type_cell_data: &TypeCellData) -> FlowyResult<bool>;
} }
/// Return object that describes the cell. /// Serialize the cell data in Protobuf/String format.
pub trait CellDisplayable<CD> { ///
/// Each cell data is a opaque data, it needs to deserialized to a concrete data struct.
/// Essentially when the field type is SingleSelect/Multi-Select, the cell data contains a
/// list of option ids. So it need to be decoded including convert the option's id to
/// option's name
///
pub trait CellDataSerialize<CD> {
/// Serialize the cell data into `CellBytes` that will be posted to the `Dart` side. Using the /// Serialize the cell data into `CellBytes` that will be posted to the `Dart` side. Using the
/// corresponding protobuf struct implement in `Dart` to deserialize the data. /// corresponding protobuf struct implemented in `Dart` to deserialize the data.
/// ///
/// Using `utf8` to encode the cell data if the cell data use `String` as its data container. /// Using `utf8` to encode the cell data if the cell data use `String` as its data container.
/// Using `protobuf` to encode the cell data if the cell data use `Protobuf struct` as its data container. /// Using `protobuf` to encode the cell data if the cell data use `Protobuf struct` as its data container.
@ -43,9 +49,9 @@ pub trait CellDisplayable<CD> {
/// ///
/// returns: Result<CellBytes, FlowyError> /// returns: Result<CellBytes, FlowyError>
/// ///
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<CD>, cell_data: IntoCellData<CD>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes>; ) -> FlowyResult<CellBytes>;
@ -55,14 +61,14 @@ pub trait CellDisplayable<CD> {
/// The cell data is not readable which means it can't display the cell data directly to user. /// The cell data is not readable which means it can't display the cell data directly to user.
/// For example, /// For example,
/// 1. the cell data is timestamp if its field type is FieldType::Date that is not readable. /// 1. the cell data is timestamp if its field type is FieldType::Date that is not readable.
/// It needs to be parsed as the date string. /// So it needs to be parsed as the date string with custom format setting.
/// ///
/// 2. the cell data is a commas separated id if its field type if FieldType::MultiSelect that is not readable. /// 2. the cell data is a commas separated id if its field type if FieldType::MultiSelect that is not readable.
/// It needs to be parsed as a commas separated option name. /// So it needs to be parsed as a commas separated option name.
/// ///
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<CD>, cell_data: IntoCellData<CD>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<String>; ) -> FlowyResult<String>;
@ -76,7 +82,10 @@ pub trait CellDataOperation<CD, CS> {
/// FieldType::URL => URLCellData /// FieldType::URL => URLCellData
/// FieldType::Date=> DateCellData /// FieldType::Date=> DateCellData
/// ///
/// Each cell data is a opaque data, it needs to deserialized to a concrete data struct /// Each cell data is a opaque data, it needs to deserialized to a concrete data struct.
/// Essentially when the field type is SingleSelect/Multi-Select, the cell data contains a
/// list of option ids. So it need to be decoded including convert the option's id to
/// option's name
/// ///
/// `cell_data`: the opaque data of the cell. /// `cell_data`: the opaque data of the cell.
/// `decoded_field_type`: the field type of the cell data when doing serialization /// `decoded_field_type`: the field type of the cell data when doing serialization
@ -86,7 +95,7 @@ pub trait CellDataOperation<CD, CS> {
/// ///
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<CD>, cell_data: IntoCellData<CD>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes>; ) -> FlowyResult<CellBytes>;
@ -130,14 +139,14 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
Ok(TypeCellData::new(s, field_type).to_json()) Ok(TypeCellData::new(s, field_type).to_json())
} }
pub fn decode_any_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debug>( pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debug>(
data: T, data: T,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> (FieldType, CellBytes) { ) -> (FieldType, CellBytes) {
let to_field_type = field_rev.ty.into(); let to_field_type = field_rev.ty.into();
match data.try_into() { match data.try_into() {
Ok(any_cell_data) => { Ok(type_cell_data) => {
let TypeCellData { data, field_type } = any_cell_data; let TypeCellData { data, field_type } = type_cell_data;
match try_decode_cell_data(data.into(), &field_type, &to_field_type, field_rev) { match try_decode_cell_data(data.into(), &field_type, &to_field_type, field_rev) {
Ok(cell_bytes) => (field_type, cell_bytes), Ok(cell_bytes) => (field_type, cell_bytes),
Err(e) => { Err(e) => {
@ -156,40 +165,40 @@ pub fn decode_any_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debug
} }
} }
pub fn decode_cell_data_to_string( pub fn decode_cell_data_to_string<C: Into<IntoCellData<String>>>(
cell_data: CellData<String>, cell_data: C,
from_field_type: &FieldType, from_field_type: &FieldType,
to_field_type: &FieldType, to_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {
let cell_data = cell_data.try_into_inner()?; let cell_data = cell_data.into().try_into_inner()?;
let get_cell_display_str = || { let get_cell_display_str = || {
let field_type: FieldTypeRevision = to_field_type.into(); let field_type: FieldTypeRevision = to_field_type.into();
let result = match to_field_type { let result = match to_field_type {
FieldType::RichText => field_rev FieldType::RichText => field_rev
.get_type_option::<RichTextTypeOptionPB>(field_type)? .get_type_option::<RichTextTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::Number => field_rev FieldType::Number => field_rev
.get_type_option::<NumberTypeOptionPB>(field_type)? .get_type_option::<NumberTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::DateTime => field_rev FieldType::DateTime => field_rev
.get_type_option::<DateTypeOptionPB>(field_type)? .get_type_option::<DateTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::SingleSelect => field_rev FieldType::SingleSelect => field_rev
.get_type_option::<SingleSelectTypeOptionPB>(field_type)? .get_type_option::<SingleSelectTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::MultiSelect => field_rev FieldType::MultiSelect => field_rev
.get_type_option::<MultiSelectTypeOptionPB>(field_type)? .get_type_option::<MultiSelectTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::Checklist => field_rev FieldType::Checklist => field_rev
.get_type_option::<ChecklistTypeOptionPB>(field_type)? .get_type_option::<ChecklistTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::Checkbox => field_rev FieldType::Checkbox => field_rev
.get_type_option::<CheckboxTypeOptionPB>(field_type)? .get_type_option::<CheckboxTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
FieldType::URL => field_rev FieldType::URL => field_rev
.get_type_option::<URLTypeOptionPB>(field_type)? .get_type_option::<URLTypeOptionPB>(field_type)?
.displayed_cell_string(cell_data.into(), from_field_type, field_rev), .serialize_cell_data_to_str(cell_data.into(), from_field_type, field_rev),
}; };
Some(result) Some(result)
}; };
@ -210,7 +219,7 @@ pub fn decode_cell_data_to_string(
/// and `CellDataOperation` traits. /// and `CellDataOperation` traits.
/// ///
pub fn try_decode_cell_data( pub fn try_decode_cell_data(
cell_data: CellData<String>, cell_data: IntoCellData<String>,
from_field_type: &FieldType, from_field_type: &FieldType,
to_field_type: &FieldType, to_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
@ -312,9 +321,10 @@ pub trait FromCellString {
Self: Sized; Self: Sized;
} }
/// CellData is a helper struct. String will be parser into Option<T> only if the T impl the FromCellString trait. /// IntoCellData is a helper struct. String will be parser into Option<T> only if the T impl the FromCellString trait.
pub struct CellData<T>(pub Option<T>); ///
impl<T> CellData<T> { pub struct IntoCellData<T>(pub Option<T>);
impl<T> IntoCellData<T> {
pub fn try_into_inner(self) -> FlowyResult<T> { pub fn try_into_inner(self) -> FlowyResult<T> {
match self.0 { match self.0 {
None => Err(ErrorCode::InvalidData.into()), None => Err(ErrorCode::InvalidData.into()),
@ -323,35 +333,35 @@ impl<T> CellData<T> {
} }
} }
impl<T> std::convert::From<String> for CellData<T> impl<T> std::convert::From<String> for IntoCellData<T>
where where
T: FromCellString, T: FromCellString,
{ {
fn from(s: String) -> Self { fn from(s: String) -> Self {
match T::from_cell_str(&s) { match T::from_cell_str(&s) {
Ok(inner) => CellData(Some(inner)), Ok(inner) => IntoCellData(Some(inner)),
Err(e) => { Err(e) => {
tracing::error!("Deserialize Cell Data failed: {}", e); tracing::error!("Deserialize Cell Data failed: {}", e);
CellData(None) IntoCellData(None)
} }
} }
} }
} }
impl std::convert::From<usize> for CellData<String> { impl std::convert::From<usize> for IntoCellData<String> {
fn from(n: usize) -> Self { fn from(n: usize) -> Self {
CellData(Some(n.to_string())) IntoCellData(Some(n.to_string()))
} }
} }
impl<T> std::convert::From<T> for CellData<T> { impl<T> std::convert::From<T> for IntoCellData<T> {
fn from(val: T) -> Self { fn from(val: T) -> Self {
CellData(Some(val)) IntoCellData(Some(val))
} }
} }
impl std::convert::From<CellData<String>> for String { impl std::convert::From<IntoCellData<String>> for String {
fn from(p: CellData<String>) -> Self { fn from(p: IntoCellData<String>) -> Self {
p.try_into_inner().unwrap_or_else(|_| String::new()) p.try_into_inner().unwrap_or_else(|_| String::new())
} }
} }

View File

@ -1,5 +1,5 @@
mod any_cell_data;
mod cell_operation; mod cell_operation;
mod type_cell_data;
pub use any_cell_data::*;
pub use cell_operation::*; pub use cell_operation::*;
pub use type_cell_data::*;

View File

@ -1,13 +1,13 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellData, FromCellString}; use crate::services::cell::{FromCellString, IntoCellData};
use bytes::Bytes; use bytes::Bytes;
use flowy_error::{internal_error, FlowyError, FlowyResult}; use flowy_error::{internal_error, FlowyError, FlowyResult};
use grid_rev_model::CellRevision; use grid_rev_model::CellRevision;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
/// TypeCellData is a generic CellData, you can parse the cell_data according to the field_type. /// TypeCellData is a generic CellData, you can parse the type_cell_data according to the field_type.
/// When the type of field is changed, it's different from the field_type of AnyCellData. /// When the type of field is changed, it's different from the field_type of TypeCellData.
/// So it will return an empty data. You could check the CellDataOperation trait for more information. /// So it will return an empty data. You could check the CellDataOperation trait for more information.
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct TypeCellData { pub struct TypeCellData {
@ -60,12 +60,12 @@ impl std::convert::TryFrom<CellRevision> for TypeCellData {
} }
} }
impl<T> std::convert::From<TypeCellData> for CellData<T> impl<T> std::convert::From<TypeCellData> for IntoCellData<T>
where where
T: FromCellString, T: FromCellString,
{ {
fn from(any_call_data: TypeCellData) -> Self { fn from(any_call_data: TypeCellData) -> Self {
CellData::from(any_call_data.data) IntoCellData::from(any_call_data.data)
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::{CheckboxFilterConditionPB, CheckboxFilterPB}; use crate::entities::{CheckboxFilterConditionPB, CheckboxFilterPB};
use crate::services::cell::{CellData, CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, IntoCellData, TypeCellData};
use crate::services::field::{CheckboxCellData, CheckboxTypeOptionPB}; use crate::services::field::{CheckboxCellData, CheckboxTypeOptionPB};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -13,12 +13,12 @@ impl CheckboxFilterPB {
} }
} }
impl CellFilterOperation<CheckboxFilterPB> for CheckboxTypeOptionPB { impl CellFilterable<CheckboxFilterPB> for CheckboxTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &CheckboxFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &CheckboxFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_checkbox() { if !type_cell_data.is_checkbox() {
return Ok(true); return Ok(true);
} }
let cell_data: CellData<CheckboxCellData> = any_cell_data.into(); let cell_data: IntoCellData<CheckboxCellData> = type_cell_data.into();
let checkbox_cell_data = cell_data.try_into_inner()?; let checkbox_cell_data = cell_data.try_into_inner()?;
Ok(filter.is_visible(&checkbox_cell_data)) Ok(filter.is_visible(&checkbox_cell_data))
} }

View File

@ -1,6 +1,6 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::{BoxTypeOptionBuilder, CheckboxCellData, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, CheckboxCellData, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
@ -42,10 +42,10 @@ pub struct CheckboxTypeOptionPB {
} }
impl_type_option!(CheckboxTypeOptionPB, FieldType::Checkbox); impl_type_option!(CheckboxTypeOptionPB, FieldType::Checkbox);
impl CellDisplayable<CheckboxCellData> for CheckboxTypeOptionPB { impl CellDataSerialize<CheckboxCellData> for CheckboxTypeOptionPB {
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<CheckboxCellData>, cell_data: IntoCellData<CheckboxCellData>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -53,9 +53,9 @@ impl CellDisplayable<CheckboxCellData> for CheckboxTypeOptionPB {
Ok(CellBytes::new(cell_data)) Ok(CellBytes::new(cell_data))
} }
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<CheckboxCellData>, cell_data: IntoCellData<CheckboxCellData>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {
@ -69,7 +69,7 @@ pub type CheckboxCellChangeset = String;
impl CellDataOperation<CheckboxCellData, CheckboxCellChangeset> for CheckboxTypeOptionPB { impl CellDataOperation<CheckboxCellData, CheckboxCellChangeset> for CheckboxTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<CheckboxCellData>, cell_data: IntoCellData<CheckboxCellData>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -77,7 +77,7 @@ impl CellDataOperation<CheckboxCellData, CheckboxCellChangeset> for CheckboxType
return Ok(CellBytes::default()); return Ok(CellBytes::default());
} }
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -73,7 +73,7 @@ impl CellBytesParser for CheckboxCellDataParser {
type Object = CheckboxCellData; type Object = CheckboxCellData;
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> { fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
match String::from_utf8(bytes.to_vec()) { match String::from_utf8(bytes.to_vec()) {
Ok(s) => CheckboxCellData::from_str(&s), Ok(s) => CheckboxCellData::from_cell_str(&s),
Err(_) => Ok(CheckboxCellData("".to_string())), Err(_) => Ok(CheckboxCellData("".to_string())),
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::{DateFilterConditionPB, DateFilterPB}; use crate::entities::{DateFilterConditionPB, DateFilterPB};
use crate::services::cell::{CellData, CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, IntoCellData, TypeCellData};
use crate::services::field::{DateTimestamp, DateTypeOptionPB}; use crate::services::field::{DateTimestamp, DateTypeOptionPB};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -59,12 +59,12 @@ impl DateFilterPB {
} }
} }
impl CellFilterOperation<DateFilterPB> for DateTypeOptionPB { impl CellFilterable<DateFilterPB> for DateTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &DateFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &DateFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_date() { if !type_cell_data.is_date() {
return Ok(true); return Ok(true);
} }
let cell_data: CellData<DateTimestamp> = any_cell_data.into(); let cell_data: IntoCellData<DateTimestamp> = type_cell_data.into();
let timestamp = cell_data.try_into_inner()?; let timestamp = cell_data.try_into_inner()?;
Ok(filter.is_visible(timestamp)) Ok(filter.is_visible(timestamp))
} }

View File

@ -1,6 +1,6 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::{ use crate::services::field::{
BoxTypeOptionBuilder, DateCellChangeset, DateCellDataPB, DateFormat, DateTimestamp, TimeFormat, TypeOptionBuilder, BoxTypeOptionBuilder, DateCellChangeset, DateCellDataPB, DateFormat, DateTimestamp, TimeFormat, TypeOptionBuilder,
}; };
@ -107,21 +107,21 @@ impl DateTypeOptionPB {
} }
} }
impl CellDisplayable<DateTimestamp> for DateTypeOptionPB { impl CellDataSerialize<DateTimestamp> for DateTypeOptionPB {
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<DateTimestamp>, cell_data: IntoCellData<DateTimestamp>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
let timestamp = cell_data.try_into_inner()?; let timestamp = cell_data.try_into_inner()?;
let date_cell_data = self.today_desc_from_timestamp(timestamp); let cell_data_pb = self.today_desc_from_timestamp(timestamp);
CellBytes::from(date_cell_data) CellBytes::from(cell_data_pb)
} }
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<DateTimestamp>, cell_data: IntoCellData<DateTimestamp>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {
@ -134,7 +134,7 @@ impl CellDisplayable<DateTimestamp> for DateTypeOptionPB {
impl CellDataOperation<DateTimestamp, DateCellChangeset> for DateTypeOptionPB { impl CellDataOperation<DateTimestamp, DateCellChangeset> for DateTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<DateTimestamp>, cell_data: IntoCellData<DateTimestamp>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -145,7 +145,7 @@ impl CellDataOperation<DateTimestamp, DateCellChangeset> for DateTypeOptionPB {
if !decoded_field_type.is_date() { if !decoded_field_type.is_date() {
return Ok(CellBytes::default()); return Ok(CellBytes::default());
} }
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -1,5 +1,5 @@
use crate::entities::{NumberFilterConditionPB, NumberFilterPB}; use crate::entities::{NumberFilterConditionPB, NumberFilterPB};
use crate::services::cell::{CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, TypeCellData};
use crate::services::field::{NumberCellData, NumberTypeOptionPB}; use crate::services::field::{NumberCellData, NumberTypeOptionPB};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
use rust_decimal::prelude::Zero; use rust_decimal::prelude::Zero;
@ -37,13 +37,13 @@ impl NumberFilterPB {
} }
} }
impl CellFilterOperation<NumberFilterPB> for NumberTypeOptionPB { impl CellFilterable<NumberFilterPB> for NumberTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &NumberFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &NumberFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_number() { if !type_cell_data.is_number() {
return Ok(true); return Ok(true);
} }
let cell_data = any_cell_data.data; let cell_data = type_cell_data.data;
let num_cell_data = self.format_cell_data(&cell_data)?; let num_cell_data = self.format_cell_data(&cell_data)?;
Ok(filter.is_visible(&num_cell_data)) Ok(filter.is_visible(&num_cell_data))

View File

@ -1,15 +1,13 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::type_options::number_type_option::format::*; use crate::services::field::type_options::number_type_option::format::*;
use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, NumberCellData, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer}; use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
use rust_decimal::Decimal; use rust_decimal::Decimal;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
@ -105,10 +103,10 @@ pub(crate) fn strip_currency_symbol<T: ToString>(s: T) -> String {
s s
} }
impl CellDisplayable<String> for NumberTypeOptionPB { impl CellDataSerialize<String> for NumberTypeOptionPB {
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<String>, cell_data: IntoCellData<String>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -119,9 +117,9 @@ impl CellDisplayable<String> for NumberTypeOptionPB {
} }
} }
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<String>, cell_data: IntoCellData<String>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {
@ -135,7 +133,7 @@ pub type NumberCellChangeset = String;
impl CellDataOperation<String, NumberCellChangeset> for NumberTypeOptionPB { impl CellDataOperation<String, NumberCellChangeset> for NumberTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<String>, cell_data: IntoCellData<String>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -143,7 +141,7 @@ impl CellDataOperation<String, NumberCellChangeset> for NumberTypeOptionPB {
return Ok(CellBytes::default()); return Ok(CellBytes::default());
} }
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -99,6 +99,7 @@ impl CellDataIsEmpty for NumberCellData {
self.decimal.is_none() self.decimal.is_none()
} }
} }
pub struct NumberCellDataParser(); pub struct NumberCellDataParser();
impl CellBytesParser for NumberCellDataParser { impl CellBytesParser for NumberCellDataParser {
type Object = NumberCellData; type Object = NumberCellData;

View File

@ -1,6 +1,6 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer; use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
use crate::services::field::type_options::util::get_cell_data; use crate::services::field::type_options::util::get_cell_data;
use crate::services::field::{ use crate::services::field::{
@ -41,11 +41,11 @@ impl SelectTypeOptionSharedAction for ChecklistTypeOptionPB {
impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for ChecklistTypeOptionPB { impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for ChecklistTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -1,6 +1,6 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer; use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
use crate::services::field::type_options::util::get_cell_data; use crate::services::field::type_options::util::get_cell_data;
use crate::services::field::{ use crate::services::field::{
@ -41,11 +41,11 @@ impl SelectTypeOptionSharedAction for MultiSelectTypeOptionPB {
impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSelectTypeOptionPB { impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSelectTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -1,7 +1,7 @@
#![allow(clippy::needless_collect)] #![allow(clippy::needless_collect)]
use crate::entities::{ChecklistFilterPB, FieldType, SelectOptionConditionPB, SelectOptionFilterPB}; use crate::entities::{ChecklistFilterPB, FieldType, SelectOptionConditionPB, SelectOptionFilterPB};
use crate::services::cell::{CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, TypeCellData};
use crate::services::field::{ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use crate::services::field::{ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
use crate::services::field::{SelectTypeOptionSharedAction, SelectedSelectOptions}; use crate::services::field::{SelectTypeOptionSharedAction, SelectedSelectOptions};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -78,33 +78,33 @@ impl SelectOptionFilterPB {
} }
} }
impl CellFilterOperation<SelectOptionFilterPB> for MultiSelectTypeOptionPB { impl CellFilterable<SelectOptionFilterPB> for MultiSelectTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &SelectOptionFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &SelectOptionFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_multi_select() { if !type_cell_data.is_multi_select() {
return Ok(true); return Ok(true);
} }
let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into())); let selected_options = SelectedSelectOptions::from(self.get_selected_options(type_cell_data.into()));
Ok(filter.is_visible(&selected_options, FieldType::MultiSelect)) Ok(filter.is_visible(&selected_options, FieldType::MultiSelect))
} }
} }
impl CellFilterOperation<SelectOptionFilterPB> for SingleSelectTypeOptionPB { impl CellFilterable<SelectOptionFilterPB> for SingleSelectTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &SelectOptionFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &SelectOptionFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_single_select() { if !type_cell_data.is_single_select() {
return Ok(true); return Ok(true);
} }
let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into())); let selected_options = SelectedSelectOptions::from(self.get_selected_options(type_cell_data.into()));
Ok(filter.is_visible(&selected_options, FieldType::SingleSelect)) Ok(filter.is_visible(&selected_options, FieldType::SingleSelect))
} }
} }
impl CellFilterOperation<ChecklistFilterPB> for ChecklistTypeOptionPB { impl CellFilterable<ChecklistFilterPB> for ChecklistTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &ChecklistFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &ChecklistFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_checklist() { if !type_cell_data.is_checklist() {
return Ok(true); return Ok(true);
} }
let selected_options = SelectedSelectOptions::from(self.get_selected_options(any_cell_data.into())); let selected_options = SelectedSelectOptions::from(self.get_selected_options(type_cell_data.into()));
Ok(filter.is_visible(&self.options, &selected_options)) Ok(filter.is_visible(&self.options, &selected_options))
} }
} }

View File

@ -1,7 +1,7 @@
use crate::entities::parser::NotEmptyStr; use crate::entities::parser::NotEmptyStr;
use crate::entities::{CellChangesetPB, CellPathPB, CellPathParams, FieldType}; use crate::entities::{CellChangesetPB, CellPathPB, CellPathParams, FieldType};
use crate::services::cell::{ use crate::services::cell::{
CellBytes, CellBytesParser, CellData, CellDataIsEmpty, CellDisplayable, FromCellChangeset, FromCellString, CellBytes, CellBytesParser, CellDataIsEmpty, CellDataSerialize, FromCellChangeset, FromCellString, IntoCellData,
}; };
use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer; use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
use crate::services::field::{ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use crate::services::field::{ChecklistTypeOptionPB, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
@ -69,7 +69,10 @@ impl std::default::Default for SelectOptionColorPB {
} }
} }
pub fn make_selected_options(cell_data: CellData<SelectOptionIds>, options: &[SelectOptionPB]) -> Vec<SelectOptionPB> { pub fn make_selected_options(
cell_data: IntoCellData<SelectOptionIds>,
options: &[SelectOptionPB],
) -> Vec<SelectOptionPB> {
if let Ok(ids) = cell_data.try_into_inner() { if let Ok(ids) = cell_data.try_into_inner() {
ids.iter() ids.iter()
.flat_map(|option_id| options.iter().find(|option| &option.id == option_id).cloned()) .flat_map(|option_id| options.iter().find(|option| &option.id == option_id).cloned())
@ -110,7 +113,7 @@ pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
} }
/// Return a list of options that are selected by user /// Return a list of options that are selected by user
fn get_selected_options(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellDataPB { fn get_selected_options(&self, cell_data: IntoCellData<SelectOptionIds>) -> SelectOptionCellDataPB {
let mut select_options = make_selected_options(cell_data, self.options()); let mut select_options = make_selected_options(cell_data, self.options());
match self.number_of_max_options() { match self.number_of_max_options() {
None => {} None => {}
@ -126,7 +129,7 @@ pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
fn transform_cell_data( fn transform_cell_data(
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -150,7 +153,9 @@ pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
}) })
}); });
return CellBytes::from(self.get_selected_options(CellData(Some(SelectOptionIds(transformed_ids))))); return CellBytes::from(
self.get_selected_options(IntoCellData(Some(SelectOptionIds(transformed_ids)))),
);
} }
_ => { _ => {
return Ok(CellBytes::default()); return Ok(CellBytes::default());
@ -165,13 +170,13 @@ pub trait SelectTypeOptionSharedAction: TypeOptionDataSerializer + Send + Sync {
fn mut_options(&mut self) -> &mut Vec<SelectOptionPB>; fn mut_options(&mut self) -> &mut Vec<SelectOptionPB>;
} }
impl<T> CellDisplayable<SelectOptionIds> for T impl<T> CellDataSerialize<SelectOptionIds> for T
where where
T: SelectTypeOptionSharedAction, T: SelectTypeOptionSharedAction,
{ {
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -183,9 +188,9 @@ where
) )
} }
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {

View File

@ -1,6 +1,6 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer; use crate::services::field::selection_type_option::type_option_transform::SelectOptionTypeOptionTransformer;
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use crate::services::field::{ use crate::services::field::{
@ -40,11 +40,11 @@ impl SelectTypeOptionSharedAction for SingleSelectTypeOptionPB {
impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSelectTypeOptionPB { impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSelectTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -1,5 +1,5 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellBytes, CellData}; use crate::services::cell::{CellBytes, IntoCellData};
use crate::services::field::{ use crate::services::field::{
MultiSelectTypeOptionPB, SelectOptionColorPB, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction, MultiSelectTypeOptionPB, SelectOptionColorPB, SelectOptionIds, SelectOptionPB, SelectTypeOptionSharedAction,
SingleSelectTypeOptionPB, CHECK, UNCHECK, SingleSelectTypeOptionPB, CHECK, UNCHECK,
@ -57,7 +57,7 @@ impl SelectOptionTypeOptionTransformer {
pub fn transform_type_option_cell_data<T>( pub fn transform_type_option_cell_data<T>(
shared: &T, shared: &T,
cell_data: CellData<SelectOptionIds>, cell_data: IntoCellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> ) -> FlowyResult<CellBytes>
@ -78,7 +78,7 @@ impl SelectOptionTypeOptionTransformer {
transformed_ids.push(option.id.clone()); transformed_ids.push(option.id.clone());
} }
}); });
let transformed_cell_data = CellData::from(SelectOptionIds::from(transformed_ids)); let transformed_cell_data = IntoCellData::from(SelectOptionIds::from(transformed_ids));
CellBytes::from(shared.get_selected_options(transformed_cell_data)) CellBytes::from(shared.get_selected_options(transformed_cell_data))
} }
_ => Ok(CellBytes::default()), _ => Ok(CellBytes::default()),

View File

@ -1,5 +1,5 @@
use crate::entities::{TextFilterConditionPB, TextFilterPB}; use crate::entities::{TextFilterConditionPB, TextFilterPB};
use crate::services::cell::{CellData, CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, IntoCellData, TypeCellData};
use crate::services::field::{RichTextTypeOptionPB, TextCellData}; use crate::services::field::{RichTextTypeOptionPB, TextCellData};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
@ -20,13 +20,13 @@ impl TextFilterPB {
} }
} }
impl CellFilterOperation<TextFilterPB> for RichTextTypeOptionPB { impl CellFilterable<TextFilterPB> for RichTextTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &TextFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &TextFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_text() { if !type_cell_data.is_text() {
return Ok(false); return Ok(false);
} }
let cell_data: CellData<TextCellData> = any_cell_data.into(); let cell_data: IntoCellData<TextCellData> = type_cell_data.into();
let text_cell_data = cell_data.try_into_inner()?; let text_cell_data = cell_data.try_into_inner()?;
Ok(filter.is_visible(text_cell_data)) Ok(filter.is_visible(text_cell_data))
} }

View File

@ -1,8 +1,8 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{ use crate::services::cell::{
decode_cell_data_to_string, AnyCellChangeset, CellBytes, CellBytesParser, CellData, CellDataIsEmpty, decode_cell_data_to_string, AnyCellChangeset, CellBytes, CellBytesParser, CellDataIsEmpty, CellDataOperation,
CellDataOperation, CellDisplayable, FromCellString, CellDataSerialize, FromCellString, IntoCellData,
}; };
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
@ -39,32 +39,32 @@ pub struct RichTextTypeOptionPB {
} }
impl_type_option!(RichTextTypeOptionPB, FieldType::RichText); impl_type_option!(RichTextTypeOptionPB, FieldType::RichText);
impl CellDisplayable<String> for RichTextTypeOptionPB { impl CellDataSerialize<RichTextCellData> for RichTextTypeOptionPB {
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<String>, cell_data: IntoCellData<RichTextCellData>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
let cell_str: String = cell_data.try_into_inner()?; let cell_str: RichTextCellData = cell_data.try_into_inner()?;
Ok(CellBytes::new(cell_str)) Ok(CellBytes::new(cell_str))
} }
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<String>, cell_data: IntoCellData<RichTextCellData>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {
let cell_str: String = cell_data.try_into_inner()?; let cell_str: RichTextCellData = cell_data.try_into_inner()?;
Ok(cell_str) Ok(cell_str)
} }
} }
impl CellDataOperation<String, String> for RichTextTypeOptionPB { impl CellDataOperation<RichTextCellData, String> for RichTextTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<String>, cell_data: IntoCellData<RichTextCellData>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
@ -77,7 +77,7 @@ impl CellDataOperation<String, String> for RichTextTypeOptionPB {
let s = decode_cell_data_to_string(cell_data, decoded_field_type, decoded_field_type, field_rev); let s = decode_cell_data_to_string(cell_data, decoded_field_type, decoded_field_type, field_rev);
Ok(CellBytes::new(s.unwrap_or_else(|_| "".to_owned()))) Ok(CellBytes::new(s.unwrap_or_else(|_| "".to_owned())))
} else { } else {
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) self.serialize_cell_data_to_bytes(cell_data, decoded_field_type, field_rev)
} }
} }
@ -141,3 +141,5 @@ impl CellBytesParser for TextCellDataParser {
} }
} }
} }
pub type RichTextCellData = String;

View File

@ -1,15 +1,15 @@
use crate::entities::TextFilterPB; use crate::entities::TextFilterPB;
use crate::services::cell::{CellData, CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, IntoCellData, TypeCellData};
use crate::services::field::{TextCellData, URLTypeOptionPB}; use crate::services::field::{TextCellData, URLTypeOptionPB};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
impl CellFilterOperation<TextFilterPB> for URLTypeOptionPB { impl CellFilterable<TextFilterPB> for URLTypeOptionPB {
fn apply_filter(&self, any_cell_data: TypeCellData, filter: &TextFilterPB) -> FlowyResult<bool> { fn apply_filter(&self, type_cell_data: TypeCellData, filter: &TextFilterPB) -> FlowyResult<bool> {
if !any_cell_data.is_url() { if !type_cell_data.is_url() {
return Ok(true); return Ok(true);
} }
let cell_data: CellData<TextCellData> = any_cell_data.into(); let cell_data: IntoCellData<TextCellData> = type_cell_data.into();
let text_cell_data = cell_data.try_into_inner()?; let text_cell_data = cell_data.try_into_inner()?;
Ok(filter.is_visible(&text_cell_data)) Ok(filter.is_visible(&text_cell_data))
} }

View File

@ -1,9 +1,9 @@
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellData, CellDataOperation}; use crate::services::cell::{CellDataOperation, IntoCellData};
use crate::services::field::{FieldBuilder, URLCellDataParser}; use crate::services::field::{FieldBuilder, URLCellDataParser};
use crate::services::field::{URLCellDataPB, URLTypeOptionPB}; use crate::services::field::{URLCellData, URLTypeOptionPB};
use grid_rev_model::FieldRevision; use grid_rev_model::FieldRevision;
/// The expected_str will equal to the input string, but the expected_url will be empty if there's no /// The expected_str will equal to the input string, but the expected_url will be empty if there's no
@ -175,12 +175,12 @@ mod tests {
assert_eq!(expected_url.to_owned(), decode_cell_data.url); assert_eq!(expected_url.to_owned(), decode_cell_data.url);
} }
fn decode_cell_data<T: Into<CellData<URLCellDataPB>>>( fn decode_cell_data<T: Into<IntoCellData<URLCellData>>>(
encoded_data: T, encoded_data: T,
type_option: &URLTypeOptionPB, type_option: &URLTypeOptionPB,
field_rev: &FieldRevision, field_rev: &FieldRevision,
field_type: &FieldType, field_type: &FieldType,
) -> URLCellDataPB { ) -> URLCellData {
type_option type_option
.decode_cell_data(encoded_data.into(), field_type, field_rev) .decode_cell_data(encoded_data.into(), field_type, field_rev)
.unwrap() .unwrap()

View File

@ -1,7 +1,7 @@
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{AnyCellChangeset, CellBytes, CellData, CellDataOperation, CellDisplayable}; use crate::services::cell::{AnyCellChangeset, CellBytes, CellDataOperation, CellDataSerialize, IntoCellData};
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder, URLCellDataPB}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder, URLCellData, URLCellDataPB};
use bytes::Bytes; use bytes::Bytes;
use fancy_regex::Regex; use fancy_regex::Regex;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
@ -36,41 +36,42 @@ pub struct URLTypeOptionPB {
} }
impl_type_option!(URLTypeOptionPB, FieldType::URL); impl_type_option!(URLTypeOptionPB, FieldType::URL);
impl CellDisplayable<URLCellDataPB> for URLTypeOptionPB { impl CellDataSerialize<URLCellData> for URLTypeOptionPB {
fn displayed_cell_bytes( fn serialize_cell_data_to_bytes(
&self, &self,
cell_data: CellData<URLCellDataPB>, cell_data: IntoCellData<URLCellData>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
let cell_data: URLCellDataPB = cell_data.try_into_inner()?; let cell_data_pb: URLCellDataPB = cell_data.try_into_inner()?.into();
CellBytes::from(cell_data) CellBytes::from(cell_data_pb)
} }
fn displayed_cell_string( fn serialize_cell_data_to_str(
&self, &self,
cell_data: CellData<URLCellDataPB>, cell_data: IntoCellData<URLCellData>,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<String> { ) -> FlowyResult<String> {
let cell_data: URLCellDataPB = cell_data.try_into_inner()?; let cell_data: URLCellData = cell_data.try_into_inner()?;
Ok(cell_data.content) Ok(cell_data.content)
} }
} }
pub type URLCellChangeset = String; pub type URLCellChangeset = String;
impl CellDataOperation<URLCellDataPB, URLCellChangeset> for URLTypeOptionPB { impl CellDataOperation<URLCellData, URLCellChangeset> for URLTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<URLCellDataPB>, cell_data: IntoCellData<URLCellData>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<CellBytes> { ) -> FlowyResult<CellBytes> {
if !decoded_field_type.is_url() { if !decoded_field_type.is_url() {
return Ok(CellBytes::default()); return Ok(CellBytes::default());
} }
self.displayed_cell_bytes(cell_data, decoded_field_type, field_rev) let cell_data = cell_data.try_into_inner()?.to_json()?;
Ok(CellBytes::new(cell_data))
} }
fn apply_changeset( fn apply_changeset(
@ -83,7 +84,7 @@ impl CellDataOperation<URLCellDataPB, URLCellChangeset> for URLTypeOptionPB {
if let Ok(Some(m)) = URL_REGEX.find(&content) { if let Ok(Some(m)) = URL_REGEX.find(&content) {
url = auto_append_scheme(m.as_str()); url = auto_append_scheme(m.as_str());
} }
URLCellDataPB { url, content }.to_json() URLCellData { url, content }.to_json()
} }
} }

View File

@ -4,7 +4,7 @@ use flowy_derive::ProtoBuf;
use flowy_error::{internal_error, FlowyResult}; use flowy_error::{internal_error, FlowyResult};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Default, ProtoBuf)]
pub struct URLCellDataPB { pub struct URLCellDataPB {
#[pb(index = 1)] #[pb(index = 1)]
pub url: String, pub url: String,
@ -13,7 +13,22 @@ pub struct URLCellDataPB {
pub content: String, pub content: String,
} }
impl URLCellDataPB { impl From<URLCellData> for URLCellDataPB {
fn from(data: URLCellData) -> Self {
Self {
url: data.url,
content: data.content,
}
}
}
#[derive(Clone, Default, Serialize, Deserialize)]
pub struct URLCellData {
pub url: String,
pub content: String,
}
impl URLCellData {
pub fn new(s: &str) -> Self { pub fn new(s: &str) -> Self {
Self { Self {
url: "".to_string(), url: "".to_string(),
@ -26,7 +41,7 @@ impl URLCellDataPB {
} }
} }
impl CellDataIsEmpty for URLCellDataPB { impl CellDataIsEmpty for URLCellData {
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
self.content.is_empty() self.content.is_empty()
} }
@ -34,15 +49,18 @@ impl CellDataIsEmpty for URLCellDataPB {
pub struct URLCellDataParser(); pub struct URLCellDataParser();
impl CellBytesParser for URLCellDataParser { impl CellBytesParser for URLCellDataParser {
type Object = URLCellDataPB; type Object = URLCellData;
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> { fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
URLCellDataPB::try_from(bytes.as_ref()).map_err(internal_error) match String::from_utf8(bytes.to_vec()) {
Ok(s) => URLCellData::from_cell_str(&s),
Err(_) => Ok(URLCellData::default()),
}
} }
} }
impl FromCellString for URLCellDataPB { impl FromCellString for URLCellData {
fn from_cell_str(s: &str) -> FlowyResult<Self> { fn from_cell_str(s: &str) -> FlowyResult<Self> {
serde_json::from_str::<URLCellDataPB>(s).map_err(internal_error) serde_json::from_str::<URLCellData>(s).map_err(internal_error)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::entities::filter_entities::*; use crate::entities::filter_entities::*;
use crate::entities::{FieldType, InsertedRowPB, RowPB}; use crate::entities::{FieldType, InsertedRowPB, RowPB};
use crate::services::cell::{CellFilterOperation, TypeCellData}; use crate::services::cell::{CellFilterable, TypeCellData};
use crate::services::field::*; use crate::services::field::*;
use crate::services::filter::{FilterChangeset, FilterMap, FilterResult, FilterResultNotification, FilterType}; use crate::services::filter::{FilterChangeset, FilterMap, FilterResult, FilterResultNotification, FilterType};
use crate::services::row::GridBlockRowRevision; use crate::services::row::GridBlockRowRevision;
@ -352,7 +352,7 @@ fn filter_cell(
filter_map: &FilterMap, filter_map: &FilterMap,
cell_rev: Option<&CellRevision>, cell_rev: Option<&CellRevision>,
) -> Option<bool> { ) -> Option<bool> {
let any_cell_data = match cell_rev { let type_cell_data = match cell_rev {
None => TypeCellData::from_field_type(&filter_id.field_type), None => TypeCellData::from_field_type(&filter_id.field_type),
Some(cell_rev) => match TypeCellData::try_from(cell_rev) { Some(cell_rev) => match TypeCellData::try_from(cell_rev) {
Ok(cell_data) => cell_data, Ok(cell_data) => cell_data,
@ -362,13 +362,13 @@ fn filter_cell(
} }
}, },
}; };
let cloned_cell_data = any_cell_data.data.clone(); let cloned_type_cell_data = type_cell_data.data.clone();
let is_visible = match &filter_id.field_type { let is_visible = match &filter_id.field_type {
FieldType::RichText => filter_map.text_filter.get(filter_id).and_then(|filter| { FieldType::RichText => filter_map.text_filter.get(filter_id).and_then(|filter| {
Some( Some(
field_rev field_rev
.get_type_option::<RichTextTypeOptionPB>(field_rev.ty)? .get_type_option::<RichTextTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -376,7 +376,7 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<NumberTypeOptionPB>(field_rev.ty)? .get_type_option::<NumberTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -384,7 +384,7 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<DateTypeOptionPB>(field_rev.ty)? .get_type_option::<DateTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -392,7 +392,7 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<SingleSelectTypeOptionPB>(field_rev.ty)? .get_type_option::<SingleSelectTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -400,7 +400,7 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<MultiSelectTypeOptionPB>(field_rev.ty)? .get_type_option::<MultiSelectTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -408,7 +408,7 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<CheckboxTypeOptionPB>(field_rev.ty)? .get_type_option::<CheckboxTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -416,7 +416,7 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<URLTypeOptionPB>(field_rev.ty)? .get_type_option::<URLTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
@ -424,14 +424,14 @@ fn filter_cell(
Some( Some(
field_rev field_rev
.get_type_option::<ChecklistTypeOptionPB>(field_rev.ty)? .get_type_option::<ChecklistTypeOptionPB>(field_rev.ty)?
.apply_filter(any_cell_data, filter) .apply_filter(type_cell_data, filter)
.ok(), .ok(),
) )
}), }),
}?; }?;
tracing::Span::current().record( tracing::Span::current().record(
"cell_content", "cell_content",
&format!("{} => {:?}", cloned_cell_data, is_visible.unwrap()).as_str(), &format!("{} => {:?}", cloned_type_cell_data, is_visible.unwrap()).as_str(),
); );
is_visible is_visible
} }

View File

@ -71,9 +71,9 @@ pub struct FilterType {
pub field_type: FieldType, pub field_type: FieldType,
} }
impl Into<FieldTypeRevision> for FilterType { impl From<FilterType> for FieldTypeRevision {
fn into(self) -> FieldTypeRevision { fn from(filter_type: FilterType) -> Self {
self.field_type.into() filter_type.field_type.into()
} }
} }
impl std::convert::From<&Arc<FieldRevision>> for FilterType { impl std::convert::From<&Arc<FieldRevision>> for FilterType {

View File

@ -3,7 +3,7 @@ use crate::entities::CellPathParams;
use crate::entities::*; use crate::entities::*;
use crate::manager::GridUser; use crate::manager::GridUser;
use crate::services::block_manager::GridBlockManager; use crate::services::block_manager::GridBlockManager;
use crate::services::cell::{apply_cell_data_changeset, decode_any_cell_data, CellBytes}; use crate::services::cell::{apply_cell_data_changeset, decode_type_cell_data, CellBytes};
use crate::services::field::{ use crate::services::field::{
default_type_option_builder_from_type, type_option_builder_from_bytes, type_option_builder_from_json_str, default_type_option_builder_from_type, type_option_builder_from_bytes, type_option_builder_from_json_str,
FieldBuilder, FieldBuilder,
@ -431,20 +431,20 @@ impl GridRevisionEditor {
} }
pub async fn get_cell(&self, params: &CellPathParams) -> Option<CellPB> { pub async fn get_cell(&self, params: &CellPathParams) -> Option<CellPB> {
let (field_type, cell_bytes) = self.decode_any_cell_data(params).await?; let (field_type, cell_bytes) = self.decode_cell_data_from(params).await?;
Some(CellPB::new(&params.field_id, field_type, cell_bytes.to_vec())) Some(CellPB::new(&params.field_id, field_type, cell_bytes.to_vec()))
} }
pub async fn get_cell_bytes(&self, params: &CellPathParams) -> Option<CellBytes> { pub async fn get_cell_bytes(&self, params: &CellPathParams) -> Option<CellBytes> {
let (_, cell_data) = self.decode_any_cell_data(params).await?; let (_, cell_data) = self.decode_cell_data_from(params).await?;
Some(cell_data) Some(cell_data)
} }
async fn decode_any_cell_data(&self, params: &CellPathParams) -> Option<(FieldType, CellBytes)> { async fn decode_cell_data_from(&self, params: &CellPathParams) -> Option<(FieldType, CellBytes)> {
let field_rev = self.get_field_rev(&params.field_id).await?; let field_rev = self.get_field_rev(&params.field_id).await?;
let (_, row_rev) = self.block_manager.get_row_rev(&params.row_id).await.ok()??; let (_, row_rev) = self.block_manager.get_row_rev(&params.row_id).await.ok()??;
let cell_rev = row_rev.cells.get(&params.field_id)?.clone(); let cell_rev = row_rev.cells.get(&params.field_id)?.clone();
Some(decode_any_cell_data(cell_rev.data, &field_rev)) Some(decode_type_cell_data(cell_rev.data, &field_rev))
} }
pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> { pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> {

View File

@ -1,5 +1,5 @@
use crate::entities::{GroupRowsNotificationPB, GroupViewChangesetPB, InsertedRowPB, RowPB}; use crate::entities::{GroupRowsNotificationPB, GroupViewChangesetPB, InsertedRowPB, RowPB};
use crate::services::cell::{decode_any_cell_data, CellBytesParser, CellDataIsEmpty}; use crate::services::cell::{decode_type_cell_data, CellBytesParser, CellDataIsEmpty};
use crate::services::group::action::{GroupControllerCustomActions, GroupControllerSharedActions}; use crate::services::group::action::{GroupControllerCustomActions, GroupControllerSharedActions};
use crate::services::group::configuration::GroupContext; use crate::services::group::configuration::GroupContext;
use crate::services::group::entities::Group; use crate::services::group::entities::Group;
@ -184,7 +184,7 @@ where
if let Some(cell_rev) = cell_rev { if let Some(cell_rev) = cell_rev {
let mut grouped_rows: Vec<GroupedRow> = vec![]; let mut grouped_rows: Vec<GroupedRow> = vec![];
let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.data, field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
for group in self.group_ctx.groups() { for group in self.group_ctx.groups() {
if self.can_group(&group.filter_content, &cell_data) { if self.can_group(&group.filter_content, &cell_data) {
@ -224,7 +224,7 @@ where
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<Vec<GroupRowsNotificationPB>> { ) -> FlowyResult<Vec<GroupRowsNotificationPB>> {
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.data.clone(), field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data); let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data);
@ -247,7 +247,7 @@ where
) -> FlowyResult<Vec<GroupRowsNotificationPB>> { ) -> FlowyResult<Vec<GroupRowsNotificationPB>> {
// if the cell_rev is none, then the row must in the default group. // if the cell_rev is none, then the row must in the default group.
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.data.clone(), field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
if !cell_data.is_empty() { if !cell_data.is_empty() {
tracing::error!("did_delete_delete_row {:?}", cell_rev.data); tracing::error!("did_delete_delete_row {:?}", cell_rev.data);
@ -280,7 +280,7 @@ where
}; };
if let Some(cell_rev) = cell_rev { if let Some(cell_rev) = cell_rev {
let cell_bytes = decode_any_cell_data(cell_rev.data, context.field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.data, context.field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
Ok(self.move_row(&cell_data, context)) Ok(self.move_row(&cell_data, context))
} else { } else {

View File

@ -1,3 +1,5 @@
#![allow(clippy::all)]
#[allow(unused_attributes)]
use crate::entities::{GridSortPB, SortChangesetNotificationPB}; use crate::entities::{GridSortPB, SortChangesetNotificationPB};
use crate::services::sort::{SortChangeset, SortType}; use crate::services::sort::{SortChangeset, SortType};
use flowy_task::TaskDispatcher; use flowy_task::TaskDispatcher;
@ -13,10 +15,14 @@ pub trait SortDelegate: Send + Sync {
} }
pub struct SortController { pub struct SortController {
#[allow(dead_code)]
view_id: String, view_id: String,
#[allow(dead_code)]
handler_id: String, handler_id: String,
#[allow(dead_code)]
delegate: Box<dyn SortDelegate>, delegate: Box<dyn SortDelegate>,
task_scheduler: Arc<RwLock<TaskDispatcher>>, task_scheduler: Arc<RwLock<TaskDispatcher>>,
#[allow(dead_code)]
sorts: Vec<GridSortPB>, sorts: Vec<GridSortPB>,
} }
@ -42,11 +48,11 @@ impl SortController {
.await; .await;
} }
pub fn sort_rows(&self, rows: &mut Vec<Arc<RowRevision>>) { pub fn sort_rows(&self, _rows: &mut Vec<Arc<RowRevision>>) {
todo!() //
} }
pub async fn did_receive_changes(&self, changeset: SortChangeset) -> Option<SortChangesetNotificationPB> { pub async fn did_receive_changes(&mut self, _changeset: SortChangeset) -> Option<SortChangesetNotificationPB> {
todo!() None
} }
} }

View File

@ -8,9 +8,9 @@ pub struct SortType {
pub field_type: FieldType, pub field_type: FieldType,
} }
impl Into<FieldTypeRevision> for SortType { impl From<SortType> for FieldTypeRevision {
fn into(self) -> FieldTypeRevision { fn from(sort_type: SortType) -> Self {
self.field_type.into() sort_type.field_type.into()
} }
} }
@ -32,6 +32,7 @@ impl std::convert::From<&Arc<FieldRevision>> for SortType {
} }
} }
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub struct SortChangeset { pub struct SortChangeset {
pub(crate) insert_sort: Option<SortType>, pub(crate) insert_sort: Option<SortType>,

View File

@ -6,6 +6,7 @@ use tokio::sync::RwLock;
pub struct SortTaskHandler { pub struct SortTaskHandler {
handler_id: String, handler_id: String,
#[allow(dead_code)]
sort_controller: Arc<RwLock<SortController>>, sort_controller: Arc<RwLock<SortController>>,
} }
@ -23,7 +24,7 @@ impl TaskHandler for SortTaskHandler {
&self.handler_id &self.handler_id
} }
fn run(&self, content: TaskContent) -> BoxResultFuture<(), anyhow::Error> { fn run(&self, _content: TaskContent) -> BoxResultFuture<(), anyhow::Error> {
todo!(); todo!();
} }
} }

View File

@ -417,7 +417,7 @@ impl GridViewRevisionEditor {
} }
pub async fn delete_view_sort(&self, params: DeleteSortParams) -> FlowyResult<()> { pub async fn delete_view_sort(&self, params: DeleteSortParams) -> FlowyResult<()> {
let sort_type = SortType::from(&params); let sort_type = params.sort_type;
let changeset = self let changeset = self
.sort_controller .sort_controller
.write() .write()

View File

@ -99,7 +99,7 @@ impl GridFilterTest {
} }
} }
fn view_id(&self) -> String { pub fn view_id(&self) -> String {
self.grid_id.clone() self.grid_id.clone()
} }
@ -134,7 +134,7 @@ impl GridFilterTest {
}; };
let payload = let payload =
AlterFilterPayloadPB::new( AlterFilterPayloadPB::new(
view_id: self.view_id(), & self.view_id(),
field_rev, text_filter); field_rev, text_filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
@ -157,7 +157,7 @@ impl GridFilterTest {
}; };
let payload = let payload =
AlterFilterPayloadPB::new( AlterFilterPayloadPB::new(
view_id: self.view_id(), &self.view_id(),
field_rev, number_filter); field_rev, number_filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
@ -167,7 +167,7 @@ impl GridFilterTest {
condition condition
}; };
let payload = let payload =
AlterFilterPayloadPB::new(view_id: self.view_id(), field_rev, checkbox_filter); AlterFilterPayloadPB::new(& self.view_id(), field_rev, checkbox_filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
FilterScript::CreateDateFilter { condition, start, end, timestamp} => { FilterScript::CreateDateFilter { condition, start, end, timestamp} => {
@ -180,21 +180,21 @@ impl GridFilterTest {
}; };
let payload = let payload =
AlterFilterPayloadPB::new(view_id: self.view_id(), field_rev, date_filter); AlterFilterPayloadPB::new( &self.view_id(), field_rev, date_filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
FilterScript::CreateMultiSelectFilter { condition, option_ids} => { FilterScript::CreateMultiSelectFilter { condition, option_ids} => {
let field_rev = self.get_first_field_rev(FieldType::MultiSelect); let field_rev = self.get_first_field_rev(FieldType::MultiSelect);
let filter = SelectOptionFilterPB { condition, option_ids }; let filter = SelectOptionFilterPB { condition, option_ids };
let payload = let payload =
AlterFilterPayloadPB::new(view_id: self.view_id(),field_rev, filter); AlterFilterPayloadPB::new( &self.view_id(),field_rev, filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
FilterScript::CreateSingleSelectFilter { condition, option_ids} => { FilterScript::CreateSingleSelectFilter { condition, option_ids} => {
let field_rev = self.get_first_field_rev(FieldType::SingleSelect); let field_rev = self.get_first_field_rev(FieldType::SingleSelect);
let filter = SelectOptionFilterPB { condition, option_ids }; let filter = SelectOptionFilterPB { condition, option_ids };
let payload = let payload =
AlterFilterPayloadPB::new(view_id: self.view_id(),field_rev, filter); AlterFilterPayloadPB::new(& self.view_id(),field_rev, filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
FilterScript::CreateChecklistFilter { condition} => { FilterScript::CreateChecklistFilter { condition} => {
@ -202,7 +202,7 @@ impl GridFilterTest {
// let type_option = self.get_checklist_type_option(&field_rev.id); // let type_option = self.get_checklist_type_option(&field_rev.id);
let filter = ChecklistFilterPB { condition }; let filter = ChecklistFilterPB { condition };
let payload = let payload =
AlterFilterPayloadPB::new(view_id: self.view_id(),field_rev, filter); AlterFilterPayloadPB::new(& self.view_id(),field_rev, filter);
self.insert_filter(payload).await; self.insert_filter(payload).await;
} }
FilterScript::AssertFilterCount { count } => { FilterScript::AssertFilterCount { count } => {

View File

@ -189,7 +189,7 @@ async fn grid_filter_delete_test() {
condition: TextFilterConditionPB::TextIsEmpty, condition: TextFilterConditionPB::TextIsEmpty,
content: "".to_string(), content: "".to_string(),
}; };
let payload = AlterFilterPayloadPB::new(&field_rev, text_filter); let payload = AlterFilterPayloadPB::new(&test.view_id(), &field_rev, text_filter);
let scripts = vec![ let scripts = vec![
InsertFilter { payload }, InsertFilter { payload },
AssertFilterCount { count: 1 }, AssertFilterCount { count: 1 },

View File

@ -2,7 +2,6 @@ use crate::{FieldRevision, FieldTypeRevision, FilterRevision, GroupConfiguration
use indexmap::IndexMap; use indexmap::IndexMap;
use nanoid::nanoid; use nanoid::nanoid;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Debug; use std::fmt::Debug;
use std::sync::Arc; use std::sync::Arc;

View File

@ -85,7 +85,7 @@ mod tests {
let s = serde_json::to_string(&grid_view_revision).unwrap(); let s = serde_json::to_string(&grid_view_revision).unwrap();
assert_eq!( assert_eq!(
s, s,
r#"{"view_id":"1","grid_id":"1","layout":0,"filters":[],"groups":[]}"# r#"{"view_id":"1","grid_id":"1","layout":0,"filters":[],"groups":[],"sorts":[]}"#
); );
} }
} }