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
..fieldId = cellId.fieldId
..rowId = cellId.rowId
..content = data;
..typeCellData = data;
return GridEventUpdateCell(payload).send();
}

View File

@ -139,7 +139,7 @@ pub struct CellChangesetPB {
pub field_id: String,
#[pb(index = 4)]
pub content: String,
pub type_cell_data: String,
}
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 field_id = changeset.field_id;
let cell_rev = CellRevision {
data: changeset.content,
type_cell_data: changeset.type_cell_data,
};
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,
row_id: changeset.cell_identifier.row_id,
field_id: changeset.cell_identifier.field_id.clone(),
content: cell_content_changeset,
type_cell_data: cell_content_changeset,
};
let cloned_editor = editor.clone();
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_cell_data: TypeCellData = match cell_rev {
None => TypeCellData {
data: "".to_string(),
cell_str: "".to_string(),
field_type: field_rev.ty.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);
data_result(selected_options)
}

View File

@ -24,7 +24,7 @@ pub trait CellComparable {
/// Decode the opaque cell data into readable format content
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
/// the field type of the `FieldRevision` to another field type). So the cell data is need to do
/// 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
/// 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.
fn decode_cell_data(
fn decode_cell_str(
&self,
cell_data: String,
cell_str: String,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> 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();
match data.try_into() {
Ok(type_cell_data) => {
let TypeCellData { data, field_type } = type_cell_data;
match try_decode_cell_data(data, &field_type, &to_field_type, field_rev) {
let TypeCellData { cell_str, field_type } = type_cell_data;
match try_decode_cell_str(cell_str, &field_type, &to_field_type, field_rev) {
Ok(cell_bytes) => (field_type, cell_bytes),
Err(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
///
/// * `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`
/// 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
@ -129,15 +129,15 @@ pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debu
///
/// returns: CellBytes
///
pub fn try_decode_cell_data(
cell_data: String,
pub fn try_decode_cell_str(
cell_str: String,
from_field_type: &FieldType,
to_field_type: &FieldType,
field_rev: &FieldRevision,
) -> FlowyResult<CellProtobufBlob> {
match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(to_field_type) {
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 {
match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(to_field_type) {
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)]
pub struct TypeCellData {
pub data: String,
#[serde(rename = "data")]
pub cell_str: String,
pub field_type: FieldType,
}
impl TypeCellData {
pub fn from_field_type(field_type: &FieldType) -> TypeCellData {
Self {
data: "".to_string(),
cell_str: "".to_string(),
field_type: field_type.clone(),
}
}
pub fn from_json_str(s: &str) -> FlowyResult<Self> {
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)
})?;
Ok(type_cell_data)
}
pub fn into_inner(self) -> String {
self.data
self.cell_str
}
}
@ -54,13 +55,13 @@ where
T: FromCellString,
{
fn from(any_call_data: TypeCellData) -> Self {
IntoCellData::from(any_call_data.data)
IntoCellData::from(any_call_data.cell_str)
}
}
impl ToString for TypeCellData {
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;
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 {
pub fn new(content: String, field_type: FieldType) -> Self {
TypeCellData {
data: content,
cell_str: content,
field_type,
}
}

View File

@ -22,7 +22,7 @@ impl CellFilterable for CheckboxTypeOptionPB {
if !type_cell_data.is_checkbox() {
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))
}
}

View File

@ -36,7 +36,7 @@ mod tests {
) {
assert_eq!(
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()
.to_string(),
expected_str.to_owned()

View File

@ -58,15 +58,15 @@ impl TypeOptionCellData for CheckboxTypeOptionPB {
cell_data
}
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> {
CheckboxCellData::from_cell_str(&cell_data)
fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
CheckboxCellData::from_cell_str(&cell_str)
}
}
impl CellDataDecoder for CheckboxTypeOptionPB {
fn decode_cell_data(
fn decode_cell_str(
&self,
cell_data: String,
cell_str: String,
decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -74,7 +74,7 @@ impl CellDataDecoder for CheckboxTypeOptionPB {
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 {

View File

@ -70,7 +70,7 @@ impl CellFilterable for DateTypeOptionPB {
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))
}
}

View File

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

View File

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

View File

@ -47,7 +47,7 @@ impl CellFilterable for NumberTypeOptionPB {
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)?;
Ok(filter.is_visible(&num_cell_data))

View File

@ -439,7 +439,7 @@ mod tests {
) {
assert_eq!(
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()
.to_string(),
expected_str.to_owned()

View File

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

View File

@ -38,8 +38,8 @@ impl TypeOptionCellData for ChecklistTypeOptionPB {
self.get_selected_options(cell_data)
}
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_data)
fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_str)
}
}
@ -72,7 +72,7 @@ impl CellDataChangeset for ChecklistTypeOptionPB {
match type_cell_data {
None => Ok(SelectOptionIds::from(insert_option_ids).to_string()),
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 {
if !select_ids.contains(&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)
}
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_data)
fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_str)
}
}
@ -75,7 +75,7 @@ impl CellDataChangeset for MultiSelectTypeOptionPB {
new_cell_data = SelectOptionIds::from(insert_option_ids).to_string();
}
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 {
if !select_ids.contains(&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() {
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));
Ok(filter.is_visible(&selected_options, FieldType::MultiSelect))
}
@ -96,7 +96,7 @@ impl CellFilterable for SingleSelectTypeOptionPB {
if !type_cell_data.is_single_select() {
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));
Ok(filter.is_visible(&selected_options, FieldType::SingleSelect))
}
@ -107,7 +107,7 @@ impl CellFilterable for ChecklistTypeOptionPB {
if !type_cell_data.is_checklist() {
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));
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,
cell_data: &str,
decoded_field_type: &FieldType,
cell_str: &str,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> Option<<Self as TypeOption>::CellData> {
match decoded_field_type {
match _decoded_field_type {
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) => {
let cell_content = checkbox_cell_data.to_string();
let mut transformed_ids = Vec::new();
@ -177,13 +177,13 @@ impl<T> CellDataDecoder for T
where
T: SelectTypeOptionSharedAction + TypeOption<CellData = SelectOptionIds> + TypeOptionCellData,
{
fn decode_cell_data(
fn decode_cell_str(
&self,
cell_data: String,
cell_str: String,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> 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 {
@ -390,7 +390,7 @@ impl std::convert::From<SelectOptionCellChangesetParams> for CellChangesetPB {
grid_id: params.cell_identifier.view_id,
row_id: params.cell_identifier.row_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)
}
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_data)
fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
SelectOptionIds::from_cell_str(&cell_str)
}
}

View File

@ -30,7 +30,7 @@ impl CellFilterable for RichTextTypeOptionPB {
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))
}
}

View File

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

View File

@ -58,15 +58,15 @@ impl TypeOptionCellData for RichTextTypeOptionPB {
cell_data
}
fn decode_type_option_cell_data(&self, cell_data: String) -> FlowyResult<<Self as TypeOption>::CellData> {
StrCellData::from_cell_str(&cell_data)
fn decode_type_option_cell_str(&self, cell_str: String) -> FlowyResult<<Self as TypeOption>::CellData> {
StrCellData::from_cell_str(&cell_str)
}
}
impl CellDataDecoder for RichTextTypeOptionPB {
fn decode_cell_data(
fn decode_cell_str(
&self,
cell_data: String,
cell_str: String,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> FlowyResult<<Self as TypeOption>::CellData> {
@ -76,9 +76,9 @@ impl CellDataDecoder for RichTextTypeOptionPB {
|| decoded_field_type.is_number()
|| 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 {
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
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
// 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`
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 {
@ -83,13 +83,13 @@ pub trait TypeOptionTransform: TypeOption {
///
/// # 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
/// current `TypeOption` field type.
///
fn transform_type_option_cell_data(
fn transform_type_option_cell_str(
&self,
_cell_data: &str,
_cell_str: &str,
_decoded_field_type: &FieldType,
_field_rev: &FieldRevision,
) -> Option<<Self as TypeOption>::CellData> {
@ -126,9 +126,9 @@ where
/// 2.there are no generic types parameters.
///
pub trait TypeOptionCellDataHandler {
fn handle_cell_data(
fn handle_cell_str(
&self,
cell_data: String,
cell_str: String,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> FlowyResult<CellProtobufBlob>;
@ -139,26 +139,28 @@ pub trait TypeOptionCellDataHandler {
old_type_cell_data: Option<TypeCellData>,
) -> 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
where
T: TypeOption + CellDataDecoder + CellDataChangeset + TypeOptionCellData + TypeOptionTransform,
{
fn handle_cell_data(
fn handle_cell_str(
&self,
cell_data: String,
cell_str: String,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> FlowyResult<CellProtobufBlob> {
let cell_data = if self.transformable() {
match self.transform_type_option_cell_data(&cell_data, decoded_field_type, field_rev) {
None => self.decode_cell_data(cell_data, decoded_field_type, field_rev)?,
Some(new_cell_data) => new_cell_data,
match self.transform_type_option_cell_str(&cell_str, decoded_field_type, field_rev) {
None => self.decode_cell_str(cell_str, decoded_field_type, field_rev)?,
Some(cell_data) => cell_data,
}
} 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))
}
@ -173,19 +175,14 @@ where
Ok(cell_data)
}
fn stringify_cell_data(
&self,
cell_data: String,
decoded_field_type: &FieldType,
field_rev: &FieldRevision,
) -> String {
fn stringify_cell_str(&self, cell_str: String, field_type: &FieldType, field_rev: &FieldRevision) -> String {
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 {
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),
Err(_) => "".to_string(),
}

View File

@ -12,7 +12,7 @@ impl CellFilterable for URLTypeOptionPB {
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))
}
}

View File

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

View File

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

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 {
FieldType::RichText => filter_map.text_filter.get(filter_id).and_then(|filter| {
Some(

View File

@ -439,7 +439,7 @@ impl GridRevisionEditor {
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 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>> {
@ -458,7 +458,7 @@ impl GridRevisionEditor {
grid_id,
row_id,
field_id,
mut content,
type_cell_data: mut content,
} = cell_changeset;
match self.grid_pad.read().await.get_field_rev(&field_id) {
@ -475,7 +475,7 @@ impl GridRevisionEditor {
grid_id,
row_id: row_id.clone(),
field_id: field_id.clone(),
content,
type_cell_data: content,
};
let _ = self.block_manager.update_cell(cell_changeset).await?;
self.view_manager.did_update_cell(&row_id).await;
@ -496,7 +496,7 @@ impl GridRevisionEditor {
grid_id,
row_id,
field_id,
content: content.to_string(),
type_cell_data: content.to_string(),
})
.await
}
@ -645,7 +645,7 @@ impl GridRevisionEditor {
grid_id: view_id.clone(),
row_id: row_changeset.row_id.clone(),
field_id,
content: cell_rev.data,
type_cell_data: cell_rev.type_cell_data,
})
.collect::<Vec<CellChangesetPB>>();

View File

@ -184,7 +184,7 @@ where
if let Some(cell_rev) = cell_rev {
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>()?;
for group in self.group_ctx.groups() {
if self.can_group(&group.filter_content, &cell_data) {
@ -224,7 +224,7 @@ where
field_rev: &FieldRevision,
) -> FlowyResult<Vec<GroupRowsNotificationPB>> {
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 mut changesets = self.add_or_remove_row_in_groups_if_match(row_rev, &cell_data);
@ -247,10 +247,10 @@ where
) -> FlowyResult<Vec<GroupRowsNotificationPB>> {
// 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) {
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>()?;
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));
}
}
@ -280,7 +280,7 @@ where
};
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>()?;
Ok(self.move_row(&cell_data, context))
} else {

View File

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

View File

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

View File

@ -137,7 +137,7 @@ impl GridFieldTest {
let cell_rev = row_rev.cells.get(&field_id).unwrap().clone();
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);
}
}

View File

@ -163,14 +163,21 @@ async fn grid_switch_from_checkbox_to_select_option_test() {
let mut test = GridFieldTest::new().await;
let field_rev = test.get_first_field_rev(FieldType::Checkbox).clone();
let scripts = vec![
// switch to single-select field type
SwitchToField {
field_id: field_rev.id.clone(),
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 {
field_id: field_rev.id.clone(),
// the mock data of the checkbox with row_index one is "true"
row_index: 1,
// the from_field_type represents as the current field type
from_field_type: FieldType::Checkbox,
// The content of the checkbox should transform to the corresponding option name.
expected_content: CHECK.to_string(),
@ -189,3 +196,36 @@ async fn grid_switch_from_checkbox_to_select_option_test() {
.iter()
.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(),
row_id: row_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();
@ -295,7 +295,7 @@ impl GridFilterTest {
grid_id: self.grid_id.clone(),
row_id: row_rev.id.clone(),
field_id: field_rev.id.clone(),
content,
type_cell_data: content,
};
self.editor.update_cell_with_changeset(changeset).await.unwrap();

View File

@ -101,6 +101,8 @@ impl GridEditorTest {
.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> {
self.field_revs
.iter()
@ -164,7 +166,9 @@ pub const PAUSED: &str = "Paused";
pub const FIRST_THING: &str = "Wake up at 6:00 am";
pub const SECOND_THING: &str = "Get some coffee";
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 {
let mut grid_builder = GridBuilder::new();
// 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 {
let block_id = grid_builder.block_id().to_owned();
let field_revs = grid_builder.field_revs();
@ -412,6 +415,7 @@ fn make_test_board() -> BuildGridContext {
match field_type {
FieldType::RichText => row_builder.insert_text_cell("A"),
FieldType::Number => row_builder.insert_number_cell("1"),
// 1647251762 => Mar 14,2022
FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
FieldType::SingleSelect => {
row_builder.insert_single_select_cell(|mut options| options.remove(0))
@ -428,6 +432,7 @@ fn make_test_board() -> BuildGridContext {
match field_type {
FieldType::RichText => row_builder.insert_text_cell("B"),
FieldType::Number => row_builder.insert_number_cell("2"),
// 1647251762 => Mar 14,2022
FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
FieldType::SingleSelect => {
row_builder.insert_single_select_cell(|mut options| options.remove(0))
@ -444,6 +449,7 @@ fn make_test_board() -> BuildGridContext {
match field_type {
FieldType::RichText => row_builder.insert_text_cell("C"),
FieldType::Number => row_builder.insert_number_cell("3"),
// 1647251762 => Mar 14,2022
FieldType::DateTime => row_builder.insert_date_cell("1647251762"),
FieldType::SingleSelect => {
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)]
pub struct CellRevision {
pub data: String,
#[serde(rename = "data")]
pub type_cell_data: String,
}
impl CellRevision {
pub fn new(data: String) -> Self {
Self { data }
Self { type_cell_data: data }
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
self.type_cell_data.is_empty()
}
}