Create test template (#1594)

* refactor: rename functions

* chore: create test templagte

Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
Nathan.fooo 2022-12-21 11:00:08 +08:00 committed by GitHub
parent af716be7aa
commit eee3dcf43a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 169 additions and 123 deletions

View File

@ -38,7 +38,7 @@ class CellService {
..gridId = cellId.gridId ..gridId = cellId.gridId
..fieldId = cellId.fieldId ..fieldId = cellId.fieldId
..rowId = cellId.rowId ..rowId = cellId.rowId
..content = data; ..typeCellData = data;
return GridEventUpdateCell(payload).send(); return GridEventUpdateCell(payload).send();
} }

View File

@ -139,7 +139,7 @@ pub struct CellChangesetPB {
pub field_id: String, pub field_id: String,
#[pb(index = 4)] #[pb(index = 4)]
pub content: String, pub type_cell_data: String,
} }
impl std::convert::From<CellChangesetPB> for RowChangeset { impl std::convert::From<CellChangesetPB> for RowChangeset {
@ -147,7 +147,7 @@ impl std::convert::From<CellChangesetPB> for RowChangeset {
let mut cell_by_field_id = HashMap::with_capacity(1); let mut cell_by_field_id = HashMap::with_capacity(1);
let field_id = changeset.field_id; let field_id = changeset.field_id;
let cell_rev = CellRevision { let cell_rev = CellRevision {
data: changeset.content, type_cell_data: changeset.type_cell_data,
}; };
cell_by_field_id.insert(field_id, cell_rev); cell_by_field_id.insert(field_id, cell_rev);

View File

@ -378,7 +378,7 @@ pub(crate) async fn update_select_option_handler(
grid_id: changeset.cell_identifier.view_id, grid_id: changeset.cell_identifier.view_id,
row_id: changeset.cell_identifier.row_id, row_id: changeset.cell_identifier.row_id,
field_id: changeset.cell_identifier.field_id.clone(), field_id: changeset.cell_identifier.field_id.clone(),
content: cell_content_changeset, type_cell_data: cell_content_changeset,
}; };
let cloned_editor = editor.clone(); let cloned_editor = editor.clone();
tokio::spawn(async move { tokio::spawn(async move {
@ -413,12 +413,12 @@ pub(crate) async fn get_select_option_handler(
let type_option = select_type_option_from_field_rev(&field_rev)?; let type_option = select_type_option_from_field_rev(&field_rev)?;
let type_cell_data: TypeCellData = match cell_rev { let type_cell_data: TypeCellData = match cell_rev {
None => TypeCellData { None => TypeCellData {
data: "".to_string(), cell_str: "".to_string(),
field_type: field_rev.ty.into(), field_type: field_rev.ty.into(),
}, },
Some(cell_rev) => cell_rev.try_into()?, Some(cell_rev) => cell_rev.try_into()?,
}; };
let ids = SelectOptionIds::from_cell_str(&type_cell_data.data)?; let ids = SelectOptionIds::from_cell_str(&type_cell_data.cell_str)?;
let selected_options = type_option.get_selected_options(ids); let selected_options = type_option.get_selected_options(ids);
data_result(selected_options) data_result(selected_options)
} }

View File

@ -24,7 +24,7 @@ pub trait CellComparable {
/// Decode the opaque cell data into readable format content /// Decode the opaque cell data into readable format content
pub trait CellDataDecoder: TypeOption { pub trait CellDataDecoder: TypeOption {
/// ///
/// Tries to decode the opaque cell data to `decoded_field_type`. Sometimes, the `field_type` /// Tries to decode the opaque cell string to `decoded_field_type`'s cell data. Sometimes, the `field_type`
/// of the `FieldRevision` is not equal to the `decoded_field_type`(This happened When switching /// of the `FieldRevision` is not equal to the `decoded_field_type`(This happened When switching
/// the field type of the `FieldRevision` to another field type). So the cell data is need to do /// the field type of the `FieldRevision` to another field type). So the cell data is need to do
/// some transformation. /// some transformation.
@ -35,9 +35,9 @@ pub trait CellDataDecoder: TypeOption {
/// data that can be parsed by the current field type. One approach is to transform the cell data /// data that can be parsed by the current field type. One approach is to transform the cell data
/// when it get read. For the moment, the cell data is a string, `Yes` or `No`. It needs to compare /// when it get read. For the moment, the cell data is a string, `Yes` or `No`. It needs to compare
/// with the option's name, if match return the id of the option. /// with the option's name, if match return the id of the option.
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData>; ) -> FlowyResult<<Self as TypeOption>::CellData>;
@ -94,8 +94,8 @@ pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debu
let to_field_type = field_rev.ty.into(); let to_field_type = field_rev.ty.into();
match data.try_into() { match data.try_into() {
Ok(type_cell_data) => { Ok(type_cell_data) => {
let TypeCellData { data, field_type } = type_cell_data; let TypeCellData { cell_str, field_type } = type_cell_data;
match try_decode_cell_data(data, &field_type, &to_field_type, field_rev) { match try_decode_cell_str(cell_str, &field_type, &to_field_type, field_rev) {
Ok(cell_bytes) => (field_type, cell_bytes), Ok(cell_bytes) => (field_type, cell_bytes),
Err(e) => { Err(e) => {
tracing::error!("Decode cell data failed, {:?}", e); tracing::error!("Decode cell data failed, {:?}", e);
@ -120,7 +120,7 @@ pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debu
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `cell_data`: the opaque cell data /// * `cell_str`: the opaque cell string
/// * `from_field_type`: the original field type of the passed-in cell data. Check the `TypeCellData` /// * `from_field_type`: the original field type of the passed-in cell data. Check the `TypeCellData`
/// that is used to save the origin field type of the cell data. /// that is used to save the origin field type of the cell data.
/// * `to_field_type`: decode the passed-in cell data to this field type. It will use the to_field_type's /// * `to_field_type`: decode the passed-in cell data to this field type. It will use the to_field_type's
@ -129,15 +129,15 @@ pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debu
/// ///
/// returns: CellBytes /// returns: CellBytes
/// ///
pub fn try_decode_cell_data( pub fn try_decode_cell_str(
cell_data: String, cell_str: String,
from_field_type: &FieldType, from_field_type: &FieldType,
to_field_type: &FieldType, to_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellProtobufBlob> { ) -> FlowyResult<CellProtobufBlob> {
match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(to_field_type) { match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(to_field_type) {
None => Ok(CellProtobufBlob::default()), None => Ok(CellProtobufBlob::default()),
Some(handler) => handler.handle_cell_data(cell_data, from_field_type, field_rev), Some(handler) => handler.handle_cell_str(cell_str, from_field_type, field_rev),
} }
} }
@ -153,7 +153,7 @@ pub fn stringify_cell_data(
) -> String { ) -> String {
match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(to_field_type) { match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(to_field_type) {
None => "".to_string(), None => "".to_string(),
Some(handler) => handler.stringify_cell_data(cell_data, from_field_type, field_rev), Some(handler) => handler.stringify_cell_str(cell_data, from_field_type, field_rev),
} }
} }

View File

@ -16,28 +16,29 @@ use serde::{Deserialize, Serialize};
/// ///
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct TypeCellData { pub struct TypeCellData {
pub data: String, #[serde(rename = "data")]
pub cell_str: String,
pub field_type: FieldType, pub field_type: FieldType,
} }
impl TypeCellData { impl TypeCellData {
pub fn from_field_type(field_type: &FieldType) -> TypeCellData { pub fn from_field_type(field_type: &FieldType) -> TypeCellData {
Self { Self {
data: "".to_string(), cell_str: "".to_string(),
field_type: field_type.clone(), field_type: field_type.clone(),
} }
} }
pub fn from_json_str(s: &str) -> FlowyResult<Self> { pub fn from_json_str(s: &str) -> FlowyResult<Self> {
let type_cell_data: TypeCellData = serde_json::from_str(s).map_err(|err| { let type_cell_data: TypeCellData = serde_json::from_str(s).map_err(|err| {
let msg = format!("Deserialize {} to any cell data failed.{}", s, err); let msg = format!("Deserialize {} to type cell data failed.{}", s, err);
FlowyError::internal().context(msg) FlowyError::internal().context(msg)
})?; })?;
Ok(type_cell_data) Ok(type_cell_data)
} }
pub fn into_inner(self) -> String { pub fn into_inner(self) -> String {
self.data self.cell_str
} }
} }
@ -54,13 +55,13 @@ where
T: FromCellString, T: FromCellString,
{ {
fn from(any_call_data: TypeCellData) -> Self { fn from(any_call_data: TypeCellData) -> Self {
IntoCellData::from(any_call_data.data) IntoCellData::from(any_call_data.cell_str)
} }
} }
impl ToString for TypeCellData { impl ToString for TypeCellData {
fn to_string(&self) -> String { fn to_string(&self) -> String {
self.data.clone() self.cell_str.clone()
} }
} }
@ -68,7 +69,7 @@ impl std::convert::TryFrom<&CellRevision> for TypeCellData {
type Error = FlowyError; type Error = FlowyError;
fn try_from(value: &CellRevision) -> Result<Self, Self::Error> { fn try_from(value: &CellRevision) -> Result<Self, Self::Error> {
Self::from_json_str(&value.data) Self::from_json_str(&value.type_cell_data)
} }
} }
@ -83,7 +84,7 @@ impl std::convert::TryFrom<CellRevision> for TypeCellData {
impl TypeCellData { impl TypeCellData {
pub fn new(content: String, field_type: FieldType) -> Self { pub fn new(content: String, field_type: FieldType) -> Self {
TypeCellData { TypeCellData {
data: content, cell_str: content,
field_type, field_type,
} }
} }

View File

@ -22,7 +22,7 @@ impl CellFilterable for CheckboxTypeOptionPB {
if !type_cell_data.is_checkbox() { if !type_cell_data.is_checkbox() {
return Ok(true); return Ok(true);
} }
let checkbox_cell_data = self.decode_type_option_cell_data(type_cell_data.data)?; let checkbox_cell_data = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
Ok(filter.is_visible(&checkbox_cell_data)) Ok(filter.is_visible(&checkbox_cell_data))
} }
} }

View File

@ -36,7 +36,7 @@ mod tests {
) { ) {
assert_eq!( assert_eq!(
type_option type_option
.decode_cell_data(input_str.to_owned(), field_type, field_rev) .decode_cell_str(input_str.to_owned(), field_type, field_rev)
.unwrap() .unwrap()
.to_string(), .to_string(),
expected_str.to_owned() expected_str.to_owned()

View File

@ -58,15 +58,15 @@ impl TypeOptionCellData for CheckboxTypeOptionPB {
cell_data cell_data
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
CheckboxCellData::from_cell_str(&cell_data) CheckboxCellData::from_cell_str(&cell_str)
} }
} }
impl CellDataDecoder for CheckboxTypeOptionPB { impl CellDataDecoder for CheckboxTypeOptionPB {
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> { ) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -74,7 +74,7 @@ impl CellDataDecoder for CheckboxTypeOptionPB {
return Ok(Default::default()); return Ok(Default::default());
} }
self.decode_type_option_cell_data(cell_data) self.decode_type_option_cell_str(cell_str)
} }
fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String { fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {

View File

@ -70,7 +70,7 @@ impl CellFilterable for DateTypeOptionPB {
return Ok(true); return Ok(true);
} }
let date_cell_data = self.decode_type_option_cell_data(type_cell_data.data)?; let date_cell_data = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
Ok(filter.is_visible(date_cell_data)) Ok(filter.is_visible(date_cell_data))
} }
} }

View File

@ -162,7 +162,7 @@ mod tests {
fn decode_cell_data(encoded_data: String, type_option: &DateTypeOptionPB, field_rev: &FieldRevision) -> String { fn decode_cell_data(encoded_data: String, type_option: &DateTypeOptionPB, field_rev: &FieldRevision) -> String {
let decoded_data = type_option let decoded_data = type_option
.decode_cell_data(encoded_data, &FieldType::DateTime, field_rev) .decode_cell_str(encoded_data, &FieldType::DateTime, field_rev)
.unwrap(); .unwrap();
let decoded_data = type_option.convert_to_protobuf(decoded_data); let decoded_data = type_option.convert_to_protobuf(decoded_data);
if type_option.include_time { if type_option.include_time {

View File

@ -42,8 +42,8 @@ impl TypeOptionCellData for DateTypeOptionPB {
self.today_desc_from_timestamp(cell_data) self.today_desc_from_timestamp(cell_data)
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
DateCellData::from_cell_str(&cell_data) DateCellData::from_cell_str(&cell_str)
} }
} }
@ -131,9 +131,9 @@ impl DateTypeOptionPB {
impl TypeOptionTransform for DateTypeOptionPB {} impl TypeOptionTransform for DateTypeOptionPB {}
impl CellDataDecoder for DateTypeOptionPB { impl CellDataDecoder for DateTypeOptionPB {
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> { ) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -145,7 +145,7 @@ impl CellDataDecoder for DateTypeOptionPB {
return Ok(Default::default()); return Ok(Default::default());
} }
self.decode_type_option_cell_data(cell_data) self.decode_type_option_cell_str(cell_str)
} }
fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String { fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {

View File

@ -47,7 +47,7 @@ impl CellFilterable for NumberTypeOptionPB {
return Ok(true); return Ok(true);
} }
let cell_data = type_cell_data.data; let cell_data = type_cell_data.cell_str;
let num_cell_data = self.format_cell_data(&cell_data)?; let num_cell_data = self.format_cell_data(&cell_data)?;
Ok(filter.is_visible(&num_cell_data)) Ok(filter.is_visible(&num_cell_data))

View File

@ -439,7 +439,7 @@ mod tests {
) { ) {
assert_eq!( assert_eq!(
type_option type_option
.decode_cell_data(input_str.to_owned(), field_type, field_rev) .decode_cell_str(input_str.to_owned(), field_type, field_rev)
.unwrap() .unwrap()
.to_string(), .to_string(),
expected_str.to_owned() expected_str.to_owned()

View File

@ -88,8 +88,8 @@ impl TypeOptionCellData for NumberTypeOptionPB {
cell_data cell_data
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
Ok(cell_data.into()) Ok(cell_str.into())
} }
} }
@ -128,9 +128,9 @@ pub(crate) fn strip_currency_symbol<T: ToString>(s: T) -> String {
impl TypeOptionTransform for NumberTypeOptionPB {} impl TypeOptionTransform for NumberTypeOptionPB {}
impl CellDataDecoder for NumberTypeOptionPB { impl CellDataDecoder for NumberTypeOptionPB {
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> { ) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -138,7 +138,7 @@ impl CellDataDecoder for NumberTypeOptionPB {
return Ok(Default::default()); return Ok(Default::default());
} }
let str_cell_data = self.decode_type_option_cell_data(cell_data)?; let str_cell_data = self.decode_type_option_cell_str(cell_str)?;
let s = self.format_cell_data(&str_cell_data)?.to_string(); let s = self.format_cell_data(&str_cell_data)?.to_string();
Ok(s.into()) Ok(s.into())
} }

View File

@ -38,8 +38,8 @@ impl TypeOptionCellData for ChecklistTypeOptionPB {
self.get_selected_options(cell_data) self.get_selected_options(cell_data)
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_data) SelectOptionIds::from_cell_str(&cell_str)
} }
} }
@ -72,7 +72,7 @@ impl CellDataChangeset for ChecklistTypeOptionPB {
match type_cell_data { match type_cell_data {
None => Ok(SelectOptionIds::from(insert_option_ids).to_string()), None => Ok(SelectOptionIds::from(insert_option_ids).to_string()),
Some(type_cell_data) => { Some(type_cell_data) => {
let mut select_ids: SelectOptionIds = type_cell_data.data.into(); let mut select_ids: SelectOptionIds = type_cell_data.cell_str.into();
for insert_option_id in insert_option_ids { for insert_option_id in insert_option_ids {
if !select_ids.contains(&insert_option_id) { if !select_ids.contains(&insert_option_id) {
select_ids.push(insert_option_id); select_ids.push(insert_option_id);

View File

@ -38,8 +38,8 @@ impl TypeOptionCellData for MultiSelectTypeOptionPB {
self.get_selected_options(cell_data) self.get_selected_options(cell_data)
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_data) SelectOptionIds::from_cell_str(&cell_str)
} }
} }
@ -75,7 +75,7 @@ impl CellDataChangeset for MultiSelectTypeOptionPB {
new_cell_data = SelectOptionIds::from(insert_option_ids).to_string(); new_cell_data = SelectOptionIds::from(insert_option_ids).to_string();
} }
Some(type_cell_data) => { Some(type_cell_data) => {
let mut select_ids: SelectOptionIds = type_cell_data.data.into(); let mut select_ids: SelectOptionIds = type_cell_data.cell_str.into();
for insert_option_id in insert_option_ids { for insert_option_id in insert_option_ids {
if !select_ids.contains(&insert_option_id) { if !select_ids.contains(&insert_option_id) {
select_ids.push(insert_option_id); select_ids.push(insert_option_id);

View File

@ -85,7 +85,7 @@ impl CellFilterable for MultiSelectTypeOptionPB {
if !type_cell_data.is_multi_select() { if !type_cell_data.is_multi_select() {
return Ok(true); return Ok(true);
} }
let ids = self.decode_type_option_cell_data(type_cell_data.data)?; let ids = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
let selected_options = SelectedSelectOptions::from(self.get_selected_options(ids)); let selected_options = SelectedSelectOptions::from(self.get_selected_options(ids));
Ok(filter.is_visible(&selected_options, FieldType::MultiSelect)) Ok(filter.is_visible(&selected_options, FieldType::MultiSelect))
} }
@ -96,7 +96,7 @@ impl CellFilterable for SingleSelectTypeOptionPB {
if !type_cell_data.is_single_select() { if !type_cell_data.is_single_select() {
return Ok(true); return Ok(true);
} }
let ids = self.decode_type_option_cell_data(type_cell_data.data)?; let ids = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
let selected_options = SelectedSelectOptions::from(self.get_selected_options(ids)); let selected_options = SelectedSelectOptions::from(self.get_selected_options(ids));
Ok(filter.is_visible(&selected_options, FieldType::SingleSelect)) Ok(filter.is_visible(&selected_options, FieldType::SingleSelect))
} }
@ -107,7 +107,7 @@ impl CellFilterable for ChecklistTypeOptionPB {
if !type_cell_data.is_checklist() { if !type_cell_data.is_checklist() {
return Ok(true); return Ok(true);
} }
let ids = self.decode_type_option_cell_data(type_cell_data.data)?; let ids = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
let selected_options = SelectedSelectOptions::from(self.get_selected_options(ids)); let selected_options = SelectedSelectOptions::from(self.get_selected_options(ids));
Ok(filter.is_visible(&self.options, &selected_options)) Ok(filter.is_visible(&self.options, &selected_options))
} }

View File

@ -148,15 +148,15 @@ where
); );
} }
fn transform_type_option_cell_data( fn transform_type_option_cell_str(
&self, &self,
cell_data: &str, cell_str: &str,
decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> Option<<Self as TypeOption>::CellData> { ) -> Option<<Self as TypeOption>::CellData> {
match decoded_field_type { match _decoded_field_type {
FieldType::SingleSelect | FieldType::MultiSelect | FieldType::Checklist => None, FieldType::SingleSelect | FieldType::MultiSelect | FieldType::Checklist => None,
FieldType::Checkbox => match CheckboxCellData::from_cell_str(cell_data) { FieldType::Checkbox => match CheckboxCellData::from_cell_str(cell_str) {
Ok(checkbox_cell_data) => { Ok(checkbox_cell_data) => {
let cell_content = checkbox_cell_data.to_string(); let cell_content = checkbox_cell_data.to_string();
let mut transformed_ids = Vec::new(); let mut transformed_ids = Vec::new();
@ -177,13 +177,13 @@ impl<T> CellDataDecoder for T
where where
T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + TypeOptionCellData, T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + TypeOptionCellData,
{ {
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> { ) -> FlowyResult<<Self as TypeOption>::CellData> {
self.decode_type_option_cell_data(cell_data) self.decode_type_option_cell_str(cell_str)
} }
fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String { fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {
@ -390,7 +390,7 @@ impl std::convert::From<SelectOptionCellChangesetParams> for CellChangesetPB {
grid_id: params.cell_identifier.view_id, grid_id: params.cell_identifier.view_id,
row_id: params.cell_identifier.row_id, row_id: params.cell_identifier.row_id,
field_id: params.cell_identifier.field_id, field_id: params.cell_identifier.field_id,
content, type_cell_data: content,
} }
} }
} }

View File

@ -41,8 +41,8 @@ impl TypeOptionCellData for SingleSelectTypeOptionPB {
self.get_selected_options(cell_data) self.get_selected_options(cell_data)
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_data) SelectOptionIds::from_cell_str(&cell_str)
} }
} }

View File

@ -30,7 +30,7 @@ impl CellFilterable for RichTextTypeOptionPB {
return Ok(false); return Ok(false);
} }
let text_cell_data = self.decode_type_option_cell_data(type_cell_data.data)?; let text_cell_data = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
Ok(filter.is_visible(text_cell_data)) Ok(filter.is_visible(text_cell_data))
} }
} }

View File

@ -16,7 +16,7 @@ mod tests {
assert_eq!( assert_eq!(
type_option type_option
.decode_cell_data(1647251762.to_string(), &field_type, &field_rev) .decode_cell_str(1647251762.to_string(), &field_type, &field_rev)
.unwrap() .unwrap()
.as_str(), .as_str(),
"Mar 14,2022" "Mar 14,2022"
@ -37,7 +37,7 @@ mod tests {
assert_eq!( assert_eq!(
type_option type_option
.decode_cell_data(option_id, &field_type, &field_rev) .decode_cell_str(option_id, &field_type, &field_rev)
.unwrap() .unwrap()
.to_string(), .to_string(),
done_option.name, done_option.name,

View File

@ -58,15 +58,15 @@ impl TypeOptionCellData for RichTextTypeOptionPB {
cell_data cell_data
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
StrCellData::from_cell_str(&cell_data) StrCellData::from_cell_str(&cell_str)
} }
} }
impl CellDataDecoder for RichTextTypeOptionPB { impl CellDataDecoder for RichTextTypeOptionPB {
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> { ) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -76,9 +76,9 @@ impl CellDataDecoder for RichTextTypeOptionPB {
|| decoded_field_type.is_number() || decoded_field_type.is_number()
|| decoded_field_type.is_url() || decoded_field_type.is_url()
{ {
Ok(stringify_cell_data(cell_data, decoded_field_type, decoded_field_type, field_rev).into()) Ok(stringify_cell_data(cell_str, decoded_field_type, decoded_field_type, field_rev).into())
} else { } else {
StrCellData::from_cell_str(&cell_data) StrCellData::from_cell_str(&cell_str)
} }
} }

View File

@ -48,11 +48,11 @@ pub trait TypeOptionCellData: TypeOption {
/// FieldType::Date=> DateCellDataPB /// FieldType::Date=> DateCellDataPB
fn convert_to_protobuf(&self, cell_data: <Self as TypeOption>::CellData) -> <Self as TypeOption>::CellProtobufType; fn convert_to_protobuf(&self, cell_data: <Self as TypeOption>::CellData) -> <Self as TypeOption>::CellProtobufType;
/// Decodes the opaque cell data to corresponding data struct. /// Decodes the opaque cell string to corresponding data struct.
// For example, the cell data is timestamp if its field type is `FieldType::Date`. This cell // For example, the cell data is timestamp if its field type is `FieldType::Date`. This cell
// data can not directly show to user. So it needs to be encode as the date string with custom // data can not directly show to user. So it needs to be encode as the date string with custom
// format setting. Encode `1647251762` to `"Mar 14,2022` // format setting. Encode `1647251762` to `"Mar 14,2022`
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData>; fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData>;
} }
pub trait TypeOptionConfiguration { pub trait TypeOptionConfiguration {
@ -83,13 +83,13 @@ pub trait TypeOptionTransform: TypeOption {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `cell_data`: the cell data of the current field type /// * `cell_str`: the cell string of the current field type
/// * `decoded_field_type`: the field type of the cell data that's going to be transformed into /// * `decoded_field_type`: the field type of the cell data that's going to be transformed into
/// current `TypeOption` field type. /// current `TypeOption` field type.
/// ///
fn transform_type_option_cell_data( fn transform_type_option_cell_str(
&self, &self,
_cell_data: &str, _cell_str: &str,
_decoded_field_type: &FieldType, _decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> Option<<Self as TypeOption>::CellData> { ) -> Option<<Self as TypeOption>::CellData> {
@ -126,9 +126,9 @@ where
/// 2.there are no generic types parameters. /// 2.there are no generic types parameters.
/// ///
pub trait TypeOptionCellDataHandler { pub trait TypeOptionCellDataHandler {
fn handle_cell_data( fn handle_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellProtobufBlob>; ) -> FlowyResult<CellProtobufBlob>;
@ -139,26 +139,28 @@ pub trait TypeOptionCellDataHandler {
old_type_cell_data: Option<TypeCellData>, old_type_cell_data: Option<TypeCellData>,
) -> FlowyResult<String>; ) -> FlowyResult<String>;
fn stringify_cell_data(&self, cell_data: String, field_type: &FieldType, field_rev: &FieldRevision) -> String; /// Decode the cell_str to corresponding cell data, and then return the display string of the
/// cell data.
fn stringify_cell_str(&self, cell_str: String, field_type: &FieldType, field_rev: &FieldRevision) -> String;
} }
impl<T> TypeOptionCellDataHandler for T impl<T> TypeOptionCellDataHandler for T
where where
T: TypeOption + CellDataDecoder + CellDataChangeset + TypeOptionCellData + TypeOptionTransform, T: TypeOption + CellDataDecoder + CellDataChangeset + TypeOptionCellData + TypeOptionTransform,
{ {
fn handle_cell_data( fn handle_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<CellProtobufBlob> { ) -> FlowyResult<CellProtobufBlob> {
let cell_data = if self.transformable() { let cell_data = if self.transformable() {
match self.transform_type_option_cell_data(&cell_data, decoded_field_type, field_rev) { match self.transform_type_option_cell_str(&cell_str, decoded_field_type, field_rev) {
None => self.decode_cell_data(cell_data, decoded_field_type, field_rev)?, None => self.decode_cell_str(cell_str, decoded_field_type, field_rev)?,
Some(new_cell_data) => new_cell_data, Some(cell_data) => cell_data,
} }
} else { } else {
self.decode_cell_data(cell_data, decoded_field_type, field_rev)? self.decode_cell_str(cell_str, decoded_field_type, field_rev)?
}; };
CellProtobufBlob::from(self.convert_to_protobuf(cell_data)) CellProtobufBlob::from(self.convert_to_protobuf(cell_data))
} }
@ -173,19 +175,14 @@ where
Ok(cell_data) Ok(cell_data)
} }
fn stringify_cell_data( fn stringify_cell_str(&self, cell_str: String, field_type: &FieldType, field_rev: &FieldRevision) -> String {
&self,
cell_data: String,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> String {
if self.transformable() { if self.transformable() {
let cell_data = self.transform_type_option_cell_data(&cell_data, decoded_field_type, field_rev); let cell_data = self.transform_type_option_cell_str(&cell_str, field_type, field_rev);
if let Some(cell_data) = cell_data { if let Some(cell_data) = cell_data {
return self.decode_cell_data_to_str(cell_data); return self.decode_cell_data_to_str(cell_data);
} }
} }
match <Self as TypeOption>::CellData::from_cell_str(&cell_data) { match <Self as TypeOption>::CellData::from_cell_str(&cell_str) {
Ok(cell_data) => self.decode_cell_data_to_str(cell_data), Ok(cell_data) => self.decode_cell_data_to_str(cell_data),
Err(_) => "".to_string(), Err(_) => "".to_string(),
} }

View File

@ -12,7 +12,7 @@ impl CellFilterable for URLTypeOptionPB {
return Ok(true); return Ok(true);
} }
let url_cell_data = self.decode_type_option_cell_data(type_cell_data.data)?; let url_cell_data = self.decode_type_option_cell_str(type_cell_data.cell_str)?;
Ok(filter.is_visible(&url_cell_data)) Ok(filter.is_visible(&url_cell_data))
} }
} }

View File

@ -183,7 +183,7 @@ mod tests {
field_type: &FieldType, field_type: &FieldType,
) -> URLCellData { ) -> URLCellData {
type_option type_option
.decode_cell_data(encoded_data, field_type, field_rev) .decode_cell_str(encoded_data, field_type, field_rev)
.unwrap() .unwrap()
} }
} }

View File

@ -52,15 +52,15 @@ impl TypeOptionCellData for URLTypeOptionPB {
cell_data.into() cell_data.into()
} }
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> { fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
URLCellData::from_cell_str(&cell_data) URLCellData::from_cell_str(&cell_str)
} }
} }
impl CellDataDecoder for URLTypeOptionPB { impl CellDataDecoder for URLTypeOptionPB {
fn decode_cell_data( fn decode_cell_str(
&self, &self,
cell_data: String, cell_str: String,
decoded_field_type: &FieldType, decoded_field_type: &FieldType,
_field_rev: &FieldRevision, _field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> { ) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -68,7 +68,7 @@ impl CellDataDecoder for URLTypeOptionPB {
return Ok(Default::default()); return Ok(Default::default());
} }
self.decode_type_option_cell_data(cell_data) self.decode_type_option_cell_str(cell_str)
} }
fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String { fn decode_cell_data_to_str(&self, cell_data: <Self as TypeOption>::CellData) -> String {

View File

@ -363,7 +363,7 @@ fn filter_cell(
} }
}, },
}; };
let cloned_type_cell_data = type_cell_data.data.clone(); let cloned_type_cell_data = type_cell_data.cell_str.clone();
let is_visible = match &filter_id.field_type { let is_visible = match &filter_id.field_type {
FieldType::RichText => filter_map.text_filter.get(filter_id).and_then(|filter| { FieldType::RichText => filter_map.text_filter.get(filter_id).and_then(|filter| {
Some( Some(

View File

@ -439,7 +439,7 @@ impl GridRevisionEditor {
let field_rev = self.get_field_rev(&params.field_id).await?; let field_rev = self.get_field_rev(&params.field_id).await?;
let (_, row_rev) = self.block_manager.get_row_rev(&params.row_id).await.ok()??; let (_, row_rev) = self.block_manager.get_row_rev(&params.row_id).await.ok()??;
let cell_rev = row_rev.cells.get(&params.field_id)?.clone(); let cell_rev = row_rev.cells.get(&params.field_id)?.clone();
Some(decode_type_cell_data(cell_rev.data, &field_rev)) Some(decode_type_cell_data(cell_rev.type_cell_data, &field_rev))
} }
pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> { pub async fn get_cell_rev(&self, row_id: &str, field_id: &str) -> FlowyResult<Option<CellRevision>> {
@ -458,7 +458,7 @@ impl GridRevisionEditor {
grid_id, grid_id,
row_id, row_id,
field_id, field_id,
mut content, type_cell_data: mut content,
} = cell_changeset; } = cell_changeset;
match self.grid_pad.read().await.get_field_rev(&field_id) { match self.grid_pad.read().await.get_field_rev(&field_id) {
@ -475,7 +475,7 @@ impl GridRevisionEditor {
grid_id, grid_id,
row_id: row_id.clone(), row_id: row_id.clone(),
field_id: field_id.clone(), field_id: field_id.clone(),
content, type_cell_data: content,
}; };
let _ = self.block_manager.update_cell(cell_changeset).await?; let _ = self.block_manager.update_cell(cell_changeset).await?;
self.view_manager.did_update_cell(&row_id).await; self.view_manager.did_update_cell(&row_id).await;
@ -496,7 +496,7 @@ impl GridRevisionEditor {
grid_id, grid_id,
row_id, row_id,
field_id, field_id,
content: content.to_string(), type_cell_data: content.to_string(),
}) })
.await .await
} }
@ -645,7 +645,7 @@ impl GridRevisionEditor {
grid_id: view_id.clone(), grid_id: view_id.clone(),
row_id: row_changeset.row_id.clone(), row_id: row_changeset.row_id.clone(),
field_id, field_id,
content: cell_rev.data, type_cell_data: cell_rev.type_cell_data,
}) })
.collect::<Vec<CellChangesetPB>>(); .collect::<Vec<CellChangesetPB>>();

View File

@ -184,7 +184,7 @@ where
if let Some(cell_rev) = cell_rev { if let Some(cell_rev) = cell_rev {
let mut grouped_rows: Vec<GroupedRow> = vec![]; let mut grouped_rows: Vec<GroupedRow> = vec![];
let cell_bytes = decode_type_cell_data(cell_rev.data, field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.type_cell_data, field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
for group in self.group_ctx.groups() { for group in self.group_ctx.groups() {
if self.can_group(&group.filter_content, &cell_data) { if self.can_group(&group.filter_content, &cell_data) {
@ -224,7 +224,7 @@ where
field_rev: &FieldRevision, field_rev: &FieldRevision,
) -> FlowyResult<Vec<GroupRowsNotificationPB>> { ) -> FlowyResult<Vec<GroupRowsNotificationPB>> {
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
let cell_bytes = decode_type_cell_data(cell_rev.data.clone(), field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.type_cell_data.clone(), field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data); let mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data);
@ -247,10 +247,10 @@ where
) -> FlowyResult<Vec<GroupRowsNotificationPB>> { ) -> FlowyResult<Vec<GroupRowsNotificationPB>> {
// if the cell_rev is none, then the row must in the default group. // if the cell_rev is none, then the row must in the default group.
if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) {
let cell_bytes = decode_type_cell_data(cell_rev.data.clone(), field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.type_cell_data.clone(), field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
if !cell_data.is_empty() { if !cell_data.is_empty() {
tracing::error!("did_delete_delete_row {:?}", cell_rev.data); tracing::error!("did_delete_delete_row {:?}", cell_rev.type_cell_data);
return Ok(self.delete_row(row_rev, &cell_data)); return Ok(self.delete_row(row_rev, &cell_data));
} }
} }
@ -280,7 +280,7 @@ where
}; };
if let Some(cell_rev) = cell_rev { if let Some(cell_rev) = cell_rev {
let cell_bytes = decode_type_cell_data(cell_rev.data, context.field_rev).1; let cell_bytes = decode_type_cell_data(cell_rev.type_cell_data, context.field_rev).1;
let cell_data = cell_bytes.parser::<P>()?; let cell_data = cell_bytes.parser::<P>()?;
Ok(self.move_row(&cell_data, context)) Ok(self.move_row(&cell_data, context))
} else { } else {

View File

@ -92,6 +92,7 @@ impl RevisionSnapshotDiskCache for SQLiteGridRevisionSnapshotPersistence {
Ok(Some(latest_record.into())) Ok(Some(latest_record.into()))
} }
} }
//noinspection ALL
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
#[table_name = "grid_rev_snapshot"] #[table_name = "grid_rev_snapshot"]
#[primary_key("snapshot_id")] #[primary_key("snapshot_id")]

View File

@ -44,7 +44,7 @@ async fn grid_cell_update() {
grid_id: block_id.to_string(), grid_id: block_id.to_string(),
row_id: row_rev.id.clone(), row_id: row_rev.id.clone(),
field_id: field_rev.id.clone(), field_id: field_rev.id.clone(),
content: data, type_cell_data: data,
}, },
is_err: false, is_err: false,
}); });

View File

@ -137,7 +137,7 @@ impl GridFieldTest {
let cell_rev = row_rev.cells.get(&field_id).unwrap().clone(); let cell_rev = row_rev.cells.get(&field_id).unwrap().clone();
let type_cell_data: TypeCellData = cell_rev.try_into().unwrap(); let type_cell_data: TypeCellData = cell_rev.try_into().unwrap();
let content = stringify_cell_data(type_cell_data.data, &from_field_type, &field_type, &field_rev); let content = stringify_cell_data(type_cell_data.cell_str, &from_field_type, &field_type, &field_rev);
assert_eq!(content, expected_content); assert_eq!(content, expected_content);
} }
} }

View File

@ -163,14 +163,21 @@ async fn grid_switch_from_checkbox_to_select_option_test() {
let mut test = GridFieldTest::new().await; let mut test = GridFieldTest::new().await;
let field_rev = test.get_first_field_rev(FieldType::Checkbox).clone(); let field_rev = test.get_first_field_rev(FieldType::Checkbox).clone();
let scripts = vec![ let scripts = vec![
// switch to single-select field type
SwitchToField { SwitchToField {
field_id: field_rev.id.clone(), field_id: field_rev.id.clone(),
new_field_type: FieldType::SingleSelect, new_field_type: FieldType::SingleSelect,
}, },
// Assert the cell content after switch the field type. The cell content will be changed if
// the FieldType::SingleSelect implement the cell data TypeOptionTransform. Check out the
// TypeOptionTransform trait for more information.
//
// Make sure which cell of the row you want to check.
AssertCellContent { AssertCellContent {
field_id: field_rev.id.clone(), field_id: field_rev.id.clone(),
// the mock data of the checkbox with row_index one is "true" // the mock data of the checkbox with row_index one is "true"
row_index: 1, row_index: 1,
// the from_field_type represents as the current field type
from_field_type: FieldType::Checkbox, from_field_type: FieldType::Checkbox,
// The content of the checkbox should transform to the corresponding option name. // The content of the checkbox should transform to the corresponding option name.
expected_content: CHECK.to_string(), expected_content: CHECK.to_string(),
@ -189,3 +196,36 @@ async fn grid_switch_from_checkbox_to_select_option_test() {
.iter() .iter()
.any(|option| option.name == CHECK)); .any(|option| option.name == CHECK));
} }
// Test when switching the current field from Multi-select to Text test
// The build-in test data is located in `make_test_grid` method(flowy-grid/tests/grid_editor.rs).
// input:
// option1, option2 -> "option1.name, option2.name"
#[tokio::test]
async fn grid_switch_from_multi_select_to_text_test() {}
// Test when switching the current field from Checkbox to Text test
// input:
// check -> "Yes"
// unchecked -> ""
#[tokio::test]
async fn grid_switch_from_checkbox_to_text_test() {}
// Test when switching the current field from Checkbox to Text test
// input:
// "Yes" -> check
// "" -> unchecked
#[tokio::test]
async fn grid_switch_from_text_to_checkbox_test() {}
// Test when switching the current field from Date to Text test
// input:
// 1647251762 -> Mar 14,2022 (This string will be different base on current data setting)
#[tokio::test]
async fn grid_switch_from_date_to_text_test() {}
// Test when switching the current field from Number to Text test
// input:
// $1 -> "$1"(This string will be different base on current data setting)
#[tokio::test]
async fn grid_switch_from_number_to_text_test() {}

View File

@ -278,7 +278,7 @@ impl GridFilterTest {
grid_id: self.grid_id.clone(), grid_id: self.grid_id.clone(),
row_id: row_rev.id.clone(), row_id: row_rev.id.clone(),
field_id: field_rev.id.clone(), field_id: field_rev.id.clone(),
content: content.to_string(), type_cell_data: content.to_string(),
}; };
self.editor.update_cell_with_changeset(changeset).await.unwrap(); self.editor.update_cell_with_changeset(changeset).await.unwrap();
@ -295,7 +295,7 @@ impl GridFilterTest {
grid_id: self.grid_id.clone(), grid_id: self.grid_id.clone(),
row_id: row_rev.id.clone(), row_id: row_rev.id.clone(),
field_id: field_rev.id.clone(), field_id: field_rev.id.clone(),
content, type_cell_data: content,
}; };
self.editor.update_cell_with_changeset(changeset).await.unwrap(); self.editor.update_cell_with_changeset(changeset).await.unwrap();

View File

@ -101,6 +101,8 @@ impl GridEditorTest {
.unwrap() .unwrap()
} }
/// returns the first `FieldRevision` in the build-in test grid.
/// Not support duplicate `FieldType` in test grid yet.
pub fn get_first_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> { pub fn get_first_field_rev(&self, field_type: FieldType) -> &Arc<FieldRevision> {
self.field_revs self.field_revs
.iter() .iter()
@ -164,7 +166,9 @@ pub const PAUSED: &str = "Paused";
pub const FIRST_THING: &str = "Wake up at 6:00 am"; pub const FIRST_THING: &str = "Wake up at 6:00 am";
pub const SECOND_THING: &str = "Get some coffee"; pub const SECOND_THING: &str = "Get some coffee";
pub const THIRD_THING: &str = "Start working"; pub const THIRD_THING: &str = "Start working";
// This grid is assumed to contain all the Fields.
/// The build-in test data for grid. Currently, there are five rows in this grid, if you want to add
/// more rows or alter the data in this grid. Some tests may fail. So you need to fix the failed tests.
fn make_test_grid() -> BuildGridContext { fn make_test_grid() -> BuildGridContext {
let mut grid_builder = GridBuilder::new(); let mut grid_builder = GridBuilder::new();
// Iterate through the FieldType to create the corresponding Field. // Iterate through the FieldType to create the corresponding Field.
@ -239,7 +243,6 @@ fn make_test_grid() -> BuildGridContext {
} }
} }
// We have many assumptions base on the number of the rows, so do not change the number of the loop.
for i in 0..5 { for i in 0..5 {
let block_id = grid_builder.block_id().to_owned(); let block_id = grid_builder.block_id().to_owned();
let field_revs = grid_builder.field_revs(); let field_revs = grid_builder.field_revs();
@ -412,6 +415,7 @@ fn make_test_board() -> BuildGridContext {
match field_type { match field_type {
FieldType::RichText => row_builder.insert_text_cell("A"), FieldType::RichText => row_builder.insert_text_cell("A"),
FieldType::Number => row_builder.insert_number_cell("1"), FieldType::Number => row_builder.insert_number_cell("1"),
// 1647251762 => Mar 14,2022
FieldType::DateTime => row_builder.insert_date_cell("1647251762"), FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
FieldType::SingleSelect => { FieldType::SingleSelect => {
row_builder.insert_single_select_cell(|mut options| options.remove(0)) row_builder.insert_single_select_cell(|mut options| options.remove(0))
@ -428,6 +432,7 @@ fn make_test_board() -> BuildGridContext {
match field_type { match field_type {
FieldType::RichText => row_builder.insert_text_cell("B"), FieldType::RichText => row_builder.insert_text_cell("B"),
FieldType::Number => row_builder.insert_number_cell("2"), FieldType::Number => row_builder.insert_number_cell("2"),
// 1647251762 => Mar 14,2022
FieldType::DateTime => row_builder.insert_date_cell("1647251762"), FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
FieldType::SingleSelect => { FieldType::SingleSelect => {
row_builder.insert_single_select_cell(|mut options| options.remove(0)) row_builder.insert_single_select_cell(|mut options| options.remove(0))
@ -444,6 +449,7 @@ fn make_test_board() -> BuildGridContext {
match field_type { match field_type {
FieldType::RichText => row_builder.insert_text_cell("C"), FieldType::RichText => row_builder.insert_text_cell("C"),
FieldType::Number => row_builder.insert_number_cell("3"), FieldType::Number => row_builder.insert_number_cell("3"),
// 1647251762 => Mar 14,2022
FieldType::DateTime => row_builder.insert_date_cell("1647251762"), FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
FieldType::SingleSelect => { FieldType::SingleSelect => {
row_builder.insert_single_select_cell(|mut options| options.remove(1)) row_builder.insert_single_select_cell(|mut options| options.remove(1))

View File

@ -68,15 +68,16 @@ impl RowChangeset {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CellRevision { pub struct CellRevision {
pub data: String, #[serde(rename = "data")]
pub type_cell_data: String,
} }
impl CellRevision { impl CellRevision {
pub fn new(data: String) -> Self { pub fn new(data: String) -> Self {
Self { data } Self { type_cell_data: data }
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.data.is_empty() self.type_cell_data.is_empty()
} }
} }