chore: config update cell

This commit is contained in:
appflowy 2022-03-14 23:16:25 +08:00
parent 196d254278
commit 46be04f94e
18 changed files with 486 additions and 294 deletions

View File

@ -15,7 +15,7 @@ export 'number_description.pbenum.dart';
class NumberDescription extends $pb.GeneratedMessage { class NumberDescription extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberDescription', createEmptyInstance: create) static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberDescription', createEmptyInstance: create)
..e<MoneySymbol>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'money', $pb.PbFieldType.OE, defaultOrMaker: MoneySymbol.CNY, valueOf: MoneySymbol.valueOf, enumValues: MoneySymbol.values) ..e<NumberFormat>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: NumberFormat.Number, valueOf: NumberFormat.valueOf, enumValues: NumberFormat.values)
..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3) ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3)
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol')
..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive') ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive')
@ -25,15 +25,15 @@ class NumberDescription extends $pb.GeneratedMessage {
NumberDescription._() : super(); NumberDescription._() : super();
factory NumberDescription({ factory NumberDescription({
MoneySymbol? money, NumberFormat? format,
$core.int? scale, $core.int? scale,
$core.String? symbol, $core.String? symbol,
$core.bool? signPositive, $core.bool? signPositive,
$core.String? name, $core.String? name,
}) { }) {
final _result = create(); final _result = create();
if (money != null) { if (format != null) {
_result.money = money; _result.format = format;
} }
if (scale != null) { if (scale != null) {
_result.scale = scale; _result.scale = scale;
@ -71,13 +71,13 @@ class NumberDescription extends $pb.GeneratedMessage {
static NumberDescription? _defaultInstance; static NumberDescription? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
MoneySymbol get money => $_getN(0); NumberFormat get format => $_getN(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
set money(MoneySymbol v) { setField(1, v); } set format(NumberFormat v) { setField(1, v); }
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.bool hasMoney() => $_has(0); $core.bool hasFormat() => $_has(0);
@$pb.TagNumber(1) @$pb.TagNumber(1)
void clearMoney() => clearField(1); void clearFormat() => clearField(1);
@$pb.TagNumber(2) @$pb.TagNumber(2)
$core.int get scale => $_getIZ(1); $core.int get scale => $_getIZ(1);

View File

@ -9,20 +9,22 @@
import 'dart:core' as $core; import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb; import 'package:protobuf/protobuf.dart' as $pb;
class MoneySymbol extends $pb.ProtobufEnum { class NumberFormat extends $pb.ProtobufEnum {
static const MoneySymbol CNY = MoneySymbol._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY'); static const NumberFormat Number = NumberFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number');
static const MoneySymbol EUR = MoneySymbol._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR'); static const NumberFormat USD = NumberFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD');
static const MoneySymbol USD = MoneySymbol._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD'); static const NumberFormat CNY = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY');
static const NumberFormat EUR = NumberFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR');
static const $core.List<MoneySymbol> values = <MoneySymbol> [ static const $core.List<NumberFormat> values = <NumberFormat> [
Number,
USD,
CNY, CNY,
EUR, EUR,
USD,
]; ];
static final $core.Map<$core.int, MoneySymbol> _byValue = $pb.ProtobufEnum.initByValue(values); static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
static MoneySymbol? valueOf($core.int value) => _byValue[value]; static NumberFormat? valueOf($core.int value) => _byValue[value];
const MoneySymbol._($core.int v, $core.String n) : super(v, n); const NumberFormat._($core.int v, $core.String n) : super(v, n);
} }

View File

@ -8,23 +8,24 @@
import 'dart:core' as $core; import 'dart:core' as $core;
import 'dart:convert' as $convert; import 'dart:convert' as $convert;
import 'dart:typed_data' as $typed_data; import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use moneySymbolDescriptor instead') @$core.Deprecated('Use numberFormatDescriptor instead')
const MoneySymbol$json = const { const NumberFormat$json = const {
'1': 'MoneySymbol', '1': 'NumberFormat',
'2': const [ '2': const [
const {'1': 'CNY', '2': 0}, const {'1': 'Number', '2': 0},
const {'1': 'EUR', '2': 1}, const {'1': 'USD', '2': 1},
const {'1': 'USD', '2': 2}, const {'1': 'CNY', '2': 2},
const {'1': 'EUR', '2': 3},
], ],
}; };
/// Descriptor for `MoneySymbol`. Decode as a `google.protobuf.EnumDescriptorProto`. /// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List moneySymbolDescriptor = $convert.base64Decode('CgtNb25leVN5bWJvbBIHCgNDTlkQABIHCgNFVVIQARIHCgNVU0QQAg=='); final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESBwoDQ05ZEAISBwoDRVVSEAM=');
@$core.Deprecated('Use numberDescriptionDescriptor instead') @$core.Deprecated('Use numberDescriptionDescriptor instead')
const NumberDescription$json = const { const NumberDescription$json = const {
'1': 'NumberDescription', '1': 'NumberDescription',
'2': const [ '2': const [
const {'1': 'money', '3': 1, '4': 1, '5': 14, '6': '.MoneySymbol', '10': 'money'}, const {'1': 'format', '3': 1, '4': 1, '5': 14, '6': '.NumberFormat', '10': 'format'},
const {'1': 'scale', '3': 2, '4': 1, '5': 13, '10': 'scale'}, const {'1': 'scale', '3': 2, '4': 1, '5': 13, '10': 'scale'},
const {'1': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'}, const {'1': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'},
const {'1': 'sign_positive', '3': 4, '4': 1, '5': 8, '10': 'signPositive'}, const {'1': 'sign_positive', '3': 4, '4': 1, '5': 8, '10': 'signPositive'},
@ -33,4 +34,4 @@ const NumberDescription$json = const {
}; };
/// Descriptor for `NumberDescription`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `NumberDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIiCgVtb25leRgBIAEoDjIMLk1vbmV5U3ltYm9sUgVtb25leRIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU='); final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIlCgZmb3JtYXQYASABKA4yDS5OdW1iZXJGb3JtYXRSBmZvcm1hdBIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU=');

View File

@ -26,7 +26,7 @@
#[derive(PartialEq,Clone,Default)] #[derive(PartialEq,Clone,Default)]
pub struct NumberDescription { pub struct NumberDescription {
// message fields // message fields
pub money: MoneySymbol, pub format: NumberFormat,
pub scale: u32, pub scale: u32,
pub symbol: ::std::string::String, pub symbol: ::std::string::String,
pub sign_positive: bool, pub sign_positive: bool,
@ -47,19 +47,19 @@ impl NumberDescription {
::std::default::Default::default() ::std::default::Default::default()
} }
// .MoneySymbol money = 1; // .NumberFormat format = 1;
pub fn get_money(&self) -> MoneySymbol { pub fn get_format(&self) -> NumberFormat {
self.money self.format
} }
pub fn clear_money(&mut self) { pub fn clear_format(&mut self) {
self.money = MoneySymbol::CNY; self.format = NumberFormat::Number;
} }
// Param is passed by value, moved // Param is passed by value, moved
pub fn set_money(&mut self, v: MoneySymbol) { pub fn set_format(&mut self, v: NumberFormat) {
self.money = v; self.format = v;
} }
// uint32 scale = 2; // uint32 scale = 2;
@ -155,7 +155,7 @@ impl ::protobuf::Message for NumberDescription {
let (field_number, wire_type) = is.read_tag_unpack()?; let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number { match field_number {
1 => { 1 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.money, 1, &mut self.unknown_fields)? ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.format, 1, &mut self.unknown_fields)?
}, },
2 => { 2 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint { if wire_type != ::protobuf::wire_format::WireTypeVarint {
@ -189,8 +189,8 @@ impl ::protobuf::Message for NumberDescription {
#[allow(unused_variables)] #[allow(unused_variables)]
fn compute_size(&self) -> u32 { fn compute_size(&self) -> u32 {
let mut my_size = 0; let mut my_size = 0;
if self.money != MoneySymbol::CNY { if self.format != NumberFormat::Number {
my_size += ::protobuf::rt::enum_size(1, self.money); my_size += ::protobuf::rt::enum_size(1, self.format);
} }
if self.scale != 0 { if self.scale != 0 {
my_size += ::protobuf::rt::value_size(2, self.scale, ::protobuf::wire_format::WireTypeVarint); my_size += ::protobuf::rt::value_size(2, self.scale, ::protobuf::wire_format::WireTypeVarint);
@ -210,8 +210,8 @@ impl ::protobuf::Message for NumberDescription {
} }
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.money != MoneySymbol::CNY { if self.format != NumberFormat::Number {
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.money))?; os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.format))?;
} }
if self.scale != 0 { if self.scale != 0 {
os.write_uint32(2, self.scale)?; os.write_uint32(2, self.scale)?;
@ -263,10 +263,10 @@ impl ::protobuf::Message for NumberDescription {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| { descriptor.get(|| {
let mut fields = ::std::vec::Vec::new(); let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<MoneySymbol>>( fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<NumberFormat>>(
"money", "format",
|m: &NumberDescription| { &m.money }, |m: &NumberDescription| { &m.format },
|m: &mut NumberDescription| { &mut m.money }, |m: &mut NumberDescription| { &mut m.format },
)); ));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>( fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>(
"scale", "scale",
@ -304,7 +304,7 @@ impl ::protobuf::Message for NumberDescription {
impl ::protobuf::Clear for NumberDescription { impl ::protobuf::Clear for NumberDescription {
fn clear(&mut self) { fn clear(&mut self) {
self.money = MoneySymbol::CNY; self.format = NumberFormat::Number;
self.scale = 0; self.scale = 0;
self.symbol.clear(); self.symbol.clear();
self.sign_positive = false; self.sign_positive = false;
@ -326,31 +326,34 @@ impl ::protobuf::reflect::ProtobufValue for NumberDescription {
} }
#[derive(Clone,PartialEq,Eq,Debug,Hash)] #[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum MoneySymbol { pub enum NumberFormat {
CNY = 0, Number = 0,
EUR = 1, USD = 1,
USD = 2, CNY = 2,
EUR = 3,
} }
impl ::protobuf::ProtobufEnum for MoneySymbol { impl ::protobuf::ProtobufEnum for NumberFormat {
fn value(&self) -> i32 { fn value(&self) -> i32 {
*self as i32 *self as i32
} }
fn from_i32(value: i32) -> ::std::option::Option<MoneySymbol> { fn from_i32(value: i32) -> ::std::option::Option<NumberFormat> {
match value { match value {
0 => ::std::option::Option::Some(MoneySymbol::CNY), 0 => ::std::option::Option::Some(NumberFormat::Number),
1 => ::std::option::Option::Some(MoneySymbol::EUR), 1 => ::std::option::Option::Some(NumberFormat::USD),
2 => ::std::option::Option::Some(MoneySymbol::USD), 2 => ::std::option::Option::Some(NumberFormat::CNY),
3 => ::std::option::Option::Some(NumberFormat::EUR),
_ => ::std::option::Option::None _ => ::std::option::Option::None
} }
} }
fn values() -> &'static [Self] { fn values() -> &'static [Self] {
static values: &'static [MoneySymbol] = &[ static values: &'static [NumberFormat] = &[
MoneySymbol::CNY, NumberFormat::Number,
MoneySymbol::EUR, NumberFormat::USD,
MoneySymbol::USD, NumberFormat::CNY,
NumberFormat::EUR,
]; ];
values values
} }
@ -358,34 +361,34 @@ impl ::protobuf::ProtobufEnum for MoneySymbol {
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor { fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT; static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| { descriptor.get(|| {
::protobuf::reflect::EnumDescriptor::new_pb_name::<MoneySymbol>("MoneySymbol", file_descriptor_proto()) ::protobuf::reflect::EnumDescriptor::new_pb_name::<NumberFormat>("NumberFormat", file_descriptor_proto())
}) })
} }
} }
impl ::std::marker::Copy for MoneySymbol { impl ::std::marker::Copy for NumberFormat {
} }
impl ::std::default::Default for MoneySymbol { impl ::std::default::Default for NumberFormat {
fn default() -> Self { fn default() -> Self {
MoneySymbol::CNY NumberFormat::Number
} }
} }
impl ::protobuf::reflect::ProtobufValue for MoneySymbol { impl ::protobuf::reflect::ProtobufValue for NumberFormat {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
} }
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x18number_description.proto\"\x9e\x01\n\x11NumberDescription\x12\"\n\ \n\x18number_description.proto\"\xa1\x01\n\x11NumberDescription\x12%\n\
\x05money\x18\x01\x20\x01(\x0e2\x0c.MoneySymbolR\x05money\x12\x14\n\x05s\ \x06format\x18\x01\x20\x01(\x0e2\r.NumberFormatR\x06format\x12\x14\n\x05\
cale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\t\ scale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\
R\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositive\ \tR\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositiv\
\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04name*(\n\x0bMoneySymbol\x12\ e\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04name*5\n\x0cNumberFormat\x12\
\x07\n\x03CNY\x10\0\x12\x07\n\x03EUR\x10\x01\x12\x07\n\x03USD\x10\x02b\ \n\n\x06Number\x10\0\x12\x07\n\x03USD\x10\x01\x12\x07\n\x03CNY\x10\x02\
\x06proto3\ \x12\x07\n\x03EUR\x10\x03b\x06proto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,14 +1,15 @@
syntax = "proto3"; syntax = "proto3";
message NumberDescription { message NumberDescription {
MoneySymbol money = 1; NumberFormat format = 1;
uint32 scale = 2; uint32 scale = 2;
string symbol = 3; string symbol = 3;
bool sign_positive = 4; bool sign_positive = 4;
string name = 5; string name = 5;
} }
enum MoneySymbol { enum NumberFormat {
CNY = 0; Number = 0;
EUR = 1; USD = 1;
USD = 2; CNY = 2;
EUR = 3;
} }

View File

@ -19,7 +19,6 @@ use lib_ot::core::PlainTextAttributes;
use std::collections::HashMap; use std::collections::HashMap;
use dashmap::mapref::one::Ref;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
@ -84,12 +83,11 @@ impl GridBlockMetaEditorManager {
pub(crate) async fn delete_rows(&self, row_ids: Vec<String>) -> FlowyResult<Vec<GridBlockChangeset>> { pub(crate) async fn delete_rows(&self, row_ids: Vec<String>) -> FlowyResult<Vec<GridBlockChangeset>> {
let row_orders = row_ids let row_orders = row_ids
.into_iter() .into_iter()
.flat_map(|row_id| match self.block_id_by_row_id.get(&row_id) { .flat_map(|row_id| {
None => None, self.block_id_by_row_id.get(&row_id).map(|block_id| RowOrder {
Some(block_id) => Some(RowOrder {
row_id, row_id,
block_id: block_id.clone(), block_id: block_id.clone(),
}), })
}) })
.collect::<Vec<RowOrder>>(); .collect::<Vec<RowOrder>>();
let mut changesets = vec![]; let mut changesets = vec![];

View File

@ -26,8 +26,8 @@ impl NumberTypeOptionsBuilder {
self self
} }
pub fn set_money_symbol(mut self, money_symbol: MoneySymbol) -> Self { pub fn set_format(mut self, format: NumberFormat) -> Self {
self.0.set_money_symbol(money_symbol); self.0.set_format(format);
self self
} }

View File

@ -1,6 +1,6 @@
use crate::impl_from_and_to_type_option; use crate::impl_from_and_to_type_option;
use crate::services::row::StringifyCellData; use crate::services::row::StringifyCellData;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::ProtoBuf;
use flowy_error::FlowyError; use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType}; use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -38,3 +38,23 @@ fn string_to_bool(bool_str: &str) -> bool {
_ => false, _ => false,
} }
} }
#[cfg(test)]
mod tests {
use crate::services::cell::CheckboxDescription;
use crate::services::row::StringifyCellData;
#[test]
fn checkout_box_description_test() {
let description = CheckboxDescription::default();
assert_eq!(description.str_to_cell_data("true").unwrap(), "1".to_owned());
assert_eq!(description.str_to_cell_data("1").unwrap(), "1".to_owned());
assert_eq!(description.str_to_cell_data("yes").unwrap(), "1".to_owned());
assert_eq!(description.str_to_cell_data("false").unwrap(), "0".to_owned());
assert_eq!(description.str_to_cell_data("no").unwrap(), "0".to_owned());
assert_eq!(description.str_to_cell_data("123").unwrap(), "0".to_owned());
assert_eq!(description.str_from_cell_data("1".to_owned()), "1".to_owned());
}
}

View File

@ -1,6 +1,6 @@
use crate::impl_from_and_to_type_option; use crate::impl_from_and_to_type_option;
use crate::services::row::StringifyCellData; use crate::services::row::StringifyCellData;
use crate::services::util::*;
use chrono::format::strftime::StrftimeItems; use chrono::format::strftime::StrftimeItems;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
@ -8,6 +8,8 @@ use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType}; use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use strum_macros::EnumIter;
// Date // Date
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct DateDescription { pub struct DateDescription {
@ -20,10 +22,6 @@ pub struct DateDescription {
impl_from_and_to_type_option!(DateDescription, FieldType::DateTime); impl_from_and_to_type_option!(DateDescription, FieldType::DateTime);
impl DateDescription { impl DateDescription {
fn date_time_format_str(&self) -> String {
format!("{} {}", self.date_format.format_str(), self.time_format.format_str())
}
#[allow(dead_code)] #[allow(dead_code)]
fn today_from_timestamp(&self, timestamp: i64) -> String { fn today_from_timestamp(&self, timestamp: i64) -> String {
let native = chrono::NaiveDateTime::from_timestamp(timestamp, 0); let native = chrono::NaiveDateTime::from_timestamp(timestamp, 0);
@ -34,7 +32,7 @@ impl DateDescription {
let utc: chrono::DateTime<chrono::Utc> = chrono::DateTime::from_utc(naive, chrono::Utc); let utc: chrono::DateTime<chrono::Utc> = chrono::DateTime::from_utc(naive, chrono::Utc);
let local: chrono::DateTime<chrono::Local> = chrono::DateTime::from(utc); let local: chrono::DateTime<chrono::Local> = chrono::DateTime::from(utc);
let fmt_str = self.date_time_format_str(); let fmt_str = format!("{} {}", self.date_format.format_str(), self.time_format.format_str());
let output = format!("{}", local.format_with_items(StrftimeItems::new(&fmt_str))); let output = format!("{}", local.format_with_items(StrftimeItems::new(&fmt_str)));
output output
} }
@ -55,14 +53,18 @@ impl StringifyCellData for DateDescription {
} }
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> { fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
let timestamp = s let timestamp = match s.parse::<i64>() {
.parse::<i64>() Ok(timestamp) => timestamp,
.map_err(|e| FlowyError::internal().context(format!("Parse {} to i64 failed: {}", s, e)))?; Err(e) => {
tracing::error!("Parse {} to i64 failed: {}", s, e);
chrono::Utc::now().timestamp()
}
};
Ok(format!("{}", timestamp)) Ok(format!("{}", timestamp))
} }
} }
#[derive(Clone, Debug, Copy, Serialize, Deserialize, ProtoBuf_Enum)] #[derive(Clone, Debug, Copy, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum DateFormat { pub enum DateFormat {
Local = 0, Local = 0,
US = 1, US = 1,
@ -105,7 +107,7 @@ impl DateFormat {
} }
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, ProtoBuf_Enum)] #[derive(Clone, Copy, PartialEq, Eq, EnumIter, Debug, Hash, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum TimeFormat { pub enum TimeFormat {
TwelveHour = 0, TwelveHour = 0,
TwentyFourHour = 1, TwentyFourHour = 1,
@ -143,3 +145,98 @@ impl std::default::Default for TimeFormat {
TimeFormat::TwentyFourHour TimeFormat::TwentyFourHour
} }
} }
#[cfg(test)]
mod tests {
use crate::services::cell::{DateDescription, DateFormat, TimeFormat};
use crate::services::row::StringifyCellData;
use strum::IntoEnumIterator;
#[test]
fn date_description_date_format_test() {
let mut description = DateDescription::default();
let _timestamp = 1647251762;
for date_format in DateFormat::iter() {
description.date_format = date_format;
match date_format {
DateFormat::Friendly => {
assert_eq!(
"Mar 14,2022 17:56".to_owned(),
description.today_from_timestamp(1647251762)
);
assert_eq!(
"Mar 14,2022 17:56".to_owned(),
description.str_from_cell_data("1647251762".to_owned())
);
}
DateFormat::US => {
assert_eq!(
"2022/03/14 17:56".to_owned(),
description.today_from_timestamp(1647251762)
);
assert_eq!(
"2022/03/14 17:56".to_owned(),
description.str_from_cell_data("1647251762".to_owned())
);
}
DateFormat::ISO => {
assert_eq!(
"2022-03-14 17:56".to_owned(),
description.today_from_timestamp(1647251762)
);
assert_eq!(
"2022-03-14 17:56".to_owned(),
description.str_from_cell_data("1647251762".to_owned())
);
}
DateFormat::Local => {
assert_eq!(
"2022/03/14 17:56".to_owned(),
description.today_from_timestamp(1647251762)
);
assert_eq!(
"2022/03/14 17:56".to_owned(),
description.str_from_cell_data("1647251762".to_owned())
);
}
}
}
}
#[test]
fn date_description_time_format_test() {
let mut description = DateDescription::default();
for time_format in TimeFormat::iter() {
description.time_format = time_format;
match time_format {
TimeFormat::TwentyFourHour => {
assert_eq!(
"Mar 14,2022 17:56".to_owned(),
description.today_from_timestamp(1647251762)
);
assert_eq!(
"Mar 14,2022 17:56".to_owned(),
description.str_from_cell_data("1647251762".to_owned())
);
}
TimeFormat::TwelveHour => {
assert_eq!(
"Mar 14,2022 05:56:02 PM".to_owned(),
description.today_from_timestamp(1647251762)
);
assert_eq!(
"Mar 14,2022 05:56:02 PM".to_owned(),
description.str_from_cell_data("1647251762".to_owned())
);
}
}
}
}
#[test]
fn date_description_invalid_data_test() {
let description = DateDescription::default();
description.str_to_cell_data("he").unwrap();
}
}

View File

@ -1,25 +1,62 @@
use crate::impl_from_and_to_type_option; use crate::impl_from_and_to_type_option;
use crate::services::row::StringifyCellData; use crate::services::row::StringifyCellData;
use crate::services::util::*;
use chrono::format::strftime::StrftimeItems;
use chrono::NaiveDateTime;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::FlowyError; use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType}; use flowy_grid_data_model::entities::{Field, FieldType};
use lazy_static::lazy_static;
use rust_decimal::prelude::Zero;
use rust_decimal::Decimal; use rust_decimal::Decimal;
use rusty_money::{ use rusty_money::iso::{Currency, CNY, EUR, USD};
iso::{Currency, CNY, EUR, USD},
Money,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
use strum::IntoEnumIterator;
use strum_macros::EnumIter; use strum_macros::EnumIter;
lazy_static! {
static ref STRIP_SYMBOL: Vec<String> = make_strip_symbol();
}
#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum NumberFormat {
Number = 0,
USD = 1,
CNY = 2,
EUR = 3,
}
impl std::default::Default for NumberFormat {
fn default() -> Self {
NumberFormat::Number
}
}
impl NumberFormat {
pub fn symbol(&self) -> String {
match self {
NumberFormat::Number => "".to_string(),
NumberFormat::USD => USD.symbol.to_string(),
NumberFormat::CNY => CNY.symbol.to_string(),
NumberFormat::EUR => EUR.symbol.to_string(),
}
}
#[allow(dead_code)]
pub fn code(&self) -> String {
match self {
NumberFormat::Number => "".to_string(),
NumberFormat::USD => USD.iso_alpha_code.to_string(),
NumberFormat::CNY => CNY.iso_alpha_code.to_string(),
NumberFormat::EUR => EUR.iso_alpha_code.to_string(),
}
}
}
// Number // Number
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
pub struct NumberDescription { pub struct NumberDescription {
#[pb(index = 1)] #[pb(index = 1)]
pub money: MoneySymbol, pub format: NumberFormat,
#[pb(index = 2)] #[pb(index = 2)]
pub scale: u32, pub scale: u32,
@ -37,10 +74,10 @@ impl_from_and_to_type_option!(NumberDescription, FieldType::Number);
impl std::default::Default for NumberDescription { impl std::default::Default for NumberDescription {
fn default() -> Self { fn default() -> Self {
let money = MoneySymbol::default(); let format = NumberFormat::default();
let symbol = money.symbol_str(); let symbol = format.symbol();
NumberDescription { NumberDescription {
money, format,
scale: 0, scale: 0,
symbol, symbol,
sign_positive: true, sign_positive: true,
@ -50,101 +87,156 @@ impl std::default::Default for NumberDescription {
} }
impl NumberDescription { impl NumberDescription {
pub fn set_money_symbol(&mut self, money_symbol: MoneySymbol) { pub fn set_format(&mut self, format: NumberFormat) {
self.money = money_symbol; self.format = format;
self.symbol = money_symbol.symbol_str(); self.symbol = format.symbol();
} }
fn money_from_str(&self, s: &str) -> Option<String> { fn decimal_from_str(&self, s: &str) -> Decimal {
match Decimal::from_str(s) { let mut decimal = Decimal::from_str(s).unwrap_or(Decimal::zero());
Ok(mut decimal) => { match decimal.set_scale(self.scale) {
match decimal.set_scale(self.scale) { Ok(_) => {}
Ok(_) => {}
Err(e) => {
tracing::error!("Set decimal scale failed: {:?}", e);
}
}
decimal.set_sign_positive(self.sign_positive);
Some(self.money.with_decimal(decimal).to_string())
}
Err(e) => { Err(e) => {
tracing::error!("Parser money from {} failed: {:?}", s, e); tracing::error!("Set decimal scale failed: {:?}", e);
None
} }
} }
decimal.set_sign_positive(self.sign_positive);
decimal
}
fn money_from_str(&self, s: &str, currency: &'static Currency) -> String {
let decimal = self.decimal_from_str(s);
let money = rusty_money::Money::from_decimal(decimal, currency);
money.to_string()
}
fn strip_symbol(&self, s: &str) -> String {
let mut s = String::from(s);
if !s.chars().all(char::is_numeric) {
s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
}
s
} }
} }
impl StringifyCellData for NumberDescription { impl StringifyCellData for NumberDescription {
fn str_from_cell_data(&self, data: String) -> String { fn str_from_cell_data(&self, data: String) -> String {
match self.money_from_str(&data) { match self.format {
Some(money_str) => money_str, NumberFormat::Number => data,
None => String::default(), NumberFormat::USD => self.money_from_str(&data, USD),
NumberFormat::CNY => self.money_from_str(&data, CNY),
NumberFormat::EUR => self.money_from_str(&data, EUR),
} }
} }
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> { fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
let strip_symbol_money = strip_money_symbol(s); Ok(self.strip_symbol(s))
let decimal = Decimal::from_str(&strip_symbol_money).map_err(|err| FlowyError::internal().context(err))?;
Ok(decimal.to_string())
} }
} }
#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] fn make_strip_symbol() -> Vec<String> {
pub enum MoneySymbol { let mut symbols = vec![",".to_owned(), ".".to_owned()];
CNY = 0, for format in NumberFormat::iter() {
EUR = 1, symbols.push(format.symbol());
USD = 2,
}
impl std::default::Default for MoneySymbol {
fn default() -> Self {
MoneySymbol::USD
} }
symbols
} }
impl MoneySymbol { #[cfg(test)]
// Currency list https://docs.rs/rusty-money/0.4.0/rusty_money/iso/index.html mod tests {
pub fn from_symbol_str(s: &str) -> MoneySymbol { use crate::services::cell::{NumberDescription, NumberFormat};
match s { use crate::services::row::StringifyCellData;
"CNY" => MoneySymbol::CNY, use strum::IntoEnumIterator;
"EUR" => MoneySymbol::EUR,
"USD" => MoneySymbol::USD, #[test]
_ => MoneySymbol::CNY, fn number_description_test() {
let mut description = NumberDescription::default();
assert_eq!(description.str_to_cell_data("¥18,443").unwrap(), "18443".to_owned());
assert_eq!(description.str_to_cell_data("$18,443").unwrap(), "18443".to_owned());
assert_eq!(description.str_to_cell_data("€18.443").unwrap(), "18443".to_owned());
for format in NumberFormat::iter() {
description.format = format;
match format {
NumberFormat::Number => {
assert_eq!(description.str_from_cell_data("18443".to_owned()), "18443".to_owned());
}
NumberFormat::USD => {
assert_eq!(description.str_from_cell_data("18443".to_owned()), "$18,443".to_owned());
}
NumberFormat::CNY => {
assert_eq!(description.str_from_cell_data("18443".to_owned()), "¥18,443".to_owned());
}
NumberFormat::EUR => {
assert_eq!(description.str_from_cell_data("18443".to_owned()), "€18.443".to_owned());
}
}
} }
} }
pub fn from_money(money: &rusty_money::Money<Currency>) -> MoneySymbol { #[test]
MoneySymbol::from_symbol_str(&money.currency().symbol.to_string()) fn number_description_scale_test() {
} let mut description = NumberDescription::default();
description.scale = 1;
pub fn currency(&self) -> &'static Currency { for format in NumberFormat::iter() {
match self { description.format = format;
MoneySymbol::CNY => CNY, match format {
MoneySymbol::EUR => EUR, NumberFormat::Number => {
MoneySymbol::USD => USD, assert_eq!(description.str_from_cell_data("18443".to_owned()), "18443".to_owned());
}
NumberFormat::USD => {
assert_eq!(
description.str_from_cell_data("18443".to_owned()),
"$1,844.3".to_owned()
);
}
NumberFormat::CNY => {
assert_eq!(
description.str_from_cell_data("18443".to_owned()),
"¥1,844.3".to_owned()
);
}
NumberFormat::EUR => {
assert_eq!(
description.str_from_cell_data("18443".to_owned()),
"€1.844,3".to_owned()
);
}
}
} }
} }
// string_to_money("¥18,443").unwrap(); #[test]
// string_to_money("$18,443").unwrap(); fn number_description_sign_test() {
// string_to_money("€18,443").unwrap(); let mut description = NumberDescription::default();
pub fn code(&self) -> String { description.sign_positive = false;
self.currency().iso_alpha_code.to_string()
}
pub fn symbol_str(&self) -> String { for format in NumberFormat::iter() {
self.currency().symbol.to_string() description.format = format;
} match format {
NumberFormat::Number => {
pub fn zero(&self) -> Money<Currency> { assert_eq!(description.str_from_cell_data("18443".to_owned()), "18443".to_owned());
let mut decimal = Decimal::new(0, 0); }
decimal.set_sign_positive(true); NumberFormat::USD => {
self.with_decimal(decimal) assert_eq!(
} description.str_from_cell_data("18443".to_owned()),
"-$18,443".to_owned()
pub fn with_decimal(&self, decimal: Decimal) -> Money<Currency> { );
let money = rusty_money::Money::from_decimal(decimal, self.currency()); }
money NumberFormat::CNY => {
assert_eq!(
description.str_from_cell_data("18443".to_owned()),
"-¥18,443".to_owned()
);
}
NumberFormat::EUR => {
assert_eq!(
description.str_from_cell_data("18443".to_owned()),
"-€18.443".to_owned()
);
}
}
}
} }
} }

View File

@ -1,7 +1,7 @@
use crate::impl_from_and_to_type_option; use crate::impl_from_and_to_type_option;
use crate::services::row::StringifyCellData; use crate::services::row::StringifyCellData;
use crate::services::util::*; use crate::services::util::*;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::ProtoBuf;
use flowy_error::FlowyError; use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType}; use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -23,7 +23,7 @@ impl StringifyCellData for SingleSelectDescription {
} }
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> { fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned()) Ok(select_option_id_from_data(s.to_owned(), true))
} }
} }
@ -43,10 +43,22 @@ impl StringifyCellData for MultiSelectDescription {
} }
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> { fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned()) Ok(select_option_id_from_data(s.to_owned(), false))
} }
} }
fn select_option_id_from_data(data: String, is_single_select: bool) -> String {
if !is_single_select {
return data;
}
let select_option_ids = data.split(',').collect::<Vec<&str>>();
if select_option_ids.is_empty() {
return "".to_owned();
}
select_option_ids.split_first().unwrap().0.to_string()
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct SelectOption { pub struct SelectOption {
#[pb(index = 1)] #[pb(index = 1)]
@ -68,3 +80,18 @@ impl SelectOption {
} }
} }
} }
#[cfg(test)]
mod tests {
use crate::services::cell::{MultiSelectDescription, SingleSelectDescription};
use crate::services::row::StringifyCellData;
#[test]
fn selection_description_test() {
let description = SingleSelectDescription::default();
assert_eq!(description.str_to_cell_data("1,2,3").unwrap(), "1".to_owned());
let description = MultiSelectDescription::default();
assert_eq!(description.str_to_cell_data("1,2,3").unwrap(), "1,2,3".to_owned());
}
}

