chore: config cell displayable data

This commit is contained in:
appflowy
2022-07-12 22:24:01 +08:00
parent 284755eccf
commit 1e3640f8ac
13 changed files with 171 additions and 107 deletions

View File

@ -376,7 +376,7 @@ pub(crate) async fn get_select_option_handler(
}, },
Some(cell_rev) => cell_rev.try_into()?, Some(cell_rev) => cell_rev.try_into()?,
}; };
let option_context = type_option.selected_select_option(any_cell_data); let option_context = type_option.selected_select_option(any_cell_data.into());
data_result(option_context) data_result(option_context)
} }
} }

View File

@ -100,36 +100,33 @@ impl AnyCellData {
/// * Use String to parse the data when the FieldType is RichText, Number, or Checkbox. /// * Use String to parse the data when the FieldType is RichText, Number, or Checkbox.
/// * Check out the implementation of CellDataOperation trait for more information. /// * Check out the implementation of CellDataOperation trait for more information.
#[derive(Default)] #[derive(Default)]
pub struct DecodedCellData { pub struct CellBytes(pub Bytes);
pub data: Vec<u8>,
}
impl DecodedCellData { impl CellBytes {
pub fn new<T: AsRef<[u8]>>(data: T) -> Self { pub fn new<T: AsRef<[u8]>>(data: T) -> Self {
Self { let bytes = Bytes::from(data.as_ref().to_vec());
data: data.as_ref().to_vec(), Self(bytes)
}
} }
pub fn try_from_bytes<T: TryInto<Bytes>>(bytes: T) -> FlowyResult<Self> pub fn from<T: TryInto<Bytes>>(bytes: T) -> FlowyResult<Self>
where where
<T as TryInto<Bytes>>::Error: std::fmt::Debug, <T as TryInto<Bytes>>::Error: std::fmt::Debug,
{ {
let bytes = bytes.try_into().map_err(internal_error)?; let bytes = bytes.try_into().map_err(internal_error)?;
Ok(Self { data: bytes.to_vec() }) Ok(Self(bytes))
} }
pub fn parse<'a, T: TryFrom<&'a [u8]>>(&'a self) -> FlowyResult<T> pub fn parse<'a, T: TryFrom<&'a [u8]>>(&'a self) -> FlowyResult<T>
where where
<T as TryFrom<&'a [u8]>>::Error: std::fmt::Debug, <T as TryFrom<&'a [u8]>>::Error: std::fmt::Debug,
{ {
T::try_from(self.data.as_ref()).map_err(internal_error) T::try_from(self.0.as_ref()).map_err(internal_error)
} }
} }
impl ToString for DecodedCellData { impl ToString for CellBytes {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match String::from_utf8(self.data.clone()) { match String::from_utf8(self.0.to_vec()) {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
tracing::error!("DecodedCellData to string failed: {:?}", e); tracing::error!("DecodedCellData to string failed: {:?}", e);
@ -138,3 +135,11 @@ impl ToString for DecodedCellData {
} }
} }
} }
impl std::ops::Deref for CellBytes {
type Target = Bytes;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View File

@ -1,31 +1,45 @@
use crate::entities::FieldType;
use crate::services::cell::{AnyCellData, CellBytes};
use crate::services::field::*;
use flowy_error::{ErrorCode, FlowyError, FlowyResult}; use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, FieldTypeRevision}; use flowy_grid_data_model::revision::{CellRevision, FieldRevision, FieldTypeRevision};
use crate::entities::FieldType; /// This trait is used when doing filter/search on the grid.
use crate::services::cell::{AnyCellData, DecodedCellData};
use crate::services::field::*;
pub trait CellFilterOperation<T> { pub trait CellFilterOperation<T> {
/// Return true if any_cell_data match the filter condition. /// Return true if any_cell_data match the filter condition.
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &T) -> FlowyResult<bool>; fn apply_filter(&self, any_cell_data: AnyCellData, filter: &T) -> FlowyResult<bool>;
} }
pub trait CellDataOperation<D, C> { /// Return object that describes the cell.
/// The cell_data is able to parse into the specific data that was impl the FromCellData trait. pub trait CellDisplayable<CD, DC> {
fn display_data(
&self,
cell_data: CellData<CD>,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> FlowyResult<DC>;
}
// CD: Short for CellData. This type is the type return by apply_changeset function.
// CS: Short for Changeset. Parse the string into specific Changeset type.
pub trait CellDataOperation<CD, CS> {
/// The cell_data is able to parse into the specific data if CD impl the FromCellData trait.
/// For example: /// For example:
/// URLCellData, DateCellData. etc. /// URLCellData, DateCellData. etc.
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<D>, cell_data: CellData<CD>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData>; ) -> FlowyResult<CellBytes>;
/// The changeset is able to parse into the specific data that was impl the FromCellChangeset trait. /// The changeset is able to parse into the specific data if CS impl the FromCellChangeset trait.
/// For example: /// For example:
/// SelectOptionCellChangeset,DateCellChangeset. etc. /// SelectOptionCellChangeset,DateCellChangeset. etc.
fn apply_changeset(&self, changeset: CellDataChangeset<C>, cell_rev: Option<CellRevision>) -> FlowyResult<String>; fn apply_changeset(&self, changeset: CellDataChangeset<CS>, cell_rev: Option<CellRevision>) -> FlowyResult<String>;
} }
/// changeset: It will be deserialized into specific data base on the FieldType. /// changeset: It will be deserialized into specific data base on the FieldType.
/// For example, /// For example,
/// FieldType::RichText => String /// FieldType::RichText => String
@ -53,23 +67,20 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
Ok(AnyCellData::new(s, field_type).json()) Ok(AnyCellData::new(s, field_type).json())
} }
pub fn decode_any_cell_data<T: TryInto<AnyCellData>>(data: T, field_rev: &FieldRevision) -> DecodedCellData { pub fn decode_any_cell_data<T: TryInto<AnyCellData>>(data: T, field_rev: &FieldRevision) -> CellBytes {
if let Ok(any_cell_data) = data.try_into() { if let Ok(any_cell_data) = data.try_into() {
let AnyCellData { let AnyCellData { data, field_type } = any_cell_data;
data: cell_data,
field_type,
} = any_cell_data;
let to_field_type = field_rev.field_type_rev.into(); let to_field_type = field_rev.field_type_rev.into();
match try_decode_cell_data(CellData(Some(cell_data)), field_rev, &field_type, &to_field_type) { match try_decode_cell_data(data.into(), field_rev, &field_type, &to_field_type) {
Ok(cell_data) => cell_data, Ok(cell_bytes) => cell_bytes,
Err(e) => { Err(e) => {
tracing::error!("Decode cell data failed, {:?}", e); tracing::error!("Decode cell data failed, {:?}", e);
DecodedCellData::default() CellBytes::default()
} }
} }
} else { } else {
tracing::error!("Decode type option data failed"); tracing::error!("Decode type option data failed");
DecodedCellData::default() CellBytes::default()
} }
} }
@ -78,7 +89,7 @@ pub fn try_decode_cell_data(
field_rev: &FieldRevision, field_rev: &FieldRevision,
s_field_type: &FieldType, s_field_type: &FieldType,
t_field_type: &FieldType, t_field_type: &FieldType,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
let cell_data = cell_data.try_into_inner()?; let cell_data = cell_data.try_into_inner()?;
let get_cell_data = || { let get_cell_data = || {
let field_type: FieldTypeRevision = t_field_type.into(); let field_type: FieldTypeRevision = t_field_type.into();
@ -112,9 +123,9 @@ pub fn try_decode_cell_data(
Some(Ok(data)) => Ok(data), Some(Ok(data)) => Ok(data),
Some(Err(err)) => { Some(Err(err)) => {
tracing::error!("{:?}", err); tracing::error!("{:?}", err);
Ok(DecodedCellData::default()) Ok(CellBytes::default())
} }
None => Ok(DecodedCellData::default()), None => Ok(CellBytes::default()),
} }
} }

