refactor: grid unit test

This commit is contained in:
appflowy
2022-05-22 23:33:08 +08:00
parent f521c18512
commit 1ae0b188b1
6 changed files with 614 additions and 539 deletions

View File

@ -44,15 +44,18 @@ const YES: &str = "Yes";
const NO: &str = "No"; const NO: &str = "No";
impl CellDataOperation for CheckboxTypeOption { impl CellDataOperation for CheckboxTypeOption {
fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> DecodedCellData { fn decode_cell_data<T: Into<TypeOptionCellData>>(
if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { &self,
if !type_option_cell_data.is_checkbox() { type_option_cell_data: T,
return DecodedCellData::default(); _field_meta: &FieldMeta,
} ) -> DecodedCellData {
let cell_data = type_option_cell_data.data; let type_option_cell_data = type_option_cell_data.into();
if cell_data == YES || cell_data == NO { if !type_option_cell_data.is_checkbox() {
return DecodedCellData::from_content(cell_data); return DecodedCellData::default();
} }
let cell_data = type_option_cell_data.data;
if cell_data == YES || cell_data == NO {
return DecodedCellData::from_content(cell_data);
} }
DecodedCellData::default() DecodedCellData::default()
@ -68,7 +71,7 @@ impl CellDataOperation for CheckboxTypeOption {
true => YES, true => YES,
false => NO, false => NO,
}; };
Ok(TypeOptionCellData::new(s, self.field_type()).json()) Ok(s.to_string())
} }
} }
@ -90,30 +93,59 @@ mod tests {
use crate::services::field::type_options::checkbox_type_option::{NO, YES}; use crate::services::field::type_options::checkbox_type_option::{NO, YES};
use crate::services::field::CheckboxTypeOption; use crate::services::field::CheckboxTypeOption;
use crate::services::field::FieldBuilder; use crate::services::field::FieldBuilder;
use crate::services::row::CellDataOperation; use crate::services::row::{apply_cell_data_changeset, decode_cell_data, CellDataOperation};
use diesel::types::IsNull::No;
use flowy_grid_data_model::entities::FieldType; use flowy_grid_data_model::entities::FieldType;
#[test] #[test]
fn checkout_box_description_test() { fn checkout_box_description_test() {
let type_option = CheckboxTypeOption::default(); let field_meta = FieldBuilder::from_field_type(&FieldType::Checkbox).build();
let field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).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,
YES
);
let data = type_option.apply_changeset("true", None).unwrap(); let data = apply_cell_data_changeset("1", None, &field_meta).unwrap();
assert_eq!(type_option.decode_cell_data(data, &field_meta).content, YES); assert_eq!(
decode_cell_data(data, &field_meta, &field_meta.field_type)
.unwrap()
.content,
YES
);
let data = type_option.apply_changeset("1", None).unwrap(); let data = apply_cell_data_changeset("yes", None, &field_meta).unwrap();
assert_eq!(type_option.decode_cell_data(data, &field_meta).content, YES); assert_eq!(
decode_cell_data(data, &field_meta, &field_meta.field_type)
.unwrap()
.content,
YES
);
let data = type_option.apply_changeset("yes", None).unwrap(); let data = apply_cell_data_changeset("false", None, &field_meta).unwrap();
assert_eq!(type_option.decode_cell_data(data, &field_meta).content, YES); assert_eq!(
decode_cell_data(data, &field_meta, &field_meta.field_type)
.unwrap()
.content,
NO
);
let data = type_option.apply_changeset("false", None).unwrap(); let data = apply_cell_data_changeset("no", None, &field_meta).unwrap();
assert_eq!(type_option.decode_cell_data(data, &field_meta).content, NO); assert_eq!(
decode_cell_data(data, &field_meta, &field_meta.field_type)
.unwrap()
.content,
NO
);
let data = type_option.apply_changeset("no", None).unwrap(); let data = apply_cell_data_changeset("12", None, &field_meta).unwrap();
assert_eq!(type_option.decode_cell_data(data, &field_meta).content, NO); assert_eq!(
decode_cell_data(data, &field_meta, &field_meta.field_type)
let data = type_option.apply_changeset("123", None).unwrap(); .unwrap()
assert_eq!(type_option.decode_cell_data(data, &field_meta).content, NO); .content,
NO
);
} }
} }

View File

