mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Create test template (#1594)
* refactor: rename functions * chore: create test templagte Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
af716be7aa
commit
eee3dcf43a
@ -38,7 +38,7 @@ class CellService {
|
||||
..gridId = cellId.gridId
|
||||
..fieldId = cellId.fieldId
|
||||
..rowId = cellId.rowId
|
||||
..content = data;
|
||||
..typeCellData = data;
|
||||
return GridEventUpdateCell(payload).send();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
|
@ -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()
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -439,7 +439,7 @@ impl GridRevisionEditor {
|
||||
let field_rev = self.get_field_rev(¶ms.field_id).await?;
|
||||
let (_, row_rev) = self.block_manager.get_row_rev(¶ms.row_id).await.ok()??;
|
||||
let cell_rev = row_rev.cells.get(¶ms.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>>();
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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")]
|
||||
|
@ -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,
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user