mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: apply cell change set (#1589)
* refactor: update cell changeset trait * refactor: update cell changeset documentation Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
5d7008edd7
commit
4643851b3f
@ -55,8 +55,8 @@ pub trait CellDataChangeset: TypeOption {
|
|||||||
///
|
///
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<<Self as TypeOption>::CellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
cell_rev: Option<CellRevision>,
|
type_cell_data: Option<TypeCellData>,
|
||||||
) -> FlowyResult<String>;
|
) -> FlowyResult<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,21 +73,18 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
|
|||||||
) -> Result<String, FlowyError> {
|
) -> Result<String, FlowyError> {
|
||||||
let field_rev = field_rev.as_ref();
|
let field_rev = field_rev.as_ref();
|
||||||
let changeset = changeset.to_string();
|
let changeset = changeset.to_string();
|
||||||
let field_type = field_rev.ty.into();
|
let field_type: FieldType = field_rev.ty.into();
|
||||||
let s = match field_type {
|
|
||||||
FieldType::RichText => RichTextTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
FieldType::Number => NumberTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
FieldType::DateTime => DateTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
FieldType::SingleSelect => {
|
|
||||||
SingleSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev)
|
|
||||||
}
|
|
||||||
FieldType::MultiSelect => MultiSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
FieldType::Checklist => ChecklistTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
FieldType::Checkbox => CheckboxTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
FieldType::URL => URLTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
Ok(TypeCellData::new(s, field_type).to_json())
|
let type_cell_data = cell_rev.and_then(|cell_rev| match TypeCellData::try_from(cell_rev) {
|
||||||
|
Ok(type_cell_data) => Some(type_cell_data),
|
||||||
|
Err(_) => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let cell_data = match FieldRevisionExt::new(field_rev).get_type_option_cell_data_handler(&field_type) {
|
||||||
|
None => "".to_string(),
|
||||||
|
Some(handler) => handler.handle_cell_changeset(changeset, type_cell_data)?,
|
||||||
|
};
|
||||||
|
Ok(TypeCellData::new(cell_data, field_type).to_json())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debug>(
|
pub fn decode_type_cell_data<T: TryInto<TypeCellData, Error = FlowyError> + Debug>(
|
||||||
@ -138,7 +135,7 @@ pub fn try_decode_cell_data(
|
|||||||
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_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_data(cell_data, from_field_type, field_rev),
|
||||||
}
|
}
|
||||||
@ -154,7 +151,7 @@ pub fn stringify_cell_data(
|
|||||||
to_field_type: &FieldType,
|
to_field_type: &FieldType,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> String {
|
) -> String {
|
||||||
match FieldRevisionExt::new(field_rev).get_type_option_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_data(cell_data, from_field_type, field_rev),
|
||||||
}
|
}
|
||||||
@ -269,6 +266,15 @@ pub trait FromCellChangeset {
|
|||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromCellChangeset for String {
|
||||||
|
fn from_changeset(changeset: String) -> FlowyResult<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Ok(changeset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AnyCellChangeset<T>(pub Option<T>);
|
pub struct AnyCellChangeset<T>(pub Option<T>);
|
||||||
|
|
||||||
impl<T> AnyCellChangeset<T> {
|
impl<T> AnyCellChangeset<T> {
|
||||||
@ -294,8 +300,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::convert::From<String> for AnyCellChangeset<String> {
|
// impl std::convert::From<String> for AnyCellChangeset<String> {
|
||||||
fn from(s: String) -> Self {
|
// fn from(s: String) -> Self {
|
||||||
AnyCellChangeset(Some(s))
|
// AnyCellChangeset(Some(s))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use crate::entities::{CheckboxFilterPB, FieldType};
|
use crate::entities::{CheckboxFilterPB, FieldType};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellDataChangeset, CellDataDecoder, FromCellString};
|
use crate::services::cell::{CellDataChangeset, CellDataDecoder, FromCellString, TypeCellData};
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, CheckboxCellData, TypeOption, TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration,
|
BoxTypeOptionBuilder, CheckboxCellData, TypeOption, TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration,
|
||||||
TypeOptionTransform,
|
TypeOptionTransform,
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::FlowyResult;
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
@ -87,10 +87,9 @@ pub type CheckboxCellChangeset = String;
|
|||||||
impl CellDataChangeset for CheckboxTypeOptionPB {
|
impl CellDataChangeset for CheckboxTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<CheckboxCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
_cell_rev: Option<CellRevision>,
|
_type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let changeset = changeset.try_into_inner()?;
|
|
||||||
let cell_data = CheckboxCellData::from_str(&changeset)?;
|
let cell_data = CheckboxCellData::from_str(&changeset)?;
|
||||||
Ok(cell_data.to_string())
|
Ok(cell_data.to_string())
|
||||||
}
|
}
|
||||||
|
@ -147,13 +147,12 @@ mod tests {
|
|||||||
expected_str: &str,
|
expected_str: &str,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) {
|
) {
|
||||||
let s = serde_json::to_string(&DateCellChangeset {
|
let changeset = DateCellChangeset {
|
||||||
date: Some(timestamp.to_string()),
|
date: Some(timestamp.to_string()),
|
||||||
time: include_time_str,
|
time: include_time_str,
|
||||||
is_utc: false,
|
is_utc: false,
|
||||||
})
|
};
|
||||||
.unwrap();
|
let encoded_data = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
let encoded_data = type_option.apply_changeset(s.into(), None).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
decode_cell_data(encoded_data, type_option, field_rev),
|
decode_cell_data(encoded_data, type_option, field_rev),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{DateFilterPB, FieldType};
|
use crate::entities::{DateFilterPB, FieldType};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellDataChangeset, CellDataDecoder, FromCellString};
|
use crate::services::cell::{CellDataChangeset, CellDataDecoder, FromCellString, TypeCellData};
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, DateCellChangeset, DateCellData, DateCellDataPB, DateFormat, TimeFormat, TypeOption,
|
BoxTypeOptionBuilder, DateCellChangeset, DateCellData, DateCellDataPB, DateFormat, TimeFormat, TypeOption,
|
||||||
TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration, TypeOptionTransform,
|
TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration, TypeOptionTransform,
|
||||||
@ -10,7 +10,7 @@ use chrono::format::strftime::StrftimeItems;
|
|||||||
use chrono::{NaiveDateTime, Timelike};
|
use chrono::{NaiveDateTime, Timelike};
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// Date
|
// Date
|
||||||
@ -156,10 +156,9 @@ impl CellDataDecoder for DateTypeOptionPB {
|
|||||||
impl CellDataChangeset for DateTypeOptionPB {
|
impl CellDataChangeset for DateTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<DateCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
_cell_rev: Option<CellRevision>,
|
_type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let changeset = changeset.try_into_inner()?;
|
|
||||||
let cell_data = match changeset.date_timestamp() {
|
let cell_data = match changeset.date_timestamp() {
|
||||||
None => 0,
|
None => 0,
|
||||||
Some(date_timestamp) => match (self.include_time, changeset.time) {
|
Some(date_timestamp) => match (self.include_time, changeset.time) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{FieldType, NumberFilterPB};
|
use crate::entities::{FieldType, NumberFilterPB};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellComparable, CellDataChangeset, CellDataDecoder};
|
use crate::services::cell::{CellComparable, CellDataChangeset, CellDataDecoder, TypeCellData};
|
||||||
use crate::services::field::type_options::number_type_option::format::*;
|
use crate::services::field::type_options::number_type_option::format::*;
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, NumberCellData, StrCellData, TypeOption, TypeOptionBuilder, TypeOptionCellData,
|
BoxTypeOptionBuilder, NumberCellData, StrCellData, TypeOption, TypeOptionBuilder, TypeOptionCellData,
|
||||||
@ -8,8 +8,8 @@ use crate::services::field::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::FlowyResult;
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -156,10 +156,9 @@ pub type NumberCellChangeset = String;
|
|||||||
impl CellDataChangeset for NumberTypeOptionPB {
|
impl CellDataChangeset for NumberTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<NumberCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
_cell_rev: Option<CellRevision>,
|
_type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let changeset = changeset.try_into_inner()?;
|
|
||||||
let data = changeset.trim().to_string();
|
let data = changeset.trim().to_string();
|
||||||
let _ = self.format_cell_data(&data)?;
|
let _ = self.format_cell_data(&data)?;
|
||||||
Ok(data)
|
Ok(data)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{ChecklistFilterPB, FieldType};
|
use crate::entities::{ChecklistFilterPB, FieldType};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellDataChangeset, FromCellString, TypeCellData};
|
use crate::services::cell::{CellDataChangeset, FromCellString, TypeCellData};
|
||||||
|
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB, SelectOptionIds, SelectOptionPB,
|
BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB, SelectOptionIds, SelectOptionPB,
|
||||||
@ -8,8 +8,8 @@ use crate::services::field::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::FlowyResult;
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// Multiple select
|
// Multiple select
|
||||||
@ -60,31 +60,26 @@ impl SelectTypeOptionSharedAction for ChecklistTypeOptionPB {
|
|||||||
impl CellDataChangeset for ChecklistTypeOptionPB {
|
impl CellDataChangeset for ChecklistTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<SelectOptionCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
cell_rev: Option<CellRevision>,
|
type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let content_changeset = changeset.try_into_inner()?;
|
let insert_option_ids = changeset
|
||||||
|
|
||||||
let insert_option_ids = content_changeset
|
|
||||||
.insert_option_ids
|
.insert_option_ids
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
.filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
match cell_rev {
|
match type_cell_data {
|
||||||
None => Ok(SelectOptionIds::from(insert_option_ids).to_string()),
|
None => Ok(SelectOptionIds::from(insert_option_ids).to_string()),
|
||||||
Some(cell_rev) => {
|
Some(type_cell_data) => {
|
||||||
let cell_data = TypeCellData::try_from(cell_rev)
|
let mut select_ids: SelectOptionIds = type_cell_data.data.into();
|
||||||
.map(|data| data.into_inner())
|
|
||||||
.unwrap_or_default();
|
|
||||||
let mut select_ids: SelectOptionIds = cell_data.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for delete_option_id in content_changeset.delete_option_ids {
|
for delete_option_id in changeset.delete_option_ids {
|
||||||
select_ids.retain(|id| id != &delete_option_id);
|
select_ids.retain(|id| id != &delete_option_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{FieldType, SelectOptionFilterPB};
|
use crate::entities::{FieldType, SelectOptionFilterPB};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellDataChangeset, FromCellString, TypeCellData};
|
use crate::services::cell::{CellDataChangeset, FromCellString, TypeCellData};
|
||||||
|
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB, SelectOptionIds, SelectOptionPB,
|
BoxTypeOptionBuilder, SelectOptionCellChangeset, SelectOptionCellDataPB, SelectOptionIds, SelectOptionPB,
|
||||||
@ -8,8 +8,8 @@ use crate::services::field::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::FlowyResult;
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// Multiple select
|
// Multiple select
|
||||||
@ -60,34 +60,29 @@ impl SelectTypeOptionSharedAction for MultiSelectTypeOptionPB {
|
|||||||
impl CellDataChangeset for MultiSelectTypeOptionPB {
|
impl CellDataChangeset for MultiSelectTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<SelectOptionCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
cell_rev: Option<CellRevision>,
|
type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let content_changeset = changeset.try_into_inner()?;
|
let insert_option_ids = changeset
|
||||||
|
|
||||||
let insert_option_ids = content_changeset
|
|
||||||
.insert_option_ids
|
.insert_option_ids
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
.filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
let new_cell_data: String;
|
let new_cell_data: String;
|
||||||
match cell_rev {
|
match type_cell_data {
|
||||||
None => {
|
None => {
|
||||||
new_cell_data = SelectOptionIds::from(insert_option_ids).to_string();
|
new_cell_data = SelectOptionIds::from(insert_option_ids).to_string();
|
||||||
}
|
}
|
||||||
Some(cell_rev) => {
|
Some(type_cell_data) => {
|
||||||
let cell_data = TypeCellData::try_from(cell_rev)
|
let mut select_ids: SelectOptionIds = type_cell_data.data.into();
|
||||||
.map(|data| data.into_inner())
|
|
||||||
.unwrap_or_default();
|
|
||||||
let mut select_ids: SelectOptionIds = cell_data.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for delete_option_id in content_changeset.delete_option_ids {
|
for delete_option_id in changeset.delete_option_ids {
|
||||||
select_ids.retain(|id| id != &delete_option_id);
|
select_ids.retain(|id| id != &delete_option_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,8 +172,8 @@ mod tests {
|
|||||||
let field_rev = FieldBuilder::new(multi_select).name("Platform").build();
|
let field_rev = FieldBuilder::new(multi_select).name("Platform").build();
|
||||||
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
||||||
let option_ids = vec![google.id, facebook.id];
|
let option_ids = vec![google.id, facebook.id];
|
||||||
let data = SelectOptionCellChangeset::from_insert_options(option_ids.clone()).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_options(option_ids.clone());
|
||||||
let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
let select_option_ids: SelectOptionIds = type_option.apply_changeset(changeset, None).unwrap().into();
|
||||||
|
|
||||||
assert_eq!(&*select_option_ids, &option_ids);
|
assert_eq!(&*select_option_ids, &option_ids);
|
||||||
}
|
}
|
||||||
@ -196,13 +191,13 @@ mod tests {
|
|||||||
let option_ids = vec![google.id, facebook.id];
|
let option_ids = vec![google.id, facebook.id];
|
||||||
|
|
||||||
// insert
|
// insert
|
||||||
let data = SelectOptionCellChangeset::from_insert_options(option_ids.clone()).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_options(option_ids.clone());
|
||||||
let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
let select_option_ids: SelectOptionIds = type_option.apply_changeset(changeset, None).unwrap().into();
|
||||||
assert_eq!(&*select_option_ids, &option_ids);
|
assert_eq!(&*select_option_ids, &option_ids);
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
let data = SelectOptionCellChangeset::from_delete_options(option_ids).to_str();
|
let changeset = SelectOptionCellChangeset::from_delete_options(option_ids);
|
||||||
let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
let select_option_ids: SelectOptionIds = type_option.apply_changeset(changeset, None).unwrap().into();
|
||||||
assert!(select_option_ids.is_empty());
|
assert!(select_option_ids.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,8 +212,8 @@ mod tests {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
||||||
let data = SelectOptionCellChangeset::from_insert_option_id(&google.id).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_option_id(&google.id);
|
||||||
let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
let cell_option_ids = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
assert_eq!(cell_option_ids, google.id);
|
assert_eq!(cell_option_ids, google.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +227,8 @@ mod tests {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
||||||
let data = SelectOptionCellChangeset::from_insert_option_id(&google.id).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_option_id(&google.id);
|
||||||
let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
let cell_option_ids = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
assert!(cell_option_ids.is_empty());
|
assert!(cell_option_ids.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,22 +245,12 @@ mod tests {
|
|||||||
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
||||||
|
|
||||||
// empty option id string
|
// empty option id string
|
||||||
let data = SelectOptionCellChangeset::from_insert_option_id("").to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_option_id("");
|
||||||
let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
let cell_option_ids = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
assert_eq!(cell_option_ids, "");
|
assert_eq!(cell_option_ids, "");
|
||||||
|
|
||||||
let data = SelectOptionCellChangeset::from_insert_option_id("123,456").to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_option_id("123,456");
|
||||||
let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
let cell_option_ids = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
assert_eq!(cell_option_ids, "");
|
assert_eq!(cell_option_ids, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multi_select_invalid_changeset_data_test() {
|
|
||||||
let multi_select = MultiSelectTypeOptionBuilder::default();
|
|
||||||
let field_rev = FieldBuilder::new(multi_select).name("Platform").build();
|
|
||||||
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
|
||||||
|
|
||||||
// The type of the changeset should be SelectOptionCellChangeset
|
|
||||||
assert!(type_option.apply_changeset("123".to_owned().into(), None).is_err());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{FieldType, SelectOptionFilterPB};
|
use crate::entities::{FieldType, SelectOptionFilterPB};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellDataChangeset, FromCellString};
|
use crate::services::cell::{CellDataChangeset, FromCellString, TypeCellData};
|
||||||
|
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, SelectOptionCellDataPB, TypeOption, TypeOptionBuilder, TypeOptionCellData,
|
BoxTypeOptionBuilder, SelectOptionCellDataPB, TypeOption, TypeOptionBuilder, TypeOptionCellData,
|
||||||
@ -11,8 +11,8 @@ use crate::services::field::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::FlowyResult;
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// Single select
|
// Single select
|
||||||
@ -63,12 +63,10 @@ impl SelectTypeOptionSharedAction for SingleSelectTypeOptionPB {
|
|||||||
impl CellDataChangeset for SingleSelectTypeOptionPB {
|
impl CellDataChangeset for SingleSelectTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<SelectOptionCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
_cell_rev: Option<CellRevision>,
|
_type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let content_changeset = changeset.try_into_inner()?;
|
let mut insert_option_ids = changeset
|
||||||
|
|
||||||
let mut insert_option_ids = content_changeset
|
|
||||||
.insert_option_ids
|
.insert_option_ids
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
.filter(|insert_option_id| self.options.iter().any(|option| &option.id == insert_option_id))
|
||||||
@ -162,8 +160,8 @@ mod tests {
|
|||||||
let field_rev = FieldBuilder::new(single_select).name("Platform").build();
|
let field_rev = FieldBuilder::new(single_select).name("Platform").build();
|
||||||
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
||||||
let option_ids = vec![google.id.clone(), facebook.id];
|
let option_ids = vec![google.id.clone(), facebook.id];
|
||||||
let data = SelectOptionCellChangeset::from_insert_options(option_ids).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_options(option_ids);
|
||||||
let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
let select_option_ids: SelectOptionIds = type_option.apply_changeset(changeset, None).unwrap().into();
|
||||||
|
|
||||||
assert_eq!(&*select_option_ids, &vec![google.id]);
|
assert_eq!(&*select_option_ids, &vec![google.id]);
|
||||||
}
|
}
|
||||||
@ -181,13 +179,13 @@ mod tests {
|
|||||||
let option_ids = vec![google.id.clone(), facebook.id];
|
let option_ids = vec![google.id.clone(), facebook.id];
|
||||||
|
|
||||||
// insert
|
// insert
|
||||||
let data = SelectOptionCellChangeset::from_insert_options(option_ids.clone()).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_options(option_ids.clone());
|
||||||
let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
let select_option_ids: SelectOptionIds = type_option.apply_changeset(changeset, None).unwrap().into();
|
||||||
assert_eq!(&*select_option_ids, &vec![google.id]);
|
assert_eq!(&*select_option_ids, &vec![google.id]);
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
let data = SelectOptionCellChangeset::from_delete_options(option_ids).to_str();
|
let changeset = SelectOptionCellChangeset::from_delete_options(option_ids);
|
||||||
let select_option_ids: SelectOptionIds = type_option.apply_changeset(data.into(), None).unwrap().into();
|
let select_option_ids: SelectOptionIds = type_option.apply_changeset(changeset, None).unwrap().into();
|
||||||
assert!(select_option_ids.is_empty());
|
assert!(select_option_ids.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,8 +197,8 @@ mod tests {
|
|||||||
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
||||||
|
|
||||||
let option_ids = vec![google.id];
|
let option_ids = vec![google.id];
|
||||||
let data = SelectOptionCellChangeset::from_insert_options(option_ids).to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_options(option_ids);
|
||||||
let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
let cell_option_ids = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
|
|
||||||
assert!(cell_option_ids.is_empty());
|
assert!(cell_option_ids.is_empty());
|
||||||
}
|
}
|
||||||
@ -211,18 +209,8 @@ mod tests {
|
|||||||
let field_rev = FieldBuilder::new(single_select).name("Platform").build();
|
let field_rev = FieldBuilder::new(single_select).name("Platform").build();
|
||||||
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
||||||
|
|
||||||
let data = SelectOptionCellChangeset::from_insert_option_id("").to_str();
|
let changeset = SelectOptionCellChangeset::from_insert_option_id("");
|
||||||
let cell_option_ids = type_option.apply_changeset(data.into(), None).unwrap();
|
let cell_option_ids = type_option.apply_changeset(changeset, None).unwrap();
|
||||||
assert_eq!(cell_option_ids, "");
|
assert_eq!(cell_option_ids, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn single_select_invalid_changeset_data_test() {
|
|
||||||
let single_select = SingleSelectTypeOptionBuilder::default();
|
|
||||||
let field_rev = FieldBuilder::new(single_select).name("Platform").build();
|
|
||||||
let type_option = SingleSelectTypeOptionPB::from(&field_rev);
|
|
||||||
|
|
||||||
// The type of the changeset should be SelectOptionCellChangeset
|
|
||||||
assert!(type_option.apply_changeset("123".to_owned().into(), None).is_err());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::entities::{FieldType, TextFilterPB};
|
use crate::entities::{FieldType, TextFilterPB};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{
|
use crate::services::cell::{
|
||||||
stringify_cell_data, AnyCellChangeset, CellComparable, CellDataChangeset, CellDataDecoder, CellProtobufBlobParser,
|
stringify_cell_data, CellComparable, CellDataChangeset, CellDataDecoder, CellProtobufBlobParser, DecodedCellData,
|
||||||
DecodedCellData, FromCellString,
|
FromCellString, TypeCellData,
|
||||||
};
|
};
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, TypeOption, TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration,
|
BoxTypeOptionBuilder, TypeOption, TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration,
|
||||||
@ -11,7 +11,7 @@ use crate::services::field::{
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use protobuf::ProtobufError;
|
use protobuf::ProtobufError;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -90,14 +90,13 @@ impl CellDataDecoder for RichTextTypeOptionPB {
|
|||||||
impl CellDataChangeset for RichTextTypeOptionPB {
|
impl CellDataChangeset for RichTextTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<String>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
_cell_rev: Option<CellRevision>,
|
_type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let data = changeset.try_into_inner()?;
|
if changeset.len() > 10000 {
|
||||||
if data.len() > 10000 {
|
|
||||||
Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000"))
|
Err(FlowyError::text_too_long().context("The len of the text should not be more than 10000"))
|
||||||
} else {
|
} else {
|
||||||
Ok(data)
|
Ok(changeset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::entities::FieldType;
|
use crate::entities::FieldType;
|
||||||
use crate::services::cell::{CellDataChangeset, CellDataDecoder, CellProtobufBlob, FromCellString};
|
use crate::services::cell::{
|
||||||
|
CellDataChangeset, CellDataDecoder, CellProtobufBlob, FromCellChangeset, FromCellString, TypeCellData,
|
||||||
|
};
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
CheckboxTypeOptionPB, ChecklistTypeOptionPB, DateTypeOptionPB, MultiSelectTypeOptionPB, NumberTypeOptionPB,
|
CheckboxTypeOptionPB, ChecklistTypeOptionPB, DateTypeOptionPB, MultiSelectTypeOptionPB, NumberTypeOptionPB,
|
||||||
RichTextTypeOptionPB, SingleSelectTypeOptionPB, URLTypeOptionPB,
|
RichTextTypeOptionPB, SingleSelectTypeOptionPB, URLTypeOptionPB,
|
||||||
@ -23,8 +25,11 @@ pub trait TypeOption {
|
|||||||
///
|
///
|
||||||
type CellData: FromCellString + Default;
|
type CellData: FromCellString + Default;
|
||||||
|
|
||||||
|
/// Represents as the corresponding field type cell changeset.
|
||||||
|
/// The changeset must implements the `FromCellChangeset` trait. The `CellChangeset` is implemented
|
||||||
|
/// for `String`.
|
||||||
///
|
///
|
||||||
type CellChangeset;
|
type CellChangeset: FromCellChangeset;
|
||||||
|
|
||||||
/// For the moment, the protobuf type only be used in the FFI of `Dart`. If the decoded cell
|
/// For the moment, the protobuf type only be used in the FFI of `Dart`. If the decoded cell
|
||||||
/// struct is just a `String`, then use the `StrCellData` as its `CellProtobufType`.
|
/// struct is just a `String`, then use the `StrCellData` as its `CellProtobufType`.
|
||||||
@ -92,6 +97,7 @@ pub trait TypeOptionTransform: TypeOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper trait that used to erase the `Self` of `TypeOption` trait to make it become a Object-safe trait.
|
||||||
pub trait TypeOptionTransformHandler {
|
pub trait TypeOptionTransformHandler {
|
||||||
fn transform(&mut self, old_type_option_field_type: FieldType, old_type_option_data: String);
|
fn transform(&mut self, old_type_option_field_type: FieldType, old_type_option_data: String);
|
||||||
|
|
||||||
@ -113,6 +119,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper trait that used to erase the `Self` of `TypeOption` trait to make it become a Object-safe trait
|
||||||
|
/// Only object-safe traits can be made into trait objects.
|
||||||
|
/// > Object-safe traits are traits with methods that follow these two rules:
|
||||||
|
/// 1.the return type is not Self.
|
||||||
|
/// 2.there are no generic types parameters.
|
||||||
|
///
|
||||||
pub trait TypeOptionCellDataHandler {
|
pub trait TypeOptionCellDataHandler {
|
||||||
fn handle_cell_data(
|
fn handle_cell_data(
|
||||||
&self,
|
&self,
|
||||||
@ -121,6 +133,12 @@ pub trait TypeOptionCellDataHandler {
|
|||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<CellProtobufBlob>;
|
) -> FlowyResult<CellProtobufBlob>;
|
||||||
|
|
||||||
|
fn handle_cell_changeset(
|
||||||
|
&self,
|
||||||
|
cell_changeset: String,
|
||||||
|
old_type_cell_data: Option<TypeCellData>,
|
||||||
|
) -> FlowyResult<String>;
|
||||||
|
|
||||||
fn stringify_cell_data(&self, cell_data: String, field_type: &FieldType, field_rev: &FieldRevision) -> String;
|
fn stringify_cell_data(&self, cell_data: String, field_type: &FieldType, field_rev: &FieldRevision) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +163,16 @@ where
|
|||||||
CellProtobufBlob::from(self.convert_to_protobuf(cell_data))
|
CellProtobufBlob::from(self.convert_to_protobuf(cell_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_cell_changeset(
|
||||||
|
&self,
|
||||||
|
cell_changeset: String,
|
||||||
|
old_type_cell_data: Option<TypeCellData>,
|
||||||
|
) -> FlowyResult<String> {
|
||||||
|
let changeset = <Self as TypeOption>::CellChangeset::from_changeset(cell_changeset)?;
|
||||||
|
let cell_data = self.apply_changeset(changeset, old_type_cell_data)?;
|
||||||
|
Ok(cell_data)
|
||||||
|
}
|
||||||
|
|
||||||
fn stringify_cell_data(
|
fn stringify_cell_data(
|
||||||
&self,
|
&self,
|
||||||
cell_data: String,
|
cell_data: String,
|
||||||
@ -173,7 +201,10 @@ impl<'a> FieldRevisionExt<'a> {
|
|||||||
Self { field_rev }
|
Self { field_rev }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_type_option_handler(&self, field_type: &FieldType) -> Option<Box<dyn TypeOptionCellDataHandler>> {
|
pub fn get_type_option_cell_data_handler(
|
||||||
|
&self,
|
||||||
|
field_type: &FieldType,
|
||||||
|
) -> Option<Box<dyn TypeOptionCellDataHandler>> {
|
||||||
match field_type {
|
match field_type {
|
||||||
FieldType::RichText => self
|
FieldType::RichText => self
|
||||||
.field_rev
|
.field_rev
|
||||||
|
@ -170,7 +170,7 @@ mod tests {
|
|||||||
field_type: &FieldType,
|
field_type: &FieldType,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) {
|
) {
|
||||||
let encoded_data = type_option.apply_changeset(input_str.to_owned().into(), None).unwrap();
|
let encoded_data = type_option.apply_changeset(input_str.to_owned(), None).unwrap();
|
||||||
let decode_cell_data = decode_cell_data(encoded_data, type_option, field_rev, field_type);
|
let decode_cell_data = decode_cell_data(encoded_data, type_option, field_rev, field_type);
|
||||||
assert_eq!(expected_str.to_owned(), decode_cell_data.content);
|
assert_eq!(expected_str.to_owned(), decode_cell_data.content);
|
||||||
assert_eq!(expected_url.to_owned(), decode_cell_data.url);
|
assert_eq!(expected_url.to_owned(), decode_cell_data.url);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{FieldType, TextFilterPB};
|
use crate::entities::{FieldType, TextFilterPB};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::cell::{AnyCellChangeset, CellDataChangeset, CellDataDecoder, FromCellString};
|
use crate::services::cell::{CellDataChangeset, CellDataDecoder, FromCellString, TypeCellData};
|
||||||
use crate::services::field::{
|
use crate::services::field::{
|
||||||
BoxTypeOptionBuilder, TypeOption, TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration,
|
BoxTypeOptionBuilder, TypeOption, TypeOptionBuilder, TypeOptionCellData, TypeOptionConfiguration,
|
||||||
TypeOptionTransform, URLCellData, URLCellDataPB,
|
TypeOptionTransform, URLCellData, URLCellDataPB,
|
||||||
@ -8,8 +8,8 @@ use crate::services::field::{
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use fancy_regex::Regex;
|
use fancy_regex::Regex;
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::FlowyResult;
|
||||||
use grid_rev_model::{CellRevision, FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
use grid_rev_model::{FieldRevision, TypeOptionDataDeserializer, TypeOptionDataSerializer};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -81,15 +81,18 @@ pub type URLCellChangeset = String;
|
|||||||
impl CellDataChangeset for URLTypeOptionPB {
|
impl CellDataChangeset for URLTypeOptionPB {
|
||||||
fn apply_changeset(
|
fn apply_changeset(
|
||||||
&self,
|
&self,
|
||||||
changeset: AnyCellChangeset<URLCellChangeset>,
|
changeset: <Self as TypeOption>::CellChangeset,
|
||||||
_cell_rev: Option<CellRevision>,
|
_type_cell_data: Option<TypeCellData>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> FlowyResult<String> {
|
||||||
let content = changeset.try_into_inner()?;
|
|
||||||
let mut url = "".to_string();
|
let mut url = "".to_string();
|
||||||
if let Ok(Some(m)) = URL_REGEX.find(&content) {
|
if let Ok(Some(m)) = URL_REGEX.find(&changeset) {
|
||||||
url = auto_append_scheme(m.as_str());
|
url = auto_append_scheme(m.as_str());
|
||||||
}
|
}
|
||||||
URLCellData { url, content }.to_json()
|
URLCellData {
|
||||||
|
url,
|
||||||
|
content: changeset,
|
||||||
|
}
|
||||||
|
.to_json()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user