View File

@ -1,5 +1,5 @@
use crate::entities::{CellChangeset, CellIdentifier, CellIdentifierPayload, FieldType}; use crate::entities::{CellChangeset, CellIdentifier, CellIdentifierPayload, FieldType};
use crate::services::cell::{AnyCellData, FromCellChangeset, FromCellString}; use crate::services::cell::{AnyCellData, CellData, CellDisplayable, FromCellChangeset, FromCellString};
use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption}; use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOption};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult}; use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult};
@ -60,12 +60,11 @@ impl std::default::Default for SelectOptionColor {
} }
} }
pub fn make_selected_select_options<T: TryInto<AnyCellData>>( pub fn make_selected_select_options(
any_cell_data: T, cell_data: CellData<SelectOptionIds>,
options: &[SelectOption], options: &[SelectOption],
) -> Vec<SelectOption> { ) -> Vec<SelectOption> {
if let Ok(type_option_cell_data) = any_cell_data.try_into() { if let Ok(ids) = cell_data.try_into_inner() {
let ids = SelectOptionIds::from(type_option_cell_data.data);
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())
.collect() .collect()
@ -100,13 +99,27 @@ pub trait SelectOptionOperation: TypeOptionDataEntry + Send + Sync {
SelectOption::with_color(name, color) SelectOption::with_color(name, color)
} }
fn selected_select_option(&self, any_cell_data: AnyCellData) -> SelectOptionCellData; fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellData;
fn options(&self) -> &Vec<SelectOption>; fn options(&self) -> &Vec<SelectOption>;
fn mut_options(&mut self) -> &mut Vec<SelectOption>; fn mut_options(&mut self) -> &mut Vec<SelectOption>;
} }
impl<T> CellDisplayable<SelectOptionIds, SelectOptionCellData> for T
where
T: SelectOptionOperation,
{
fn display_data(
&self,
cell_data: CellData<SelectOptionIds>,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> FlowyResult<SelectOptionCellData> {
Ok(self.selected_select_option(cell_data))
}
}
pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult<Box<dyn SelectOptionOperation>> { pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult<Box<dyn SelectOptionOperation>> {
let field_type: FieldType = field_rev.field_type_rev.into(); let field_type: FieldType = field_rev.field_type_rev.into();
match &field_type { match &field_type {
@ -155,6 +168,12 @@ impl std::convert::TryFrom<AnyCellData> for SelectOptionIds {
} }
} }
impl std::convert::From<AnyCellData> for CellData<SelectOptionIds> {
fn from(any_cell_data: AnyCellData) -> Self {
any_cell_data.data.into()
}
}
impl FromCellString for SelectOptionIds { impl FromCellString for SelectOptionIds {
fn from_cell_str(s: &str) -> FlowyResult<Self> fn from_cell_str(s: &str) -> FlowyResult<Self>
where where

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::{AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData}; use crate::services::cell::{AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
@ -40,23 +40,35 @@ impl_type_option!(CheckboxTypeOption, FieldType::Checkbox);
const YES: &str = "Yes"; const YES: &str = "Yes";
const NO: &str = "No"; const NO: &str = "No";
impl CellDisplayable<String, bool> for CheckboxTypeOption {
fn display_data(
&self,
cell_data: CellData<String>,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> FlowyResult<bool> {
let s: String = cell_data.try_into_inner()?;
Ok(s == YES)
}
}
impl CellDataOperation<String, String> for CheckboxTypeOption { impl CellDataOperation<String, String> for CheckboxTypeOption {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<String>, cell_data: CellData<String>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
if !decoded_field_type.is_checkbox() { if !decoded_field_type.is_checkbox() {
return Ok(DecodedCellData::default()); return Ok(CellBytes::default());
} }
let s: String = cell_data.try_into_inner()?; let s: String = cell_data.try_into_inner()?;
if s == YES || s == NO { if s == YES || s == NO {
return Ok(DecodedCellData::new(s)); return Ok(CellBytes::new(s));
} }
Ok(DecodedCellData::default()) Ok(CellBytes::default())
} }
fn apply_changeset( fn apply_changeset(

View File

@ -2,7 +2,8 @@ use crate::entities::{CellChangeset, FieldType};
use crate::entities::{CellIdentifier, CellIdentifierPayload}; use crate::entities::{CellIdentifier, CellIdentifierPayload};
use crate::impl_type_option; use crate::impl_type_option;
use crate::services::cell::{ use crate::services::cell::{
AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData, FromCellChangeset, FromCellString, AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable, FromCellChangeset,
FromCellString,
}; };
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
@ -121,23 +122,33 @@ impl DateTypeOption {
} }
} }
impl CellDisplayable<DateTimestamp, DateCellData> for DateTypeOption {
fn display_data(
&self,
cell_data: CellData<DateTimestamp>,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> FlowyResult<DateCellData> {
let timestamp = cell_data.try_into_inner()?;
Ok(self.today_desc_from_timestamp(timestamp.0))
}
}
impl CellDataOperation<DateTimestamp, DateCellChangeset> for DateTypeOption { impl CellDataOperation<DateTimestamp, DateCellChangeset> for DateTypeOption {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<DateTimestamp>, cell_data: CellData<DateTimestamp>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
// Return default data if the type_option_cell_data is not FieldType::DateTime. // Return default data if the type_option_cell_data is not FieldType::DateTime.
// It happens when switching from one field to another. // It happens when switching from one field to another.
// For example: // For example:
// FieldType::RichText -> FieldType::DateTime, it will display empty content on the screen. // FieldType::RichText -> FieldType::DateTime, it will display empty content on the screen.
if !decoded_field_type.is_date() { if !decoded_field_type.is_date() {
return Ok(DecodedCellData::default()); return Ok(CellBytes::default());
} }
let timestamp = cell_data.try_into_inner()?; CellBytes::from(self.display_data(cell_data, decoded_field_type, field_rev)?)
let date = self.today_desc_from_timestamp(timestamp.0);
DecodedCellData::try_from_bytes(date)
} }
fn apply_changeset( fn apply_changeset(

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::{AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData}; use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
use crate::services::field::select_option::{ use crate::services::field::select_option::{
make_selected_select_options, SelectOption, SelectOptionCellChangeset, SelectOptionCellData, SelectOptionIds, make_selected_select_options, SelectOption, SelectOptionCellChangeset, SelectOptionCellData, SelectOptionIds,
SelectOptionOperation, SELECTION_IDS_SEPARATOR, SelectOptionOperation, SELECTION_IDS_SEPARATOR,
@ -28,8 +28,8 @@ pub struct MultiSelectTypeOption {
impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect); impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect);
impl SelectOptionOperation for MultiSelectTypeOption { impl SelectOptionOperation for MultiSelectTypeOption {
fn selected_select_option(&self, any_cell_data: AnyCellData) -> SelectOptionCellData { fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellData {
let select_options = make_selected_select_options(any_cell_data, &self.options); let select_options = make_selected_select_options(cell_data, &self.options);
SelectOptionCellData { SelectOptionCellData {
options: self.options.clone(), options: self.options.clone(),
select_options, select_options,
@ -50,24 +50,14 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSele
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: CellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
if !decoded_field_type.is_select_option() { if !decoded_field_type.is_select_option() {
return Ok(DecodedCellData::default()); return Ok(CellBytes::default());
} }
let ids: SelectOptionIds = cell_data.try_into_inner()?; let cell_data = self.display_data(cell_data, decoded_field_type, field_rev)?;
let select_options = ids CellBytes::from(cell_data)
.iter()
.flat_map(|option_id| self.options.iter().find(|option| &option.id == option_id).cloned())
.collect::<Vec<SelectOption>>();
let cell_data = SelectOptionCellData {
options: self.options.clone(),
select_options,
};
DecodedCellData::try_from_bytes(cell_data)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -1,7 +1,7 @@
use crate::impl_type_option; use crate::impl_type_option;
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellData, CellDataChangeset, CellDataOperation, DecodedCellData}; use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation};
use crate::services::field::number_currency::Currency; use crate::services::field::number_currency::Currency;
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, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
@ -110,15 +110,15 @@ impl CellDataOperation<String, String> for NumberTypeOption {
cell_data: CellData<String>, cell_data: CellData<String>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
if decoded_field_type.is_date() { if decoded_field_type.is_date() {
return Ok(DecodedCellData::default()); return Ok(CellBytes::default());
} }
let cell_data: String = cell_data.try_into_inner()?; let cell_data: String = cell_data.try_into_inner()?;
match self.format_cell_data(&cell_data) { match self.format_cell_data(&cell_data) {
Ok(num) => Ok(DecodedCellData::new(num.to_string())), Ok(num) => Ok(CellBytes::new(num.to_string())),
Err(_) => Ok(DecodedCellData::default()), Err(_) => Ok(CellBytes::default()),
} }
} }

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::{AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData}; use crate::services::cell::{CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable};
use crate::services::field::select_option::{ use crate::services::field::select_option::{
make_selected_select_options, SelectOption, SelectOptionCellChangeset, SelectOptionCellData, SelectOptionIds, make_selected_select_options, SelectOption, SelectOptionCellChangeset, SelectOptionCellData, SelectOptionIds,
SelectOptionOperation, SelectOptionOperation,
@ -24,8 +24,10 @@ pub struct SingleSelectTypeOption {
impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect); impl_type_option!(SingleSelectTypeOption, FieldType::SingleSelect);
impl SelectOptionOperation for SingleSelectTypeOption { impl SelectOptionOperation for SingleSelectTypeOption {
fn selected_select_option(&self, any_cell_data: AnyCellData) -> SelectOptionCellData { fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellData {
let select_options = make_selected_select_options(any_cell_data, &self.options); let mut select_options = make_selected_select_options(cell_data, &self.options);
// only keep option in single select
select_options.truncate(1);
SelectOptionCellData { SelectOptionCellData {
options: self.options.clone(), options: self.options.clone(),
select_options, select_options,
@ -46,24 +48,14 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for SingleSel
&self, &self,
cell_data: CellData<SelectOptionIds>, cell_data: CellData<SelectOptionIds>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
if !decoded_field_type.is_select_option() { if !decoded_field_type.is_select_option() {
return Ok(DecodedCellData::default()); return Ok(CellBytes::default());
} }
let ids: SelectOptionIds = cell_data.try_into_inner()?; let cell_data = self.display_data(cell_data, decoded_field_type, field_rev)?;
let mut cell_data = SelectOptionCellData { CellBytes::from(cell_data)
options: self.options.clone(),
select_options: vec![],
};
if let Some(option_id) = ids.first() {
if let Some(option) = self.options.iter().find(|option| &option.id == option_id) {
cell_data.select_options.push(option.clone());
}
}
DecodedCellData::try_from_bytes(cell_data)
} }
fn apply_changeset( fn apply_changeset(

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::{ use crate::services::cell::{
try_decode_cell_data, AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData, try_decode_cell_data, AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable,
}; };
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
@ -32,13 +32,25 @@ pub struct RichTextTypeOption {
} }
impl_type_option!(RichTextTypeOption, FieldType::RichText); impl_type_option!(RichTextTypeOption, FieldType::RichText);
impl CellDisplayable<String, String> for RichTextTypeOption {
fn display_data(
&self,
cell_data: CellData<String>,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> FlowyResult<String> {
let cell_str: String = cell_data.try_into_inner()?;
Ok(cell_str)
}
}
impl CellDataOperation<String, String> for RichTextTypeOption { impl CellDataOperation<String, String> for RichTextTypeOption {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<String>, cell_data: CellData<String>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
if decoded_field_type.is_date() if decoded_field_type.is_date()
|| decoded_field_type.is_single_select() || decoded_field_type.is_single_select()
|| decoded_field_type.is_multi_select() || decoded_field_type.is_multi_select()
@ -46,8 +58,8 @@ impl CellDataOperation<String, String> for RichTextTypeOption {
{ {
try_decode_cell_data(cell_data, field_rev, decoded_field_type, decoded_field_type) try_decode_cell_data(cell_data, field_rev, decoded_field_type, decoded_field_type)
} else { } else {
let cell_data: String = cell_data.try_into_inner()?; let content = self.display_data(cell_data, decoded_field_type, field_rev)?;
Ok(DecodedCellData::new(cell_data)) Ok(CellBytes::new(content))
} }
} }

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::{ use crate::services::cell::{
AnyCellData, CellData, CellDataChangeset, CellDataOperation, DecodedCellData, FromCellString, AnyCellData, CellBytes, CellData, CellDataChangeset, CellDataOperation, CellDisplayable, FromCellString,
}; };
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder}; use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use bytes::Bytes; use bytes::Bytes;
@ -34,18 +34,30 @@ pub struct URLTypeOption {
} }
impl_type_option!(URLTypeOption, FieldType::URL); impl_type_option!(URLTypeOption, FieldType::URL);
impl CellDisplayable<URLCellData, URLCellData> for URLTypeOption {
fn display_data(
&self,
cell_data: CellData<URLCellData>,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> FlowyResult<URLCellData> {
let cell_data: URLCellData = cell_data.try_into_inner()?;
Ok(cell_data)
}
}
impl CellDataOperation<URLCellData, String> for URLTypeOption { impl CellDataOperation<URLCellData, String> for URLTypeOption {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<URLCellData>, cell_data: CellData<URLCellData>,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<DecodedCellData> { ) -> FlowyResult<CellBytes> {
if !decoded_field_type.is_url() { if !decoded_field_type.is_url() {
return Ok(DecodedCellData::default()); return Ok(CellBytes::default());
} }
let cell_data: URLCellData = cell_data.try_into_inner()?; let cell_data = self.display_data(cell_data, decoded_field_type, field_rev)?;
DecodedCellData::try_from_bytes(cell_data) CellBytes::from(cell_data)
} }
fn apply_changeset( fn apply_changeset(

View File

@ -45,7 +45,7 @@ impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOption {
return Ok(true); return Ok(true);
} }
let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data)); let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data.into()));
Ok(filter.is_visible(&selected_options)) Ok(filter.is_visible(&selected_options))
} }
} }
@ -55,7 +55,7 @@ impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOption {
if !any_cell_data.is_single_select() { if !any_cell_data.is_single_select() {
return Ok(true); return Ok(true);
} }
let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data)); let selected_options = SelectedSelectOptions::from(self.selected_select_option(any_cell_data.into()));
Ok(filter.is_visible(&selected_options)) Ok(filter.is_visible(&selected_options))
} }
} }

View File

@ -344,7 +344,7 @@ impl GridRevisionEditor {
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();
let data = decode_any_cell_data(cell_rev.data, &field_rev).data; let data = decode_any_cell_data(cell_rev.data, &field_rev).to_vec();
Some(Cell::new(&params.field_id, data)) Some(Cell::new(&params.field_id, data))
} }