mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: unit test
This commit is contained in:
parent
5b2b50dc9c
commit
8c7b0bd5a7
@ -1,15 +1,14 @@
|
||||
use crate::impl_type_option;
|
||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
|
||||
use bytes::Bytes;
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{
|
||||
CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CheckboxTypeOptionBuilder(CheckboxTypeOption);
|
||||
@ -43,23 +42,26 @@ impl_type_option!(CheckboxTypeOption, FieldType::Checkbox);
|
||||
const YES: &str = "Yes";
|
||||
const NO: &str = "No";
|
||||
|
||||
impl CellDataOperation<String> for CheckboxTypeOption {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
impl CellDataOperation<String, String> for CheckboxTypeOption {
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
type_option_cell_data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
_field_meta: &FieldMeta,
|
||||
) -> DecodedCellData {
|
||||
let type_option_cell_data = type_option_cell_data.into();
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
if !decoded_field_type.is_checkbox() {
|
||||
return DecodedCellData::default();
|
||||
}
|
||||
let cell_data = type_option_cell_data.data;
|
||||
if cell_data == YES || cell_data == NO {
|
||||
return DecodedCellData::from_content(cell_data);
|
||||
return Ok(DecodedCellData::default());
|
||||
}
|
||||
|
||||
DecodedCellData::default()
|
||||
let encoded_data = encoded_data.into();
|
||||
if encoded_data == YES || encoded_data == NO {
|
||||
return Ok(DecodedCellData::from_content(encoded_data));
|
||||
}
|
||||
|
||||
Ok(DecodedCellData::default())
|
||||
}
|
||||
|
||||
fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
|
||||
@ -91,10 +93,10 @@ fn string_to_bool(bool_str: &str) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::services::field::type_options::checkbox_type_option::{NO, YES};
|
||||
use crate::services::field::CheckboxTypeOption;
|
||||
|
||||
use crate::services::field::FieldBuilder;
|
||||
use crate::services::row::{apply_cell_data_changeset, decode_cell_data, CellDataOperation};
|
||||
use diesel::types::IsNull::No;
|
||||
use crate::services::row::{apply_cell_data_changeset, decode_cell_data_from_type_option_cell_data};
|
||||
|
||||
use flowy_grid_data_model::entities::FieldType;
|
||||
|
||||
#[test]
|
||||
@ -102,49 +104,37 @@ mod tests {
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::Checkbox).build();
|
||||
let data = apply_cell_data_changeset("true", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
YES
|
||||
);
|
||||
|
||||
let data = apply_cell_data_changeset("1", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
YES
|
||||
);
|
||||
|
||||
let data = apply_cell_data_changeset("yes", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
YES
|
||||
);
|
||||
|
||||
let data = apply_cell_data_changeset("false", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
NO
|
||||
);
|
||||
|
||||
let data = apply_cell_data_changeset("no", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
NO
|
||||
);
|
||||
|
||||
let data = apply_cell_data_changeset("12", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
NO
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::entities::{CellIdentifier, CellIdentifierPayload};
|
||||
use crate::impl_type_option;
|
||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
||||
use crate::services::row::{
|
||||
CellContentChangeset, CellDataOperation, DecodedCellData, EncodedCellData, TypeOptionCellData,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use chrono::format::strftime::StrftimeItems;
|
||||
use chrono::NaiveDateTime;
|
||||
@ -90,10 +92,10 @@ impl DateTypeOption {
|
||||
|
||||
let serde_cell_data = DateCellDataSerde::from_str(&result.unwrap().data)?;
|
||||
let date = self.decode_cell_data_from_timestamp(&serde_cell_data).content;
|
||||
let time = serde_cell_data.time.unwrap_or("".to_owned());
|
||||
let time = serde_cell_data.time.unwrap_or_else(|| "".to_owned());
|
||||
let timestamp = serde_cell_data.timestamp;
|
||||
|
||||
return Ok(DateCellData { date, time, timestamp });
|
||||
Ok(DateCellData { date, time, timestamp })
|
||||
}
|
||||
|
||||
fn decode_cell_data_from_timestamp(&self, serde_cell_data: &DateCellDataSerde) -> DecodedCellData {
|
||||
@ -102,7 +104,7 @@ impl DateTypeOption {
|
||||
}
|
||||
|
||||
let cell_content = self.today_desc_from_timestamp(serde_cell_data.timestamp, &serde_cell_data.time);
|
||||
return DecodedCellData::new(serde_cell_data.timestamp.to_string(), cell_content);
|
||||
DecodedCellData::new(serde_cell_data.timestamp.to_string(), cell_content)
|
||||
}
|
||||
|
||||
fn timestamp_from_utc_with_time(
|
||||
@ -131,29 +133,30 @@ impl DateTypeOption {
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(utc.timestamp());
|
||||
Ok(utc.timestamp())
|
||||
}
|
||||
}
|
||||
|
||||
impl CellDataOperation<DateCellDataSerde> for DateTypeOption {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
impl CellDataOperation<EncodedCellData<DateCellDataSerde>, DateCellDataSerde> for DateTypeOption {
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
type_option_cell_data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
_field_meta: &FieldMeta,
|
||||
) -> DecodedCellData {
|
||||
let type_option_cell_data = type_option_cell_data.into();
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<EncodedCellData<DateCellDataSerde>>,
|
||||
{
|
||||
// Return default data if the type_option_cell_data is not FieldType::DateTime.
|
||||
// It happens when switching from one field to another.
|
||||
// For example:
|
||||
// FieldType::RichText -> FieldType::DateTime, it will display empty content on the screen.
|
||||
if !decoded_field_type.is_date() {
|
||||
return DecodedCellData::default();
|
||||
}
|
||||
match DateCellDataSerde::from_str(&type_option_cell_data.data) {
|
||||
Ok(serde_cell_data) => self.decode_cell_data_from_timestamp(&serde_cell_data),
|
||||
Err(_) => DecodedCellData::default(),
|
||||
return Ok(DecodedCellData::default());
|
||||
}
|
||||
|
||||
let encoded_data = encoded_data.into().try_into_inner()?;
|
||||
Ok(self.decode_cell_data_from_timestamp(&encoded_data))
|
||||
}
|
||||
|
||||
fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<DateCellDataSerde, FlowyError>
|
||||
@ -308,22 +311,26 @@ impl DateCellDataSerde {
|
||||
fn new(timestamp: i64, time: Option<String>, time_format: &TimeFormat) -> Self {
|
||||
Self {
|
||||
timestamp,
|
||||
time: Some(time.unwrap_or(default_time_str(time_format))),
|
||||
time: Some(time.unwrap_or_else(|| default_time_str(time_format))),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_timestamp(timestamp: i64, time: Option<String>) -> Self {
|
||||
Self { timestamp, time }
|
||||
}
|
||||
}
|
||||
|
||||
fn from_str(s: &str) -> FlowyResult<Self> {
|
||||
impl FromStr for DateCellDataSerde {
|
||||
type Err = FlowyError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
serde_json::from_str::<DateCellDataSerde>(s).map_err(internal_error)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for DateCellDataSerde {
|
||||
fn to_string(&self) -> String {
|
||||
serde_json::to_string(&self).unwrap_or("".to_string())
|
||||
serde_json::to_string(&self).unwrap_or_else(|_| "".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,11 +417,11 @@ impl std::convert::From<DateCellContentChangeset> for CellContentChangeset {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::services::field::FieldBuilder;
|
||||
use crate::services::field::{
|
||||
DateCellContentChangeset, DateCellData, DateCellDataSerde, DateFormat, DateTypeOption, TimeFormat,
|
||||
use crate::services::field::{DateCellContentChangeset, DateCellDataSerde, DateFormat, DateTypeOption, TimeFormat};
|
||||
use crate::services::row::{
|
||||
apply_cell_data_changeset, decode_cell_data_from_type_option_cell_data, CellDataOperation, EncodedCellData,
|
||||
};
|
||||
use crate::services::row::{apply_cell_data_changeset, decode_cell_data, CellDataOperation, TypeOptionCellData};
|
||||
use flowy_grid_data_model::entities::FieldType;
|
||||
use flowy_grid_data_model::entities::{FieldMeta, FieldType};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
#[test]
|
||||
@ -422,9 +429,7 @@ mod tests {
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
let data = apply_cell_data_changeset("1e", None, &field_meta).unwrap();
|
||||
assert_eq!(
|
||||
decode_cell_data(data, &field_meta, &field_meta.field_type)
|
||||
.unwrap()
|
||||
.content,
|
||||
decode_cell_data_from_type_option_cell_data(data, &field_meta, &field_meta.field_type).content,
|
||||
"".to_owned()
|
||||
);
|
||||
}
|
||||
@ -432,32 +437,44 @@ mod tests {
|
||||
#[test]
|
||||
fn date_description_date_format_test() {
|
||||
let mut type_option = DateTypeOption::default();
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build();
|
||||
for date_format in DateFormat::iter() {
|
||||
type_option.date_format = date_format;
|
||||
match date_format {
|
||||
DateFormat::Friendly => {
|
||||
assert_eq!(
|
||||
"Mar 14,2022".to_owned(),
|
||||
type_option.decode_cell_data(data(1647251762), &field_meta).content
|
||||
type_option
|
||||
.decode_cell_data(data(1647251762), &FieldType::DateTime, &field_meta)
|
||||
.unwrap()
|
||||
.content
|
||||
);
|
||||
}
|
||||
DateFormat::US => {
|
||||
assert_eq!(
|
||||
"2022/03/14".to_owned(),
|
||||
type_option.decode_cell_data(data(1647251762), &field_meta).content
|
||||
type_option
|
||||
.decode_cell_data(data(1647251762), &FieldType::DateTime, &field_meta)
|
||||
.unwrap()
|
||||
.content
|
||||
);
|
||||
}
|
||||
DateFormat::ISO => {
|
||||
assert_eq!(
|
||||
"2022-03-14".to_owned(),
|
||||
type_option.decode_cell_data(data(1647251762), &field_meta).content
|
||||
type_option
|
||||
.decode_cell_data(data(1647251762), &FieldType::DateTime, &field_meta)
|
||||
.unwrap()
|
||||
.content
|
||||
);
|
||||
}
|
||||
DateFormat::Local => {
|
||||
assert_eq!(
|
||||
"2022/03/14".to_owned(),
|
||||
type_option.decode_cell_data(data(1647251762), &field_meta).content
|
||||
type_option
|
||||
.decode_cell_data(data(1647251762), &FieldType::DateTime, &field_meta)
|
||||
.unwrap()
|
||||
.content
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -467,7 +484,7 @@ mod tests {
|
||||
#[test]
|
||||
fn date_description_time_format_test() {
|
||||
let mut type_option = DateTypeOption::default();
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build();
|
||||
for time_format in TimeFormat::iter() {
|
||||
type_option.time_format = time_format;
|
||||
match time_format {
|
||||
@ -478,7 +495,10 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
"Mar 14,2022".to_owned(),
|
||||
type_option.decode_cell_data(data(1647251762), &field_meta).content
|
||||
type_option
|
||||
.decode_cell_data(data(1647251762), &FieldType::DateTime, &field_meta)
|
||||
.unwrap()
|
||||
.content
|
||||
);
|
||||
}
|
||||
TimeFormat::TwelveHour => {
|
||||
@ -488,7 +508,10 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
"Mar 14,2022".to_owned(),
|
||||
type_option.decode_cell_data(data(1647251762), &field_meta).content
|
||||
type_option
|
||||
.decode_cell_data(data(1647251762), &FieldType::DateTime, &field_meta)
|
||||
.unwrap()
|
||||
.content
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -498,124 +521,171 @@ mod tests {
|
||||
#[test]
|
||||
fn date_description_time_format_test2() {
|
||||
let mut type_option = DateTypeOption::default();
|
||||
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
let field_type = FieldType::DateTime;
|
||||
let field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
|
||||
for time_format in TimeFormat::iter() {
|
||||
type_option.time_format = time_format;
|
||||
type_option.include_time = true;
|
||||
match time_format {
|
||||
TimeFormat::TwentyFourHour => {
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: None,
|
||||
};
|
||||
let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
assert_eq!("May 27,2022 00:00".to_owned(), content);
|
||||
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: Some("23:00".to_owned()),
|
||||
};
|
||||
|
||||
let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
assert_eq!("May 27,2022 23:00".to_owned(), content);
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: None,
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 00:00",
|
||||
);
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: Some("23:00".to_owned()),
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 23:00",
|
||||
);
|
||||
}
|
||||
TimeFormat::TwelveHour => {
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: None,
|
||||
};
|
||||
let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
assert_eq!("May 27,2022 12:00 AM".to_owned(), content);
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: None,
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 12:00 AM",
|
||||
);
|
||||
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: Some("".to_owned()),
|
||||
};
|
||||
let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
assert_eq!("May 27,2022".to_owned(), content);
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: Some("".to_owned()),
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022",
|
||||
);
|
||||
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: Some("11:23 pm".to_owned()),
|
||||
};
|
||||
let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
assert_eq!("May 27,2022 11:23 PM".to_owned(), content);
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(1653609600.to_string()),
|
||||
time: Some("11:23 pm".to_owned()),
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 11:23 PM",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn date_description_apply_changeset_test() {
|
||||
// let mut type_option = DateTypeOption::default();
|
||||
// let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
// let date_timestamp = "1653609600".to_owned();
|
||||
//
|
||||
// let changeset = DateCellContentChangeset {
|
||||
// date: Some(date_timestamp.clone()),
|
||||
// time: None,
|
||||
// };
|
||||
// let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
// let content = type_option.decode_cell_data(result.clone(), &field_meta).content;
|
||||
// assert_eq!(content, "May 27,2022".to_owned());
|
||||
//
|
||||
// type_option.include_time = true;
|
||||
// let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
// assert_eq!(content, "May 27,2022 00:00".to_owned());
|
||||
//
|
||||
// let changeset = DateCellContentChangeset {
|
||||
// date: Some(date_timestamp.clone()),
|
||||
// time: Some("1:00".to_owned()),
|
||||
// };
|
||||
// let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
// let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
// assert_eq!(content, "May 27,2022 01:00".to_owned());
|
||||
//
|
||||
// let changeset = DateCellContentChangeset {
|
||||
// date: Some(date_timestamp),
|
||||
// time: Some("1:00 am".to_owned()),
|
||||
// };
|
||||
// type_option.time_format = TimeFormat::TwelveHour;
|
||||
// let result = type_option.apply_changeset(changeset, None).unwrap();
|
||||
// let content = type_option.decode_cell_data(result, &field_meta).content;
|
||||
// assert_eq!(content, "May 27,2022 01:00 AM".to_owned());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[should_panic]
|
||||
// fn date_description_apply_changeset_error_test() {
|
||||
// let mut type_option = DateTypeOption::default();
|
||||
// type_option.include_time = true;
|
||||
// let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
// let date_timestamp = "1653609600".to_owned();
|
||||
//
|
||||
// let changeset = DateCellContentChangeset {
|
||||
// date: Some(date_timestamp.clone()),
|
||||
// time: Some("1:a0".to_owned()),
|
||||
// };
|
||||
// let _ = type_option.apply_changeset(changeset, None).unwrap();
|
||||
//
|
||||
// let changeset = DateCellContentChangeset {
|
||||
// date: Some(date_timestamp.clone()),
|
||||
// time: Some("1:".to_owned()),
|
||||
// };
|
||||
// let _ = type_option.apply_changeset(changeset, None).unwrap();
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[should_panic]
|
||||
// fn date_description_invalid_data_test() {
|
||||
// let type_option = DateTypeOption::default();
|
||||
// type_option.apply_changeset("he", None).unwrap();
|
||||
// }
|
||||
//
|
||||
fn data(s: i64) -> TypeOptionCellData {
|
||||
let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(s, None)).unwrap();
|
||||
TypeOptionCellData::new(&json, FieldType::DateTime)
|
||||
#[test]
|
||||
fn date_description_apply_changeset_test() {
|
||||
let mut type_option = DateTypeOption::default();
|
||||
let field_type = FieldType::DateTime;
|
||||
let field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
let date_timestamp = "1653609600".to_owned();
|
||||
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(date_timestamp.clone()),
|
||||
time: None,
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022",
|
||||
);
|
||||
|
||||
type_option.include_time = true;
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(date_timestamp.clone()),
|
||||
time: None,
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 00:00",
|
||||
);
|
||||
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(date_timestamp.clone()),
|
||||
time: Some("1:00".to_owned()),
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 01:00",
|
||||
);
|
||||
|
||||
type_option.time_format = TimeFormat::TwelveHour;
|
||||
assert_result(
|
||||
&type_option,
|
||||
DateCellContentChangeset {
|
||||
date: Some(date_timestamp),
|
||||
time: Some("1:00 am".to_owned()),
|
||||
},
|
||||
&field_type,
|
||||
&field_meta,
|
||||
"May 27,2022 01:00 AM",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn date_description_apply_changeset_error_test() {
|
||||
let mut type_option = DateTypeOption::default();
|
||||
type_option.include_time = true;
|
||||
let _field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build();
|
||||
let date_timestamp = "1653609600".to_owned();
|
||||
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(date_timestamp.clone()),
|
||||
time: Some("1:a0".to_owned()),
|
||||
};
|
||||
let _ = type_option.apply_changeset(changeset, None).unwrap();
|
||||
|
||||
let changeset = DateCellContentChangeset {
|
||||
date: Some(date_timestamp),
|
||||
time: Some("1:".to_owned()),
|
||||
};
|
||||
let _ = type_option.apply_changeset(changeset, None).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn date_description_invalid_data_test() {
|
||||
let type_option = DateTypeOption::default();
|
||||
type_option.apply_changeset("he", None).unwrap();
|
||||
}
|
||||
|
||||
fn data(s: i64) -> String {
|
||||
serde_json::to_string(&DateCellDataSerde::from_timestamp(s, None)).unwrap()
|
||||
}
|
||||
|
||||
fn assert_result(
|
||||
type_option: &DateTypeOption,
|
||||
changeset: DateCellContentChangeset,
|
||||
field_type: &FieldType,
|
||||
field_meta: &FieldMeta,
|
||||
expected: &str,
|
||||
) {
|
||||
let encoded_data = EncodedCellData(Some(type_option.apply_changeset(changeset, None).unwrap()));
|
||||
let content = type_option
|
||||
.decode_cell_data(encoded_data, field_type, field_meta)
|
||||
.unwrap()
|
||||
.content;
|
||||
assert_eq!(expected.to_owned(), content);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use crate::impl_type_option;
|
||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
|
||||
use bytes::Bytes;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{
|
||||
CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
|
||||
};
|
||||
@ -76,38 +76,40 @@ pub struct NumberTypeOption {
|
||||
}
|
||||
impl_type_option!(NumberTypeOption, FieldType::Number);
|
||||
|
||||
impl CellDataOperation<String> for NumberTypeOption {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
impl CellDataOperation<String, String> for NumberTypeOption {
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
type_option_cell_data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
_field_meta: &FieldMeta,
|
||||
) -> DecodedCellData {
|
||||
let type_option_cell_data = type_option_cell_data.into();
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
if decoded_field_type.is_date() {
|
||||
return DecodedCellData::default();
|
||||
return Ok(DecodedCellData::default());
|
||||
}
|
||||
|
||||
let cell_data = type_option_cell_data.data;
|
||||
let cell_data = encoded_data.into();
|
||||
match self.format {
|
||||
NumberFormat::Number => {
|
||||
if let Ok(v) = cell_data.parse::<f64>() {
|
||||
return DecodedCellData::from_content(v.to_string());
|
||||
return Ok(DecodedCellData::from_content(v.to_string()));
|
||||
}
|
||||
|
||||
if let Ok(v) = cell_data.parse::<i64>() {
|
||||
return DecodedCellData::from_content(v.to_string());
|
||||
return Ok(DecodedCellData::from_content(v.to_string()));
|
||||
}
|
||||
|
||||
DecodedCellData::default()
|
||||
Ok(DecodedCellData::default())
|
||||
}
|
||||
NumberFormat::Percent => {
|
||||
let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
|
||||
DecodedCellData::from_content(content)
|
||||
Ok(DecodedCellData::from_content(content))
|
||||
}
|
||||
_ => {
|
||||
let content = self.money_from_str(&cell_data);
|
||||
DecodedCellData::from_content(content)
|
||||
Ok(DecodedCellData::from_content(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,163 +618,132 @@ fn make_strip_symbol() -> Vec<String> {
|
||||
symbols
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::services::field::FieldBuilder;
|
||||
// use crate::services::field::{NumberFormat, NumberTypeOption};
|
||||
// use crate::services::row::{CellDataOperation, TypeOptionCellData};
|
||||
// use flowy_grid_data_model::entities::FieldType;
|
||||
// use strum::IntoEnumIterator;
|
||||
//
|
||||
// #[test]
|
||||
// fn number_description_invalid_input_test() {
|
||||
// let type_option = NumberTypeOption::default();
|
||||
// let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
// assert_eq!(
|
||||
// "".to_owned(),
|
||||
// type_option.decode_cell_data(data(""), &field_meta).content
|
||||
// );
|
||||
// assert_eq!(
|
||||
// "".to_owned(),
|
||||
// type_option.decode_cell_data(data("abc"), &field_meta).content
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn number_description_test() {
|
||||
// let mut type_option = NumberTypeOption::default();
|
||||
// let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
// assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
|
||||
// assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
|
||||
// assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
|
||||
//
|
||||
// for format in NumberFormat::iter() {
|
||||
// type_option.format = format;
|
||||
// match format {
|
||||
// NumberFormat::Number => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "18443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::USD => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "$18,443".to_owned()
|
||||
// );
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data(""), &field_meta).content,
|
||||
// "".to_owned()
|
||||
// );
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("abc"), &field_meta).content,
|
||||
// "".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::Yen => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "¥18,443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::Yuan => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "CN¥18,443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::EUR => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "€18.443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn data(s: &str) -> String {
|
||||
// TypeOptionCellData::new(s, FieldType::Number).json()
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn number_description_scale_test() {
|
||||
// let mut type_option = NumberTypeOption {
|
||||
// scale: 1,
|
||||
// ..Default::default()
|
||||
// };
|
||||
// let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
//
|
||||
// for format in NumberFormat::iter() {
|
||||
// type_option.format = format;
|
||||
// match format {
|
||||
// NumberFormat::Number => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "18443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::USD => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "$1,844.3".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::Yen => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "¥1,844.3".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::EUR => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "€1.844,3".to_owned()
|
||||
// );
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn number_description_sign_test() {
|
||||
// let mut type_option = NumberTypeOption {
|
||||
// sign_positive: false,
|
||||
// ..Default::default()
|
||||
// };
|
||||
// let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
|
||||
//
|
||||
// for format in NumberFormat::iter() {
|
||||
// type_option.format = format;
|
||||
// match format {
|
||||
// NumberFormat::Number => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "18443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::USD => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "-$18,443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::Yen => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "-¥18,443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// NumberFormat::EUR => {
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data("18443"), &field_meta).content,
|
||||
// "-€18.443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::services::field::FieldBuilder;
|
||||
use crate::services::field::{NumberFormat, NumberTypeOption};
|
||||
use crate::services::row::CellDataOperation;
|
||||
use flowy_grid_data_model::entities::{FieldMeta, FieldType};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
#[test]
|
||||
fn number_description_invalid_input_test() {
|
||||
let type_option = NumberTypeOption::default();
|
||||
let field_type = FieldType::Number;
|
||||
let field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
assert_equal(&type_option, "", "", &field_type, &field_meta);
|
||||
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_description_test() {
|
||||
let mut type_option = NumberTypeOption::default();
|
||||
let field_type = FieldType::Number;
|
||||
let field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
|
||||
assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
|
||||
assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
|
||||
|
||||
for format in NumberFormat::iter() {
|
||||
type_option.format = format;
|
||||
match format {
|
||||
NumberFormat::Number => {
|
||||
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::USD => {
|
||||
assert_equal(&type_option, "18443", "$18,443", &field_type, &field_meta);
|
||||
assert_equal(&type_option, "", "", &field_type, &field_meta);
|
||||
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::Yen => {
|
||||
assert_equal(&type_option, "18443", "¥18,443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::Yuan => {
|
||||
assert_equal(&type_option, "18443", "CN¥18,443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::EUR => {
|
||||
assert_equal(&type_option, "18443", "€18.443", &field_type, &field_meta);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_description_scale_test() {
|
||||
let mut type_option = NumberTypeOption {
|
||||
scale: 1,
|
||||
..Default::default()
|
||||
};
|
||||
let field_type = FieldType::Number;
|
||||
let field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
|
||||
for format in NumberFormat::iter() {
|
||||
type_option.format = format;
|
||||
match format {
|
||||
NumberFormat::Number => {
|
||||
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::USD => {
|
||||
assert_equal(&type_option, "18443", "$1,844.3", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::Yen => {
|
||||
assert_equal(&type_option, "18443", "¥1,844.3", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::EUR => {
|
||||
assert_equal(&type_option, "18443", "€1.844,3", &field_type, &field_meta);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_description_sign_test() {
|
||||
let mut type_option = NumberTypeOption {
|
||||
sign_positive: false,
|
||||
..Default::default()
|
||||
};
|
||||
let field_type = FieldType::Number;
|
||||
let field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
|
||||
for format in NumberFormat::iter() {
|
||||
type_option.format = format;
|
||||
match format {
|
||||
NumberFormat::Number => {
|
||||
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::USD => {
|
||||
assert_equal(&type_option, "18443", "-$18,443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::Yen => {
|
||||
assert_equal(&type_option, "18443", "-¥18,443", &field_type, &field_meta);
|
||||
}
|
||||
NumberFormat::EUR => {
|
||||
assert_equal(&type_option, "18443", "-€18.443", &field_type, &field_meta);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_equal(
|
||||
type_option: &NumberTypeOption,
|
||||
cell_data: &str,
|
||||
expected_str: &str,
|
||||
field_type: &FieldType,
|
||||
field_meta: &FieldMeta,
|
||||
) {
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(data(cell_data), field_type, field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
expected_str.to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
fn data(s: &str) -> String {
|
||||
s.to_owned()
|
||||
}
|
||||
}
|
||||
|
@ -95,26 +95,30 @@ impl SelectOptionOperation for SingleSelectTypeOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl CellDataOperation<String> for SingleSelectTypeOption {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
impl CellDataOperation<String, String> for SingleSelectTypeOption {
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
type_option_cell_data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
_field_meta: &FieldMeta,
|
||||
) -> DecodedCellData {
|
||||
let type_option_cell_data = type_option_cell_data.into();
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
if !decoded_field_type.is_select_option() {
|
||||
return DecodedCellData::default();
|
||||
return Ok(DecodedCellData::default());
|
||||
}
|
||||
|
||||
if let Some(option_id) = select_option_ids(type_option_cell_data.data).first() {
|
||||
return match self.options.iter().find(|option| &option.id == option_id) {
|
||||
let cell_data = encoded_data.into();
|
||||
if let Some(option_id) = select_option_ids(cell_data).first() {
|
||||
let data = match self.options.iter().find(|option| &option.id == option_id) {
|
||||
None => DecodedCellData::default(),
|
||||
Some(option) => DecodedCellData::from_content(option.name.clone()),
|
||||
};
|
||||
Ok(data)
|
||||
} else {
|
||||
Ok(DecodedCellData::default())
|
||||
}
|
||||
|
||||
DecodedCellData::default()
|
||||
}
|
||||
|
||||
fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
|
||||
@ -187,19 +191,21 @@ impl SelectOptionOperation for MultiSelectTypeOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl CellDataOperation<String> for MultiSelectTypeOption {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
impl CellDataOperation<String, String> for MultiSelectTypeOption {
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
type_option_cell_data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
_field_meta: &FieldMeta,
|
||||
) -> DecodedCellData {
|
||||
let type_option_cell_data = type_option_cell_data.into();
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
if !decoded_field_type.is_select_option() {
|
||||
return DecodedCellData::default();
|
||||
return Ok(DecodedCellData::default());
|
||||
}
|
||||
|
||||
let option_ids = select_option_ids(type_option_cell_data.data);
|
||||
let cell_data = encoded_data.into();
|
||||
let option_ids = select_option_ids(cell_data);
|
||||
let content = self
|
||||
.options
|
||||
.iter()
|
||||
@ -208,7 +214,7 @@ impl CellDataOperation<String> for MultiSelectTypeOption {
|
||||
.collect::<Vec<String>>()
|
||||
.join(SELECTION_IDS_SEPARATOR);
|
||||
|
||||
DecodedCellData::from_content(content)
|
||||
Ok(DecodedCellData::from_content(content))
|
||||
}
|
||||
|
||||
fn apply_changeset<T>(&self, changeset: T, cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
|
||||
@ -491,108 +497,144 @@ fn make_select_context_from(cell_meta: &Option<CellMeta>, options: &[SelectOptio
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::services::field::FieldBuilder;
|
||||
// use crate::services::field::{
|
||||
// MultiSelectTypeOption, MultiSelectTypeOptionBuilder, SelectOption, SelectOptionCellContentChangeset,
|
||||
// SingleSelectTypeOption, SingleSelectTypeOptionBuilder, SELECTION_IDS_SEPARATOR,
|
||||
// };
|
||||
// use crate::services::row::CellDataOperation;
|
||||
//
|
||||
// #[test]
|
||||
// fn single_select_test() {
|
||||
// let google_option = SelectOption::new("Google");
|
||||
// let facebook_option = SelectOption::new("Facebook");
|
||||
// let twitter_option = SelectOption::new("Twitter");
|
||||
// let single_select = SingleSelectTypeOptionBuilder::default()
|
||||
// .option(google_option.clone())
|
||||
// .option(facebook_option.clone())
|
||||
// .option(twitter_option);
|
||||
//
|
||||
// let field_meta = FieldBuilder::new(single_select)
|
||||
// .name("Platform")
|
||||
// .visibility(true)
|
||||
// .build();
|
||||
//
|
||||
// let type_option = SingleSelectTypeOption::from(&field_meta);
|
||||
//
|
||||
// let option_ids = vec![google_option.id.clone(), facebook_option.id].join(SELECTION_IDS_SEPARATOR);
|
||||
// let data = SelectOptionCellContentChangeset::from_insert(&option_ids).to_str();
|
||||
// let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(cell_data, &field_meta).content,
|
||||
// google_option.name,
|
||||
// );
|
||||
//
|
||||
// let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str();
|
||||
// let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(cell_data, &field_meta).content,
|
||||
// google_option.name,
|
||||
// );
|
||||
//
|
||||
// // Invalid option id
|
||||
// let cell_data = type_option
|
||||
// .apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None)
|
||||
// .unwrap();
|
||||
// assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
|
||||
//
|
||||
// // Invalid option id
|
||||
// let cell_data = type_option
|
||||
// .apply_changeset(SelectOptionCellContentChangeset::from_insert("123").to_str(), None)
|
||||
// .unwrap();
|
||||
// assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
|
||||
//
|
||||
// // Invalid changeset
|
||||
// assert!(type_option.apply_changeset("123", None).is_err());
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn multi_select_test() {
|
||||
// let google_option = SelectOption::new("Google");
|
||||
// let facebook_option = SelectOption::new("Facebook");
|
||||
// let twitter_option = SelectOption::new("Twitter");
|
||||
// let multi_select = MultiSelectTypeOptionBuilder::default()
|
||||
// .option(google_option.clone())
|
||||
// .option(facebook_option.clone())
|
||||
// .option(twitter_option);
|
||||
//
|
||||
// let field_meta = FieldBuilder::new(multi_select)
|
||||
// .name("Platform")
|
||||
// .visibility(true)
|
||||
// .build();
|
||||
//
|
||||
// let type_option = MultiSelectTypeOption::from(&field_meta);
|
||||
//
|
||||
// let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
|
||||
// let data = SelectOptionCellContentChangeset::from_insert(&option_ids).to_str();
|
||||
// let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(cell_data, &field_meta).content,
|
||||
// vec![google_option.name.clone(), facebook_option.name].join(SELECTION_IDS_SEPARATOR),
|
||||
// );
|
||||
//
|
||||
// let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str();
|
||||
// let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(cell_data, &field_meta).content,
|
||||
// google_option.name,
|
||||
// );
|
||||
//
|
||||
// // Invalid option id
|
||||
// let cell_data = type_option
|
||||
// .apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None)
|
||||
// .unwrap();
|
||||
// assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
|
||||
//
|
||||
// // Invalid option id
|
||||
// let cell_data = type_option
|
||||
// .apply_changeset(SelectOptionCellContentChangeset::from_insert("123,456").to_str(), None)
|
||||
// .unwrap();
|
||||
// assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
|
||||
//
|
||||
// // Invalid changeset
|
||||
// assert!(type_option.apply_changeset("123", None).is_err());
|
||||
// }
|
||||
// }
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::services::field::FieldBuilder;
|
||||
use crate::services::field::{
|
||||
MultiSelectTypeOption, MultiSelectTypeOptionBuilder, SelectOption, SelectOptionCellContentChangeset,
|
||||
SingleSelectTypeOption, SingleSelectTypeOptionBuilder, SELECTION_IDS_SEPARATOR,
|
||||
};
|
||||
use crate::services::row::CellDataOperation;
|
||||
|
||||
#[test]
|
||||
fn single_select_test() {
|
||||
let google_option = SelectOption::new("Google");
|
||||
let facebook_option = SelectOption::new("Facebook");
|
||||
let twitter_option = SelectOption::new("Twitter");
|
||||
let single_select = SingleSelectTypeOptionBuilder::default()
|
||||
.option(google_option.clone())
|
||||
.option(facebook_option.clone())
|
||||
.option(twitter_option);
|
||||
|
||||
let field_meta = FieldBuilder::new(single_select)
|
||||
.name("Platform")
|
||||
.visibility(true)
|
||||
.build();
|
||||
|
||||
let type_option = SingleSelectTypeOption::from(&field_meta);
|
||||
|
||||
let option_ids = vec![google_option.id.clone(), facebook_option.id].join(SELECTION_IDS_SEPARATOR);
|
||||
let data = SelectOptionCellContentChangeset::from_insert(&option_ids).to_str();
|
||||
let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
google_option.name,
|
||||
);
|
||||
|
||||
let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str();
|
||||
let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
google_option.name,
|
||||
);
|
||||
|
||||
// Invalid option id
|
||||
let cell_data = type_option
|
||||
.apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"",
|
||||
);
|
||||
|
||||
// Invalid option id
|
||||
let cell_data = type_option
|
||||
.apply_changeset(SelectOptionCellContentChangeset::from_insert("123").to_str(), None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"",
|
||||
);
|
||||
|
||||
// Invalid changeset
|
||||
assert!(type_option.apply_changeset("123", None).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_select_test() {
|
||||
let google_option = SelectOption::new("Google");
|
||||
let facebook_option = SelectOption::new("Facebook");
|
||||
let twitter_option = SelectOption::new("Twitter");
|
||||
let multi_select = MultiSelectTypeOptionBuilder::default()
|
||||
.option(google_option.clone())
|
||||
.option(facebook_option.clone())
|
||||
.option(twitter_option);
|
||||
|
||||
let field_meta = FieldBuilder::new(multi_select)
|
||||
.name("Platform")
|
||||
.visibility(true)
|
||||
.build();
|
||||
|
||||
let type_option = MultiSelectTypeOption::from(&field_meta);
|
||||
|
||||
let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
|
||||
let data = SelectOptionCellContentChangeset::from_insert(&option_ids).to_str();
|
||||
let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
vec![google_option.name.clone(), facebook_option.name].join(SELECTION_IDS_SEPARATOR),
|
||||
);
|
||||
|
||||
let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str();
|
||||
let cell_data = type_option.apply_changeset(data, None).unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
google_option.name,
|
||||
);
|
||||
|
||||
// Invalid option id
|
||||
let cell_data = type_option
|
||||
.apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"",
|
||||
);
|
||||
|
||||
// Invalid option id
|
||||
let cell_data = type_option
|
||||
.apply_changeset(SelectOptionCellContentChangeset::from_insert("123,456").to_str(), None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &field_meta.field_type, &field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"",
|
||||
);
|
||||
|
||||
// Invalid changeset
|
||||
assert!(type_option.apply_changeset("123", None).is_err());
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,13 @@
|
||||
use crate::impl_type_option;
|
||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||
use crate::services::row::{
|
||||
decode_cell_data, CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData,
|
||||
};
|
||||
use crate::services::row::{decode_cell_data, CellContentChangeset, CellDataOperation, DecodedCellData};
|
||||
use bytes::Bytes;
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{
|
||||
CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RichTextTypeOptionBuilder(RichTextTypeOption);
|
||||
@ -34,23 +31,25 @@ pub struct RichTextTypeOption {
|
||||
}
|
||||
impl_type_option!(RichTextTypeOption, FieldType::RichText);
|
||||
|
||||
impl CellDataOperation<String> for RichTextTypeOption {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
impl CellDataOperation<String, String> for RichTextTypeOption {
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
type_option_cell_data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
field_meta: &FieldMeta,
|
||||
) -> DecodedCellData {
|
||||
let type_option_cell_data = type_option_cell_data.into();
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
if decoded_field_type.is_date()
|
||||
|| decoded_field_type.is_single_select()
|
||||
|| decoded_field_type.is_multi_select()
|
||||
|| decoded_field_type.is_number()
|
||||
{
|
||||
let field_type = type_option_cell_data.field_type.clone();
|
||||
decode_cell_data(type_option_cell_data, field_meta, &field_type).unwrap_or_default()
|
||||
decode_cell_data(encoded_data, decoded_field_type, decoded_field_type, field_meta)
|
||||
} else {
|
||||
DecodedCellData::from_content(type_option_cell_data.data)
|
||||
let cell_data = encoded_data.into();
|
||||
Ok(DecodedCellData::from_content(cell_data))
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,64 +66,71 @@ impl CellDataOperation<String> for RichTextTypeOption {
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::services::field::FieldBuilder;
|
||||
// use crate::services::field::*;
|
||||
// use crate::services::row::{CellDataOperation, TypeOptionCellData};
|
||||
// use flowy_grid_data_model::entities::FieldType;
|
||||
//
|
||||
// #[test]
|
||||
// fn text_description_test() {
|
||||
// let type_option = RichTextTypeOption::default();
|
||||
//
|
||||
// // date
|
||||
// let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build();
|
||||
// let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(1647251762, None)).unwrap();
|
||||
// let data = TypeOptionCellData::new(&json, FieldType::DateTime).json();
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data, &date_time_field_meta).content,
|
||||
// "Mar 14,2022".to_owned()
|
||||
// );
|
||||
//
|
||||
// // Single select
|
||||
// let done_option = SelectOption::new("Done");
|
||||
// let done_option_id = done_option.id.clone();
|
||||
// let single_select = SingleSelectTypeOptionBuilder::default().option(done_option);
|
||||
// let single_select_field_meta = FieldBuilder::new(single_select).build();
|
||||
// let cell_data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json();
|
||||
// assert_eq!(
|
||||
// type_option
|
||||
// .decode_cell_data(cell_data, &single_select_field_meta)
|
||||
// .content,
|
||||
// "Done".to_owned()
|
||||
// );
|
||||
//
|
||||
// // Multiple select
|
||||
// let google_option = SelectOption::new("Google");
|
||||
// let facebook_option = SelectOption::new("Facebook");
|
||||
// let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
|
||||
// let cell_data_changeset = SelectOptionCellContentChangeset::from_insert(&ids).to_str();
|
||||
// let multi_select = MultiSelectTypeOptionBuilder::default()
|
||||
// .option(google_option)
|
||||
// .option(facebook_option);
|
||||
// let multi_select_field_meta = FieldBuilder::new(multi_select).build();
|
||||
// let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta);
|
||||
// let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap();
|
||||
// assert_eq!(
|
||||
// type_option
|
||||
// .decode_cell_data(cell_data, &multi_select_field_meta)
|
||||
// .content,
|
||||
// "Google,Facebook".to_owned()
|
||||
// );
|
||||
//
|
||||
// //Number
|
||||
// let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
|
||||
// let number_field_meta = FieldBuilder::new(number).build();
|
||||
// let data = TypeOptionCellData::new("18443", FieldType::Number).json();
|
||||
// assert_eq!(
|
||||
// type_option.decode_cell_data(data, &number_field_meta).content,
|
||||
// "$18,443".to_owned()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::services::field::FieldBuilder;
|
||||
use crate::services::field::*;
|
||||
use crate::services::row::CellDataOperation;
|
||||
use flowy_grid_data_model::entities::FieldType;
|
||||
|
||||
#[test]
|
||||
fn text_description_test() {
|
||||
let type_option = RichTextTypeOption::default();
|
||||
|
||||
// date
|
||||
let field_type = FieldType::DateTime;
|
||||
let date_time_field_meta = FieldBuilder::from_field_type(&field_type).build();
|
||||
let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(1647251762, None)).unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(json, &field_type, &date_time_field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"Mar 14,2022".to_owned()
|
||||
);
|
||||
|
||||
// Single select
|
||||
let done_option = SelectOption::new("Done");
|
||||
let done_option_id = done_option.id.clone();
|
||||
let single_select = SingleSelectTypeOptionBuilder::default().option(done_option);
|
||||
let single_select_field_meta = FieldBuilder::new(single_select).build();
|
||||
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(done_option_id, &FieldType::SingleSelect, &single_select_field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"Done".to_owned()
|
||||
);
|
||||
|
||||
// Multiple select
|
||||
let google_option = SelectOption::new("Google");
|
||||
let facebook_option = SelectOption::new("Facebook");
|
||||
let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
|
||||
let cell_data_changeset = SelectOptionCellContentChangeset::from_insert(&ids).to_str();
|
||||
let multi_select = MultiSelectTypeOptionBuilder::default()
|
||||
.option(google_option)
|
||||
.option(facebook_option);
|
||||
let multi_select_field_meta = FieldBuilder::new(multi_select).build();
|
||||
let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta);
|
||||
let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data(cell_data, &FieldType::MultiSelect, &multi_select_field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"Google,Facebook".to_owned()
|
||||
);
|
||||
|
||||
//Number
|
||||
let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
|
||||
let number_field_meta = FieldBuilder::new(number).build();
|
||||
assert_eq!(
|
||||
type_option
|
||||
.decode_cell_data("18443".to_owned(), &FieldType::Number, &number_field_meta)
|
||||
.unwrap()
|
||||
.content,
|
||||
"$18,443".to_owned()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,26 @@
|
||||
use crate::services::field::*;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Formatter;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub trait CellDataOperation<D, CO: ToString> {
|
||||
fn decode_cell_data<T: Into<TypeOptionCellData>>(
|
||||
fn decode_cell_data<T>(
|
||||
&self,
|
||||
data: T,
|
||||
encoded_data: T,
|
||||
decoded_field_type: &FieldType,
|
||||
field_meta: &FieldMeta,
|
||||
) -> DecodedCellData;
|
||||
) -> FlowyResult<DecodedCellData>
|
||||
where
|
||||
T: Into<D>;
|
||||
|
||||
//
|
||||
fn apply_changeset<C: Into<CellContentChangeset>>(
|
||||
&self,
|
||||
changeset: C,
|
||||
cell_meta: Option<CellMeta>,
|
||||
) -> Result<CO, FlowyError>;
|
||||
) -> FlowyResult<CO>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -72,14 +76,6 @@ impl std::convert::TryInto<TypeOptionCellData> for String {
|
||||
}
|
||||
}
|
||||
|
||||
// impl std::convert::Into<TypeOptionCellData> for String {
|
||||
// type Error = FlowyError;
|
||||
//
|
||||
// fn try_into(self) -> Result<TypeOptionCellData, Self::Error> {
|
||||
// TypeOptionCellData::from_str(&self)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl TypeOptionCellData {
|
||||
pub fn new<T: ToString>(data: T, field_type: FieldType) -> Self {
|
||||
TypeOptionCellData {
|
||||
@ -142,40 +138,89 @@ pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
|
||||
Ok(TypeOptionCellData::new(s, field_meta.field_type.clone()).json())
|
||||
}
|
||||
|
||||
pub fn decode_cell_data<T: TryInto<TypeOptionCellData>>(
|
||||
pub fn decode_cell_data_from_type_option_cell_data<T: TryInto<TypeOptionCellData>>(
|
||||
data: T,
|
||||
field_meta: &FieldMeta,
|
||||
field_type: &FieldType,
|
||||
) -> Option<DecodedCellData> {
|
||||
) -> DecodedCellData {
|
||||
if let Ok(type_option_cell_data) = data.try_into() {
|
||||
let (decoded_field_type, data) = &type_option_cell_data.split();
|
||||
let s = match field_type {
|
||||
FieldType::RichText => field_meta
|
||||
.get_type_option_entry::<RichTextTypeOption>(field_type)?
|
||||
.decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
|
||||
FieldType::Number => field_meta
|
||||
.get_type_option_entry::<NumberTypeOption>(field_type)?
|
||||
.decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
|
||||
FieldType::DateTime => field_meta
|
||||
.get_type_option_entry::<DateTypeOption>(field_type)?
|
||||
.decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
|
||||
FieldType::SingleSelect => field_meta
|
||||
.get_type_option_entry::<SingleSelectTypeOption>(field_type)?
|
||||
.decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
|
||||
FieldType::MultiSelect => field_meta
|
||||
.get_type_option_entry::<MultiSelectTypeOption>(field_type)?
|
||||
.decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
|
||||
FieldType::Checkbox => field_meta
|
||||
.get_type_option_entry::<CheckboxTypeOption>(field_type)?
|
||||
.decode_cell_data(type_option_cell_data, decoded_field_type, field_meta),
|
||||
};
|
||||
tracing::Span::current().record(
|
||||
"content",
|
||||
&format!("{:?}: {}", field_meta.field_type, s.content).as_str(),
|
||||
);
|
||||
Some(s)
|
||||
let (encoded_data, s_field_type) = type_option_cell_data.split();
|
||||
decode_cell_data(encoded_data, &s_field_type, field_type, field_meta).unwrap_or_default()
|
||||
} else {
|
||||
Some(DecodedCellData::default())
|
||||
DecodedCellData::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_cell_data<T: Into<String>>(
|
||||
encoded_data: T,
|
||||
s_field_type: &FieldType,
|
||||
t_field_type: &FieldType,
|
||||
field_meta: &FieldMeta,
|
||||
) -> FlowyResult<DecodedCellData> {
|
||||
let encoded_data = encoded_data.into();
|
||||
let get_cell_data = || {
|
||||
let data = match t_field_type {
|
||||
FieldType::RichText => field_meta
|
||||
.get_type_option_entry::<RichTextTypeOption>(t_field_type)?
|
||||
.decode_cell_data(encoded_data, s_field_type, field_meta),
|
||||
FieldType::Number => field_meta
|
||||
.get_type_option_entry::<NumberTypeOption>(t_field_type)?
|
||||
.decode_cell_data(encoded_data, s_field_type, field_meta),
|
||||
FieldType::DateTime => field_meta
|
||||
.get_type_option_entry::<DateTypeOption>(t_field_type)?
|
||||
.decode_cell_data(encoded_data, s_field_type, field_meta),
|
||||
FieldType::SingleSelect => field_meta
|
||||
.get_type_option_entry::<SingleSelectTypeOption>(t_field_type)?
|
||||
.decode_cell_data(encoded_data, s_field_type, field_meta),
|
||||
FieldType::MultiSelect => field_meta
|
||||
.get_type_option_entry::<MultiSelectTypeOption>(t_field_type)?
|
||||
.decode_cell_data(encoded_data, s_field_type, field_meta),
|
||||
FieldType::Checkbox => field_meta
|
||||
.get_type_option_entry::<CheckboxTypeOption>(t_field_type)?
|
||||
.decode_cell_data(encoded_data, s_field_type, field_meta),
|
||||
};
|
||||
Some(data)
|
||||
};
|
||||
|
||||
match get_cell_data() {
|
||||
Some(Ok(data)) => {
|
||||
tracing::Span::current().record(
|
||||
"content",
|
||||
&format!("{:?}: {}", field_meta.field_type, data.content).as_str(),
|
||||
);
|
||||
Ok(data)
|
||||
}
|
||||
Some(Err(err)) => {
|
||||
tracing::error!("{:?}", err);
|
||||
Ok(DecodedCellData::default())
|
||||
}
|
||||
None => Ok(DecodedCellData::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct EncodedCellData<T>(pub Option<T>);
|
||||
|
||||
impl<T> EncodedCellData<T> {
|
||||
pub fn try_into_inner(self) -> FlowyResult<T> {
|
||||
match self.0 {
|
||||
None => Err(ErrorCode::InvalidData.into()),
|
||||
Some(data) => Ok(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::convert::From<String> for EncodedCellData<T>
|
||||
where
|
||||
T: FromStr<Err = FlowyError>,
|
||||
{
|
||||
fn from(s: String) -> Self {
|
||||
match T::from_str(&s) {
|
||||
Ok(inner) => EncodedCellData(Some(inner)),
|
||||
Err(e) => {
|
||||
tracing::error!("Deserialize Cell Data failed: {}", e);
|
||||
EncodedCellData(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::services::row::decode_cell_data;
|
||||
use crate::services::row::decode_cell_data_from_type_option_cell_data;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::entities::{
|
||||
Cell, CellMeta, FieldMeta, GridBlock, GridBlockOrder, RepeatedGridBlock, Row, RowMeta, RowOrder,
|
||||
@ -31,14 +31,16 @@ pub fn make_cell_by_field_id(
|
||||
cell_meta: CellMeta,
|
||||
) -> Option<(String, Cell)> {
|
||||
let field_meta = field_map.get(&field_id)?;
|
||||
let (raw, content) = decode_cell_data(cell_meta.data, field_meta, &field_meta.field_type)?.split();
|
||||
let (raw, content) =
|
||||
decode_cell_data_from_type_option_cell_data(cell_meta.data, field_meta, &field_meta.field_type).split();
|
||||
let cell = Cell::new(&field_id, content, raw);
|
||||
Some((field_id, cell))
|
||||
}
|
||||
|
||||
pub fn make_cell(field_id: &str, field_meta: &FieldMeta, row_meta: &RowMeta) -> Option<Cell> {
|
||||
let cell_meta = row_meta.cells.get(field_id)?.clone();
|
||||
let (raw, content) = decode_cell_data(cell_meta.data, field_meta, &field_meta.field_type)?.split();
|
||||
let (raw, content) =
|
||||
decode_cell_data_from_type_option_cell_data(cell_meta.data, field_meta, &field_meta.field_type).split();
|
||||
Some(Cell::new(field_id, content, raw))
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use flowy_grid::services::field::{
|
||||
DateCellContentChangeset, MultiSelectTypeOption, SelectOption, SelectOptionCellContentChangeset,
|
||||
SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
|
||||
};
|
||||
use flowy_grid::services::row::{decode_cell_data, CreateRowMetaBuilder};
|
||||
use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowMetaBuilder};
|
||||
use flowy_grid_data_model::entities::{
|
||||
CellChangeset, FieldChangesetParams, FieldType, GridBlockMeta, GridBlockMetaChangeset, RowMetaChangeset,
|
||||
TypeOptionDataEntry,
|
||||
@ -291,8 +291,7 @@ async fn grid_row_add_date_cell_test() {
|
||||
let date_field = date_field.unwrap();
|
||||
let cell_data = context.cell_by_field_id.get(&date_field.id).unwrap().clone();
|
||||
assert_eq!(
|
||||
decode_cell_data(cell_data.data.clone(), &date_field, &date_field.field_type)
|
||||
.unwrap()
|
||||
decode_cell_data_from_type_option_cell_data(cell_data.data.clone(), &date_field, &date_field.field_type)
|
||||
.split()
|
||||
.1,
|
||||
"2022/03/16",
|
||||
|
@ -912,6 +912,34 @@ impl FieldType {
|
||||
_ => 150,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_number(&self) -> bool {
|
||||
self == &FieldType::Number
|
||||
}
|
||||
|
||||
pub fn is_text(&self) -> bool {
|
||||
self == &FieldType::RichText
|
||||
}
|
||||
|
||||
pub fn is_checkbox(&self) -> bool {
|
||||
self == &FieldType::Checkbox
|
||||
}
|
||||
|
||||
pub fn is_date(&self) -> bool {
|
||||
self == &FieldType::DateTime
|
||||
}
|
||||
|
||||
pub fn is_single_select(&self) -> bool {
|
||||
self == &FieldType::SingleSelect
|
||||
}
|
||||
|
||||
pub fn is_multi_select(&self) -> bool {
|
||||
self == &FieldType::MultiSelect
|
||||
}
|
||||
|
||||
pub fn is_select_option(&self) -> bool {
|
||||
self == &FieldType::MultiSelect || self == &FieldType::SingleSelect
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, ProtoBuf)]
|
||||
|
@ -153,27 +153,22 @@ pub fn check_pb_dart_plugin() {
|
||||
let output = Command::new("sh").arg("-c").arg("echo $PATH").output();
|
||||
let paths = String::from_utf8(output.unwrap().stdout)
|
||||
.unwrap()
|
||||
.split(":")
|
||||
.split(':')
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
paths.iter().for_each(|s| msg.push_str(&format!("{}\n", s)));
|
||||
|
||||
match Command::new("sh").arg("-c").arg("which protoc-gen-dart").output() {
|
||||
Ok(output) => {
|
||||
msg.push_str(&format!(
|
||||
"Installed protoc-gen-dart path: {:?}\n",
|
||||
String::from_utf8(output.stdout).unwrap()
|
||||
));
|
||||
}
|
||||
Err(_) => {}
|
||||
if let Ok(output) = Command::new("sh").arg("-c").arg("which protoc-gen-dart").output() {
|
||||
msg.push_str(&format!(
|
||||
"Installed protoc-gen-dart path: {:?}\n",
|
||||
String::from_utf8(output.stdout).unwrap()
|
||||
));
|
||||
}
|
||||
|
||||
msg.push_str(&format!("✅ You can fix that by adding:"));
|
||||
msg.push_str(&format!("\n\texport PATH=\"$PATH\":\"$HOME/.pub-cache/bin\"\n",));
|
||||
msg.push_str(&format!(
|
||||
"to your shell's config file.(.bashrc, .bash, .profile, .zshrc etc.)"
|
||||
));
|
||||
msg.push_str(&"✅ You can fix that by adding:".to_string());
|
||||
msg.push_str(&"\n\texport PATH=\"$PATH\":\"$HOME/.pub-cache/bin\"\n".to_string());
|
||||
msg.push_str(&"to your shell's config file.(.bashrc, .bash, .profile, .zshrc etc.)".to_string());
|
||||
panic!("{}", msg)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user