View File

@ -1,7 +1,7 @@
use crate::impl_from_and_to_type_option; use crate::impl_from_and_to_type_option;
use crate::services::row::StringifyCellData; use crate::services::row::StringifyCellData;
use crate::services::util::*;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::ProtoBuf;
use flowy_error::FlowyError; use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType}; use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -1,5 +1,5 @@
use crate::manager::GridUser; use crate::manager::GridUser;
use crate::services::grid_meta_editor::GridBlockMetaEditorManager; use crate::services::block_meta_editor::GridBlockMetaEditorManager;
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction}; use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
use bytes::Bytes; use bytes::Bytes;
use flowy_collaboration::client_grid::{GridChange, GridMetaPad}; use flowy_collaboration::client_grid::{GridChange, GridMetaPad};

View File

@ -1,8 +1,8 @@
mod util; mod util;
pub mod block_meta_editor;
pub mod cell; pub mod cell;
pub mod field; pub mod field;
pub mod grid_editor; pub mod grid_editor;
pub mod grid_meta_editor;
pub mod kv_persistence; pub mod kv_persistence;
pub mod row; pub mod row;

View File

@ -1,5 +1,5 @@
use crate::services::row::stringify_deserialize; use crate::services::row::stringify_deserialize;
use flowy_grid_data_model::entities::{Cell, CellMeta, Field, RepeatedRowOrder, Row, RowMeta, RowOrder}; use flowy_grid_data_model::entities::{Cell, CellMeta, Field, Row, RowMeta, RowOrder};
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::collections::HashMap; use std::collections::HashMap;

