feat: add new field type

This commit is contained in:
appflowy
2022-05-27 19:03:48 +08:00
parent 60b80005ac
commit 9a93a72c33
38 changed files with 1016 additions and 62 deletions

View File

@ -953,6 +953,7 @@ dependencies = [
"strum_macros",
"tokio",
"tracing",
"url",
]
[[package]]

View File

@ -35,6 +35,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = {version = "1.0"}
serde_repr = "0.1"
indexmap = {version = "1.8.1", features = ["serde"]}
url = { version = "2"}
[dev-dependencies]
flowy-test = { path = "../flowy-test" }

View File

@ -263,7 +263,7 @@ pub(crate) async fn update_cell_handler(
Ok(())
}
#[tracing::instrument(level = "debug", skip(data, manager), err)]
#[tracing::instrument(level = "trace", skip(data, manager), err)]
pub(crate) async fn get_date_cell_data_handler(
data: Data<CellIdentifierPayload>,
manager: AppData<Arc<GridManager>>,
@ -272,7 +272,7 @@ pub(crate) async fn get_date_cell_data_handler(
let editor = manager.get_grid_editor(&params.grid_id)?;
match editor.get_field_meta(&params.field_id).await {
None => {
tracing::error!("Can't find the corresponding field with id: {}", params.field_id);
tracing::error!("Can't find the date field with id: {}", params.field_id);
data_result(DateCellData::default())
}
Some(field_meta) => {
@ -350,7 +350,7 @@ pub(crate) async fn get_select_option_handler(
let editor = manager.get_grid_editor(&params.grid_id)?;
match editor.get_field_meta(&params.field_id).await {
None => {
tracing::error!("Can't find the corresponding field with id: {}", params.field_id);
tracing::error!("Can't find the select option field with id: {}", params.field_id);
data_result(SelectOptionCellData::default())
}
Some(field_meta) => {

View File

@ -19,6 +19,9 @@ pub use row_entities::*;
mod cell_entities;
pub use cell_entities::*;
mod url_type_option;
pub use url_type_option::*;
mod checkbox_type_option;
pub use checkbox_type_option::*;

View File

@ -26,7 +26,7 @@
#[derive(PartialEq,Clone,Default)]
pub struct RichTextTypeOption {
// message fields
pub format: ::std::string::String,
pub data: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -43,30 +43,30 @@ impl RichTextTypeOption {
::std::default::Default::default()
}
// string format = 1;
// string data = 1;
pub fn get_format(&self) -> &str {
&self.format
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_format(&mut self) {
self.format.clear();
pub fn clear_data(&mut self) {
self.data.clear();
}
// Param is passed by value, moved
pub fn set_format(&mut self, v: ::std::string::String) {
self.format = v;
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_format(&mut self) -> &mut ::std::string::String {
&mut self.format
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_format(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.format, ::std::string::String::new())
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
}
@ -80,7 +80,7 @@ impl ::protobuf::Message for RichTextTypeOption {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.format)?;
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -94,8 +94,8 @@ impl ::protobuf::Message for RichTextTypeOption {
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.format.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.format);
if !self.data.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.data);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
@ -103,8 +103,8 @@ impl ::protobuf::Message for RichTextTypeOption {
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.format.is_empty() {
os.write_string(1, &self.format)?;
if !self.data.is_empty() {
os.write_string(1, &self.data)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
@ -145,9 +145,9 @@ impl ::protobuf::Message for RichTextTypeOption {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"format",
|m: &RichTextTypeOption| { &m.format },
|m: &mut RichTextTypeOption| { &mut m.format },
"data",
|m: &RichTextTypeOption| { &m.data },
|m: &mut RichTextTypeOption| { &mut m.data },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<RichTextTypeOption>(
"RichTextTypeOption",
@ -165,7 +165,7 @@ impl ::protobuf::Message for RichTextTypeOption {
impl ::protobuf::Clear for RichTextTypeOption {
fn clear(&mut self) {
self.format.clear();
self.data.clear();
self.unknown_fields.clear();
}
}
@ -183,8 +183,8 @@ impl ::protobuf::reflect::ProtobufValue for RichTextTypeOption {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x16text_type_option.proto\",\n\x12RichTextTypeOption\x12\x16\n\x06for\
mat\x18\x01\x20\x01(\tR\x06formatb\x06proto3\
\n\x16text_type_option.proto\"(\n\x12RichTextTypeOption\x12\x12\n\x04dat\
a\x18\x01\x20\x01(\tR\x04datab\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -0,0 +1,403 @@
// This file is generated by rust-protobuf 2.25.2. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_imports)]
#![allow(unused_results)]
//! Generated file from `url_type_option.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(PartialEq,Clone,Default)]
pub struct URLTypeOption {
// message fields
pub data: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a URLTypeOption {
fn default() -> &'a URLTypeOption {
<URLTypeOption as ::protobuf::Message>::default_instance()
}
}
impl URLTypeOption {
pub fn new() -> URLTypeOption {
::std::default::Default::default()
}
// string data = 1;
pub fn get_data(&self) -> &str {
&self.data
}
pub fn clear_data(&mut self) {
self.data.clear();
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::string::String) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::string::String {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.data, ::std::string::String::new())
}
}
impl ::protobuf::Message for URLTypeOption {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.data.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.data);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.data.is_empty() {
os.write_string(1, &self.data)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> URLTypeOption {
URLTypeOption::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"data",
|m: &URLTypeOption| { &m.data },
|m: &mut URLTypeOption| { &mut m.data },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<URLTypeOption>(
"URLTypeOption",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static URLTypeOption {
static instance: ::protobuf::rt::LazyV2<URLTypeOption> = ::protobuf::rt::LazyV2::INIT;
instance.get(URLTypeOption::new)
}
}
impl ::protobuf::Clear for URLTypeOption {
fn clear(&mut self) {
self.data.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for URLTypeOption {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for URLTypeOption {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct URLCellData {
// message fields
pub url: ::std::string::String,
pub content: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a URLCellData {
fn default() -> &'a URLCellData {
<URLCellData as ::protobuf::Message>::default_instance()
}
}
impl URLCellData {
pub fn new() -> URLCellData {
::std::default::Default::default()
}
// string url = 1;
pub fn get_url(&self) -> &str {
&self.url
}
pub fn clear_url(&mut self) {
self.url.clear();
}
// Param is passed by value, moved
pub fn set_url(&mut self, v: ::std::string::String) {
self.url = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_url(&mut self) -> &mut ::std::string::String {
&mut self.url
}
// Take field
pub fn take_url(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.url, ::std::string::String::new())
}
// string content = 2;
pub fn get_content(&self) -> &str {
&self.content
}
pub fn clear_content(&mut self) {
self.content.clear();
}
// Param is passed by value, moved
pub fn set_content(&mut self, v: ::std::string::String) {
self.content = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_content(&mut self) -> &mut ::std::string::String {
&mut self.content
}
// Take field
pub fn take_content(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.content, ::std::string::String::new())
}
}
impl ::protobuf::Message for URLCellData {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.url)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.content)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.url.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.url);
}
if !self.content.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.content);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.url.is_empty() {
os.write_string(1, &self.url)?;
}
if !self.content.is_empty() {
os.write_string(2, &self.content)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> URLCellData {
URLCellData::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"url",
|m: &URLCellData| { &m.url },
|m: &mut URLCellData| { &mut m.url },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"content",
|m: &URLCellData| { &m.content },
|m: &mut URLCellData| { &mut m.content },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<URLCellData>(
"URLCellData",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static URLCellData {
static instance: ::protobuf::rt::LazyV2<URLCellData> = ::protobuf::rt::LazyV2::INIT;
instance.get(URLCellData::new)
}
}
impl ::protobuf::Clear for URLCellData {
fn clear(&mut self) {
self.url.clear();
self.content.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for URLCellData {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for URLCellData {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x15url_type_option.proto\"#\n\rURLTypeOption\x12\x12\n\x04data\x18\
\x01\x20\x01(\tR\x04data\"9\n\x0bURLCellData\x12\x10\n\x03url\x18\x01\
\x20\x01(\tR\x03url\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07contentb\
\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -1,5 +1,5 @@
syntax = "proto3";
message RichTextTypeOption {
string format = 1;
string data = 1;
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
message URLTypeOption {
string data = 1;
}
message URLCellData {
string url = 1;
string content = 2;
}

View File

@ -94,6 +94,7 @@ pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box<dyn
FieldType::SingleSelect => SingleSelectTypeOption::default().into(),
FieldType::MultiSelect => MultiSelectTypeOption::default().into(),
FieldType::Checkbox => CheckboxTypeOption::default().into(),
FieldType::URL => URLTypeOption::default().into(),
};
type_option_builder_from_json_str(&s, field_type)
@ -107,6 +108,7 @@ pub fn type_option_builder_from_json_str(s: &str, field_type: &FieldType) -> Box
FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_json_str(s)),
FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_json_str(s)),
FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_json_str(s)),
FieldType::URL => Box::new(URLTypeOptionBuilder::from_json_str(s)),
}
}
@ -119,5 +121,6 @@ pub fn type_option_builder_from_bytes<T: Into<Bytes>>(bytes: T, field_type: &Fie
FieldType::SingleSelect => Box::new(SingleSelectTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::MultiSelect => Box::new(MultiSelectTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::Checkbox => Box::new(CheckboxTypeOptionBuilder::from_protobuf_bytes(bytes)),
FieldType::URL => Box::new(URLTypeOptionBuilder::from_protobuf_bytes(bytes)),
}
}

View File

@ -3,6 +3,7 @@ mod date_type_option;
mod number_type_option;
mod selection_type_option;
mod text_type_option;
mod url_type_option;
mod util;
pub use checkbox_type_option::*;
@ -10,3 +11,4 @@ pub use date_type_option::*;
pub use number_type_option::*;
pub use selection_type_option::*;
pub use text_type_option::*;
pub use url_type_option::*;

View File

@ -736,14 +736,10 @@ mod tests {
) {
assert_eq!(
type_option
.decode_cell_data(data(cell_data), field_type, field_meta)
.decode_cell_data(cell_data, field_type, field_meta)
.unwrap()
.content,
expected_str.to_owned()
);
}
fn data(s: &str) -> String {
s.to_owned()
}
}

View File

@ -27,7 +27,7 @@ impl TypeOptionBuilder for RichTextTypeOptionBuilder {
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
pub struct RichTextTypeOption {
#[pb(index = 1)]
pub format: String,
data: String, //It's not used.
}
impl_type_option!(RichTextTypeOption, FieldType::RichText);

View File

@ -0,0 +1,101 @@
use crate::impl_type_option;
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
use bytes::Bytes;
use flowy_derive::ProtoBuf;
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::{
CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
};
use serde::{Deserialize, Serialize};
#[derive(Default)]
pub struct URLTypeOptionBuilder(URLTypeOption);
impl_into_box_type_option_builder!(URLTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(URLTypeOptionBuilder, URLTypeOption);
impl TypeOptionBuilder for URLTypeOptionBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn entry(&self) -> &dyn TypeOptionDataEntry {
&self.0
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
pub struct URLTypeOption {
#[pb(index = 1)]
data: String, //It's not used.
}
impl_type_option!(URLTypeOption, FieldType::URL);
impl CellDataOperation<String, String> for URLTypeOption {
fn decode_cell_data<T>(
&self,
encoded_data: T,
decoded_field_type: &FieldType,
_field_meta: &FieldMeta,
) -> FlowyResult<DecodedCellData>
where
T: Into<String>,
{
if !decoded_field_type.is_url() {
return Ok(DecodedCellData::default());
}
let cell_data = encoded_data.into();
Ok(DecodedCellData::from_content(cell_data))
}
fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
where
C: Into<CellContentChangeset>,
{
let changeset = changeset.into();
Ok(changeset.to_string())
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct URLCellData {
#[pb(index = 1)]
pub url: String,
#[pb(index = 2)]
pub content: String,
}
#[cfg(test)]
mod tests {
use crate::services::field::FieldBuilder;
use crate::services::field::URLTypeOption;
use crate::services::row::CellDataOperation;
use flowy_grid_data_model::entities::{FieldMeta, FieldType};
#[test]
fn url_type_option_format_test() {
let type_option = URLTypeOption::default();
let field_type = FieldType::URL;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
assert_equal(&type_option, "123", "123", &field_type, &field_meta);
}
fn assert_equal(
type_option: &URLTypeOption,
cell_data: &str,
expected_str: &str,
field_type: &FieldType,
field_meta: &FieldMeta,
) {
assert_eq!(
type_option
.decode_cell_data(cell_data, field_type, field_meta)
.unwrap()
.content,
expected_str.to_owned()
);
}
}

View File

@ -133,6 +133,7 @@ pub fn apply_cell_data_changeset<T: Into<CellContentChangeset>>(
FieldType::SingleSelect => SingleSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::MultiSelect => MultiSelectTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::Checkbox => CheckboxTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
FieldType::URL => URLTypeOption::from(field_meta).apply_changeset(changeset, cell_meta),
}?;
Ok(TypeOptionCellData::new(s, field_meta.field_type.clone()).json())
@ -178,6 +179,9 @@ pub fn decode_cell_data<T: Into<String>>(
FieldType::Checkbox => field_meta
.get_type_option_entry::<CheckboxTypeOption>(t_field_type)?
.decode_cell_data(encoded_data, s_field_type, field_meta),
FieldType::URL => field_meta
.get_type_option_entry::<URLTypeOption>(t_field_type)?
.decode_cell_data(encoded_data, s_field_type, field_meta),
};
Some(data)
};