@ -136,22 +136,23 @@ impl DateTypeOption {
} }
impl CellDataOperation for DateTypeOption { impl CellDataOperation for DateTypeOption {
fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> DecodedCellData { fn decode_cell_data<T: Into<TypeOptionCellData>>(
if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { &self,
// Return default data if the type_option_cell_data is not FieldType::DateTime. type_option_cell_data: T,
// It happens when switching from one field to another. _field_meta: &FieldMeta,
// For example: ) -> DecodedCellData {
// FieldType::RichText -> FieldType::DateTime, it will display empty content on the screen. let type_option_cell_data = type_option_cell_data.into();
if !type_option_cell_data.is_date() { // Return default data if the type_option_cell_data is not FieldType::DateTime.
return DecodedCellData::default(); // It happens when switching from one field to another.
} // For example:
return match DateCellDataSerde::from_str(&type_option_cell_data.data) { // FieldType::RichText -> FieldType::DateTime, it will display empty content on the screen.
Ok(serde_cell_data) => self.decode_cell_data_from_timestamp(&serde_cell_data), if !type_option_cell_data.is_date() {
Err(_) => DecodedCellData::default(), 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(),
} }
DecodedCellData::default()
} }
fn apply_changeset<T: Into<CellContentChangeset>>( fn apply_changeset<T: Into<CellContentChangeset>>(
@ -173,7 +174,7 @@ impl CellDataOperation for DateTypeOption {
}, },
}; };
Ok(TypeOptionCellData::new(cell_data.to_string(), self.field_type()).json()) Ok(cell_data.to_string())
} }
} }
@ -410,17 +411,19 @@ mod tests {
use crate::services::field::{ use crate::services::field::{
DateCellContentChangeset, DateCellData, DateCellDataSerde, DateFormat, DateTypeOption, TimeFormat, DateCellContentChangeset, DateCellData, DateCellDataSerde, DateFormat, DateTypeOption, TimeFormat,
}; };
use crate::services::row::{CellDataOperation, TypeOptionCellData}; 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::FieldType;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
#[test] #[test]
fn date_description_invalid_input_test() { fn date_description_invalid_input_test() {
let type_option = DateTypeOption::default();
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
let data = apply_cell_data_changeset("1e", None, &field_meta).unwrap();
assert_eq!( assert_eq!(
"".to_owned(), decode_cell_data(data, &field_meta, &field_meta.field_type)
type_option.decode_cell_data("1e".to_owned(), &field_meta).content .unwrap()
.content,
"".to_owned()
); );
} }
@ -545,72 +548,72 @@ mod tests {
} }
} }
#[test] // #[test]
fn date_description_apply_changeset_test() { // fn date_description_apply_changeset_test() {
let mut type_option = DateTypeOption::default(); // let mut type_option = DateTypeOption::default();
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
let date_timestamp = "1653609600".to_owned(); // let date_timestamp = "1653609600".to_owned();
//
let changeset = DateCellContentChangeset { // let changeset = DateCellContentChangeset {
date: Some(date_timestamp.clone()), // date: Some(date_timestamp.clone()),
time: None, // time: None,
}; // };
let result = type_option.apply_changeset(changeset, None).unwrap(); // let result = type_option.apply_changeset(changeset, None).unwrap();
let content = type_option.decode_cell_data(result.clone(), &field_meta).content; // let content = type_option.decode_cell_data(result.clone(), &field_meta).content;
assert_eq!(content, "May 27,2022".to_owned()); // assert_eq!(content, "May 27,2022".to_owned());
//
type_option.include_time = true; // type_option.include_time = true;
let content = type_option.decode_cell_data(result, &field_meta).content; // let content = type_option.decode_cell_data(result, &field_meta).content;
assert_eq!(content, "May 27,2022 00:00".to_owned()); // assert_eq!(content, "May 27,2022 00:00".to_owned());
//
let changeset = DateCellContentChangeset { // let changeset = DateCellContentChangeset {
date: Some(date_timestamp.clone()), // date: Some(date_timestamp.clone()),
time: Some("1:00".to_owned()), // time: Some("1:00".to_owned()),
}; // };
let result = type_option.apply_changeset(changeset, None).unwrap(); // let result = type_option.apply_changeset(changeset, None).unwrap();
let content = type_option.decode_cell_data(result, &field_meta).content; // let content = type_option.decode_cell_data(result, &field_meta).content;
assert_eq!(content, "May 27,2022 01:00".to_owned()); // assert_eq!(content, "May 27,2022 01:00".to_owned());
//
let changeset = DateCellContentChangeset { // let changeset = DateCellContentChangeset {
date: Some(date_timestamp), // date: Some(date_timestamp),
time: Some("1:00 am".to_owned()), // time: Some("1:00 am".to_owned()),
}; // };
type_option.time_format = TimeFormat::TwelveHour; // type_option.time_format = TimeFormat::TwelveHour;
let result = type_option.apply_changeset(changeset, None).unwrap(); // let result = type_option.apply_changeset(changeset, None).unwrap();
let content = type_option.decode_cell_data(result, &field_meta).content; // let content = type_option.decode_cell_data(result, &field_meta).content;
assert_eq!(content, "May 27,2022 01:00 AM".to_owned()); // assert_eq!(content, "May 27,2022 01:00 AM".to_owned());
} // }
//
#[test] // #[test]
#[should_panic] // #[should_panic]
fn date_description_apply_changeset_error_test() { // fn date_description_apply_changeset_error_test() {
let mut type_option = DateTypeOption::default(); // let mut type_option = DateTypeOption::default();
type_option.include_time = true; // type_option.include_time = true;
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
let date_timestamp = "1653609600".to_owned(); // let date_timestamp = "1653609600".to_owned();
//
let changeset = DateCellContentChangeset { // let changeset = DateCellContentChangeset {
date: Some(date_timestamp.clone()), // date: Some(date_timestamp.clone()),
time: Some("1:a0".to_owned()), // time: Some("1:a0".to_owned()),
}; // };
let _ = type_option.apply_changeset(changeset, None).unwrap(); // let _ = type_option.apply_changeset(changeset, None).unwrap();
//
let changeset = DateCellContentChangeset { // let changeset = DateCellContentChangeset {
date: Some(date_timestamp.clone()), // date: Some(date_timestamp.clone()),
time: Some("1:".to_owned()), // time: Some("1:".to_owned()),
}; // };
let _ = type_option.apply_changeset(changeset, None).unwrap(); // let _ = type_option.apply_changeset(changeset, None).unwrap();
} // }
//
#[test] // #[test]
#[should_panic] // #[should_panic]
fn date_description_invalid_data_test() { // fn date_description_invalid_data_test() {
let type_option = DateTypeOption::default(); // let type_option = DateTypeOption::default();
type_option.apply_changeset("he", None).unwrap(); // type_option.apply_changeset("he", None).unwrap();
} // }
//
fn data(s: i64) -> String { fn data(s: i64) -> TypeOptionCellData {
let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(s, None)).unwrap(); let json = serde_json::to_string(&DateCellDataSerde::from_timestamp(s, None)).unwrap();
TypeOptionCellData::new(&json, FieldType::DateTime).json() TypeOptionCellData::new(&json, FieldType::DateTime)
} }
} }

