mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: config update cell
This commit is contained in:
parent
196d254278
commit
46be04f94e
@ -15,7 +15,7 @@ export 'number_description.pbenum.dart';
|
||||
|
||||
class NumberDescription extends $pb.GeneratedMessage {
|
||||
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)
|
||||
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol')
|
||||
..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive')
|
||||
@ -25,15 +25,15 @@ class NumberDescription extends $pb.GeneratedMessage {
|
||||
|
||||
NumberDescription._() : super();
|
||||
factory NumberDescription({
|
||||
MoneySymbol? money,
|
||||
NumberFormat? format,
|
||||
$core.int? scale,
|
||||
$core.String? symbol,
|
||||
$core.bool? signPositive,
|
||||
$core.String? name,
|
||||
}) {
|
||||
final _result = create();
|
||||
if (money != null) {
|
||||
_result.money = money;
|
||||
if (format != null) {
|
||||
_result.format = format;
|
||||
}
|
||||
if (scale != null) {
|
||||
_result.scale = scale;
|
||||
@ -71,13 +71,13 @@ class NumberDescription extends $pb.GeneratedMessage {
|
||||
static NumberDescription? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
MoneySymbol get money => $_getN(0);
|
||||
NumberFormat get format => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set money(MoneySymbol v) { setField(1, v); }
|
||||
set format(NumberFormat v) { setField(1, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasMoney() => $_has(0);
|
||||
$core.bool hasFormat() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearMoney() => clearField(1);
|
||||
void clearFormat() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.int get scale => $_getIZ(1);
|
||||
|
@ -9,20 +9,22 @@
|
||||
import 'dart:core' as $core;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class MoneySymbol extends $pb.ProtobufEnum {
|
||||
static const MoneySymbol CNY = MoneySymbol._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CNY');
|
||||
static const MoneySymbol EUR = MoneySymbol._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR');
|
||||
static const MoneySymbol USD = MoneySymbol._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD');
|
||||
class NumberFormat extends $pb.ProtobufEnum {
|
||||
static const NumberFormat Number = NumberFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number');
|
||||
static const NumberFormat USD = NumberFormat._(1, 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,
|
||||
EUR,
|
||||
USD,
|
||||
];
|
||||
|
||||
static final $core.Map<$core.int, MoneySymbol> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
static MoneySymbol? valueOf($core.int value) => _byValue[value];
|
||||
static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -8,23 +8,24 @@
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
@$core.Deprecated('Use moneySymbolDescriptor instead')
|
||||
const MoneySymbol$json = const {
|
||||
'1': 'MoneySymbol',
|
||||
@$core.Deprecated('Use numberFormatDescriptor instead')
|
||||
const NumberFormat$json = const {
|
||||
'1': 'NumberFormat',
|
||||
'2': const [
|
||||
const {'1': 'CNY', '2': 0},
|
||||
const {'1': 'EUR', '2': 1},
|
||||
const {'1': 'USD', '2': 2},
|
||||
const {'1': 'Number', '2': 0},
|
||||
const {'1': 'USD', '2': 1},
|
||||
const {'1': 'CNY', '2': 2},
|
||||
const {'1': 'EUR', '2': 3},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `MoneySymbol`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List moneySymbolDescriptor = $convert.base64Decode('CgtNb25leVN5bWJvbBIHCgNDTlkQABIHCgNFVVIQARIHCgNVU0QQAg==');
|
||||
/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESBwoDQ05ZEAISBwoDRVVSEAM=');
|
||||
@$core.Deprecated('Use numberDescriptionDescriptor instead')
|
||||
const NumberDescription$json = const {
|
||||
'1': 'NumberDescription',
|
||||
'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': 'symbol', '3': 3, '4': 1, '5': 9, '10': 'symbol'},
|
||||
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`.
|
||||
final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIiCgVtb25leRgBIAEoDjIMLk1vbmV5U3ltYm9sUgVtb25leRIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU=');
|
||||
final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIlCgZmb3JtYXQYASABKA4yDS5OdW1iZXJGb3JtYXRSBmZvcm1hdBIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU=');
|
||||
|
@ -26,7 +26,7 @@
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct NumberDescription {
|
||||
// message fields
|
||||
pub money: MoneySymbol,
|
||||
pub format: NumberFormat,
|
||||
pub scale: u32,
|
||||
pub symbol: ::std::string::String,
|
||||
pub sign_positive: bool,
|
||||
@ -47,19 +47,19 @@ impl NumberDescription {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
// .MoneySymbol money = 1;
|
||||
// .NumberFormat format = 1;
|
||||
|
||||
|
||||
pub fn get_money(&self) -> MoneySymbol {
|
||||
self.money
|
||||
pub fn get_format(&self) -> NumberFormat {
|
||||
self.format
|
||||
}
|
||||
pub fn clear_money(&mut self) {
|
||||
self.money = MoneySymbol::CNY;
|
||||
pub fn clear_format(&mut self) {
|
||||
self.format = NumberFormat::Number;
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_money(&mut self, v: MoneySymbol) {
|
||||
self.money = v;
|
||||
pub fn set_format(&mut self, v: NumberFormat) {
|
||||
self.format = v;
|
||||
}
|
||||
|
||||
// uint32 scale = 2;
|
||||
@ -155,7 +155,7 @@ impl ::protobuf::Message for NumberDescription {
|
||||
let (field_number, wire_type) = is.read_tag_unpack()?;
|
||||
match field_number {
|
||||
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 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||
@ -189,8 +189,8 @@ impl ::protobuf::Message for NumberDescription {
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u32 {
|
||||
let mut my_size = 0;
|
||||
if self.money != MoneySymbol::CNY {
|
||||
my_size += ::protobuf::rt::enum_size(1, self.money);
|
||||
if self.format != NumberFormat::Number {
|
||||
my_size += ::protobuf::rt::enum_size(1, self.format);
|
||||
}
|
||||
if self.scale != 0 {
|
||||
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<()> {
|
||||
if self.money != MoneySymbol::CNY {
|
||||
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.money))?;
|
||||
if self.format != NumberFormat::Number {
|
||||
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.format))?;
|
||||
}
|
||||
if self.scale != 0 {
|
||||
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;
|
||||
descriptor.get(|| {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<MoneySymbol>>(
|
||||
"money",
|
||||
|m: &NumberDescription| { &m.money },
|
||||
|m: &mut NumberDescription| { &mut m.money },
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<NumberFormat>>(
|
||||
"format",
|
||||
|m: &NumberDescription| { &m.format },
|
||||
|m: &mut NumberDescription| { &mut m.format },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>(
|
||||
"scale",
|
||||
@ -304,7 +304,7 @@ impl ::protobuf::Message for NumberDescription {
|
||||
|
||||
impl ::protobuf::Clear for NumberDescription {
|
||||
fn clear(&mut self) {
|
||||
self.money = MoneySymbol::CNY;
|
||||
self.format = NumberFormat::Number;
|
||||
self.scale = 0;
|
||||
self.symbol.clear();
|
||||
self.sign_positive = false;
|
||||
@ -326,31 +326,34 @@ impl ::protobuf::reflect::ProtobufValue for NumberDescription {
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||
pub enum MoneySymbol {
|
||||
CNY = 0,
|
||||
EUR = 1,
|
||||
USD = 2,
|
||||
pub enum NumberFormat {
|
||||
Number = 0,
|
||||
USD = 1,
|
||||
CNY = 2,
|
||||
EUR = 3,
|
||||
}
|
||||
|
||||
impl ::protobuf::ProtobufEnum for MoneySymbol {
|
||||
impl ::protobuf::ProtobufEnum for NumberFormat {
|
||||
fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
|
||||
fn from_i32(value: i32) -> ::std::option::Option<MoneySymbol> {
|
||||
fn from_i32(value: i32) -> ::std::option::Option<NumberFormat> {
|
||||
match value {
|
||||
0 => ::std::option::Option::Some(MoneySymbol::CNY),
|
||||
1 => ::std::option::Option::Some(MoneySymbol::EUR),
|
||||
2 => ::std::option::Option::Some(MoneySymbol::USD),
|
||||
0 => ::std::option::Option::Some(NumberFormat::Number),
|
||||
1 => ::std::option::Option::Some(NumberFormat::USD),
|
||||
2 => ::std::option::Option::Some(NumberFormat::CNY),
|
||||
3 => ::std::option::Option::Some(NumberFormat::EUR),
|
||||
_ => ::std::option::Option::None
|
||||
}
|
||||
}
|
||||
|
||||
fn values() -> &'static [Self] {
|
||||
static values: &'static [MoneySymbol] = &[
|
||||
MoneySymbol::CNY,
|
||||
MoneySymbol::EUR,
|
||||
MoneySymbol::USD,
|
||||
static values: &'static [NumberFormat] = &[
|
||||
NumberFormat::Number,
|
||||
NumberFormat::USD,
|
||||
NumberFormat::CNY,
|
||||
NumberFormat::EUR,
|
||||
];
|
||||
values
|
||||
}
|
||||
@ -358,34 +361,34 @@ impl ::protobuf::ProtobufEnum for MoneySymbol {
|
||||
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
|
||||
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||
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 {
|
||||
MoneySymbol::CNY
|
||||
NumberFormat::Number
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for MoneySymbol {
|
||||
impl ::protobuf::reflect::ProtobufValue for NumberFormat {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
|
||||
}
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x18number_description.proto\"\x9e\x01\n\x11NumberDescription\x12\"\n\
|
||||
\x05money\x18\x01\x20\x01(\x0e2\x0c.MoneySymbolR\x05money\x12\x14\n\x05s\
|
||||
cale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\t\
|
||||
R\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositive\
|
||||
\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04name*(\n\x0bMoneySymbol\x12\
|
||||
\x07\n\x03CNY\x10\0\x12\x07\n\x03EUR\x10\x01\x12\x07\n\x03USD\x10\x02b\
|
||||
\x06proto3\
|
||||
\n\x18number_description.proto\"\xa1\x01\n\x11NumberDescription\x12%\n\
|
||||
\x06format\x18\x01\x20\x01(\x0e2\r.NumberFormatR\x06format\x12\x14\n\x05\
|
||||
scale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\
|
||||
\tR\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositiv\
|
||||
e\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04name*5\n\x0cNumberFormat\x12\
|
||||
\n\n\x06Number\x10\0\x12\x07\n\x03USD\x10\x01\x12\x07\n\x03CNY\x10\x02\
|
||||
\x12\x07\n\x03EUR\x10\x03b\x06proto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
@ -1,14 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message NumberDescription {
|
||||
MoneySymbol money = 1;
|
||||
NumberFormat format = 1;
|
||||
uint32 scale = 2;
|
||||
string symbol = 3;
|
||||
bool sign_positive = 4;
|
||||
string name = 5;
|
||||
}
|
||||
enum MoneySymbol {
|
||||
CNY = 0;
|
||||
EUR = 1;
|
||||
USD = 2;
|
||||
enum NumberFormat {
|
||||
Number = 0;
|
||||
USD = 1;
|
||||
CNY = 2;
|
||||
EUR = 3;
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ use lib_ot::core::PlainTextAttributes;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use dashmap::mapref::one::Ref;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
@ -84,12 +83,11 @@ impl GridBlockMetaEditorManager {
|
||||
pub(crate) async fn delete_rows(&self, row_ids: Vec<String>) -> FlowyResult<Vec<GridBlockChangeset>> {
|
||||
let row_orders = row_ids
|
||||
.into_iter()
|
||||
.flat_map(|row_id| match self.block_id_by_row_id.get(&row_id) {
|
||||
None => None,
|
||||
Some(block_id) => Some(RowOrder {
|
||||
.flat_map(|row_id| {
|
||||
self.block_id_by_row_id.get(&row_id).map(|block_id| RowOrder {
|
||||
row_id,
|
||||
block_id: block_id.clone(),
|
||||
}),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<RowOrder>>();
|
||||
let mut changesets = vec![];
|
@ -26,8 +26,8 @@ impl NumberTypeOptionsBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_money_symbol(mut self, money_symbol: MoneySymbol) -> Self {
|
||||
self.0.set_money_symbol(money_symbol);
|
||||
pub fn set_format(mut self, format: NumberFormat) -> Self {
|
||||
self.0.set_format(format);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::impl_from_and_to_type_option;
|
||||
use crate::services::row::StringifyCellData;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{Field, FieldType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -38,3 +38,23 @@ fn string_to_bool(bool_str: &str) -> bool {
|
||||
_ => 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());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::impl_from_and_to_type_option;
|
||||
use crate::services::row::StringifyCellData;
|
||||
use crate::services::util::*;
|
||||
|
||||
use chrono::format::strftime::StrftimeItems;
|
||||
use chrono::NaiveDateTime;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
@ -8,6 +8,8 @@ use flowy_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{Field, FieldType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
// Date
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
|
||||
pub struct DateDescription {
|
||||
@ -20,10 +22,6 @@ pub struct DateDescription {
|
||||
impl_from_and_to_type_option!(DateDescription, FieldType::DateTime);
|
||||
|
||||
impl DateDescription {
|
||||
fn date_time_format_str(&self) -> String {
|
||||
format!("{} {}", self.date_format.format_str(), self.time_format.format_str())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn today_from_timestamp(&self, timestamp: i64) -> String {
|
||||
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 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)));
|
||||
output
|
||||
}
|
||||
@ -55,14 +53,18 @@ impl StringifyCellData for DateDescription {
|
||||
}
|
||||
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
|
||||
let timestamp = s
|
||||
.parse::<i64>()
|
||||
.map_err(|e| FlowyError::internal().context(format!("Parse {} to i64 failed: {}", s, e)))?;
|
||||
let timestamp = match s.parse::<i64>() {
|
||||
Ok(timestamp) => timestamp,
|
||||
Err(e) => {
|
||||
tracing::error!("Parse {} to i64 failed: {}", s, e);
|
||||
chrono::Utc::now().timestamp()
|
||||
}
|
||||
};
|
||||
Ok(format!("{}", timestamp))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy, Serialize, Deserialize, ProtoBuf_Enum)]
|
||||
#[derive(Clone, Debug, Copy, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
|
||||
pub enum DateFormat {
|
||||
Local = 0,
|
||||
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 {
|
||||
TwelveHour = 0,
|
||||
TwentyFourHour = 1,
|
||||
@ -143,3 +145,98 @@ impl std::default::Default for TimeFormat {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,62 @@
|
||||
use crate::impl_from_and_to_type_option;
|
||||
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_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{Field, FieldType};
|
||||
use lazy_static::lazy_static;
|
||||
use rust_decimal::prelude::Zero;
|
||||
use rust_decimal::Decimal;
|
||||
use rusty_money::{
|
||||
iso::{Currency, CNY, EUR, USD},
|
||||
Money,
|
||||
};
|
||||
use rusty_money::iso::{Currency, CNY, EUR, USD};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::str::FromStr;
|
||||
use strum::IntoEnumIterator;
|
||||
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
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
|
||||
pub struct NumberDescription {
|
||||
#[pb(index = 1)]
|
||||
pub money: MoneySymbol,
|
||||
pub format: NumberFormat,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub scale: u32,
|
||||
@ -37,10 +74,10 @@ impl_from_and_to_type_option!(NumberDescription, FieldType::Number);
|
||||
|
||||
impl std::default::Default for NumberDescription {
|
||||
fn default() -> Self {
|
||||
let money = MoneySymbol::default();
|
||||
let symbol = money.symbol_str();
|
||||
let format = NumberFormat::default();
|
||||
let symbol = format.symbol();
|
||||
NumberDescription {
|
||||
money,
|
||||
format,
|
||||
scale: 0,
|
||||
symbol,
|
||||
sign_positive: true,
|
||||
@ -50,14 +87,13 @@ impl std::default::Default for NumberDescription {
|
||||
}
|
||||
|
||||
impl NumberDescription {
|
||||
pub fn set_money_symbol(&mut self, money_symbol: MoneySymbol) {
|
||||
self.money = money_symbol;
|
||||
self.symbol = money_symbol.symbol_str();
|
||||
pub fn set_format(&mut self, format: NumberFormat) {
|
||||
self.format = format;
|
||||
self.symbol = format.symbol();
|
||||
}
|
||||
|
||||
fn money_from_str(&self, s: &str) -> Option<String> {
|
||||
match Decimal::from_str(s) {
|
||||
Ok(mut decimal) => {
|
||||
fn decimal_from_str(&self, s: &str) -> Decimal {
|
||||
let mut decimal = Decimal::from_str(s).unwrap_or(Decimal::zero());
|
||||
match decimal.set_scale(self.scale) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
@ -65,86 +101,142 @@ impl NumberDescription {
|
||||
}
|
||||
}
|
||||
decimal.set_sign_positive(self.sign_positive);
|
||||
Some(self.money.with_decimal(decimal).to_string())
|
||||
decimal
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Parser money from {} failed: {:?}", s, e);
|
||||
None
|
||||
|
||||
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 {
|
||||
fn str_from_cell_data(&self, data: String) -> String {
|
||||
match self.money_from_str(&data) {
|
||||
Some(money_str) => money_str,
|
||||
None => String::default(),
|
||||
match self.format {
|
||||
NumberFormat::Number => data,
|
||||
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> {
|
||||
let strip_symbol_money = strip_money_symbol(s);
|
||||
let decimal = Decimal::from_str(&strip_symbol_money).map_err(|err| FlowyError::internal().context(err))?;
|
||||
Ok(decimal.to_string())
|
||||
Ok(self.strip_symbol(s))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
|
||||
pub enum MoneySymbol {
|
||||
CNY = 0,
|
||||
EUR = 1,
|
||||
USD = 2,
|
||||
fn make_strip_symbol() -> Vec<String> {
|
||||
let mut symbols = vec![",".to_owned(), ".".to_owned()];
|
||||
for format in NumberFormat::iter() {
|
||||
symbols.push(format.symbol());
|
||||
}
|
||||
symbols
|
||||
}
|
||||
|
||||
impl std::default::Default for MoneySymbol {
|
||||
fn default() -> Self {
|
||||
MoneySymbol::USD
|
||||
}
|
||||
}
|
||||
|
||||
impl MoneySymbol {
|
||||
// Currency list https://docs.rs/rusty-money/0.4.0/rusty_money/iso/index.html
|
||||
pub fn from_symbol_str(s: &str) -> MoneySymbol {
|
||||
match s {
|
||||
"CNY" => MoneySymbol::CNY,
|
||||
"EUR" => MoneySymbol::EUR,
|
||||
"USD" => MoneySymbol::USD,
|
||||
_ => MoneySymbol::CNY,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_money(money: &rusty_money::Money<Currency>) -> MoneySymbol {
|
||||
MoneySymbol::from_symbol_str(&money.currency().symbol.to_string())
|
||||
}
|
||||
|
||||
pub fn currency(&self) -> &'static Currency {
|
||||
match self {
|
||||
MoneySymbol::CNY => CNY,
|
||||
MoneySymbol::EUR => EUR,
|
||||
MoneySymbol::USD => USD,
|
||||
}
|
||||
}
|
||||
|
||||
// string_to_money("¥18,443").unwrap();
|
||||
// string_to_money("$18,443").unwrap();
|
||||
// string_to_money("€18,443").unwrap();
|
||||
pub fn code(&self) -> String {
|
||||
self.currency().iso_alpha_code.to_string()
|
||||
}
|
||||
|
||||
pub fn symbol_str(&self) -> String {
|
||||
self.currency().symbol.to_string()
|
||||
}
|
||||
|
||||
pub fn zero(&self) -> Money<Currency> {
|
||||
let mut decimal = Decimal::new(0, 0);
|
||||
decimal.set_sign_positive(true);
|
||||
self.with_decimal(decimal)
|
||||
}
|
||||
|
||||
pub fn with_decimal(&self, decimal: Decimal) -> Money<Currency> {
|
||||
let money = rusty_money::Money::from_decimal(decimal, self.currency());
|
||||
money
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::services::cell::{NumberDescription, NumberFormat};
|
||||
use crate::services::row::StringifyCellData;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
#[test]
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_description_scale_test() {
|
||||
let mut description = NumberDescription::default();
|
||||
description.scale = 1;
|
||||
|
||||
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()),
|
||||
"$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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_description_sign_test() {
|
||||
let mut description = NumberDescription::default();
|
||||
description.sign_positive = false;
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::impl_from_and_to_type_option;
|
||||
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_grid_data_model::entities::{Field, FieldType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -23,7 +23,7 @@ impl StringifyCellData for SingleSelectDescription {
|
||||
}
|
||||
|
||||
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> {
|
||||
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)]
|
||||
pub struct SelectOption {
|
||||
#[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());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::impl_from_and_to_type_option;
|
||||
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_grid_data_model::entities::{Field, FieldType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 bytes::Bytes;
|
||||
use flowy_collaboration::client_grid::{GridChange, GridMetaPad};
|
||||
|
@ -1,8 +1,8 @@
|
||||
mod util;
|
||||
|
||||
pub mod block_meta_editor;
|
||||
pub mod cell;
|
||||
pub mod field;
|
||||
pub mod grid_editor;
|
||||
pub mod grid_meta_editor;
|
||||
pub mod kv_persistence;
|
||||
pub mod row;
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 std::collections::HashMap;
|
||||
|
||||
|
@ -1,103 +1,35 @@
|
||||
use crate::services::cell::MoneySymbol;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
|
||||
use lazy_static::lazy_static;
|
||||
use rust_decimal::Decimal;
|
||||
use rusty_money::{iso::Currency, Money};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
lazy_static! {
|
||||
static ref CURRENCIES_BY_SYMBOL: HashMap<String, &'static Currency> = generate_currency_by_symbol();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn generate_currency_by_symbol() -> HashMap<String, &'static Currency> {
|
||||
let mut map: HashMap<String, &'static Currency> = HashMap::new();
|
||||
|
||||
for money in MoneySymbol::iter() {
|
||||
map.insert(money.symbol_str(), money.currency());
|
||||
}
|
||||
map
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn string_to_money(money_str: &str) -> Option<Money<Currency>> {
|
||||
let mut process_money_str = String::from(money_str);
|
||||
let default_currency = MoneySymbol::from_symbol_str("CNY").currency();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// #[allow(dead_code)]
|
||||
// pub fn string_to_money(money_str: &str) -> Option<Money<Currency>> {
|
||||
// let mut process_money_str = String::from(money_str);
|
||||
// let default_currency = MoneySymbol::from_symbol_str("CNY").currency();
|
||||
//
|
||||
// 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,
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
pub fn uuid() -> String {
|
||||
uuid::Uuid::new_v4().to_string()
|
||||
|
@ -1,10 +1,8 @@
|
||||
use crate::grid::script::EditorScript::*;
|
||||
use crate::grid::script::*;
|
||||
use flowy_grid::services::field::{SelectOption, SingleSelectDescription};
|
||||
use flowy_grid::services::row::CreateRowContextBuilder;
|
||||
use flowy_grid_data_model::entities::{
|
||||
FieldChangeset, FieldType, GridBlock, GridBlockChangeset, Row, RowMetaChangeset,
|
||||
};
|
||||
use flowy_grid::services::cell::*;
|
||||
use flowy_grid::services::row::{CreateRowContextBuilder, StringifyCellData};
|
||||
use flowy_grid_data_model::entities::{FieldChangeset, FieldType, GridBlock, GridBlockChangeset, RowMetaChangeset};
|
||||
|
||||
#[tokio::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());
|
||||
}
|
||||
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 => {
|
||||
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 => {
|
||||
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 scripts = vec![AssertRowCount(3), CreateRow { context }];
|
||||
let scripts = vec![AssertRowCount(3), CreateRow { context }, AssertGridMetaPad];
|
||||
test.run_scripts(scripts).await;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use flowy_grid::services::field::*;
|
||||
use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
|
||||
use flowy_grid::services::row::CreateRowContext;
|
||||
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_test::helper::ViewTest;
|
||||
@ -104,7 +104,7 @@ impl GridEditorTest {
|
||||
let grid_manager = self.sdk.grid_manager.clone();
|
||||
let pool = self.sdk.user_session.db_pool().unwrap();
|
||||
let rev_manager = self.editor.rev_manager();
|
||||
let cache = rev_manager.revision_cache().await;
|
||||
let _cache = rev_manager.revision_cache().await;
|
||||
|
||||
match script {
|
||||
EditorScript::CreateField { field } => {
|
||||
|
Loading…
Reference in New Issue
Block a user