Merge pull request #516 from AppFlowy-IO/fix/grid_ui

Fix: Grid UI bugs
This commit is contained in:
Nathan.fooo 2022-05-30 20:43:56 +08:00 committed by GitHub
commit e177a1433f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 885 additions and 728 deletions

View File

@ -58,11 +58,7 @@ class GridCellDataLoader<T> extends IGridCellDataLoader<T> {
return fut.then(
(result) => result.fold((Cell cell) {
try {
if (cell.data.isEmpty) {
return null;
} else {
return parser.parserData(cell.data);
}
return parser.parserData(cell.data);
} catch (e, s) {
Log.error('$parser parser cellData failed, $e');
Log.error('Stack trace \n $s');
@ -102,13 +98,17 @@ class SelectOptionCellDataLoader extends IGridCellDataLoader<SelectOptionCellDat
class StringCellDataParser implements ICellDataParser<String> {
@override
String? parserData(List<int> data) {
return utf8.decode(data);
final s = utf8.decode(data);
return s;
}
}
class DateCellDataParser implements ICellDataParser<DateCellData> {
@override
DateCellData? parserData(List<int> data) {
if (data.isEmpty) {
return null;
}
return DateCellData.fromBuffer(data);
}
}
@ -116,6 +116,9 @@ class DateCellDataParser implements ICellDataParser<DateCellData> {
class SelectOptionCellDataParser implements ICellDataParser<SelectOptionCellData> {
@override
SelectOptionCellData? parserData(List<int> data) {
if (data.isEmpty) {
return null;
}
return SelectOptionCellData.fromBuffer(data);
}
}
@ -123,6 +126,9 @@ class SelectOptionCellDataParser implements ICellDataParser<SelectOptionCellData
class URLCellDataParser implements ICellDataParser<URLCellData> {
@override
URLCellData? parserData(List<int> data) {
if (data.isEmpty) {
return null;
}
return URLCellData.fromBuffer(data);
}
}

View File

@ -1,6 +1,8 @@
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'cell_service/cell_service.dart';
part 'number_cell_bloc.freezed.dart';
@ -14,25 +16,28 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
}) : super(NumberCellState.initial(cellContext)) {
on<NumberCellEvent>(
(event, emit) async {
await event.map(
initial: (_Initial value) async {
event.when(
initial: () {
_startListening();
},
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
emit(state.copyWith(content: value.cellContent ?? ""));
didReceiveCellUpdate: (content) {
emit(state.copyWith(content: content));
},
updateCell: (_UpdateCell value) async {
await _updateCellValue(value, emit);
updateCell: (text) {
cellContext.saveCellData(text, resultCallback: (result) {
result.fold(
() => null,
(err) {
if (!isClosed) add(NumberCellEvent.didReceiveCellUpdate(right(err)));
},
);
});
},
);
},
);
}
Future<void> _updateCellValue(_UpdateCell value, Emitter<NumberCellState> emit) async {
cellContext.saveCellData(value.text);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
@ -47,7 +52,7 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
_onCellChangedFn = cellContext.startListening(
onCellChanged: ((cellContent) {
if (!isClosed) {
add(NumberCellEvent.didReceiveCellUpdate(cellContent));
add(NumberCellEvent.didReceiveCellUpdate(left(cellContent ?? "")));
}
}),
);
@ -58,17 +63,19 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
class NumberCellEvent with _$NumberCellEvent {
const factory NumberCellEvent.initial() = _Initial;
const factory NumberCellEvent.updateCell(String text) = _UpdateCell;
const factory NumberCellEvent.didReceiveCellUpdate(String? cellContent) = _DidReceiveCellUpdate;
const factory NumberCellEvent.didReceiveCellUpdate(Either<String, FlowyError> cellContent) = _DidReceiveCellUpdate;
}
@freezed
class NumberCellState with _$NumberCellState {
const factory NumberCellState({
required String content,
required Either<String, FlowyError> content,
}) = _NumberCellState;
factory NumberCellState.initial(GridCellContext context) {
final cellContent = context.getCellData() ?? "";
return NumberCellState(content: cellContent);
return NumberCellState(
content: left(cellContent),
);
}
}

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View File

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

View File

@ -29,7 +29,7 @@ class _NumberCellState extends State<NumberCell> {
void initState() {
final cellContext = widget.cellContextBuilder.build();
_cellBloc = getIt<NumberCellBloc>(param1: cellContext)..add(const NumberCellEvent.initial());
_controller = TextEditingController(text: _cellBloc.state.content);
_controller = TextEditingController(text: contentFromState(_cellBloc.state));
_focusNode = CellSingleFocusNode();
_listenFocusNode();
super.initState();
@ -40,26 +40,25 @@ class _NumberCellState extends State<NumberCell> {
_listenCellRequestFocus(context);
return BlocProvider.value(
value: _cellBloc,
child: BlocConsumer<NumberCellBloc, NumberCellState>(
listener: (context, state) {
if (_controller.text != state.content) {
_controller.text = state.content;
}
},
builder: (context, state) {
return TextField(
controller: _controller,
focusNode: _focusNode,
onEditingComplete: () => _focusNode.unfocus(),
maxLines: null,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
decoration: const InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
isDense: true,
),
);
},
child: MultiBlocListener(
listeners: [
BlocListener<NumberCellBloc, NumberCellState>(
listenWhen: (p, c) => p.content != c.content,
listener: (context, state) => _controller.text = contentFromState(state),
),
],
child: TextField(
controller: _controller,
focusNode: _focusNode,
onEditingComplete: () => _focusNode.unfocus(),
maxLines: null,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
decoration: const InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
isDense: true,
),
),
),
);
}
@ -86,13 +85,8 @@ class _NumberCellState extends State<NumberCell> {
if (mounted) {
_delayOperation?.cancel();
_delayOperation = Timer(const Duration(milliseconds: 300), () {
if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) {
final number = num.tryParse(_controller.text);
if (number != null) {
_cellBloc.add(NumberCellEvent.updateCell(_controller.text));
} else {
_controller.text = "";
}
if (_cellBloc.isClosed == false && _controller.text != contentFromState(_cellBloc.state)) {
_cellBloc.add(NumberCellEvent.updateCell(_controller.text));
}
});
}
@ -113,4 +107,8 @@ class _NumberCellState extends State<NumberCell> {
}
});
}
String contentFromState(NumberCellState state) {
return state.content.fold((l) => l, (r) => "");
}
}

View File

@ -64,9 +64,11 @@ class SelectOptionTag extends StatelessWidget {
final String name;
final Color color;
final bool isSelected;
final VoidCallback? onSelected;
const SelectOptionTag({
required this.name,
required this.color,
this.onSelected,
this.isSelected = false,
Key? key,
}) : super(key: key);
@ -74,12 +76,14 @@ class SelectOptionTag extends StatelessWidget {
factory SelectOptionTag.fromSelectOption({
required BuildContext context,
required SelectOption option,
VoidCallback? onSelected,
bool isSelected = false,
}) {
return SelectOptionTag(
name: option.name,
color: option.color.make(context),
isSelected: isSelected,
onSelected: onSelected,
);
}
@ -92,19 +96,12 @@ class SelectOptionTag extends StatelessWidget {
backgroundColor: color,
labelPadding: const EdgeInsets.symmetric(horizontal: 6),
selected: true,
onSelected: (_) {},
onSelected: (_) {
if (onSelected != null) {
onSelected!();
}
},
);
// return Container(
// decoration: BoxDecoration(
// color: option.color.make(context),
// shape: BoxShape.rectangle,
// borderRadius: BorderRadius.circular(8.0),
// ),
// child: Center(child: FlowyText.medium(option.name, fontSize: 12)),
// margin: const EdgeInsets.symmetric(horizontal: 3.0),
// padding: const EdgeInsets.symmetric(horizontal: 6.0),
// );
}
}
@ -136,7 +133,11 @@ class SelectOptionTagCell extends StatelessWidget {
Flexible(
fit: FlexFit.loose,
flex: 2,
child: SelectOptionTag.fromSelectOption(context: context, option: option),
child: SelectOptionTag.fromSelectOption(
context: context,
option: option,
onSelected: () => onSelected(option),
),
),
const Spacer(),
...children,

View File

@ -233,7 +233,11 @@ class _SelectOptionCell extends StatelessWidget {
context.read<SelectOptionCellEditorBloc>().add(SelectOptionEditorEvent.selectOption(option.id));
},
children: [
if (isSelected) svgWidget("grid/checkmark"),
if (isSelected)
Padding(
padding: const EdgeInsets.only(right: 6),
child: svgWidget("grid/checkmark"),
),
],
),
),

View File

@ -72,7 +72,10 @@ class _GridURLCellState extends State<GridURLCell> {
return CellEnterRegion(
child: Align(alignment: Alignment.centerLeft, child: richText),
expander: _EditCellIndicator(onTap: () {}),
expander: _EditCellIndicator(onTap: () {
final cellContext = widget.cellContextBuilder.build() as GridURLCellContext;
URLCellEditor.show(context, cellContext);
}),
);
},
),

View File

@ -9,7 +9,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:easy_localization/easy_localization.dart' hide NumberFormat;

View File

@ -0,0 +1,11 @@
///
// Generated code. Do not modify.
// source: format.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
import 'dart:core' as $core;
export 'format.pbenum.dart';

View File

@ -0,0 +1,94 @@
///
// Generated code. Do not modify.
// source: format.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
// ignore_for_file: UNDEFINED_SHOWN_NAME
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
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 CanadianDollar = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CanadianDollar');
static const NumberFormat EUR = NumberFormat._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR');
static const NumberFormat Pound = NumberFormat._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Pound');
static const NumberFormat Yen = NumberFormat._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yen');
static const NumberFormat Ruble = NumberFormat._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ruble');
static const NumberFormat Rupee = NumberFormat._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupee');
static const NumberFormat Won = NumberFormat._(9, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Won');
static const NumberFormat Yuan = NumberFormat._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yuan');
static const NumberFormat Real = NumberFormat._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Real');
static const NumberFormat Lira = NumberFormat._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Lira');
static const NumberFormat Rupiah = NumberFormat._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupiah');
static const NumberFormat Franc = NumberFormat._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Franc');
static const NumberFormat HongKongDollar = NumberFormat._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'HongKongDollar');
static const NumberFormat NewZealandDollar = NumberFormat._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewZealandDollar');
static const NumberFormat Krona = NumberFormat._(17, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Krona');
static const NumberFormat NorwegianKrone = NumberFormat._(18, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NorwegianKrone');
static const NumberFormat MexicanPeso = NumberFormat._(19, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MexicanPeso');
static const NumberFormat Rand = NumberFormat._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rand');
static const NumberFormat NewTaiwanDollar = NumberFormat._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewTaiwanDollar');
static const NumberFormat DanishKrone = NumberFormat._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DanishKrone');
static const NumberFormat Baht = NumberFormat._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Baht');
static const NumberFormat Forint = NumberFormat._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Forint');
static const NumberFormat Koruna = NumberFormat._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Koruna');
static const NumberFormat Shekel = NumberFormat._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Shekel');
static const NumberFormat ChileanPeso = NumberFormat._(27, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ChileanPeso');
static const NumberFormat PhilippinePeso = NumberFormat._(28, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PhilippinePeso');
static const NumberFormat Dirham = NumberFormat._(29, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Dirham');
static const NumberFormat ColombianPeso = NumberFormat._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ColombianPeso');
static const NumberFormat Riyal = NumberFormat._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Riyal');
static const NumberFormat Ringgit = NumberFormat._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ringgit');
static const NumberFormat Leu = NumberFormat._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Leu');
static const NumberFormat ArgentinePeso = NumberFormat._(34, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ArgentinePeso');
static const NumberFormat UruguayanPeso = NumberFormat._(35, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UruguayanPeso');
static const NumberFormat Percent = NumberFormat._(36, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Percent');
static const $core.List<NumberFormat> values = <NumberFormat> [
Number,
USD,
CanadianDollar,
EUR,
Pound,
Yen,
Ruble,
Rupee,
Won,
Yuan,
Real,
Lira,
Rupiah,
Franc,
HongKongDollar,
NewZealandDollar,
Krona,
NorwegianKrone,
MexicanPeso,
Rand,
NewTaiwanDollar,
DanishKrone,
Baht,
Forint,
Koruna,
Shekel,
ChileanPeso,
PhilippinePeso,
Dirham,
ColombianPeso,
Riyal,
Ringgit,
Leu,
ArgentinePeso,
UruguayanPeso,
Percent,
];
static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
static NumberFormat? valueOf($core.int value) => _byValue[value];
const NumberFormat._($core.int v, $core.String n) : super(v, n);
}

View File

@ -0,0 +1,55 @@
///
// Generated code. Do not modify.
// source: format.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
import 'dart:core' as $core;
import 'dart:convert' as $convert;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use numberFormatDescriptor instead')
const NumberFormat$json = const {
'1': 'NumberFormat',
'2': const [
const {'1': 'Number', '2': 0},
const {'1': 'USD', '2': 1},
const {'1': 'CanadianDollar', '2': 2},
const {'1': 'EUR', '2': 4},
const {'1': 'Pound', '2': 5},
const {'1': 'Yen', '2': 6},
const {'1': 'Ruble', '2': 7},
const {'1': 'Rupee', '2': 8},
const {'1': 'Won', '2': 9},
const {'1': 'Yuan', '2': 10},
const {'1': 'Real', '2': 11},
const {'1': 'Lira', '2': 12},
const {'1': 'Rupiah', '2': 13},
const {'1': 'Franc', '2': 14},
const {'1': 'HongKongDollar', '2': 15},
const {'1': 'NewZealandDollar', '2': 16},
const {'1': 'Krona', '2': 17},
const {'1': 'NorwegianKrone', '2': 18},
const {'1': 'MexicanPeso', '2': 19},
const {'1': 'Rand', '2': 20},
const {'1': 'NewTaiwanDollar', '2': 21},
const {'1': 'DanishKrone', '2': 22},
const {'1': 'Baht', '2': 23},
const {'1': 'Forint', '2': 24},
const {'1': 'Koruna', '2': 25},
const {'1': 'Shekel', '2': 26},
const {'1': 'ChileanPeso', '2': 27},
const {'1': 'PhilippinePeso', '2': 28},
const {'1': 'Dirham', '2': 29},
const {'1': 'ColombianPeso', '2': 30},
const {'1': 'Riyal', '2': 31},
const {'1': 'Ringgit', '2': 32},
const {'1': 'Leu', '2': 33},
const {'1': 'ArgentinePeso', '2': 34},
const {'1': 'UruguayanPeso', '2': 35},
const {'1': 'Percent', '2': 36},
],
};
/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESEgoOQ2FuYWRpYW5Eb2xsYXIQAhIHCgNFVVIQBBIJCgVQb3VuZBAFEgcKA1llbhAGEgkKBVJ1YmxlEAcSCQoFUnVwZWUQCBIHCgNXb24QCRIICgRZdWFuEAoSCAoEUmVhbBALEggKBExpcmEQDBIKCgZSdXBpYWgQDRIJCgVGcmFuYxAOEhIKDkhvbmdLb25nRG9sbGFyEA8SFAoQTmV3WmVhbGFuZERvbGxhchAQEgkKBUtyb25hEBESEgoOTm9yd2VnaWFuS3JvbmUQEhIPCgtNZXhpY2FuUGVzbxATEggKBFJhbmQQFBITCg9OZXdUYWl3YW5Eb2xsYXIQFRIPCgtEYW5pc2hLcm9uZRAWEggKBEJhaHQQFxIKCgZGb3JpbnQQGBIKCgZLb3J1bmEQGRIKCgZTaGVrZWwQGhIPCgtDaGlsZWFuUGVzbxAbEhIKDlBoaWxpcHBpbmVQZXNvEBwSCgoGRGlyaGFtEB0SEQoNQ29sb21iaWFuUGVzbxAeEgkKBVJpeWFsEB8SCwoHUmluZ2dpdBAgEgcKA0xldRAhEhEKDUFyZ2VudGluZVBlc28QIhIRCg1VcnVndWF5YW5QZXNvECMSCwoHUGVyY2VudBAk');

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: format.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
export 'format.pb.dart';

View File

@ -9,13 +9,11 @@ import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
import 'number_type_option.pbenum.dart';
export 'number_type_option.pbenum.dart';
import 'format.pbenum.dart' as $0;
class NumberTypeOption extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberTypeOption', createEmptyInstance: create)
..e<NumberFormat>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: NumberFormat.Number, valueOf: NumberFormat.valueOf, enumValues: NumberFormat.values)
..e<$0.NumberFormat>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: $0.NumberFormat.Number, valueOf: $0.NumberFormat.valueOf, enumValues: $0.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,7 +23,7 @@ class NumberTypeOption extends $pb.GeneratedMessage {
NumberTypeOption._() : super();
factory NumberTypeOption({
NumberFormat? format,
$0.NumberFormat? format,
$core.int? scale,
$core.String? symbol,
$core.bool? signPositive,
@ -71,9 +69,9 @@ class NumberTypeOption extends $pb.GeneratedMessage {
static NumberTypeOption? _defaultInstance;
@$pb.TagNumber(1)
NumberFormat get format => $_getN(0);
$0.NumberFormat get format => $_getN(0);
@$pb.TagNumber(1)
set format(NumberFormat v) { setField(1, v); }
set format($0.NumberFormat v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasFormat() => $_has(0);
@$pb.TagNumber(1)

View File

@ -5,90 +5,3 @@
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
// ignore_for_file: UNDEFINED_SHOWN_NAME
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
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 CanadianDollar = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CanadianDollar');
static const NumberFormat EUR = NumberFormat._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR');
static const NumberFormat Pound = NumberFormat._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Pound');
static const NumberFormat Yen = NumberFormat._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yen');
static const NumberFormat Ruble = NumberFormat._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ruble');
static const NumberFormat Rupee = NumberFormat._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupee');
static const NumberFormat Won = NumberFormat._(9, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Won');
static const NumberFormat Yuan = NumberFormat._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yuan');
static const NumberFormat Real = NumberFormat._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Real');
static const NumberFormat Lira = NumberFormat._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Lira');
static const NumberFormat Rupiah = NumberFormat._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupiah');
static const NumberFormat Franc = NumberFormat._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Franc');
static const NumberFormat HongKongDollar = NumberFormat._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'HongKongDollar');
static const NumberFormat NewZealandDollar = NumberFormat._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewZealandDollar');
static const NumberFormat Krona = NumberFormat._(17, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Krona');
static const NumberFormat NorwegianKrone = NumberFormat._(18, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NorwegianKrone');
static const NumberFormat MexicanPeso = NumberFormat._(19, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MexicanPeso');
static const NumberFormat Rand = NumberFormat._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rand');
static const NumberFormat NewTaiwanDollar = NumberFormat._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewTaiwanDollar');
static const NumberFormat DanishKrone = NumberFormat._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DanishKrone');
static const NumberFormat Baht = NumberFormat._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Baht');
static const NumberFormat Forint = NumberFormat._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Forint');
static const NumberFormat Koruna = NumberFormat._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Koruna');
static const NumberFormat Shekel = NumberFormat._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Shekel');
static const NumberFormat ChileanPeso = NumberFormat._(27, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ChileanPeso');
static const NumberFormat PhilippinePeso = NumberFormat._(28, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PhilippinePeso');
static const NumberFormat Dirham = NumberFormat._(29, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Dirham');
static const NumberFormat ColombianPeso = NumberFormat._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ColombianPeso');
static const NumberFormat Riyal = NumberFormat._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Riyal');
static const NumberFormat Ringgit = NumberFormat._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ringgit');
static const NumberFormat Leu = NumberFormat._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Leu');
static const NumberFormat ArgentinePeso = NumberFormat._(34, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ArgentinePeso');
static const NumberFormat UruguayanPeso = NumberFormat._(35, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UruguayanPeso');
static const NumberFormat Percent = NumberFormat._(36, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Percent');
static const $core.List<NumberFormat> values = <NumberFormat> [
Number,
USD,
CanadianDollar,
EUR,
Pound,
Yen,
Ruble,
Rupee,
Won,
Yuan,
Real,
Lira,
Rupiah,
Franc,
HongKongDollar,
NewZealandDollar,
Krona,
NorwegianKrone,
MexicanPeso,
Rand,
NewTaiwanDollar,
DanishKrone,
Baht,
Forint,
Koruna,
Shekel,
ChileanPeso,
PhilippinePeso,
Dirham,
ColombianPeso,
Riyal,
Ringgit,
Leu,
ArgentinePeso,
UruguayanPeso,
Percent,
];
static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
static NumberFormat? valueOf($core.int value) => _byValue[value];
const NumberFormat._($core.int v, $core.String n) : super(v, n);
}

View File

@ -8,51 +8,6 @@
import 'dart:core' as $core;
import 'dart:convert' as $convert;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use numberFormatDescriptor instead')
const NumberFormat$json = const {
'1': 'NumberFormat',
'2': const [
const {'1': 'Number', '2': 0},
const {'1': 'USD', '2': 1},
const {'1': 'CanadianDollar', '2': 2},
const {'1': 'EUR', '2': 4},
const {'1': 'Pound', '2': 5},
const {'1': 'Yen', '2': 6},
const {'1': 'Ruble', '2': 7},
const {'1': 'Rupee', '2': 8},
const {'1': 'Won', '2': 9},
const {'1': 'Yuan', '2': 10},
const {'1': 'Real', '2': 11},
const {'1': 'Lira', '2': 12},
const {'1': 'Rupiah', '2': 13},
const {'1': 'Franc', '2': 14},
const {'1': 'HongKongDollar', '2': 15},
const {'1': 'NewZealandDollar', '2': 16},
const {'1': 'Krona', '2': 17},
const {'1': 'NorwegianKrone', '2': 18},
const {'1': 'MexicanPeso', '2': 19},
const {'1': 'Rand', '2': 20},
const {'1': 'NewTaiwanDollar', '2': 21},
const {'1': 'DanishKrone', '2': 22},
const {'1': 'Baht', '2': 23},
const {'1': 'Forint', '2': 24},
const {'1': 'Koruna', '2': 25},
const {'1': 'Shekel', '2': 26},
const {'1': 'ChileanPeso', '2': 27},
const {'1': 'PhilippinePeso', '2': 28},
const {'1': 'Dirham', '2': 29},
const {'1': 'ColombianPeso', '2': 30},
const {'1': 'Riyal', '2': 31},
const {'1': 'Ringgit', '2': 32},
const {'1': 'Leu', '2': 33},
const {'1': 'ArgentinePeso', '2': 34},
const {'1': 'UruguayanPeso', '2': 35},
const {'1': 'Percent', '2': 36},
],
};
/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESEgoOQ2FuYWRpYW5Eb2xsYXIQAhIHCgNFVVIQBBIJCgVQb3VuZBAFEgcKA1llbhAGEgkKBVJ1YmxlEAcSCQoFUnVwZWUQCBIHCgNXb24QCRIICgRZdWFuEAoSCAoEUmVhbBALEggKBExpcmEQDBIKCgZSdXBpYWgQDRIJCgVGcmFuYxAOEhIKDkhvbmdLb25nRG9sbGFyEA8SFAoQTmV3WmVhbGFuZERvbGxhchAQEgkKBUtyb25hEBESEgoOTm9yd2VnaWFuS3JvbmUQEhIPCgtNZXhpY2FuUGVzbxATEggKBFJhbmQQFBITCg9OZXdUYWl3YW5Eb2xsYXIQFRIPCgtEYW5pc2hLcm9uZRAWEggKBEJhaHQQFxIKCgZGb3JpbnQQGBIKCgZLb3J1bmEQGRIKCgZTaGVrZWwQGhIPCgtDaGlsZWFuUGVzbxAbEhIKDlBoaWxpcHBpbmVQZXNvEBwSCgoGRGlyaGFtEB0SEQoNQ29sb21iaWFuUGVzbxAeEgkKBVJpeWFsEB8SCwoHUmluZ2dpdBAgEgcKA0xldRAhEhEKDUFyZ2VudGluZVBlc28QIhIRCg1VcnVndWF5YW5QZXNvECMSCwoHUGVyY2VudBAk');
@$core.Deprecated('Use numberTypeOptionDescriptor instead')
const NumberTypeOption$json = const {
'1': 'NumberTypeOption',

View File

@ -7,6 +7,7 @@ export './row_entities.pb.dart';
export './cell_entities.pb.dart';
export './url_type_option.pb.dart';
export './checkbox_type_option.pb.dart';
export './format.pb.dart';
export './event_map.pb.dart';
export './text_type_option.pb.dart';
export './date_type_option.pb.dart';

View File

@ -0,0 +1,207 @@
// 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 `format.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum NumberFormat {
Number = 0,
USD = 1,
CanadianDollar = 2,
EUR = 4,
Pound = 5,
Yen = 6,
Ruble = 7,
Rupee = 8,
Won = 9,
Yuan = 10,
Real = 11,
Lira = 12,
Rupiah = 13,
Franc = 14,
HongKongDollar = 15,
NewZealandDollar = 16,
Krona = 17,
NorwegianKrone = 18,
MexicanPeso = 19,
Rand = 20,
NewTaiwanDollar = 21,
DanishKrone = 22,
Baht = 23,
Forint = 24,
Koruna = 25,
Shekel = 26,
ChileanPeso = 27,
PhilippinePeso = 28,
Dirham = 29,
ColombianPeso = 30,
Riyal = 31,
Ringgit = 32,
Leu = 33,
ArgentinePeso = 34,
UruguayanPeso = 35,
Percent = 36,
}
impl ::protobuf::ProtobufEnum for NumberFormat {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<NumberFormat> {
match value {
0 => ::std::option::Option::Some(NumberFormat::Number),
1 => ::std::option::Option::Some(NumberFormat::USD),
2 => ::std::option::Option::Some(NumberFormat::CanadianDollar),
4 => ::std::option::Option::Some(NumberFormat::EUR),
5 => ::std::option::Option::Some(NumberFormat::Pound),
6 => ::std::option::Option::Some(NumberFormat::Yen),
7 => ::std::option::Option::Some(NumberFormat::Ruble),
8 => ::std::option::Option::Some(NumberFormat::Rupee),
9 => ::std::option::Option::Some(NumberFormat::Won),
10 => ::std::option::Option::Some(NumberFormat::Yuan),
11 => ::std::option::Option::Some(NumberFormat::Real),
12 => ::std::option::Option::Some(NumberFormat::Lira),
13 => ::std::option::Option::Some(NumberFormat::Rupiah),
14 => ::std::option::Option::Some(NumberFormat::Franc),
15 => ::std::option::Option::Some(NumberFormat::HongKongDollar),
16 => ::std::option::Option::Some(NumberFormat::NewZealandDollar),
17 => ::std::option::Option::Some(NumberFormat::Krona),
18 => ::std::option::Option::Some(NumberFormat::NorwegianKrone),
19 => ::std::option::Option::Some(NumberFormat::MexicanPeso),
20 => ::std::option::Option::Some(NumberFormat::Rand),
21 => ::std::option::Option::Some(NumberFormat::NewTaiwanDollar),
22 => ::std::option::Option::Some(NumberFormat::DanishKrone),
23 => ::std::option::Option::Some(NumberFormat::Baht),
24 => ::std::option::Option::Some(NumberFormat::Forint),
25 => ::std::option::Option::Some(NumberFormat::Koruna),
26 => ::std::option::Option::Some(NumberFormat::Shekel),
27 => ::std::option::Option::Some(NumberFormat::ChileanPeso),
28 => ::std::option::Option::Some(NumberFormat::PhilippinePeso),
29 => ::std::option::Option::Some(NumberFormat::Dirham),
30 => ::std::option::Option::Some(NumberFormat::ColombianPeso),
31 => ::std::option::Option::Some(NumberFormat::Riyal),
32 => ::std::option::Option::Some(NumberFormat::Ringgit),
33 => ::std::option::Option::Some(NumberFormat::Leu),
34 => ::std::option::Option::Some(NumberFormat::ArgentinePeso),
35 => ::std::option::Option::Some(NumberFormat::UruguayanPeso),
36 => ::std::option::Option::Some(NumberFormat::Percent),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [NumberFormat] = &[
NumberFormat::Number,
NumberFormat::USD,
NumberFormat::CanadianDollar,
NumberFormat::EUR,
NumberFormat::Pound,
NumberFormat::Yen,
NumberFormat::Ruble,
NumberFormat::Rupee,
NumberFormat::Won,
NumberFormat::Yuan,
NumberFormat::Real,
NumberFormat::Lira,
NumberFormat::Rupiah,
NumberFormat::Franc,
NumberFormat::HongKongDollar,
NumberFormat::NewZealandDollar,
NumberFormat::Krona,
NumberFormat::NorwegianKrone,
NumberFormat::MexicanPeso,
NumberFormat::Rand,
NumberFormat::NewTaiwanDollar,
NumberFormat::DanishKrone,
NumberFormat::Baht,
NumberFormat::Forint,
NumberFormat::Koruna,
NumberFormat::Shekel,
NumberFormat::ChileanPeso,
NumberFormat::PhilippinePeso,
NumberFormat::Dirham,
NumberFormat::ColombianPeso,
NumberFormat::Riyal,
NumberFormat::Ringgit,
NumberFormat::Leu,
NumberFormat::ArgentinePeso,
NumberFormat::UruguayanPeso,
NumberFormat::Percent,
];
values
}
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::<NumberFormat>("NumberFormat", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for NumberFormat {
}
impl ::std::default::Default for NumberFormat {
fn default() -> Self {
NumberFormat::Number
}
}
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\x0cformat.proto*\xf8\x03\n\x0cNumberFormat\x12\n\n\x06Number\x10\0\
\x12\x07\n\x03USD\x10\x01\x12\x12\n\x0eCanadianDollar\x10\x02\x12\x07\n\
\x03EUR\x10\x04\x12\t\n\x05Pound\x10\x05\x12\x07\n\x03Yen\x10\x06\x12\t\
\n\x05Ruble\x10\x07\x12\t\n\x05Rupee\x10\x08\x12\x07\n\x03Won\x10\t\x12\
\x08\n\x04Yuan\x10\n\x12\x08\n\x04Real\x10\x0b\x12\x08\n\x04Lira\x10\x0c\
\x12\n\n\x06Rupiah\x10\r\x12\t\n\x05Franc\x10\x0e\x12\x12\n\x0eHongKongD\
ollar\x10\x0f\x12\x14\n\x10NewZealandDollar\x10\x10\x12\t\n\x05Krona\x10\
\x11\x12\x12\n\x0eNorwegianKrone\x10\x12\x12\x0f\n\x0bMexicanPeso\x10\
\x13\x12\x08\n\x04Rand\x10\x14\x12\x13\n\x0fNewTaiwanDollar\x10\x15\x12\
\x0f\n\x0bDanishKrone\x10\x16\x12\x08\n\x04Baht\x10\x17\x12\n\n\x06Forin\
t\x10\x18\x12\n\n\x06Koruna\x10\x19\x12\n\n\x06Shekel\x10\x1a\x12\x0f\n\
\x0bChileanPeso\x10\x1b\x12\x12\n\x0ePhilippinePeso\x10\x1c\x12\n\n\x06D\
irham\x10\x1d\x12\x11\n\rColombianPeso\x10\x1e\x12\t\n\x05Riyal\x10\x1f\
\x12\x0b\n\x07Ringgit\x10\x20\x12\x07\n\x03Leu\x10!\x12\x11\n\rArgentine\
Peso\x10\"\x12\x11\n\rUruguayanPeso\x10#\x12\x0b\n\x07Percent\x10$b\x06p\
roto3\
";
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

@ -25,6 +25,9 @@ pub use url_type_option::*;
mod checkbox_type_option;
pub use checkbox_type_option::*;
mod format;
pub use format::*;
mod event_map;
pub use event_map::*;

View File

@ -26,7 +26,7 @@
#[derive(PartialEq,Clone,Default)]
pub struct NumberTypeOption {
// message fields
pub format: NumberFormat,
pub format: super::format::NumberFormat,
pub scale: u32,
pub symbol: ::std::string::String,
pub sign_positive: bool,
@ -50,15 +50,15 @@ impl NumberTypeOption {
// .NumberFormat format = 1;
pub fn get_format(&self) -> NumberFormat {
pub fn get_format(&self) -> super::format::NumberFormat {
self.format
}
pub fn clear_format(&mut self) {
self.format = NumberFormat::Number;
self.format = super::format::NumberFormat::Number;
}
// Param is passed by value, moved
pub fn set_format(&mut self, v: NumberFormat) {
pub fn set_format(&mut self, v: super::format::NumberFormat) {
self.format = v;
}
@ -189,7 +189,7 @@ impl ::protobuf::Message for NumberTypeOption {
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.format != NumberFormat::Number {
if self.format != super::format::NumberFormat::Number {
my_size += ::protobuf::rt::enum_size(1, self.format);
}
if self.scale != 0 {
@ -210,7 +210,7 @@ impl ::protobuf::Message for NumberTypeOption {
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.format != NumberFormat::Number {
if self.format != super::format::NumberFormat::Number {
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.format))?;
}
if self.scale != 0 {
@ -263,7 +263,7 @@ impl ::protobuf::Message for NumberTypeOption {
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<NumberFormat>>(
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<super::format::NumberFormat>>(
"format",
|m: &NumberTypeOption| { &m.format },
|m: &mut NumberTypeOption| { &mut m.format },
@ -304,7 +304,7 @@ impl ::protobuf::Message for NumberTypeOption {
impl ::protobuf::Clear for NumberTypeOption {
fn clear(&mut self) {
self.format = NumberFormat::Number;
self.format = super::format::NumberFormat::Number;
self.scale = 0;
self.symbol.clear();
self.sign_positive = false;
@ -325,179 +325,13 @@ impl ::protobuf::reflect::ProtobufValue for NumberTypeOption {
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum NumberFormat {
Number = 0,
USD = 1,
CanadianDollar = 2,
EUR = 4,
Pound = 5,
Yen = 6,
Ruble = 7,
Rupee = 8,
Won = 9,
Yuan = 10,
Real = 11,
Lira = 12,
Rupiah = 13,
Franc = 14,
HongKongDollar = 15,
NewZealandDollar = 16,
Krona = 17,
NorwegianKrone = 18,
MexicanPeso = 19,
Rand = 20,
NewTaiwanDollar = 21,
DanishKrone = 22,
Baht = 23,
Forint = 24,
Koruna = 25,
Shekel = 26,
ChileanPeso = 27,
PhilippinePeso = 28,
Dirham = 29,
ColombianPeso = 30,
Riyal = 31,
Ringgit = 32,
Leu = 33,
ArgentinePeso = 34,
UruguayanPeso = 35,
Percent = 36,
}
impl ::protobuf::ProtobufEnum for NumberFormat {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<NumberFormat> {
match value {
0 => ::std::option::Option::Some(NumberFormat::Number),
1 => ::std::option::Option::Some(NumberFormat::USD),
2 => ::std::option::Option::Some(NumberFormat::CanadianDollar),
4 => ::std::option::Option::Some(NumberFormat::EUR),
5 => ::std::option::Option::Some(NumberFormat::Pound),
6 => ::std::option::Option::Some(NumberFormat::Yen),
7 => ::std::option::Option::Some(NumberFormat::Ruble),
8 => ::std::option::Option::Some(NumberFormat::Rupee),
9 => ::std::option::Option::Some(NumberFormat::Won),
10 => ::std::option::Option::Some(NumberFormat::Yuan),
11 => ::std::option::Option::Some(NumberFormat::Real),
12 => ::std::option::Option::Some(NumberFormat::Lira),
13 => ::std::option::Option::Some(NumberFormat::Rupiah),
14 => ::std::option::Option::Some(NumberFormat::Franc),
15 => ::std::option::Option::Some(NumberFormat::HongKongDollar),
16 => ::std::option::Option::Some(NumberFormat::NewZealandDollar),
17 => ::std::option::Option::Some(NumberFormat::Krona),
18 => ::std::option::Option::Some(NumberFormat::NorwegianKrone),
19 => ::std::option::Option::Some(NumberFormat::MexicanPeso),
20 => ::std::option::Option::Some(NumberFormat::Rand),
21 => ::std::option::Option::Some(NumberFormat::NewTaiwanDollar),
22 => ::std::option::Option::Some(NumberFormat::DanishKrone),
23 => ::std::option::Option::Some(NumberFormat::Baht),
24 => ::std::option::Option::Some(NumberFormat::Forint),
25 => ::std::option::Option::Some(NumberFormat::Koruna),
26 => ::std::option::Option::Some(NumberFormat::Shekel),
27 => ::std::option::Option::Some(NumberFormat::ChileanPeso),
28 => ::std::option::Option::Some(NumberFormat::PhilippinePeso),
29 => ::std::option::Option::Some(NumberFormat::Dirham),
30 => ::std::option::Option::Some(NumberFormat::ColombianPeso),
31 => ::std::option::Option::Some(NumberFormat::Riyal),
32 => ::std::option::Option::Some(NumberFormat::Ringgit),
33 => ::std::option::Option::Some(NumberFormat::Leu),
34 => ::std::option::Option::Some(NumberFormat::ArgentinePeso),
35 => ::std::option::Option::Some(NumberFormat::UruguayanPeso),
36 => ::std::option::Option::Some(NumberFormat::Percent),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [NumberFormat] = &[
NumberFormat::Number,
NumberFormat::USD,
NumberFormat::CanadianDollar,
NumberFormat::EUR,
NumberFormat::Pound,
NumberFormat::Yen,
NumberFormat::Ruble,
NumberFormat::Rupee,
NumberFormat::Won,
NumberFormat::Yuan,
NumberFormat::Real,
NumberFormat::Lira,
NumberFormat::Rupiah,
NumberFormat::Franc,
NumberFormat::HongKongDollar,
NumberFormat::NewZealandDollar,
NumberFormat::Krona,
NumberFormat::NorwegianKrone,
NumberFormat::MexicanPeso,
NumberFormat::Rand,
NumberFormat::NewTaiwanDollar,
NumberFormat::DanishKrone,
NumberFormat::Baht,
NumberFormat::Forint,
NumberFormat::Koruna,
NumberFormat::Shekel,
NumberFormat::ChileanPeso,
NumberFormat::PhilippinePeso,
NumberFormat::Dirham,
NumberFormat::ColombianPeso,
NumberFormat::Riyal,
NumberFormat::Ringgit,
NumberFormat::Leu,
NumberFormat::ArgentinePeso,
NumberFormat::UruguayanPeso,
NumberFormat::Percent,
];
values
}
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::<NumberFormat>("NumberFormat", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for NumberFormat {
}
impl ::std::default::Default for NumberFormat {
fn default() -> Self {
NumberFormat::Number
}
}
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_type_option.proto\"\xa0\x01\n\x10NumberTypeOption\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*\xf8\x03\n\x0cNumberForm\
at\x12\n\n\x06Number\x10\0\x12\x07\n\x03USD\x10\x01\x12\x12\n\x0eCanadia\
nDollar\x10\x02\x12\x07\n\x03EUR\x10\x04\x12\t\n\x05Pound\x10\x05\x12\
\x07\n\x03Yen\x10\x06\x12\t\n\x05Ruble\x10\x07\x12\t\n\x05Rupee\x10\x08\
\x12\x07\n\x03Won\x10\t\x12\x08\n\x04Yuan\x10\n\x12\x08\n\x04Real\x10\
\x0b\x12\x08\n\x04Lira\x10\x0c\x12\n\n\x06Rupiah\x10\r\x12\t\n\x05Franc\
\x10\x0e\x12\x12\n\x0eHongKongDollar\x10\x0f\x12\x14\n\x10NewZealandDoll\
ar\x10\x10\x12\t\n\x05Krona\x10\x11\x12\x12\n\x0eNorwegianKrone\x10\x12\
\x12\x0f\n\x0bMexicanPeso\x10\x13\x12\x08\n\x04Rand\x10\x14\x12\x13\n\
\x0fNewTaiwanDollar\x10\x15\x12\x0f\n\x0bDanishKrone\x10\x16\x12\x08\n\
\x04Baht\x10\x17\x12\n\n\x06Forint\x10\x18\x12\n\n\x06Koruna\x10\x19\x12\
\n\n\x06Shekel\x10\x1a\x12\x0f\n\x0bChileanPeso\x10\x1b\x12\x12\n\x0ePhi\
lippinePeso\x10\x1c\x12\n\n\x06Dirham\x10\x1d\x12\x11\n\rColombianPeso\
\x10\x1e\x12\t\n\x05Riyal\x10\x1f\x12\x0b\n\x07Ringgit\x10\x20\x12\x07\n\
\x03Leu\x10!\x12\x11\n\rArgentinePeso\x10\"\x12\x11\n\rUruguayanPeso\x10\
#\x12\x0b\n\x07Percent\x10$b\x06proto3\
\n\x18number_type_option.proto\x1a\x0cformat.proto\"\xa0\x01\n\x10Number\
TypeOption\x12%\n\x06format\x18\x01\x20\x01(\x0e2\r.NumberFormatR\x06for\
mat\x12\x14\n\x05scale\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\x0csignPositive\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04nameb\x06\
proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -0,0 +1,40 @@
syntax = "proto3";
enum NumberFormat {
Number = 0;
USD = 1;
CanadianDollar = 2;
EUR = 4;
Pound = 5;
Yen = 6;
Ruble = 7;
Rupee = 8;
Won = 9;
Yuan = 10;
Real = 11;
Lira = 12;
Rupiah = 13;
Franc = 14;
HongKongDollar = 15;
NewZealandDollar = 16;
Krona = 17;
NorwegianKrone = 18;
MexicanPeso = 19;
Rand = 20;
NewTaiwanDollar = 21;
DanishKrone = 22;
Baht = 23;
Forint = 24;
Koruna = 25;
Shekel = 26;
ChileanPeso = 27;
PhilippinePeso = 28;
Dirham = 29;
ColombianPeso = 30;
Riyal = 31;
Ringgit = 32;
Leu = 33;
ArgentinePeso = 34;
UruguayanPeso = 35;
Percent = 36;
}

View File

@ -1,4 +1,5 @@
syntax = "proto3";
import "format.proto";
message NumberTypeOption {
NumberFormat format = 1;
@ -7,41 +8,3 @@ message NumberTypeOption {
bool sign_positive = 4;
string name = 5;
}
enum NumberFormat {
Number = 0;
USD = 1;
CanadianDollar = 2;
EUR = 4;
Pound = 5;
Yen = 6;
Ruble = 7;
Rupee = 8;
Won = 9;
Yuan = 10;
Real = 11;
Lira = 12;
Rupiah = 13;
Franc = 14;
HongKongDollar = 15;
NewZealandDollar = 16;
Krona = 17;
NorwegianKrone = 18;
MexicanPeso = 19;
Rand = 20;
NewTaiwanDollar = 21;
DanishKrone = 22;
Baht = 23;
Forint = 24;
Koruna = 25;
Shekel = 26;
ChileanPeso = 27;
PhilippinePeso = 28;
Dirham = 29;
ColombianPeso = 30;
Riyal = 31;
Ringgit = 32;
Leu = 33;
ArgentinePeso = 34;
UruguayanPeso = 35;
Percent = 36;
}

View File

@ -1,182 +1,16 @@
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, ProtoBuf_Enum};
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::{
CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
};
use flowy_derive::ProtoBuf_Enum;
use lazy_static::lazy_static;
use rust_decimal::Decimal;
use rusty_money::define_currency_set;
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(Default)]
pub struct NumberTypeOptionBuilder(NumberTypeOption);
impl_into_box_type_option_builder!(NumberTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption);
impl NumberTypeOptionBuilder {
pub fn name(mut self, name: &str) -> Self {
self.0.name = name.to_string();
self
}
pub fn set_format(mut self, format: NumberFormat) -> Self {
self.0.set_format(format);
self
}
pub fn scale(mut self, scale: u32) -> Self {
self.0.scale = scale;
self
}
pub fn positive(mut self, positive: bool) -> Self {
self.0.sign_positive = positive;
self
}
}
impl TypeOptionBuilder for NumberTypeOptionBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn entry(&self) -> &dyn TypeOptionDataEntry {
&self.0
}
}
// Number
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
pub struct NumberTypeOption {
#[pb(index = 1)]
pub format: NumberFormat,
#[pb(index = 2)]
pub scale: u32,
#[pb(index = 3)]
pub symbol: String,
#[pb(index = 4)]
pub sign_positive: bool,
#[pb(index = 5)]
pub name: String,
}
impl_type_option!(NumberTypeOption, FieldType::Number);
impl CellDataOperation<String, String> for NumberTypeOption {
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_date() {
return Ok(DecodedCellData::default());
}
let cell_data = encoded_data.into();
match self.format {
NumberFormat::Number => {
if let Ok(v) = cell_data.parse::<f64>() {
return Ok(DecodedCellData::new(v.to_string()));
}
if let Ok(v) = cell_data.parse::<i64>() {
return Ok(DecodedCellData::new(v.to_string()));
}
Ok(DecodedCellData::default())
}
NumberFormat::Percent => {
let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
Ok(DecodedCellData::new(content))
}
_ => {
let content = self.money_from_str(&cell_data);
Ok(DecodedCellData::new(content))
}
}
}
fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
where
C: Into<CellContentChangeset>,
{
let changeset = changeset.into();
let mut data = changeset.trim().to_string();
if self.format != NumberFormat::Number {
data = self.strip_symbol(data);
if !data.chars().all(char::is_numeric) {
return Err(FlowyError::invalid_data().context("Should only contain numbers"));
}
}
Ok(data)
}
}
impl std::default::Default for NumberTypeOption {
fn default() -> Self {
let format = NumberFormat::default();
let symbol = format.symbol();
NumberTypeOption {
format,
scale: 0,
symbol,
sign_positive: true,
name: "Number".to_string(),
}
}
}
impl NumberTypeOption {
pub fn set_format(&mut self, format: NumberFormat) {
self.format = format;
self.symbol = format.symbol();
}
fn money_from_str(&self, s: &str) -> String {
match Decimal::from_str(s) {
Ok(mut decimal) => {
match decimal.set_scale(self.scale) {
Ok(_) => {}
Err(e) => {
tracing::error!("Set decimal scale failed: {:?}", e);
}
}
decimal.set_sign_positive(self.sign_positive);
let money = rusty_money::Money::from_decimal(decimal, self.format.currency());
money.to_string()
}
Err(_) => String::new(),
}
}
fn strip_symbol<T: ToString>(&self, s: T) -> String {
let mut s = s.to_string();
if !s.chars().all(char::is_numeric) {
s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
}
s
}
pub static ref CURRENCY_SYMBOL: Vec<String> = NumberFormat::iter()
.map(|format| format.symbol())
.collect::<Vec<String>>();
pub static ref STRIP_SYMBOL: Vec<String> = vec![",".to_owned(), ".".to_owned()];
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
@ -609,137 +443,3 @@ impl NumberFormat {
self.currency().symbol.to_string()
}
}
fn make_strip_symbol() -> Vec<String> {
let mut symbols = vec![",".to_owned(), ".".to_owned()];
for format in NumberFormat::iter() {
symbols.push(format.symbol());
}
symbols
}
#[cfg(test)]
mod tests {
use crate::services::field::FieldBuilder;
use crate::services::field::{NumberFormat, NumberTypeOption};
use crate::services::row::CellDataOperation;
use flowy_grid_data_model::entities::{FieldMeta, FieldType};
use strum::IntoEnumIterator;
#[test]
fn number_description_invalid_input_test() {
let type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
assert_equal(&type_option, "", "", &field_type, &field_meta);
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
}
#[test]
fn number_description_test() {
let mut type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "$18,443", &field_type, &field_meta);
assert_equal(&type_option, "", "", &field_type, &field_meta);
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "¥18,443", &field_type, &field_meta);
}
NumberFormat::Yuan => {
assert_equal(&type_option, "18443", "CN¥18,443", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "€18.443", &field_type, &field_meta);
}
_ => {}
}
}
}
#[test]
fn number_description_scale_test() {
let mut type_option = NumberTypeOption {
scale: 1,
..Default::default()
};
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "$1,844.3", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "¥1,844.3", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "€1.844,3", &field_type, &field_meta);
}
_ => {}
}
}
}
#[test]
fn number_description_sign_test() {
let mut type_option = NumberTypeOption {
sign_positive: false,
..Default::default()
};
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "-$18,443", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "-¥18,443", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "-€18.443", &field_type, &field_meta);
}
_ => {}
}
}
}
fn assert_equal(
type_option: &NumberTypeOption,
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()
.to_string(),
expected_str.to_owned()
);
}
}

View File

@ -0,0 +1,6 @@
#![allow(clippy::module_inception)]
mod format;
mod number_type_option;
pub use format::*;
pub use number_type_option::*;

View File

@ -0,0 +1,348 @@
use crate::impl_type_option;
use crate::services::field::type_options::number_type_option::format::*;
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 rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Default)]
pub struct NumberTypeOptionBuilder(NumberTypeOption);
impl_into_box_type_option_builder!(NumberTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption);
impl NumberTypeOptionBuilder {
pub fn name(mut self, name: &str) -> Self {
self.0.name = name.to_string();
self
}
pub fn set_format(mut self, format: NumberFormat) -> Self {
self.0.set_format(format);
self
}
pub fn scale(mut self, scale: u32) -> Self {
self.0.scale = scale;
self
}
pub fn positive(mut self, positive: bool) -> Self {
self.0.sign_positive = positive;
self
}
}
impl TypeOptionBuilder for NumberTypeOptionBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn entry(&self) -> &dyn TypeOptionDataEntry {
&self.0
}
}
// Number
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
pub struct NumberTypeOption {
#[pb(index = 1)]
pub format: NumberFormat,
#[pb(index = 2)]
pub scale: u32,
#[pb(index = 3)]
pub symbol: String,
#[pb(index = 4)]
pub sign_positive: bool,
#[pb(index = 5)]
pub name: String,
}
impl_type_option!(NumberTypeOption, FieldType::Number);
impl CellDataOperation<String, String> for NumberTypeOption {
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_date() {
return Ok(DecodedCellData::default());
}
let cell_data = encoded_data.into();
match self.format {
NumberFormat::Number => {
if let Ok(v) = cell_data.parse::<f64>() {
return Ok(DecodedCellData::new(v.to_string()));
}
if let Ok(v) = cell_data.parse::<i64>() {
return Ok(DecodedCellData::new(v.to_string()));
}
Ok(DecodedCellData::default())
}
NumberFormat::Percent => {
let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
Ok(DecodedCellData::new(content))
}
_ => {
let content = self.number_from_str(&cell_data);
Ok(DecodedCellData::new(content))
}
}
}
fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
where
C: Into<CellContentChangeset>,
{
let changeset = changeset.into();
let mut data = changeset.trim().to_string();
if self.format != NumberFormat::Number {
data = self.strip_symbol(data);
if !data.chars().all(char::is_numeric) {
return Err(FlowyError::invalid_data().context("Should only contain numbers"));
}
}
Ok(data)
}
}
impl std::default::Default for NumberTypeOption {
fn default() -> Self {
let format = NumberFormat::default();
let symbol = format.symbol();
NumberTypeOption {
format,
scale: 0,
symbol,
sign_positive: true,
name: "Number".to_string(),
}
}
}
impl NumberTypeOption {
pub fn set_format(&mut self, format: NumberFormat) {
self.format = format;
self.symbol = format.symbol();
}
fn number_from_str(&self, s: &str) -> String {
match Decimal::from_str(s) {
Ok(mut decimal) => {
match decimal.set_scale(self.scale) {
Ok(_) => {}
Err(e) => {
tracing::error!("Set decimal scale failed: {:?}", e);
}
}
decimal.set_sign_positive(self.sign_positive);
let money = rusty_money::Money::from_decimal(decimal, self.format.currency());
money.to_string()
}
Err(_) => {
let s = self.strip_symbol(s);
if !s.is_empty() && s.chars().all(char::is_numeric) {
self.number_from_str(&s)
} else {
"".to_owned()
}
}
}
}
fn strip_symbol<T: ToString>(&self, s: T) -> String {
let mut s = s.to_string();
for symbol in CURRENCY_SYMBOL.iter() {
if s.starts_with(symbol) {
s = s.strip_prefix(symbol).unwrap_or("").to_string();
break;
}
}
if !s.chars().all(char::is_numeric) {
s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
}
s
}
}
#[cfg(test)]
mod tests {
use crate::services::field::FieldBuilder;
use crate::services::field::{NumberFormat, NumberTypeOption};
use crate::services::row::CellDataOperation;
use flowy_grid_data_model::entities::{FieldMeta, FieldType};
use strum::IntoEnumIterator;
#[test]
fn number_type_option_invalid_input_test() {
let type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
assert_equal(&type_option, "", "", &field_type, &field_meta);
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
}
#[test]
fn number_type_option_format_number_test() {
let mut type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "$18,443", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "¥18,443", &field_type, &field_meta);
}
NumberFormat::Yuan => {
assert_equal(&type_option, "18443", "CN¥18,443", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "€18.443", &field_type, &field_meta);
}
_ => {}
}
}
}
#[test]
fn number_type_option_format_str_test() {
let mut type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
// assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "$18,44", "$1,844", &field_type, &field_meta);
assert_equal(&type_option, "", "", &field_type, &field_meta);
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "¥18,44", "¥1,844", &field_type, &field_meta);
assert_equal(&type_option, "¥1844", "¥1,844", &field_type, &field_meta);
}
NumberFormat::Yuan => {
assert_equal(&type_option, "CN¥18,44", "CN¥1,844", &field_type, &field_meta);
assert_equal(&type_option, "CN¥1844", "CN¥1,844", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "€18.44", "€1.844", &field_type, &field_meta);
assert_equal(&type_option, "€1844", "€1.844", &field_type, &field_meta);
}
_ => {}
}
}
}
#[test]
fn number_type_option_scale_test() {
let mut type_option = NumberTypeOption {
scale: 1,
..Default::default()
};
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "$1,844.3", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "¥1,844.3", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "€1.844,3", &field_type, &field_meta);
}
_ => {}
}
}
}
#[test]
fn number_description_sign_test() {
let mut type_option = NumberTypeOption {
sign_positive: false,
..Default::default()
};
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "-$18,443", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "-¥18,443", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "-€18.443", &field_type, &field_meta);
}
_ => {}
}
}
}
fn assert_equal(
type_option: &NumberTypeOption,
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()
.to_string(),
expected_str.to_owned()
);
}
}