View File

@ -77,36 +77,37 @@ pub struct NumberTypeOption {
impl_type_option!(NumberTypeOption, FieldType::Number); impl_type_option!(NumberTypeOption, FieldType::Number);
impl CellDataOperation for NumberTypeOption { impl CellDataOperation for NumberTypeOption {
fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> DecodedCellData { fn decode_cell_data<T: Into<TypeOptionCellData>>(
if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { &self,
if type_option_cell_data.is_date() { type_option_cell_data: T,
return DecodedCellData::default(); _field_meta: &FieldMeta,
) -> DecodedCellData {
let type_option_cell_data = type_option_cell_data.into();
if type_option_cell_data.is_date() {
return DecodedCellData::default();
}
let cell_data = type_option_cell_data.data;
match self.format {
NumberFormat::Number => {
if let Ok(v) = cell_data.parse::<f64>() {
return DecodedCellData::from_content(v.to_string());
}
if let Ok(v) = cell_data.parse::<i64>() {
return DecodedCellData::from_content(v.to_string());
}
DecodedCellData::default()
} }
NumberFormat::Percent => {
let cell_data = type_option_cell_data.data; let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
match self.format { DecodedCellData::from_content(content)
NumberFormat::Number => { }
if let Ok(v) = cell_data.parse::<f64>() { _ => {
return DecodedCellData::from_content(v.to_string()); let content = self.money_from_str(&cell_data);
} DecodedCellData::from_content(content)
if let Ok(v) = cell_data.parse::<i64>() {
return DecodedCellData::from_content(v.to_string());
}
DecodedCellData::default()
}
NumberFormat::Percent => {
let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
DecodedCellData::from_content(content)
}
_ => {
let content = self.money_from_str(&cell_data);
DecodedCellData::from_content(content)
}
} }
} else {
DecodedCellData::default()
} }
} }
@ -125,7 +126,7 @@ impl CellDataOperation for NumberTypeOption {
} }
} }
Ok(TypeOptionCellData::new(&data, self.field_type()).json()) Ok(data)
} }
} }
@ -615,163 +616,163 @@ fn make_strip_symbol() -> Vec<String> {
symbols symbols
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use crate::services::field::FieldBuilder; // use crate::services::field::FieldBuilder;
use crate::services::field::{NumberFormat, NumberTypeOption}; // use crate::services::field::{NumberFormat, NumberTypeOption};
use crate::services::row::{CellDataOperation, TypeOptionCellData}; // use crate::services::row::{CellDataOperation, TypeOptionCellData};
use flowy_grid_data_model::entities::FieldType; // use flowy_grid_data_model::entities::FieldType;
use strum::IntoEnumIterator; // use strum::IntoEnumIterator;
//
#[test] // #[test]
fn number_description_invalid_input_test() { // fn number_description_invalid_input_test() {
let type_option = NumberTypeOption::default(); // let type_option = NumberTypeOption::default();
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
assert_eq!( // assert_eq!(
"".to_owned(), // "".to_owned(),
type_option.decode_cell_data(data(""), &field_meta).content // type_option.decode_cell_data(data(""), &field_meta).content
); // );
assert_eq!( // assert_eq!(
"".to_owned(), // "".to_owned(),
type_option.decode_cell_data(data("abc"), &field_meta).content // type_option.decode_cell_data(data("abc"), &field_meta).content
); // );
} // }
//
#[test] // #[test]
fn number_description_test() { // fn number_description_test() {
let mut type_option = NumberTypeOption::default(); // let mut type_option = NumberTypeOption::default();
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // 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()); // 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() { // for format in NumberFormat::iter() {
type_option.format = format; // type_option.format = format;
match format { // match format {
NumberFormat::Number => { // NumberFormat::Number => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"18443".to_owned() // "18443".to_owned()
); // );
} // }
NumberFormat::USD => { // NumberFormat::USD => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"$18,443".to_owned() // "$18,443".to_owned()
); // );
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data(""), &field_meta).content, // type_option.decode_cell_data(data(""), &field_meta).content,
"".to_owned() // "".to_owned()
); // );
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("abc"), &field_meta).content, // type_option.decode_cell_data(data("abc"), &field_meta).content,
"".to_owned() // "".to_owned()
); // );
} // }
NumberFormat::Yen => { // NumberFormat::Yen => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"¥18,443".to_owned() // "¥18,443".to_owned()
); // );
} // }
NumberFormat::Yuan => { // NumberFormat::Yuan => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"CN¥18,443".to_owned() // "CN¥18,443".to_owned()
); // );
} // }
NumberFormat::EUR => { // NumberFormat::EUR => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"€18.443".to_owned() // "€18.443".to_owned()
); // );
} // }
_ => {} // _ => {}
} // }
} // }
} // }
//
fn data(s: &str) -> String { // fn data(s: &str) -> String {
TypeOptionCellData::new(s, FieldType::Number).json() // TypeOptionCellData::new(s, FieldType::Number).json()
} // }
//
#[test] // #[test]
fn number_description_scale_test() { // fn number_description_scale_test() {
let mut type_option = NumberTypeOption { // let mut type_option = NumberTypeOption {
scale: 1, // scale: 1,
..Default::default() // ..Default::default()
}; // };
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
//
for format in NumberFormat::iter() { // for format in NumberFormat::iter() {
type_option.format = format; // type_option.format = format;
match format { // match format {
NumberFormat::Number => { // NumberFormat::Number => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"18443".to_owned() // "18443".to_owned()
); // );
} // }
NumberFormat::USD => { // NumberFormat::USD => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"$1,844.3".to_owned() // "$1,844.3".to_owned()
); // );
} // }
NumberFormat::Yen => { // NumberFormat::Yen => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"¥1,844.3".to_owned() // "¥1,844.3".to_owned()
); // );
} // }
NumberFormat::EUR => { // NumberFormat::EUR => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"€1.844,3".to_owned() // "€1.844,3".to_owned()
); // );
} // }
_ => {} // _ => {}
} // }
} // }
} // }
//
#[test] // #[test]
fn number_description_sign_test() { // fn number_description_sign_test() {
let mut type_option = NumberTypeOption { // let mut type_option = NumberTypeOption {
sign_positive: false, // sign_positive: false,
..Default::default() // ..Default::default()
}; // };
let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build(); // let field_meta = FieldBuilder::from_field_type(&FieldType::Number).build();
//
for format in NumberFormat::iter() { // for format in NumberFormat::iter() {
type_option.format = format; // type_option.format = format;
match format { // match format {
NumberFormat::Number => { // NumberFormat::Number => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"18443".to_owned() // "18443".to_owned()
); // );
} // }
NumberFormat::USD => { // NumberFormat::USD => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"-$18,443".to_owned() // "-$18,443".to_owned()
); // );
} // }
NumberFormat::Yen => { // NumberFormat::Yen => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"-¥18,443".to_owned() // "-¥18,443".to_owned()
); // );
} // }
NumberFormat::EUR => { // NumberFormat::EUR => {
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data("18443"), &field_meta).content, // type_option.decode_cell_data(data("18443"), &field_meta).content,
"-€18.443".to_owned() // "-€18.443".to_owned()
); // );
} // }
_ => {} // _ => {}
} // }
} // }
} // }
} // }