View File

@ -1,103 +1,35 @@
use crate::services::cell::MoneySymbol; //
use flowy_error::FlowyError; // #[allow(dead_code)]
use flowy_grid_data_model::entities::{AnyData, Field, FieldType}; // pub fn string_to_money(money_str: &str) -> Option<Money<Currency>> {
use lazy_static::lazy_static; // let mut process_money_str = String::from(money_str);
use rust_decimal::Decimal; // let default_currency = MoneySymbol::from_symbol_str("CNY").currency();
use rusty_money::{iso::Currency, Money}; //
use std::collections::HashMap; // if process_money_str.is_empty() {
use std::str::FromStr; // return None;
use strum::IntoEnumIterator; // }
//
lazy_static! { // return if process_money_str.chars().all(char::is_numeric) {
static ref CURRENCIES_BY_SYMBOL: HashMap<String, &'static Currency> = generate_currency_by_symbol(); // match Money::from_str(&process_money_str, default_currency) {
} // Ok(money) => Some(money),
// Err(_) => None,
#[allow(dead_code)] // }
fn generate_currency_by_symbol() -> HashMap<String, &'static Currency> { // } else {
let mut map: HashMap<String, &'static Currency> = HashMap::new(); // let symbol = process_money_str.chars().next().unwrap().to_string();
// let mut currency = default_currency;
for money in MoneySymbol::iter() { //
map.insert(money.symbol_str(), money.currency()); // for key in CURRENCIES_BY_SYMBOL.keys() {
} // if symbol.eq(key) {
map // currency = CURRENCIES_BY_SYMBOL.get(key).unwrap();
} // crop_letters(&mut process_money_str, 1);
// }
#[allow(dead_code)] // }
pub fn string_to_money(money_str: &str) -> Option<Money<Currency>> { //
let mut process_money_str = String::from(money_str); // match Money::from_str(&process_money_str, currency) {
let default_currency = MoneySymbol::from_symbol_str("CNY").currency(); // Ok(money) => Some(money),
// Err(_) => None,
if process_money_str.is_empty() { // }
return None; // };
} // }
return if process_money_str.chars().all(char::is_numeric) {
match Money::from_str(&process_money_str, default_currency) {
Ok(money) => Some(money),
Err(_) => None,
}
} else {
let symbol = process_money_str.chars().next().unwrap().to_string();
let mut currency = default_currency;
for key in CURRENCIES_BY_SYMBOL.keys() {
if symbol.eq(key) {
currency = CURRENCIES_BY_SYMBOL.get(key).unwrap();
crop_letters(&mut process_money_str, 1);
}
}
match Money::from_str(&process_money_str, currency) {
Ok(money) => Some(money),
Err(_) => None,
}
};
}
#[allow(dead_code)]
pub fn money_from_str(s: &str) -> Option<String> {
match Decimal::from_str(s) {
Ok(mut decimal) => {
match decimal.set_scale(0) {
Ok(_) => {}
Err(e) => {
tracing::error!("Set scale failed. {:?}", e);
}
}
decimal.set_sign_positive(true);
Some(MoneySymbol::USD.with_decimal(decimal).to_string())
}
Err(e) => {
tracing::debug!("Format {} to money failed, {:?}", s, e);
None
}
}
}
pub fn strip_money_symbol(money_str: &str) -> String {
let mut process_money_str = String::from(money_str);
if !process_money_str.chars().all(char::is_numeric) {
let symbol = process_money_str.chars().next().unwrap().to_string();
for key in CURRENCIES_BY_SYMBOL.keys() {
if symbol.eq(key) {
crop_letters(&mut process_money_str, 1);
}
}
}
process_money_str
}
fn crop_letters(s: &mut String, pos: usize) {
match s.char_indices().nth(pos) {
Some((pos, _)) => {
s.drain(..pos);
}
None => {
s.clear();
}
}
}
pub fn uuid() -> String { pub fn uuid() -> String {
uuid::Uuid::new_v4().to_string() uuid::Uuid::new_v4().to_string()

View File

@ -1,10 +1,8 @@
use crate::grid::script::EditorScript::*; use crate::grid::script::EditorScript::*;
use crate::grid::script::*; use crate::grid::script::*;
use flowy_grid::services::field::{SelectOption, SingleSelectDescription}; use flowy_grid::services::cell::*;
use flowy_grid::services::row::CreateRowContextBuilder; use flowy_grid::services::row::{CreateRowContextBuilder, StringifyCellData};
use flowy_grid_data_model::entities::{ use flowy_grid_data_model::entities::{FieldChangeset, FieldType, GridBlock, GridBlockChangeset, RowMetaChangeset};
FieldChangeset, FieldType, GridBlock, GridBlockChangeset, Row, RowMetaChangeset,
};
#[tokio::test] #[tokio::test]
async fn default_grid_test() { async fn default_grid_test() {
@ -249,19 +247,40 @@ async fn grid_update_cell() {
builder = builder.add_cell(&field.id, "hello world".to_owned()); builder = builder.add_cell(&field.id, "hello world".to_owned());
} }
FieldType::Number => { FieldType::Number => {
builder = builder.add_cell(&field.id, "123".to_owned()); let description = NumberDescription::from(field);
let data = description.str_to_cell_data("¥18,443").unwrap();
builder = builder.add_cell(&field.id, data);
} }
FieldType::DateTime => { FieldType::DateTime => {
builder = builder.add_cell(&field.id, "March 8, 2022".to_owned()); let description = DateDescription::from(field);
let data = description.str_to_cell_data("1647251762").unwrap();
builder = builder.add_cell(&field.id, data);
}
FieldType::SingleSelect => {
let description = SingleSelectDescription::from(field);
let options = description.options.first().unwrap();
let data = description.str_to_cell_data(&options.id).unwrap();
builder = builder.add_cell(&field.id, data);
}
FieldType::MultiSelect => {
let description = MultiSelectDescription::from(field);
let options = description
.options
.iter()
.map(|option| option.id.clone())
.collect::<Vec<_>>()
.join(",");
let data = description.str_to_cell_data(&options).unwrap();
builder = builder.add_cell(&field.id, data);
} }
FieldType::SingleSelect => {}
FieldType::MultiSelect => {}
FieldType::Checkbox => { FieldType::Checkbox => {
builder = builder.add_cell(&field.id, "1".to_owned()); let description = CheckboxDescription::from(field);
let data = description.str_to_cell_data("false").unwrap();
builder = builder.add_cell(&field.id, data);
} }
} }
} }
let context = builder.build(); let context = builder.build();
let scripts = vec![AssertRowCount(3), CreateRow { context }]; let scripts = vec![AssertRowCount(3), CreateRow { context }, AssertGridMetaPad];
test.run_scripts(scripts).await; test.run_scripts(scripts).await;
} }

View File

@ -3,7 +3,7 @@ use flowy_grid::services::field::*;
use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
use flowy_grid::services::row::CreateRowContext; use flowy_grid::services::row::CreateRowContext;
use flowy_grid_data_model::entities::{ use flowy_grid_data_model::entities::{
CellMetaChangeset, Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset, Row, RowMeta, RowMetaChangeset, CellMetaChangeset, Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset, RowMeta, RowMetaChangeset,
}; };
use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS;
use flowy_test::helper::ViewTest; use flowy_test::helper::ViewTest;
@ -104,7 +104,7 @@ impl GridEditorTest {
let grid_manager = self.sdk.grid_manager.clone(); let grid_manager = self.sdk.grid_manager.clone();
let pool = self.sdk.user_session.db_pool().unwrap(); let pool = self.sdk.user_session.db_pool().unwrap();
let rev_manager = self.editor.rev_manager(); let rev_manager = self.editor.rev_manager();
let cache = rev_manager.revision_cache().await; let _cache = rev_manager.revision_cache().await;
match script { match script {
EditorScript::CreateField { field } => { EditorScript::CreateField { field } => {