View File

@ -96,18 +96,21 @@ impl SelectOptionOperation for SingleSelectTypeOption {
} }
impl CellDataOperation for SingleSelectTypeOption { impl CellDataOperation for SingleSelectTypeOption {
fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> DecodedCellData { fn decode_cell_data<T: Into<TypeOptionCellData>>(
if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { &self,
if !type_option_cell_data.is_single_select() { type_option_cell_data: T,
return DecodedCellData::default(); _field_meta: &FieldMeta,
} ) -> DecodedCellData {
let type_option_cell_data = type_option_cell_data.into();
if !type_option_cell_data.is_select_option() {
return DecodedCellData::default();
}
if let Some(option_id) = select_option_ids(type_option_cell_data.data).first() { 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) { return match self.options.iter().find(|option| &option.id == option_id) {
None => DecodedCellData::default(), None => DecodedCellData::default(),
Some(option) => DecodedCellData::from_content(option.name.clone()), Some(option) => DecodedCellData::from_content(option.name.clone()),
}; };
}
} }
DecodedCellData::default() DecodedCellData::default()
@ -129,7 +132,7 @@ impl CellDataOperation for SingleSelectTypeOption {
new_cell_data = "".to_string() new_cell_data = "".to_string()
} }
Ok(TypeOptionCellData::new(&new_cell_data, self.field_type()).json()) Ok(new_cell_data)
} }
} }
@ -185,23 +188,26 @@ impl SelectOptionOperation for MultiSelectTypeOption {
} }
impl CellDataOperation for MultiSelectTypeOption { impl CellDataOperation for MultiSelectTypeOption {
fn decode_cell_data(&self, data: String, _field_meta: &FieldMeta) -> DecodedCellData { fn decode_cell_data<T: Into<TypeOptionCellData>>(
if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { &self,
if !type_option_cell_data.is_multi_select() { type_option_cell_data: T,
return DecodedCellData::default(); _field_meta: &FieldMeta,
} ) -> DecodedCellData {
let option_ids = select_option_ids(type_option_cell_data.data); let type_option_cell_data = type_option_cell_data.into();
let content = self if !type_option_cell_data.is_select_option() {
.options return DecodedCellData::default();
.iter()
.filter(|option| option_ids.contains(&option.id))
.map(|option| option.name.clone())
.collect::<Vec<String>>()
.join(SELECTION_IDS_SEPARATOR);
DecodedCellData::from_content(content)
} else {
DecodedCellData::default()
} }
let option_ids = select_option_ids(type_option_cell_data.data);
let content = self
.options
.iter()
.filter(|option| option_ids.contains(&option.id))
.map(|option| option.name.clone())
.collect::<Vec<String>>()
.join(SELECTION_IDS_SEPARATOR);
DecodedCellData::from_content(content)
} }
fn apply_changeset<T: Into<CellContentChangeset>>( fn apply_changeset<T: Into<CellContentChangeset>>(
@ -237,7 +243,7 @@ impl CellDataOperation for MultiSelectTypeOption {
} }
} }
Ok(TypeOptionCellData::new(&new_cell_data, self.field_type()).json()) Ok(new_cell_data)
} }
} }
@ -485,108 +491,108 @@ fn make_select_context_from(cell_meta: &Option<CellMeta>, options: &[SelectOptio
} }
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use crate::services::field::FieldBuilder; // use crate::services::field::FieldBuilder;
use crate::services::field::{ // use crate::services::field::{
MultiSelectTypeOption, MultiSelectTypeOptionBuilder, SelectOption, SelectOptionCellContentChangeset, // MultiSelectTypeOption, MultiSelectTypeOptionBuilder, SelectOption, SelectOptionCellContentChangeset,
SingleSelectTypeOption, SingleSelectTypeOptionBuilder, SELECTION_IDS_SEPARATOR, // SingleSelectTypeOption, SingleSelectTypeOptionBuilder, SELECTION_IDS_SEPARATOR,
}; // };
use crate::services::row::CellDataOperation; // use crate::services::row::CellDataOperation;
//
#[test] // #[test]
fn single_select_test() { // fn single_select_test() {
let google_option = SelectOption::new("Google"); // let google_option = SelectOption::new("Google");
let facebook_option = SelectOption::new("Facebook"); // let facebook_option = SelectOption::new("Facebook");
let twitter_option = SelectOption::new("Twitter"); // let twitter_option = SelectOption::new("Twitter");
let single_select = SingleSelectTypeOptionBuilder::default() // let single_select = SingleSelectTypeOptionBuilder::default()
.option(google_option.clone()) // .option(google_option.clone())
.option(facebook_option.clone()) // .option(facebook_option.clone())
.option(twitter_option); // .option(twitter_option);
//
let field_meta = FieldBuilder::new(single_select) // let field_meta = FieldBuilder::new(single_select)
.name("Platform") // .name("Platform")
.visibility(true) // .visibility(true)
.build(); // .build();
//
let type_option = SingleSelectTypeOption::from(&field_meta); // let type_option = SingleSelectTypeOption::from(&field_meta);
//
let option_ids = vec![google_option.id.clone(), facebook_option.id].join(SELECTION_IDS_SEPARATOR); // 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 data = SelectOptionCellContentChangeset::from_insert(&option_ids).to_str();
let cell_data = type_option.apply_changeset(data, None).unwrap(); // let cell_data = type_option.apply_changeset(data, None).unwrap();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(cell_data, &field_meta).content, // type_option.decode_cell_data(cell_data, &field_meta).content,
google_option.name, // google_option.name,
); // );
//
let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str(); // let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str();
let cell_data = type_option.apply_changeset(data, None).unwrap(); // let cell_data = type_option.apply_changeset(data, None).unwrap();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(cell_data, &field_meta).content, // type_option.decode_cell_data(cell_data, &field_meta).content,
google_option.name, // google_option.name,
); // );
//
// Invalid option id // // Invalid option id
let cell_data = type_option // let cell_data = type_option
.apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None) // .apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None)
.unwrap(); // .unwrap();
assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",); // assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
//
// Invalid option id // // Invalid option id
let cell_data = type_option // let cell_data = type_option
.apply_changeset(SelectOptionCellContentChangeset::from_insert("123").to_str(), None) // .apply_changeset(SelectOptionCellContentChangeset::from_insert("123").to_str(), None)
.unwrap(); // .unwrap();
assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",); // assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
//
// Invalid changeset // // Invalid changeset
assert!(type_option.apply_changeset("123", None).is_err()); // assert!(type_option.apply_changeset("123", None).is_err());
} // }
//
#[test] // #[test]
fn multi_select_test() { // fn multi_select_test() {
let google_option = SelectOption::new("Google"); // let google_option = SelectOption::new("Google");
let facebook_option = SelectOption::new("Facebook"); // let facebook_option = SelectOption::new("Facebook");
let twitter_option = SelectOption::new("Twitter"); // let twitter_option = SelectOption::new("Twitter");
let multi_select = MultiSelectTypeOptionBuilder::default() // let multi_select = MultiSelectTypeOptionBuilder::default()
.option(google_option.clone()) // .option(google_option.clone())
.option(facebook_option.clone()) // .option(facebook_option.clone())
.option(twitter_option); // .option(twitter_option);
//
let field_meta = FieldBuilder::new(multi_select) // let field_meta = FieldBuilder::new(multi_select)
.name("Platform") // .name("Platform")
.visibility(true) // .visibility(true)
.build(); // .build();
//
let type_option = MultiSelectTypeOption::from(&field_meta); // let type_option = MultiSelectTypeOption::from(&field_meta);
//
let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR); // 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 data = SelectOptionCellContentChangeset::from_insert(&option_ids).to_str();
let cell_data = type_option.apply_changeset(data, None).unwrap(); // let cell_data = type_option.apply_changeset(data, None).unwrap();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(cell_data, &field_meta).content, // type_option.decode_cell_data(cell_data, &field_meta).content,
vec![google_option.name.clone(), facebook_option.name].join(SELECTION_IDS_SEPARATOR), // vec![google_option.name.clone(), facebook_option.name].join(SELECTION_IDS_SEPARATOR),
); // );
//
let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str(); // let data = SelectOptionCellContentChangeset::from_insert(&google_option.id).to_str();
let cell_data = type_option.apply_changeset(data, None).unwrap(); // let cell_data = type_option.apply_changeset(data, None).unwrap();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(cell_data, &field_meta).content, // type_option.decode_cell_data(cell_data, &field_meta).content,
google_option.name, // google_option.name,
); // );
//
// Invalid option id // // Invalid option id
let cell_data = type_option // let cell_data = type_option
.apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None) // .apply_changeset(SelectOptionCellContentChangeset::from_insert("").to_str(), None)
.unwrap(); // .unwrap();
assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",); // assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
//
// Invalid option id // // Invalid option id
let cell_data = type_option // let cell_data = type_option
.apply_changeset(SelectOptionCellContentChangeset::from_insert("123,456").to_str(), None) // .apply_changeset(SelectOptionCellContentChangeset::from_insert("123,456").to_str(), None)
.unwrap(); // .unwrap();
assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",); // assert_eq!(type_option.decode_cell_data(cell_data, &field_meta).content, "",);
//
// Invalid changeset // // Invalid changeset
assert!(type_option.apply_changeset("123", None).is_err()); // assert!(type_option.apply_changeset("123", None).is_err());
} // }
} // }

View File

@ -35,19 +35,21 @@ pub struct RichTextTypeOption {
impl_type_option!(RichTextTypeOption, FieldType::RichText); impl_type_option!(RichTextTypeOption, FieldType::RichText);
impl CellDataOperation for RichTextTypeOption { impl CellDataOperation for RichTextTypeOption {
fn decode_cell_data(&self, data: String, field_meta: &FieldMeta) -> DecodedCellData { fn decode_cell_data<T: Into<TypeOptionCellData>>(
if let Ok(type_option_cell_data) = TypeOptionCellData::from_str(&data) { &self,
if type_option_cell_data.is_date() type_option_cell_data: T,
|| type_option_cell_data.is_single_select() field_meta: &FieldMeta,
|| type_option_cell_data.is_multi_select() ) -> DecodedCellData {
|| type_option_cell_data.is_number() let type_option_cell_data = type_option_cell_data.into();
{ if type_option_cell_data.is_date()
decode_cell_data(data, field_meta, &type_option_cell_data.field_type).unwrap_or_default() || type_option_cell_data.is_single_select()
} else { || type_option_cell_data.is_multi_select()
DecodedCellData::from_content(type_option_cell_data.data) || type_option_cell_data.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()
} else { } else {
DecodedCellData::default() DecodedCellData::from_content(type_option_cell_data.data)
} }
} }
@ -60,69 +62,69 @@ impl CellDataOperation for RichTextTypeOption {
if data.len() > 10000 { if data.len() > 10000 {
Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000")) Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000"))
} else { } else {
Ok(TypeOptionCellData::new(&data, self.field_type()).json()) Ok(data.to_string())
} }
} }
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use crate::services::field::FieldBuilder; // use crate::services::field::FieldBuilder;
use crate::services::field::*; // use crate::services::field::*;
use crate::services::row::{CellDataOperation, TypeOptionCellData}; // use crate::services::row::{CellDataOperation, TypeOptionCellData};
use flowy_grid_data_model::entities::FieldType; // use flowy_grid_data_model::entities::FieldType;
//
#[test] // #[test]
fn text_description_test() { // fn text_description_test() {
let type_option = RichTextTypeOption::default(); // let type_option = RichTextTypeOption::default();
//
// date // // date
let date_time_field_meta = FieldBuilder::from_field_type(&FieldType::DateTime).build(); // 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 json = serde_json::to_string(&DateCellDataSerde::from_timestamp(1647251762, None)).unwrap();
let data = TypeOptionCellData::new(&json, FieldType::DateTime).json(); // let data = TypeOptionCellData::new(&json, FieldType::DateTime).json();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data, &date_time_field_meta).content, // type_option.decode_cell_data(data, &date_time_field_meta).content,
"Mar 14,2022".to_owned() // "Mar 14,2022".to_owned()
); // );
//
// Single select // // Single select
let done_option = SelectOption::new("Done"); // let done_option = SelectOption::new("Done");
let done_option_id = done_option.id.clone(); // let done_option_id = done_option.id.clone();
let single_select = SingleSelectTypeOptionBuilder::default().option(done_option); // let single_select = SingleSelectTypeOptionBuilder::default().option(done_option);
let single_select_field_meta = FieldBuilder::new(single_select).build(); // let single_select_field_meta = FieldBuilder::new(single_select).build();
let cell_data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json(); // let cell_data = TypeOptionCellData::new(&done_option_id, FieldType::SingleSelect).json();
assert_eq!( // assert_eq!(
type_option // type_option
.decode_cell_data(cell_data, &single_select_field_meta) // .decode_cell_data(cell_data, &single_select_field_meta)
.content, // .content,
"Done".to_owned() // "Done".to_owned()
); // );
//
// Multiple select // // Multiple select
let google_option = SelectOption::new("Google"); // let google_option = SelectOption::new("Google");
let facebook_option = SelectOption::new("Facebook"); // let facebook_option = SelectOption::new("Facebook");
let ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR); // 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 cell_data_changeset = SelectOptionCellContentChangeset::from_insert(&ids).to_str();
let multi_select = MultiSelectTypeOptionBuilder::default() // let multi_select = MultiSelectTypeOptionBuilder::default()
.option(google_option) // .option(google_option)
.option(facebook_option); // .option(facebook_option);
let multi_select_field_meta = FieldBuilder::new(multi_select).build(); // let multi_select_field_meta = FieldBuilder::new(multi_select).build();
let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta); // let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_meta);
let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap(); // let cell_data = multi_type_option.apply_changeset(cell_data_changeset, None).unwrap();
assert_eq!( // assert_eq!(
type_option // type_option
.decode_cell_data(cell_data, &multi_select_field_meta) // .decode_cell_data(cell_data, &multi_select_field_meta)
.content, // .content,
"Google,Facebook".to_owned() // "Google,Facebook".to_owned()
); // );
//
//Number // //Number
let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD); // let number = NumberTypeOptionBuilder::default().set_format(NumberFormat::USD);
let number_field_meta = FieldBuilder::new(number).build(); // let number_field_meta = FieldBuilder::new(number).build();
let data = TypeOptionCellData::new("18443", FieldType::Number).json(); // let data = TypeOptionCellData::new("18443", FieldType::Number).json();
assert_eq!( // assert_eq!(
type_option.decode_cell_data(data, &number_field_meta).content, // type_option.decode_cell_data(data, &number_field_meta).content,
"$18,443".to_owned() // "$18,443".to_owned()
); // );
} // }
} // }

View File

@ -3,9 +3,10 @@ use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType}; use flowy_grid_data_model::entities::{CellMeta, FieldMeta, FieldType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Formatter; use std::fmt::Formatter;
use std::str::FromStr;
pub trait CellDataOperation { pub trait CellDataOperation {
fn decode_cell_data(&self, data: String, field_meta: &FieldMeta) -> DecodedCellData; fn decode_cell_data<T: Into<TypeOptionCellData>>(&self, data: T, field_meta: &FieldMeta) -> DecodedCellData;
fn apply_changeset<T: Into<CellContentChangeset>>( fn apply_changeset<T: Into<CellContentChangeset>>(
&self, &self,
changeset: T, changeset: T,
@ -52,6 +53,22 @@ impl std::str::FromStr for TypeOptionCellData {
} }
} }
impl std::convert::TryInto<TypeOptionCellData> for String {
type Error = FlowyError;
fn try_into(self) -> Result<TypeOptionCellData, Self::Error> {
TypeOptionCellData::from_str(&self)
}
}
// impl std::convert::Into<TypeOptionCellData> for String {
// type Error = FlowyError;
//
// fn try_into(self) -> Result<TypeOptionCellData, Self::Error> {
// TypeOptionCellData::from_str(&self)
// }
// }
impl TypeOptionCellData { impl TypeOptionCellData {
pub fn new<T: ToString>(data: T, field_type: FieldType) -> Self { pub fn new<T: ToString>(data: T, field_type: FieldType) -> Self {
TypeOptionCellData { TypeOptionCellData {
@ -87,6 +104,10 @@ impl TypeOptionCellData {
pub fn is_multi_select(&self) -> bool { pub fn is_multi_select(&self) -> bool {
self.field_type == FieldType::MultiSelect self.field_type == FieldType::MultiSelect
} }
pub fn is_select_option(&self) -> bool {
self.field_type == FieldType::MultiSelect || self.field_type == FieldType::SingleSelect
}
} }
/// The changeset will be deserialized into specific data base on the FieldType. /// The changeset will be deserialized into specific data base on the FieldType.
@ -96,47 +117,57 @@ pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
cell_meta: Option<CellMeta>, cell_meta: Option<CellMeta>,
field_meta: &FieldMeta, field_meta: &FieldMeta,
) -> Result<String, FlowyError> { ) -> Result<String, FlowyError> {
match field_meta.field_type { let s = match field_meta.field_type {
FieldType::RichText => RichTextTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), FieldType::RichText => RichTextTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::Number => NumberTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), FieldType::Number => NumberTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::DateTime => DateTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), FieldType::DateTime => DateTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::Checkbox => CheckboxTypeOption::from(field_meta).apply_changeset(changeset, cell_meta), FieldType::Checkbox => CheckboxTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
} }?;
Ok(TypeOptionCellData::new(s, field_meta.field_type.clone()).json())
} }
pub fn decode_cell_data(data: String, field_meta: &FieldMeta, field_type: &FieldType) -> Option<DecodedCellData> { pub fn decode_cell_data<T: TryInto<TypeOptionCellData>>(
let s = match field_type { data: T,
FieldType::RichText => field_meta field_meta: &FieldMeta,
.get_type_option_entry::<RichTextTypeOption>(field_type)? field_type: &FieldType,
.decode_cell_data(data, field_meta), ) -> Option<DecodedCellData> {
FieldType::Number => field_meta if let Ok(type_option_cell_data) = data.try_into() {
.get_type_option_entry::<NumberTypeOption>(field_type)? let s = match field_type {
.decode_cell_data(data, field_meta), FieldType::RichText => field_meta
FieldType::DateTime => field_meta .get_type_option_entry::<RichTextTypeOption>(field_type)?
.get_type_option_entry::<DateTypeOption>(field_type)? .decode_cell_data(type_option_cell_data, field_meta),
.decode_cell_data(data, field_meta), FieldType::Number => field_meta
FieldType::SingleSelect => field_meta .get_type_option_entry::<NumberTypeOption>(field_type)?
.get_type_option_entry::<SingleSelectTypeOption>(field_type)? .decode_cell_data(type_option_cell_data, field_meta),
.decode_cell_data(data, field_meta), FieldType::DateTime => field_meta
FieldType::MultiSelect => field_meta .get_type_option_entry::<DateTypeOption>(field_type)?
.get_type_option_entry::<MultiSelectTypeOption>(field_type)? .decode_cell_data(type_option_cell_data, field_meta),
.decode_cell_data(data, field_meta), FieldType::SingleSelect => field_meta
FieldType::Checkbox => field_meta .get_type_option_entry::<SingleSelectTypeOption>(field_type)?
.get_type_option_entry::<CheckboxTypeOption>(field_type)? .decode_cell_data(type_option_cell_data, field_meta),
.decode_cell_data(data, field_meta), FieldType::MultiSelect => field_meta
}; .get_type_option_entry::<MultiSelectTypeOption>(field_type)?
tracing::Span::current().record( .decode_cell_data(type_option_cell_data, field_meta),
"content", FieldType::Checkbox => field_meta
&format!("{:?}: {}", field_meta.field_type, s.content).as_str(), .get_type_option_entry::<CheckboxTypeOption>(field_type)?
); .decode_cell_data(type_option_cell_data, field_meta),
Some(s) };
tracing::Span::current().record(
"content",
&format!("{:?}: {}", field_meta.field_type, s.content).as_str(),
);
Some(s)
} else {
Some(DecodedCellData::default())
}
} }
#[derive(Default)] #[derive(Default)]
pub struct DecodedCellData { pub struct DecodedCellData {
pub raw: String, raw: String,
pub content: String, pub content: String,
} }