chore: add row test

This commit is contained in:
appflowy 2022-03-14 17:24:25 +08:00
parent d101509b32
commit 196d254278
66 changed files with 4187 additions and 2425 deletions

View File

@ -52,7 +52,7 @@ abstract class PluginBuilder {
PluginType get pluginType;
ViewDataType get dataType => ViewDataType.Block;
ViewDataType get dataType => ViewDataType.TextBlock;
}
abstract class PluginConfig {

View File

@ -50,7 +50,7 @@ class DocumentPluginBuilder extends PluginBuilder {
PluginType get pluginType => DefaultPlugin.quill.type();
@override
ViewDataType get dataType => ViewDataType.Block;
ViewDataType get dataType => ViewDataType.TextBlock;
}
class DocumentPlugin implements Plugin {

View File

@ -956,3 +956,91 @@ class CellMeta extends $pb.GeneratedMessage {
void clearData() => clearField(2);
}
enum CellMetaChangeset_OneOfData {
data,
notSet
}
class CellMetaChangeset extends $pb.GeneratedMessage {
static const $core.Map<$core.int, CellMetaChangeset_OneOfData> _CellMetaChangeset_OneOfDataByTag = {
3 : CellMetaChangeset_OneOfData.data,
0 : CellMetaChangeset_OneOfData.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CellMetaChangeset', createEmptyInstance: create)
..oo(0, [3])
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
..hasRequiredFields = false
;
CellMetaChangeset._() : super();
factory CellMetaChangeset({
$core.String? rowId,
$core.String? fieldId,
$core.String? data,
}) {
final _result = create();
if (rowId != null) {
_result.rowId = rowId;
}
if (fieldId != null) {
_result.fieldId = fieldId;
}
if (data != null) {
_result.data = data;
}
return _result;
}
factory CellMetaChangeset.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory CellMetaChangeset.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
CellMetaChangeset clone() => CellMetaChangeset()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
CellMetaChangeset copyWith(void Function(CellMetaChangeset) updates) => super.copyWith((message) => updates(message as CellMetaChangeset)) as CellMetaChangeset; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static CellMetaChangeset create() => CellMetaChangeset._();
CellMetaChangeset createEmptyInstance() => create();
static $pb.PbList<CellMetaChangeset> createRepeated() => $pb.PbList<CellMetaChangeset>();
@$core.pragma('dart2js:noInline')
static CellMetaChangeset getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CellMetaChangeset>(create);
static CellMetaChangeset? _defaultInstance;
CellMetaChangeset_OneOfData whichOneOfData() => _CellMetaChangeset_OneOfDataByTag[$_whichOneof(0)]!;
void clearOneOfData() => clearField($_whichOneof(0));
@$pb.TagNumber(1)
$core.String get rowId => $_getSZ(0);
@$pb.TagNumber(1)
set rowId($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasRowId() => $_has(0);
@$pb.TagNumber(1)
void clearRowId() => clearField(1);
@$pb.TagNumber(2)
$core.String get fieldId => $_getSZ(1);
@$pb.TagNumber(2)
set fieldId($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasFieldId() => $_has(1);
@$pb.TagNumber(2)
void clearFieldId() => clearField(2);
@$pb.TagNumber(3)
$core.String get data => $_getSZ(2);
@$pb.TagNumber(3)
set data($core.String v) { $_setString(2, v); }
@$pb.TagNumber(3)
$core.bool hasData() => $_has(2);
@$pb.TagNumber(3)
void clearData() => clearField(3);
}

View File

@ -186,3 +186,18 @@ const CellMeta$json = const {
/// Descriptor for `CellMeta`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List cellMetaDescriptor = $convert.base64Decode('CghDZWxsTWV0YRIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBISCgRkYXRhGAIgASgJUgRkYXRh');
@$core.Deprecated('Use cellMetaChangesetDescriptor instead')
const CellMetaChangeset$json = const {
'1': 'CellMetaChangeset',
'2': const [
const {'1': 'row_id', '3': 1, '4': 1, '5': 9, '10': 'rowId'},
const {'1': 'field_id', '3': 2, '4': 1, '5': 9, '10': 'fieldId'},
const {'1': 'data', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'data'},
],
'8': const [
const {'1': 'one_of_data'},
],
};
/// Descriptor for `CellMetaChangeset`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List cellMetaChangesetDescriptor = $convert.base64Decode('ChFDZWxsTWV0YUNoYW5nZXNldBIVCgZyb3dfaWQYASABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAIgASgJUgdmaWVsZElkEhQKBGRhdGEYAyABKAlIAFIEZGF0YUINCgtvbmVfb2ZfZGF0YQ==');

View File

@ -0,0 +1,58 @@
///
// Generated code. Do not modify.
// source: checkbox_description.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;
import 'package:protobuf/protobuf.dart' as $pb;
class CheckboxDescription extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CheckboxDescription', createEmptyInstance: create)
..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSelected')
..hasRequiredFields = false
;
CheckboxDescription._() : super();
factory CheckboxDescription({
$core.bool? isSelected,
}) {
final _result = create();
if (isSelected != null) {
_result.isSelected = isSelected;
}
return _result;
}
factory CheckboxDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory CheckboxDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
CheckboxDescription clone() => CheckboxDescription()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
CheckboxDescription copyWith(void Function(CheckboxDescription) updates) => super.copyWith((message) => updates(message as CheckboxDescription)) as CheckboxDescription; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static CheckboxDescription create() => CheckboxDescription._();
CheckboxDescription createEmptyInstance() => create();
static $pb.PbList<CheckboxDescription> createRepeated() => $pb.PbList<CheckboxDescription>();
@$core.pragma('dart2js:noInline')
static CheckboxDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CheckboxDescription>(create);
static CheckboxDescription? _defaultInstance;
@$pb.TagNumber(1)
$core.bool get isSelected => $_getBF(0);
@$pb.TagNumber(1)
set isSelected($core.bool v) { $_setBool(0, v); }
@$pb.TagNumber(1)
$core.bool hasIsSelected() => $_has(0);
@$pb.TagNumber(1)
void clearIsSelected() => clearField(1);
}

View File

@ -0,0 +1,7 @@
///
// Generated code. Do not modify.
// source: checkbox_description.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

View File

@ -0,0 +1,20 @@
///
// Generated code. Do not modify.
// source: checkbox_description.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 checkboxDescriptionDescriptor instead')
const CheckboxDescription$json = const {
'1': 'CheckboxDescription',
'2': const [
const {'1': 'is_selected', '3': 1, '4': 1, '5': 8, '10': 'isSelected'},
],
};
/// Descriptor for `CheckboxDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List checkboxDescriptionDescriptor = $convert.base64Decode('ChNDaGVja2JveERlc2NyaXB0aW9uEh8KC2lzX3NlbGVjdGVkGAEgASgIUgppc1NlbGVjdGVk');

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: checkbox_description.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 'checkbox_description.pb.dart';

View File

@ -0,0 +1,76 @@
///
// Generated code. Do not modify.
// source: date_description.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;
import 'package:protobuf/protobuf.dart' as $pb;
import 'date_description.pbenum.dart';
export 'date_description.pbenum.dart';
class DateDescription extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DateDescription', createEmptyInstance: create)
..e<DateFormat>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dateFormat', $pb.PbFieldType.OE, defaultOrMaker: DateFormat.Local, valueOf: DateFormat.valueOf, enumValues: DateFormat.values)
..e<TimeFormat>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'timeFormat', $pb.PbFieldType.OE, defaultOrMaker: TimeFormat.TwelveHour, valueOf: TimeFormat.valueOf, enumValues: TimeFormat.values)
..hasRequiredFields = false
;
DateDescription._() : super();
factory DateDescription({
DateFormat? dateFormat,
TimeFormat? timeFormat,
}) {
final _result = create();
if (dateFormat != null) {
_result.dateFormat = dateFormat;
}
if (timeFormat != null) {
_result.timeFormat = timeFormat;
}
return _result;
}
factory DateDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory DateDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
DateDescription clone() => DateDescription()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
DateDescription copyWith(void Function(DateDescription) updates) => super.copyWith((message) => updates(message as DateDescription)) as DateDescription; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static DateDescription create() => DateDescription._();
DateDescription createEmptyInstance() => create();
static $pb.PbList<DateDescription> createRepeated() => $pb.PbList<DateDescription>();
@$core.pragma('dart2js:noInline')
static DateDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DateDescription>(create);
static DateDescription? _defaultInstance;
@$pb.TagNumber(1)
DateFormat get dateFormat => $_getN(0);
@$pb.TagNumber(1)
set dateFormat(DateFormat v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasDateFormat() => $_has(0);
@$pb.TagNumber(1)
void clearDateFormat() => clearField(1);
@$pb.TagNumber(2)
TimeFormat get timeFormat => $_getN(1);
@$pb.TagNumber(2)
set timeFormat(TimeFormat v) { setField(2, v); }
@$pb.TagNumber(2)
$core.bool hasTimeFormat() => $_has(1);
@$pb.TagNumber(2)
void clearTimeFormat() => clearField(2);
}

View File

@ -0,0 +1,45 @@
///
// Generated code. Do not modify.
// source: date_description.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 DateFormat extends $pb.ProtobufEnum {
static const DateFormat Local = DateFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local');
static const DateFormat US = DateFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'US');
static const DateFormat ISO = DateFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ISO');
static const DateFormat Friendly = DateFormat._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Friendly');
static const $core.List<DateFormat> values = <DateFormat> [
Local,
US,
ISO,
Friendly,
];
static final $core.Map<$core.int, DateFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
static DateFormat? valueOf($core.int value) => _byValue[value];
const DateFormat._($core.int v, $core.String n) : super(v, n);
}
class TimeFormat extends $pb.ProtobufEnum {
static const TimeFormat TwelveHour = TimeFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwelveHour');
static const TimeFormat TwentyFourHour = TimeFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TwentyFourHour');
static const $core.List<TimeFormat> values = <TimeFormat> [
TwelveHour,
TwentyFourHour,
];
static final $core.Map<$core.int, TimeFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
static TimeFormat? valueOf($core.int value) => _byValue[value];
const TimeFormat._($core.int v, $core.String n) : super(v, n);
}

View File

@ -0,0 +1,45 @@
///
// Generated code. Do not modify.
// source: date_description.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 dateFormatDescriptor instead')
const DateFormat$json = const {
'1': 'DateFormat',
'2': const [
const {'1': 'Local', '2': 0},
const {'1': 'US', '2': 1},
const {'1': 'ISO', '2': 2},
const {'1': 'Friendly', '2': 3},
],
};
/// Descriptor for `DateFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List dateFormatDescriptor = $convert.base64Decode('CgpEYXRlRm9ybWF0EgkKBUxvY2FsEAASBgoCVVMQARIHCgNJU08QAhIMCghGcmllbmRseRAD');
@$core.Deprecated('Use timeFormatDescriptor instead')
const TimeFormat$json = const {
'1': 'TimeFormat',
'2': const [
const {'1': 'TwelveHour', '2': 0},
const {'1': 'TwentyFourHour', '2': 1},
],
};
/// Descriptor for `TimeFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List timeFormatDescriptor = $convert.base64Decode('CgpUaW1lRm9ybWF0Eg4KClR3ZWx2ZUhvdXIQABISCg5Ud2VudHlGb3VySG91chAB');
@$core.Deprecated('Use dateDescriptionDescriptor instead')
const DateDescription$json = const {
'1': 'DateDescription',
'2': const [
const {'1': 'date_format', '3': 1, '4': 1, '5': 14, '6': '.DateFormat', '10': 'dateFormat'},
const {'1': 'time_format', '3': 2, '4': 1, '5': 14, '6': '.TimeFormat', '10': 'timeFormat'},
],
};
/// Descriptor for `DateDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List dateDescriptionDescriptor = $convert.base64Decode('Cg9EYXRlRGVzY3JpcHRpb24SLAoLZGF0ZV9mb3JtYXQYASABKA4yCy5EYXRlRm9ybWF0UgpkYXRlRm9ybWF0EiwKC3RpbWVfZm9ybWF0GAIgASgOMgsuVGltZUZvcm1hdFIKdGltZUZvcm1hdA==');

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: date_description.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 'date_description.pb.dart';

View File

@ -0,0 +1,118 @@
///
// Generated code. Do not modify.
// source: number_description.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;
import 'package:protobuf/protobuf.dart' as $pb;
import 'number_description.pbenum.dart';
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)
..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')
..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
..hasRequiredFields = false
;
NumberDescription._() : super();
factory NumberDescription({
MoneySymbol? money,
$core.int? scale,
$core.String? symbol,
$core.bool? signPositive,
$core.String? name,
}) {
final _result = create();
if (money != null) {
_result.money = money;
}
if (scale != null) {
_result.scale = scale;
}
if (symbol != null) {
_result.symbol = symbol;
}
if (signPositive != null) {
_result.signPositive = signPositive;
}
if (name != null) {
_result.name = name;
}
return _result;
}
factory NumberDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory NumberDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
NumberDescription clone() => NumberDescription()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
NumberDescription copyWith(void Function(NumberDescription) updates) => super.copyWith((message) => updates(message as NumberDescription)) as NumberDescription; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static NumberDescription create() => NumberDescription._();
NumberDescription createEmptyInstance() => create();
static $pb.PbList<NumberDescription> createRepeated() => $pb.PbList<NumberDescription>();
@$core.pragma('dart2js:noInline')
static NumberDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<NumberDescription>(create);
static NumberDescription? _defaultInstance;
@$pb.TagNumber(1)
MoneySymbol get money => $_getN(0);
@$pb.TagNumber(1)
set money(MoneySymbol v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasMoney() => $_has(0);
@$pb.TagNumber(1)
void clearMoney() => clearField(1);
@$pb.TagNumber(2)
$core.int get scale => $_getIZ(1);
@$pb.TagNumber(2)
set scale($core.int v) { $_setUnsignedInt32(1, v); }
@$pb.TagNumber(2)
$core.bool hasScale() => $_has(1);
@$pb.TagNumber(2)
void clearScale() => clearField(2);
@$pb.TagNumber(3)
$core.String get symbol => $_getSZ(2);
@$pb.TagNumber(3)
set symbol($core.String v) { $_setString(2, v); }
@$pb.TagNumber(3)
$core.bool hasSymbol() => $_has(2);
@$pb.TagNumber(3)
void clearSymbol() => clearField(3);
@$pb.TagNumber(4)
$core.bool get signPositive => $_getBF(3);
@$pb.TagNumber(4)
set signPositive($core.bool v) { $_setBool(3, v); }
@$pb.TagNumber(4)
$core.bool hasSignPositive() => $_has(3);
@$pb.TagNumber(4)
void clearSignPositive() => clearField(4);
@$pb.TagNumber(5)
$core.String get name => $_getSZ(4);
@$pb.TagNumber(5)
set name($core.String v) { $_setString(4, v); }
@$pb.TagNumber(5)
$core.bool hasName() => $_has(4);
@$pb.TagNumber(5)
void clearName() => clearField(5);
}

View File

@ -0,0 +1,28 @@
///
// Generated code. Do not modify.
// source: number_description.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 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');
static const $core.List<MoneySymbol> values = <MoneySymbol> [
CNY,
EUR,
USD,
];
static final $core.Map<$core.int, MoneySymbol> _byValue = $pb.ProtobufEnum.initByValue(values);
static MoneySymbol? valueOf($core.int value) => _byValue[value];
const MoneySymbol._($core.int v, $core.String n) : super(v, n);
}

View File

@ -0,0 +1,36 @@
///
// Generated code. Do not modify.
// source: number_description.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 moneySymbolDescriptor instead')
const MoneySymbol$json = const {
'1': 'MoneySymbol',
'2': const [
const {'1': 'CNY', '2': 0},
const {'1': 'EUR', '2': 1},
const {'1': 'USD', '2': 2},
],
};
/// Descriptor for `MoneySymbol`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List moneySymbolDescriptor = $convert.base64Decode('CgtNb25leVN5bWJvbBIHCgNDTlkQABIHCgNFVVIQARIHCgNVU0QQAg==');
@$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': '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'},
const {'1': 'name', '3': 5, '4': 1, '5': 9, '10': 'name'},
],
};
/// Descriptor for `NumberDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List numberDescriptionDescriptor = $convert.base64Decode('ChFOdW1iZXJEZXNjcmlwdGlvbhIiCgVtb25leRgBIAEoDjIMLk1vbmV5U3ltYm9sUgVtb25leRIUCgVzY2FsZRgCIAEoDVIFc2NhbGUSFgoGc3ltYm9sGAMgASgJUgZzeW1ib2wSIwoNc2lnbl9wb3NpdGl2ZRgEIAEoCFIMc2lnblBvc2l0aXZlEhIKBG5hbWUYBSABKAlSBG5hbWU=');

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: number_description.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 'number_description.pb.dart';

View File

@ -1,3 +1,7 @@
// Auto-generated, do not edit
export './type_options.pb.dart';
export './date_description.pb.dart';
export './text_description.pb.dart';
export './checkbox_description.pb.dart';
export './selection_description.pb.dart';
export './event_map.pb.dart';
export './number_description.pb.dart';

View File

@ -0,0 +1,196 @@
///
// Generated code. Do not modify.
// source: selection_description.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;
import 'package:protobuf/protobuf.dart' as $pb;
class SingleSelectDescription extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SingleSelectDescription', createEmptyInstance: create)
..pc<SelectOption>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create)
..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor')
..hasRequiredFields = false
;
SingleSelectDescription._() : super();
factory SingleSelectDescription({
$core.Iterable<SelectOption>? options,
$core.bool? disableColor,
}) {
final _result = create();
if (options != null) {
_result.options.addAll(options);
}
if (disableColor != null) {
_result.disableColor = disableColor;
}
return _result;
}
factory SingleSelectDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory SingleSelectDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
SingleSelectDescription clone() => SingleSelectDescription()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
SingleSelectDescription copyWith(void Function(SingleSelectDescription) updates) => super.copyWith((message) => updates(message as SingleSelectDescription)) as SingleSelectDescription; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static SingleSelectDescription create() => SingleSelectDescription._();
SingleSelectDescription createEmptyInstance() => create();
static $pb.PbList<SingleSelectDescription> createRepeated() => $pb.PbList<SingleSelectDescription>();
@$core.pragma('dart2js:noInline')
static SingleSelectDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SingleSelectDescription>(create);
static SingleSelectDescription? _defaultInstance;
@$pb.TagNumber(1)
$core.List<SelectOption> get options => $_getList(0);
@$pb.TagNumber(2)
$core.bool get disableColor => $_getBF(1);
@$pb.TagNumber(2)
set disableColor($core.bool v) { $_setBool(1, v); }
@$pb.TagNumber(2)
$core.bool hasDisableColor() => $_has(1);
@$pb.TagNumber(2)
void clearDisableColor() => clearField(2);
}
class MultiSelectDescription extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'MultiSelectDescription', createEmptyInstance: create)
..pc<SelectOption>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'options', $pb.PbFieldType.PM, subBuilder: SelectOption.create)
..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'disableColor')
..hasRequiredFields = false
;
MultiSelectDescription._() : super();
factory MultiSelectDescription({
$core.Iterable<SelectOption>? options,
$core.bool? disableColor,
}) {
final _result = create();
if (options != null) {
_result.options.addAll(options);
}
if (disableColor != null) {
_result.disableColor = disableColor;
}
return _result;
}
factory MultiSelectDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory MultiSelectDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
MultiSelectDescription clone() => MultiSelectDescription()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
MultiSelectDescription copyWith(void Function(MultiSelectDescription) updates) => super.copyWith((message) => updates(message as MultiSelectDescription)) as MultiSelectDescription; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static MultiSelectDescription create() => MultiSelectDescription._();
MultiSelectDescription createEmptyInstance() => create();
static $pb.PbList<MultiSelectDescription> createRepeated() => $pb.PbList<MultiSelectDescription>();
@$core.pragma('dart2js:noInline')
static MultiSelectDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MultiSelectDescription>(create);
static MultiSelectDescription? _defaultInstance;
@$pb.TagNumber(1)
$core.List<SelectOption> get options => $_getList(0);
@$pb.TagNumber(2)
$core.bool get disableColor => $_getBF(1);
@$pb.TagNumber(2)
set disableColor($core.bool v) { $_setBool(1, v); }
@$pb.TagNumber(2)
$core.bool hasDisableColor() => $_has(1);
@$pb.TagNumber(2)
void clearDisableColor() => clearField(2);
}
class SelectOption extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SelectOption', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'color')
..hasRequiredFields = false
;
SelectOption._() : super();
factory SelectOption({
$core.String? id,
$core.String? name,
$core.String? color,
}) {
final _result = create();
if (id != null) {
_result.id = id;
}
if (name != null) {
_result.name = name;
}
if (color != null) {
_result.color = color;
}
return _result;
}
factory SelectOption.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory SelectOption.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
SelectOption clone() => SelectOption()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
SelectOption copyWith(void Function(SelectOption) updates) => super.copyWith((message) => updates(message as SelectOption)) as SelectOption; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static SelectOption create() => SelectOption._();
SelectOption createEmptyInstance() => create();
static $pb.PbList<SelectOption> createRepeated() => $pb.PbList<SelectOption>();
@$core.pragma('dart2js:noInline')
static SelectOption getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SelectOption>(create);
static SelectOption? _defaultInstance;
@$pb.TagNumber(1)
$core.String get id => $_getSZ(0);
@$pb.TagNumber(1)
set id($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasId() => $_has(0);
@$pb.TagNumber(1)
void clearId() => clearField(1);
@$pb.TagNumber(2)
$core.String get name => $_getSZ(1);
@$pb.TagNumber(2)
set name($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasName() => $_has(1);
@$pb.TagNumber(2)
void clearName() => clearField(2);
@$pb.TagNumber(3)
$core.String get color => $_getSZ(2);
@$pb.TagNumber(3)
set color($core.String v) { $_setString(2, v); }
@$pb.TagNumber(3)
$core.bool hasColor() => $_has(2);
@$pb.TagNumber(3)
void clearColor() => clearField(3);
}

View File

@ -0,0 +1,7 @@
///
// Generated code. Do not modify.
// source: selection_description.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

View File

@ -0,0 +1,44 @@
///
// Generated code. Do not modify.
// source: selection_description.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 singleSelectDescriptionDescriptor instead')
const SingleSelectDescription$json = const {
'1': 'SingleSelectDescription',
'2': const [
const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'},
const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'},
],
};
/// Descriptor for `SingleSelectDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List singleSelectDescriptionDescriptor = $convert.base64Decode('ChdTaW5nbGVTZWxlY3REZXNjcmlwdGlvbhInCgdvcHRpb25zGAEgAygLMg0uU2VsZWN0T3B0aW9uUgdvcHRpb25zEiMKDWRpc2FibGVfY29sb3IYAiABKAhSDGRpc2FibGVDb2xvcg==');
@$core.Deprecated('Use multiSelectDescriptionDescriptor instead')
const MultiSelectDescription$json = const {
'1': 'MultiSelectDescription',
'2': const [
const {'1': 'options', '3': 1, '4': 3, '5': 11, '6': '.SelectOption', '10': 'options'},
const {'1': 'disable_color', '3': 2, '4': 1, '5': 8, '10': 'disableColor'},
],
};
/// Descriptor for `MultiSelectDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List multiSelectDescriptionDescriptor = $convert.base64Decode('ChZNdWx0aVNlbGVjdERlc2NyaXB0aW9uEicKB29wdGlvbnMYASADKAsyDS5TZWxlY3RPcHRpb25SB29wdGlvbnMSIwoNZGlzYWJsZV9jb2xvchgCIAEoCFIMZGlzYWJsZUNvbG9y');
@$core.Deprecated('Use selectOptionDescriptor instead')
const SelectOption$json = const {
'1': 'SelectOption',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
const {'1': 'color', '3': 3, '4': 1, '5': 9, '10': 'color'},
],
};
/// Descriptor for `SelectOption`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List selectOptionDescriptor = $convert.base64Decode('CgxTZWxlY3RPcHRpb24SDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSFAoFY29sb3IYAyABKAlSBWNvbG9y');

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: selection_description.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 'selection_description.pb.dart';

View File

@ -0,0 +1,58 @@
///
// Generated code. Do not modify.
// source: text_description.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;
import 'package:protobuf/protobuf.dart' as $pb;
class RichTextDescription extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RichTextDescription', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format')
..hasRequiredFields = false
;
RichTextDescription._() : super();
factory RichTextDescription({
$core.String? format,
}) {
final _result = create();
if (format != null) {
_result.format = format;
}
return _result;
}
factory RichTextDescription.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory RichTextDescription.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
RichTextDescription clone() => RichTextDescription()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
RichTextDescription copyWith(void Function(RichTextDescription) updates) => super.copyWith((message) => updates(message as RichTextDescription)) as RichTextDescription; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static RichTextDescription create() => RichTextDescription._();
RichTextDescription createEmptyInstance() => create();
static $pb.PbList<RichTextDescription> createRepeated() => $pb.PbList<RichTextDescription>();
@$core.pragma('dart2js:noInline')
static RichTextDescription getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RichTextDescription>(create);
static RichTextDescription? _defaultInstance;
@$pb.TagNumber(1)
$core.String get format => $_getSZ(0);
@$pb.TagNumber(1)
set format($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasFormat() => $_has(0);
@$pb.TagNumber(1)
void clearFormat() => clearField(1);
}

View File

@ -0,0 +1,7 @@
///
// Generated code. Do not modify.
// source: text_description.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

View File

@ -0,0 +1,20 @@
///
// Generated code. Do not modify.
// source: text_description.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 richTextDescriptionDescriptor instead')
const RichTextDescription$json = const {
'1': 'RichTextDescription',
'2': const [
const {'1': 'format', '3': 1, '4': 1, '5': 9, '10': 'format'},
],
};
/// Descriptor for `RichTextDescription`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List richTextDescriptionDescriptor = $convert.base64Decode('ChNSaWNoVGV4dERlc2NyaXB0aW9uEhYKBmZvcm1hdBgBIAEoCVIGZm9ybWF0');

View File

@ -0,0 +1,9 @@
///
// Generated code. Do not modify.
// source: text_description.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 'text_description.pb.dart';

View File

@ -1,3 +1,3 @@
proto_crates = ["src/event_map.rs", "src/services/field/type_options.rs"]
proto_crates = ["src/event_map.rs", "src/services/cell/description"]
event_files = ["src/event_map.rs"]

View File

@ -24,7 +24,7 @@ pub(crate) async fn get_rows_handler(
) -> DataResult<RepeatedRow, FlowyError> {
let payload: QueryRowPayload = data.into_inner();
let editor = manager.get_grid_editor(&payload.grid_id)?;
let repeated_row: RepeatedRow = editor.get_rows(payload.row_orders).await?.into();
let repeated_row: RepeatedRow = editor.get_rows(Some(payload.row_orders)).await?.into();
data_result(repeated_row)
}

View File

@ -0,0 +1,193 @@
// 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 `checkbox_description.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(PartialEq,Clone,Default)]
pub struct CheckboxDescription {
// message fields
pub is_selected: bool,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a CheckboxDescription {
fn default() -> &'a CheckboxDescription {
<CheckboxDescription as ::protobuf::Message>::default_instance()
}
}
impl CheckboxDescription {
pub fn new() -> CheckboxDescription {
::std::default::Default::default()
}
// bool is_selected = 1;
pub fn get_is_selected(&self) -> bool {
self.is_selected
}
pub fn clear_is_selected(&mut self) {
self.is_selected = false;
}
// Param is passed by value, moved
pub fn set_is_selected(&mut self, v: bool) {
self.is_selected = v;
}
}
impl ::protobuf::Message for CheckboxDescription {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_bool()?;
self.is_selected = tmp;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.is_selected != false {
my_size += 2;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.is_selected != false {
os.write_bool(1, self.is_selected)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> CheckboxDescription {
CheckboxDescription::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
"is_selected",
|m: &CheckboxDescription| { &m.is_selected },
|m: &mut CheckboxDescription| { &mut m.is_selected },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<CheckboxDescription>(
"CheckboxDescription",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static CheckboxDescription {
static instance: ::protobuf::rt::LazyV2<CheckboxDescription> = ::protobuf::rt::LazyV2::INIT;
instance.get(CheckboxDescription::new)
}
}
impl ::protobuf::Clear for CheckboxDescription {
fn clear(&mut self) {
self.is_selected = false;
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for CheckboxDescription {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for CheckboxDescription {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x1acheckbox_description.proto\"6\n\x13CheckboxDescription\x12\x1f\n\
\x0bis_selected\x18\x01\x20\x01(\x08R\nisSelectedb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -0,0 +1,330 @@
// 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 `date_description.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(PartialEq,Clone,Default)]
pub struct DateDescription {
// message fields
pub date_format: DateFormat,
pub time_format: TimeFormat,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a DateDescription {
fn default() -> &'a DateDescription {
<DateDescription as ::protobuf::Message>::default_instance()
}
}
impl DateDescription {
pub fn new() -> DateDescription {
::std::default::Default::default()
}
// .DateFormat date_format = 1;
pub fn get_date_format(&self) -> DateFormat {
self.date_format
}
pub fn clear_date_format(&mut self) {
self.date_format = DateFormat::Local;
}
// Param is passed by value, moved
pub fn set_date_format(&mut self, v: DateFormat) {
self.date_format = v;
}
// .TimeFormat time_format = 2;
pub fn get_time_format(&self) -> TimeFormat {
self.time_format
}
pub fn clear_time_format(&mut self) {
self.time_format = TimeFormat::TwelveHour;
}
// Param is passed by value, moved
pub fn set_time_format(&mut self, v: TimeFormat) {
self.time_format = v;
}
}
impl ::protobuf::Message for DateDescription {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.date_format, 1, &mut self.unknown_fields)?
},
2 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.time_format, 2, &mut self.unknown_fields)?
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.date_format != DateFormat::Local {
my_size += ::protobuf::rt::enum_size(1, self.date_format);
}
if self.time_format != TimeFormat::TwelveHour {
my_size += ::protobuf::rt::enum_size(2, self.time_format);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.date_format != DateFormat::Local {
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.date_format))?;
}
if self.time_format != TimeFormat::TwelveHour {
os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.time_format))?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> DateDescription {
DateDescription::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<DateFormat>>(
"date_format",
|m: &DateDescription| { &m.date_format },
|m: &mut DateDescription| { &mut m.date_format },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<TimeFormat>>(
"time_format",
|m: &DateDescription| { &m.time_format },
|m: &mut DateDescription| { &mut m.time_format },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<DateDescription>(
"DateDescription",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static DateDescription {
static instance: ::protobuf::rt::LazyV2<DateDescription> = ::protobuf::rt::LazyV2::INIT;
instance.get(DateDescription::new)
}
}
impl ::protobuf::Clear for DateDescription {
fn clear(&mut self) {
self.date_format = DateFormat::Local;
self.time_format = TimeFormat::TwelveHour;
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for DateDescription {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for DateDescription {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum DateFormat {
Local = 0,
US = 1,
ISO = 2,
Friendly = 3,
}
impl ::protobuf::ProtobufEnum for DateFormat {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<DateFormat> {
match value {
0 => ::std::option::Option::Some(DateFormat::Local),
1 => ::std::option::Option::Some(DateFormat::US),
2 => ::std::option::Option::Some(DateFormat::ISO),
3 => ::std::option::Option::Some(DateFormat::Friendly),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [DateFormat] = &[
DateFormat::Local,
DateFormat::US,
DateFormat::ISO,
DateFormat::Friendly,
];
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::<DateFormat>("DateFormat", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for DateFormat {
}
impl ::std::default::Default for DateFormat {
fn default() -> Self {
DateFormat::Local
}
}
impl ::protobuf::reflect::ProtobufValue for DateFormat {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum TimeFormat {
TwelveHour = 0,
TwentyFourHour = 1,
}
impl ::protobuf::ProtobufEnum for TimeFormat {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<TimeFormat> {
match value {
0 => ::std::option::Option::Some(TimeFormat::TwelveHour),
1 => ::std::option::Option::Some(TimeFormat::TwentyFourHour),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [TimeFormat] = &[
TimeFormat::TwelveHour,
TimeFormat::TwentyFourHour,
];
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::<TimeFormat>("TimeFormat", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for TimeFormat {
}
impl ::std::default::Default for TimeFormat {
fn default() -> Self {
TimeFormat::TwelveHour
}
}
impl ::protobuf::reflect::ProtobufValue for TimeFormat {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x16date_description.proto\"m\n\x0fDateDescription\x12,\n\x0bdate_form\
at\x18\x01\x20\x01(\x0e2\x0b.DateFormatR\ndateFormat\x12,\n\x0btime_form\
at\x18\x02\x20\x01(\x0e2\x0b.TimeFormatR\ntimeFormat*6\n\nDateFormat\x12\
\t\n\x05Local\x10\0\x12\x06\n\x02US\x10\x01\x12\x07\n\x03ISO\x10\x02\x12\
\x0c\n\x08Friendly\x10\x03*0\n\nTimeFormat\x12\x0e\n\nTwelveHour\x10\0\
\x12\x12\n\x0eTwentyFourHour\x10\x01b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -1,8 +1,20 @@
#![cfg_attr(rustfmt, rustfmt::skip)]
// Auto-generated, do not edit
mod type_options;
pub use type_options::*;
mod date_description;
pub use date_description::*;
mod text_description;
pub use text_description::*;
mod checkbox_description;
pub use checkbox_description::*;
mod selection_description;
pub use selection_description::*;
mod event_map;
pub use event_map::*;
mod number_description;
pub use number_description::*;

View File

@ -0,0 +1,401 @@
// 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 `number_description.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(PartialEq,Clone,Default)]
pub struct NumberDescription {
// message fields
pub money: MoneySymbol,
pub scale: u32,
pub symbol: ::std::string::String,
pub sign_positive: bool,
pub name: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a NumberDescription {
fn default() -> &'a NumberDescription {
<NumberDescription as ::protobuf::Message>::default_instance()
}
}
impl NumberDescription {
pub fn new() -> NumberDescription {
::std::default::Default::default()
}
// .MoneySymbol money = 1;
pub fn get_money(&self) -> MoneySymbol {
self.money
}
pub fn clear_money(&mut self) {
self.money = MoneySymbol::CNY;
}
// Param is passed by value, moved
pub fn set_money(&mut self, v: MoneySymbol) {
self.money = v;
}
// uint32 scale = 2;
pub fn get_scale(&self) -> u32 {
self.scale
}
pub fn clear_scale(&mut self) {
self.scale = 0;
}
// Param is passed by value, moved
pub fn set_scale(&mut self, v: u32) {
self.scale = v;
}
// string symbol = 3;
pub fn get_symbol(&self) -> &str {
&self.symbol
}
pub fn clear_symbol(&mut self) {
self.symbol.clear();
}
// Param is passed by value, moved
pub fn set_symbol(&mut self, v: ::std::string::String) {
self.symbol = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_symbol(&mut self) -> &mut ::std::string::String {
&mut self.symbol
}
// Take field
pub fn take_symbol(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.symbol, ::std::string::String::new())
}
// bool sign_positive = 4;
pub fn get_sign_positive(&self) -> bool {
self.sign_positive
}
pub fn clear_sign_positive(&mut self) {
self.sign_positive = false;
}
// Param is passed by value, moved
pub fn set_sign_positive(&mut self, v: bool) {
self.sign_positive = v;
}
// string name = 5;
pub fn get_name(&self) -> &str {
&self.name
}
pub fn clear_name(&mut self) {
self.name.clear();
}
// Param is passed by value, moved
pub fn set_name(&mut self, v: ::std::string::String) {
self.name = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_name(&mut self) -> &mut ::std::string::String {
&mut self.name
}
// Take field
pub fn take_name(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.name, ::std::string::String::new())
}
}
impl ::protobuf::Message for NumberDescription {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.money, 1, &mut self.unknown_fields)?
},
2 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_uint32()?;
self.scale = tmp;
},
3 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.symbol)?;
},
4 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_bool()?;
self.sign_positive = tmp;
},
5 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.money != MoneySymbol::CNY {
my_size += ::protobuf::rt::enum_size(1, self.money);
}
if self.scale != 0 {
my_size += ::protobuf::rt::value_size(2, self.scale, ::protobuf::wire_format::WireTypeVarint);
}
if !self.symbol.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.symbol);
}
if self.sign_positive != false {
my_size += 2;
}
if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(5, &self.name);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.money != MoneySymbol::CNY {
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.money))?;
}
if self.scale != 0 {
os.write_uint32(2, self.scale)?;
}
if !self.symbol.is_empty() {
os.write_string(3, &self.symbol)?;
}
if self.sign_positive != false {
os.write_bool(4, self.sign_positive)?;
}
if !self.name.is_empty() {
os.write_string(5, &self.name)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> NumberDescription {
NumberDescription::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<MoneySymbol>>(
"money",
|m: &NumberDescription| { &m.money },
|m: &mut NumberDescription| { &mut m.money },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>(
"scale",
|m: &NumberDescription| { &m.scale },
|m: &mut NumberDescription| { &mut m.scale },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"symbol",
|m: &NumberDescription| { &m.symbol },
|m: &mut NumberDescription| { &mut m.symbol },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
"sign_positive",
|m: &NumberDescription| { &m.sign_positive },
|m: &mut NumberDescription| { &mut m.sign_positive },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"name",
|m: &NumberDescription| { &m.name },
|m: &mut NumberDescription| { &mut m.name },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<NumberDescription>(
"NumberDescription",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static NumberDescription {
static instance: ::protobuf::rt::LazyV2<NumberDescription> = ::protobuf::rt::LazyV2::INIT;
instance.get(NumberDescription::new)
}
}
impl ::protobuf::Clear for NumberDescription {
fn clear(&mut self) {
self.money = MoneySymbol::CNY;
self.scale = 0;
self.symbol.clear();
self.sign_positive = false;
self.name.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for NumberDescription {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for NumberDescription {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum MoneySymbol {
CNY = 0,
EUR = 1,
USD = 2,
}
impl ::protobuf::ProtobufEnum for MoneySymbol {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<MoneySymbol> {
match value {
0 => ::std::option::Option::Some(MoneySymbol::CNY),
1 => ::std::option::Option::Some(MoneySymbol::EUR),
2 => ::std::option::Option::Some(MoneySymbol::USD),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [MoneySymbol] = &[
MoneySymbol::CNY,
MoneySymbol::EUR,
MoneySymbol::USD,
];
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::<MoneySymbol>("MoneySymbol", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for MoneySymbol {
}
impl ::std::default::Default for MoneySymbol {
fn default() -> Self {
MoneySymbol::CNY
}
}
impl ::protobuf::reflect::ProtobufValue for MoneySymbol {
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\
";
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

@ -0,0 +1,692 @@
// 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 `selection_description.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(PartialEq,Clone,Default)]
pub struct SingleSelectDescription {
// message fields
pub options: ::protobuf::RepeatedField<SelectOption>,
pub disable_color: bool,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a SingleSelectDescription {
fn default() -> &'a SingleSelectDescription {
<SingleSelectDescription as ::protobuf::Message>::default_instance()
}
}
impl SingleSelectDescription {
pub fn new() -> SingleSelectDescription {
::std::default::Default::default()
}
// repeated .SelectOption options = 1;
pub fn get_options(&self) -> &[SelectOption] {
&self.options
}
pub fn clear_options(&mut self) {
self.options.clear();
}
// Param is passed by value, moved
pub fn set_options(&mut self, v: ::protobuf::RepeatedField<SelectOption>) {
self.options = v;
}
// Mutable pointer to the field.
pub fn mut_options(&mut self) -> &mut ::protobuf::RepeatedField<SelectOption> {
&mut self.options
}
// Take field
pub fn take_options(&mut self) -> ::protobuf::RepeatedField<SelectOption> {
::std::mem::replace(&mut self.options, ::protobuf::RepeatedField::new())
}
// bool disable_color = 2;
pub fn get_disable_color(&self) -> bool {
self.disable_color
}
pub fn clear_disable_color(&mut self) {
self.disable_color = false;
}
// Param is passed by value, moved
pub fn set_disable_color(&mut self, v: bool) {
self.disable_color = v;
}
}
impl ::protobuf::Message for SingleSelectDescription {
fn is_initialized(&self) -> bool {
for v in &self.options {
if !v.is_initialized() {
return false;
}
};
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.options)?;
},
2 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_bool()?;
self.disable_color = tmp;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
for value in &self.options {
let len = value.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
};
if self.disable_color != false {
my_size += 2;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
for v in &self.options {
os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
};
if self.disable_color != false {
os.write_bool(2, self.disable_color)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> SingleSelectDescription {
SingleSelectDescription::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<SelectOption>>(
"options",
|m: &SingleSelectDescription| { &m.options },
|m: &mut SingleSelectDescription| { &mut m.options },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
"disable_color",
|m: &SingleSelectDescription| { &m.disable_color },
|m: &mut SingleSelectDescription| { &mut m.disable_color },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<SingleSelectDescription>(
"SingleSelectDescription",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static SingleSelectDescription {
static instance: ::protobuf::rt::LazyV2<SingleSelectDescription> = ::protobuf::rt::LazyV2::INIT;
instance.get(SingleSelectDescription::new)
}
}
impl ::protobuf::Clear for SingleSelectDescription {
fn clear(&mut self) {
self.options.clear();
self.disable_color = false;
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for SingleSelectDescription {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SingleSelectDescription {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct MultiSelectDescription {
// message fields
pub options: ::protobuf::RepeatedField<SelectOption>,
pub disable_color: bool,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a MultiSelectDescription {
fn default() -> &'a MultiSelectDescription {
<MultiSelectDescription as ::protobuf::Message>::default_instance()
}
}
impl MultiSelectDescription {
pub fn new() -> MultiSelectDescription {
::std::default::Default::default()
}
// repeated .SelectOption options = 1;
pub fn get_options(&self) -> &[SelectOption] {
&self.options
}
pub fn clear_options(&mut self) {
self.options.clear();
}
// Param is passed by value, moved
pub fn set_options(&mut self, v: ::protobuf::RepeatedField<SelectOption>) {
self.options = v;
}
// Mutable pointer to the field.
pub fn mut_options(&mut self) -> &mut ::protobuf::RepeatedField<SelectOption> {
&mut self.options
}
// Take field
pub fn take_options(&mut self) -> ::protobuf::RepeatedField<SelectOption> {
::std::mem::replace(&mut self.options, ::protobuf::RepeatedField::new())
}
// bool disable_color = 2;
pub fn get_disable_color(&self) -> bool {
self.disable_color
}
pub fn clear_disable_color(&mut self) {
self.disable_color = false;
}
// Param is passed by value, moved
pub fn set_disable_color(&mut self, v: bool) {
self.disable_color = v;
}
}
impl ::protobuf::Message for MultiSelectDescription {
fn is_initialized(&self) -> bool {
for v in &self.options {
if !v.is_initialized() {
return false;
}
};
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.options)?;
},
2 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_bool()?;
self.disable_color = tmp;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
for value in &self.options {
let len = value.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
};
if self.disable_color != false {
my_size += 2;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
for v in &self.options {
os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
};
if self.disable_color != false {
os.write_bool(2, self.disable_color)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> MultiSelectDescription {
MultiSelectDescription::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<SelectOption>>(
"options",
|m: &MultiSelectDescription| { &m.options },
|m: &mut MultiSelectDescription| { &mut m.options },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
"disable_color",
|m: &MultiSelectDescription| { &m.disable_color },
|m: &mut MultiSelectDescription| { &mut m.disable_color },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<MultiSelectDescription>(
"MultiSelectDescription",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static MultiSelectDescription {
static instance: ::protobuf::rt::LazyV2<MultiSelectDescription> = ::protobuf::rt::LazyV2::INIT;
instance.get(MultiSelectDescription::new)
}
}
impl ::protobuf::Clear for MultiSelectDescription {
fn clear(&mut self) {
self.options.clear();
self.disable_color = false;
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for MultiSelectDescription {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for MultiSelectDescription {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct SelectOption {
// message fields
pub id: ::std::string::String,
pub name: ::std::string::String,
pub color: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a SelectOption {
fn default() -> &'a SelectOption {
<SelectOption as ::protobuf::Message>::default_instance()
}
}
impl SelectOption {
pub fn new() -> SelectOption {
::std::default::Default::default()
}
// string id = 1;
pub fn get_id(&self) -> &str {
&self.id
}
pub fn clear_id(&mut self) {
self.id.clear();
}
// Param is passed by value, moved
pub fn set_id(&mut self, v: ::std::string::String) {
self.id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_id(&mut self) -> &mut ::std::string::String {
&mut self.id
}
// Take field
pub fn take_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// string name = 2;
pub fn get_name(&self) -> &str {
&self.name
}
pub fn clear_name(&mut self) {
self.name.clear();
}
// Param is passed by value, moved
pub fn set_name(&mut self, v: ::std::string::String) {
self.name = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_name(&mut self) -> &mut ::std::string::String {
&mut self.name
}
// Take field
pub fn take_name(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.name, ::std::string::String::new())
}
// string color = 3;
pub fn get_color(&self) -> &str {
&self.color
}
pub fn clear_color(&mut self) {
self.color.clear();
}
// Param is passed by value, moved
pub fn set_color(&mut self, v: ::std::string::String) {
self.color = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_color(&mut self) -> &mut ::std::string::String {
&mut self.color
}
// Take field
pub fn take_color(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.color, ::std::string::String::new())
}
}
impl ::protobuf::Message for SelectOption {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?;
},
3 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.color)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.name);
}
if !self.color.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.color);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.id.is_empty() {
os.write_string(1, &self.id)?;
}
if !self.name.is_empty() {
os.write_string(2, &self.name)?;
}
if !self.color.is_empty() {
os.write_string(3, &self.color)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> SelectOption {
SelectOption::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"id",
|m: &SelectOption| { &m.id },
|m: &mut SelectOption| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"name",
|m: &SelectOption| { &m.name },
|m: &mut SelectOption| { &mut m.name },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"color",
|m: &SelectOption| { &m.color },
|m: &mut SelectOption| { &mut m.color },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<SelectOption>(
"SelectOption",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static SelectOption {
static instance: ::protobuf::rt::LazyV2<SelectOption> = ::protobuf::rt::LazyV2::INIT;
instance.get(SelectOption::new)
}
}
impl ::protobuf::Clear for SelectOption {
fn clear(&mut self) {
self.id.clear();
self.name.clear();
self.color.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for SelectOption {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SelectOption {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x1bselection_description.proto\"g\n\x17SingleSelectDescription\x12'\n\
\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x12#\n\rdis\
able_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"f\n\x16MultiSelectDesc\
ription\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectOptionR\x07optio\
ns\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisableColor\"H\n\x0cS\
electOption\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\
\x18\x02\x20\x01(\tR\x04name\x12\x14\n\x05color\x18\x03\x20\x01(\tR\x05c\
olorb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -0,0 +1,200 @@
// 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 `text_description.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
#[derive(PartialEq,Clone,Default)]
pub struct RichTextDescription {
// message fields
pub format: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a RichTextDescription {
fn default() -> &'a RichTextDescription {
<RichTextDescription as ::protobuf::Message>::default_instance()
}
}
impl RichTextDescription {
pub fn new() -> RichTextDescription {
::std::default::Default::default()
}
// string format = 1;
pub fn get_format(&self) -> &str {
&self.format
}
pub fn clear_format(&mut self) {
self.format.clear();
}
// Param is passed by value, moved
pub fn set_format(&mut self, v: ::std::string::String) {
self.format = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_format(&mut self) -> &mut ::std::string::String {
&mut self.format
}
// Take field
pub fn take_format(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.format, ::std::string::String::new())
}
}
impl ::protobuf::Message for RichTextDescription {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.format)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.format.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.format);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.format.is_empty() {
os.write_string(1, &self.format)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> RichTextDescription {
RichTextDescription::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"format",
|m: &RichTextDescription| { &m.format },
|m: &mut RichTextDescription| { &mut m.format },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<RichTextDescription>(
"RichTextDescription",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static RichTextDescription {
static instance: ::protobuf::rt::LazyV2<RichTextDescription> = ::protobuf::rt::LazyV2::INIT;
instance.get(RichTextDescription::new)
}
}
impl ::protobuf::Clear for RichTextDescription {
fn clear(&mut self) {
self.format.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for RichTextDescription {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RichTextDescription {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x16text_description.proto\"-\n\x13RichTextDescription\x12\x16\n\x06fo\
rmat\x18\x01\x20\x01(\tR\x06formatb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
syntax = "proto3";
message CheckboxDescription {
bool is_selected = 1;
}

View File

@ -0,0 +1,16 @@
syntax = "proto3";
message DateDescription {
DateFormat date_format = 1;
TimeFormat time_format = 2;
}
enum DateFormat {
Local = 0;
US = 1;
ISO = 2;
Friendly = 3;
}
enum TimeFormat {
TwelveHour = 0;
TwentyFourHour = 1;
}

View File

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

View File

@ -0,0 +1,15 @@
syntax = "proto3";
message SingleSelectDescription {
repeated SelectOption options = 1;
bool disable_color = 2;
}
message MultiSelectDescription {
repeated SelectOption options = 1;
bool disable_color = 2;
}
message SelectOption {
string id = 1;
string name = 2;
string color = 3;
}

View File

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

View File

@ -1,47 +0,0 @@
syntax = "proto3";
message RichTextDescription {
string format = 1;
}
message CheckboxDescription {
bool is_selected = 1;
}
message DateDescription {
DateFormat date_format = 1;
TimeFormat time_format = 2;
}
message SingleSelectDescription {
repeated SelectOption options = 1;
bool disable_color = 2;
}
message MultiSelectDescription {
repeated SelectOption options = 1;
bool disable_color = 2;
}
message SelectOption {
string id = 1;
string name = 2;
string color = 3;
}
message NumberDescription {
MoneySymbol money = 1;
uint32 scale = 2;
string symbol = 3;
bool sign_positive = 4;
string name = 5;
}
enum DateFormat {
Local = 0;
US = 1;
ISO = 2;
Friendly = 3;
}
enum TimeFormat {
TwelveHour = 0;
TwentyFourHour = 1;
}
enum MoneySymbol {
CNY = 0;
EUR = 1;
USD = 2;
}

View File

@ -0,0 +1,137 @@
use crate::services::cell::*;
use crate::services::field::TypeOptionsBuilder;
use flowy_grid_data_model::entities::FieldType;
// Text
#[derive(Default)]
pub struct RichTextTypeOptionsBuilder(RichTextDescription);
impl TypeOptionsBuilder for RichTextTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Number
#[derive(Default)]
pub struct NumberTypeOptionsBuilder(NumberDescription);
impl NumberTypeOptionsBuilder {
pub fn name(mut self, name: &str) -> Self {
self.0.name = name.to_string();
self
}
pub fn set_money_symbol(mut self, money_symbol: MoneySymbol) -> Self {
self.0.set_money_symbol(money_symbol);
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 TypeOptionsBuilder for NumberTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Date
#[derive(Default)]
pub struct DateTypeOptionsBuilder(DateDescription);
impl DateTypeOptionsBuilder {
pub fn date_format(mut self, date_format: DateFormat) -> Self {
self.0.date_format = date_format;
self
}
pub fn time_format(mut self, time_format: TimeFormat) -> Self {
self.0.time_format = time_format;
self
}
}
impl TypeOptionsBuilder for DateTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Single Select
#[derive(Default)]
pub struct SingleSelectTypeOptionsBuilder(SingleSelectDescription);
impl SingleSelectTypeOptionsBuilder {
pub fn option(mut self, opt: SelectOption) -> Self {
self.0.options.push(opt);
self
}
}
impl TypeOptionsBuilder for SingleSelectTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Multi Select
#[derive(Default)]
pub struct MultiSelectTypeOptionsBuilder(MultiSelectDescription);
impl MultiSelectTypeOptionsBuilder {
pub fn option(mut self, opt: SelectOption) -> Self {
self.0.options.push(opt);
self
}
}
impl TypeOptionsBuilder for MultiSelectTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Checkbox
#[derive(Default)]
pub struct CheckboxTypeOptionsBuilder(CheckboxDescription);
impl CheckboxTypeOptionsBuilder {
pub fn set_selected(mut self, is_selected: bool) -> Self {
self.0.is_selected = is_selected;
self
}
}
impl TypeOptionsBuilder for CheckboxTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}

View File

@ -0,0 +1,40 @@
use crate::impl_from_and_to_type_option;
use crate::services::row::StringifyCellData;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
pub struct CheckboxDescription {
#[pb(index = 1)]
pub is_selected: bool,
}
impl_from_and_to_type_option!(CheckboxDescription, FieldType::Checkbox);
impl StringifyCellData for CheckboxDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
let s = match string_to_bool(s) {
true => "1",
false => "0",
};
Ok(s.to_owned())
}
}
fn string_to_bool(bool_str: &str) -> bool {
let lower_case_str: &str = &bool_str.to_lowercase();
match lower_case_str {
"1" => true,
"true" => true,
"yes" => true,
"0" => false,
"false" => false,
"no" => false,
_ => false,
}
}

View File

@ -0,0 +1,145 @@
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 serde::{Deserialize, Serialize};
// Date
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct DateDescription {
#[pb(index = 1)]
pub date_format: DateFormat,
#[pb(index = 2)]
pub time_format: TimeFormat,
}
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);
self.today_from_native(native)
}
fn today_from_native(&self, naive: chrono::NaiveDateTime) -> String {
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 output = format!("{}", local.format_with_items(StrftimeItems::new(&fmt_str)));
output
}
}
impl StringifyCellData for DateDescription {
fn str_from_cell_data(&self, data: String) -> String {
match data.parse::<i64>() {
Ok(timestamp) => {
let native = NaiveDateTime::from_timestamp(timestamp, 0);
self.today_from_native(native)
}
Err(e) => {
tracing::debug!("DateDescription format {} fail. error: {:?}", data, e);
String::new()
}
}
}
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)))?;
Ok(format!("{}", timestamp))
}
}
#[derive(Clone, Debug, Copy, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum DateFormat {
Local = 0,
US = 1,
ISO = 2,
Friendly = 3,
}
impl std::default::Default for DateFormat {
fn default() -> Self {
DateFormat::Friendly
}
}
impl std::convert::From<i32> for DateFormat {
fn from(value: i32) -> Self {
match value {
0 => DateFormat::Local,
1 => DateFormat::US,
2 => DateFormat::ISO,
3 => DateFormat::Friendly,
_ => {
tracing::error!("Unsupported date format, fallback to friendly");
DateFormat::Friendly
}
}
}
}
impl DateFormat {
pub fn value(&self) -> i32 {
*self as i32
}
// https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html
pub fn format_str(&self) -> &'static str {
match self {
DateFormat::Local => "%Y/%m/%d",
DateFormat::US => "%Y/%m/%d",
DateFormat::ISO => "%Y-%m-%d",
DateFormat::Friendly => "%b %d,%Y",
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum TimeFormat {
TwelveHour = 0,
TwentyFourHour = 1,
}
impl std::convert::From<i32> for TimeFormat {
fn from(value: i32) -> Self {
match value {
0 => TimeFormat::TwelveHour,
1 => TimeFormat::TwentyFourHour,
_ => {
tracing::error!("Unsupported time format, fallback to TwentyFourHour");
TimeFormat::TwentyFourHour
}
}
}
}
impl TimeFormat {
pub fn value(&self) -> i32 {
*self as i32
}
// https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html
pub fn format_str(&self) -> &'static str {
match self {
TimeFormat::TwelveHour => "%r",
TimeFormat::TwentyFourHour => "%R",
}
}
}
impl std::default::Default for TimeFormat {
fn default() -> Self {
TimeFormat::TwentyFourHour
}
}

View File

@ -0,0 +1,11 @@
mod checkbox_description;
mod date_description;
mod number_description;
mod selection_description;
mod text_description;
pub use checkbox_description::*;
pub use date_description::*;
pub use number_description::*;
pub use selection_description::*;
pub use text_description::*;

View File

@ -0,0 +1,150 @@
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 rust_decimal::Decimal;
use rusty_money::{
iso::{Currency, CNY, EUR, USD},
Money,
};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use strum_macros::EnumIter;
// Number
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
pub struct NumberDescription {
#[pb(index = 1)]
pub money: MoneySymbol,
#[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_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();
NumberDescription {
money,
scale: 0,
symbol,
sign_positive: true,
name: "Number".to_string(),
}
}
}
impl NumberDescription {
pub fn set_money_symbol(&mut self, money_symbol: MoneySymbol) {
self.money = money_symbol;
self.symbol = money_symbol.symbol_str();
}
fn money_from_str(&self, s: &str) -> Option<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);
Some(self.money.with_decimal(decimal).to_string())
}
Err(e) => {
tracing::error!("Parser money from {} failed: {:?}", s, e);
None
}
}
}
}
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(),
}
}
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())
}
}
#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum MoneySymbol {
CNY = 0,
EUR = 1,
USD = 2,
}
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
}
}

View File

@ -0,0 +1,70 @@
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_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize};
// Single select
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct SingleSelectDescription {
#[pb(index = 1)]
pub options: Vec<SelectOption>,
#[pb(index = 2)]
pub disable_color: bool,
}
impl_from_and_to_type_option!(SingleSelectDescription, FieldType::SingleSelect);
impl StringifyCellData for SingleSelectDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned())
}
}
// Multiple select
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct MultiSelectDescription {
#[pb(index = 1)]
pub options: Vec<SelectOption>,
#[pb(index = 2)]
pub disable_color: bool,
}
impl_from_and_to_type_option!(MultiSelectDescription, FieldType::MultiSelect);
impl StringifyCellData for MultiSelectDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned())
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct SelectOption {
#[pb(index = 1)]
pub id: String,
#[pb(index = 2)]
pub name: String,
#[pb(index = 3)]
pub color: String,
}
impl SelectOption {
pub fn new(name: &str) -> Self {
SelectOption {
id: uuid(),
name: name.to_owned(),
color: "".to_string(),
}
}
}

View File

@ -0,0 +1,24 @@
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_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
pub struct RichTextDescription {
#[pb(index = 1)]
pub format: String,
}
impl_from_and_to_type_option!(RichTextDescription, FieldType::RichText);
impl StringifyCellData for RichTextDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned())
}
}

View File

@ -0,0 +1,5 @@
mod builder;
mod description;
pub use builder::*;
pub use description::*;

View File

@ -1,7 +1,3 @@
use crate::services::field::{
CheckboxDescription, DateDescription, DateFormat, MoneySymbol, MultiSelectDescription, NumberDescription,
RichTextDescription, SelectOption, SingleSelectDescription, TimeFormat,
};
use flowy_grid_data_model::entities::{Field, FieldType};
pub struct FieldBuilder {
@ -61,157 +57,3 @@ pub trait TypeOptionsBuilder {
fn field_type(&self) -> FieldType;
fn build(&self) -> String;
}
// Text
pub struct RichTextTypeOptionsBuilder(RichTextDescription);
impl RichTextTypeOptionsBuilder {
pub fn new() -> Self {
Self(RichTextDescription::default())
}
}
impl TypeOptionsBuilder for RichTextTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Number
pub struct NumberTypeOptionsBuilder(NumberDescription);
impl NumberTypeOptionsBuilder {
pub fn new() -> Self {
Self(NumberDescription::default())
}
pub fn name(mut self, name: &str) -> Self {
self.0.name = name.to_string();
self
}
pub fn set_money_symbol(mut self, money_symbol: MoneySymbol) -> Self {
self.0.set_money_symbol(money_symbol);
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 TypeOptionsBuilder for NumberTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Date
pub struct DateTypeOptionsBuilder(DateDescription);
impl DateTypeOptionsBuilder {
pub fn new() -> Self {
Self(DateDescription::default())
}
pub fn date_format(mut self, date_format: DateFormat) -> Self {
self.0.date_format = date_format;
self
}
pub fn time_format(mut self, time_format: TimeFormat) -> Self {
self.0.time_format = time_format;
self
}
}
impl TypeOptionsBuilder for DateTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Single Select
pub struct SingleSelectTypeOptionsBuilder(SingleSelectDescription);
impl SingleSelectTypeOptionsBuilder {
pub fn new() -> Self {
Self(SingleSelectDescription::default())
}
pub fn option(mut self, opt: SelectOption) -> Self {
self.0.options.push(opt);
self
}
}
impl TypeOptionsBuilder for SingleSelectTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Multi Select
pub struct MultiSelectTypeOptionsBuilder(MultiSelectDescription);
impl MultiSelectTypeOptionsBuilder {
pub fn new() -> Self {
Self(MultiSelectDescription::default())
}
pub fn option(mut self, opt: SelectOption) -> Self {
self.0.options.push(opt);
self
}
}
impl TypeOptionsBuilder for MultiSelectTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}
// Checkbox
pub struct CheckboxTypeOptionsBuilder(CheckboxDescription);
impl CheckboxTypeOptionsBuilder {
pub fn new() -> Self {
Self(CheckboxDescription::default())
}
pub fn set_selected(mut self, is_selected: bool) -> Self {
self.0.is_selected = is_selected;
self
}
}
impl TypeOptionsBuilder for CheckboxTypeOptionsBuilder {
fn field_type(&self) -> FieldType {
self.0.field_type()
}
fn build(&self) -> String {
self.0.clone().into()
}
}

View File

@ -1,5 +1,3 @@
mod field_builder;
mod type_options;
pub use field_builder::*;
pub use type_options::*;

View File

@ -1,390 +0,0 @@
#![allow(clippy::upper_case_acronyms)]
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 rust_decimal::Decimal;
use rusty_money::{
iso::{Currency, CNY, EUR, USD},
Money,
};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use strum_macros::EnumIter;
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
pub struct RichTextDescription {
#[pb(index = 1)]
pub format: String,
}
impl_from_and_to_type_option!(RichTextDescription, FieldType::RichText);
impl StringifyCellData for RichTextDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned())
}
}
// Checkbox
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
pub struct CheckboxDescription {
#[pb(index = 1)]
pub is_selected: bool,
}
impl_from_and_to_type_option!(CheckboxDescription, FieldType::Checkbox);
impl StringifyCellData for CheckboxDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
let s = match string_to_bool(s) {
true => "1",
false => "0",
};
Ok(s.to_owned())
}
}
// Date
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct DateDescription {
#[pb(index = 1)]
pub date_format: DateFormat,
#[pb(index = 2)]
pub time_format: TimeFormat,
}
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);
self.today_from_native(native)
}
fn today_from_native(&self, naive: chrono::NaiveDateTime) -> String {
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 output = format!("{}", local.format_with_items(StrftimeItems::new(&fmt_str)));
output
}
}
impl StringifyCellData for DateDescription {
fn str_from_cell_data(&self, data: String) -> String {
match data.parse::<i64>() {
Ok(timestamp) => {
let native = NaiveDateTime::from_timestamp(timestamp, 0);
self.today_from_native(native)
}
Err(e) => {
tracing::debug!("DateDescription format {} fail. error: {:?}", data, e);
String::new()
}
}
}
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)))?;
Ok(format!("{}", timestamp))
}
}
#[derive(Clone, Debug, Copy, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum DateFormat {
Local = 0,
US = 1,
ISO = 2,
Friendly = 3,
}
impl std::default::Default for DateFormat {
fn default() -> Self {
DateFormat::Friendly
}
}
impl std::convert::From<i32> for DateFormat {
fn from(value: i32) -> Self {
match value {
0 => DateFormat::Local,
1 => DateFormat::US,
2 => DateFormat::ISO,
3 => DateFormat::Friendly,
_ => {
tracing::error!("Unsupported date format, fallback to friendly");
DateFormat::Friendly
}
}
}
}
impl DateFormat {
pub fn value(&self) -> i32 {
*self as i32
}
// https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html
pub fn format_str(&self) -> &'static str {
match self {
DateFormat::Local => "%Y/%m/%d",
DateFormat::US => "%Y/%m/%d",
DateFormat::ISO => "%Y-%m-%d",
DateFormat::Friendly => "%b %d,%Y",
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum TimeFormat {
TwelveHour = 0,
TwentyFourHour = 1,
}
impl std::convert::From<i32> for TimeFormat {
fn from(value: i32) -> Self {
match value {
0 => TimeFormat::TwelveHour,
1 => TimeFormat::TwentyFourHour,
_ => {
tracing::error!("Unsupported time format, fallback to TwentyFourHour");
TimeFormat::TwentyFourHour
}
}
}
}
impl TimeFormat {
pub fn value(&self) -> i32 {
*self as i32
}
// https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html
pub fn format_str(&self) -> &'static str {
match self {
TimeFormat::TwelveHour => "%r",
TimeFormat::TwentyFourHour => "%R",
}
}
}
impl std::default::Default for TimeFormat {
fn default() -> Self {
TimeFormat::TwentyFourHour
}
}
// Single select
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct SingleSelectDescription {
#[pb(index = 1)]
pub options: Vec<SelectOption>,
#[pb(index = 2)]
pub disable_color: bool,
}
impl_from_and_to_type_option!(SingleSelectDescription, FieldType::SingleSelect);
impl StringifyCellData for SingleSelectDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned())
}
}
// Multiple select
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct MultiSelectDescription {
#[pb(index = 1)]
pub options: Vec<SelectOption>,
#[pb(index = 2)]
pub disable_color: bool,
}
impl_from_and_to_type_option!(MultiSelectDescription, FieldType::MultiSelect);
impl StringifyCellData for MultiSelectDescription {
fn str_from_cell_data(&self, data: String) -> String {
data
}
fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
Ok(s.to_owned())
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct SelectOption {
#[pb(index = 1)]
pub id: String,
#[pb(index = 2)]
pub name: String,
#[pb(index = 3)]
pub color: String,
}
impl SelectOption {
pub fn new(name: &str) -> Self {
SelectOption {
id: uuid(),
name: name.to_owned(),
color: "".to_string(),
}
}
}
// Number
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
pub struct NumberDescription {
#[pb(index = 1)]
pub money: MoneySymbol,
#[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_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();
NumberDescription {
money,
scale: 0,
symbol,
sign_positive: true,
name: "Number".to_string(),
}
}
}
impl NumberDescription {
pub fn set_money_symbol(&mut self, money_symbol: MoneySymbol) {
self.money = money_symbol;
self.symbol = money_symbol.symbol_str();
}
fn money_from_str(&self, s: &str) -> Option<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);
Some(self.money.with_decimal(decimal).to_string())
}
Err(e) => {
tracing::error!("Parser money from {} failed: {:?}", s, e);
None
}
}
}
}
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(),
}
}
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())
}
}
#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
pub enum MoneySymbol {
CNY = 0,
EUR = 1,
USD = 2,
}
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
}
}

View File

@ -1,17 +1,20 @@
use crate::manager::GridUser;
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
use crate::services::grid_meta_editor::GridBlockMetaEditorManager;
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
use bytes::Bytes;
use dashmap::DashMap;
use flowy_collaboration::client_grid::{GridChange, GridMetaPad};
use flowy_collaboration::entities::revision::Revision;
use flowy_collaboration::util::make_delta_from_revisions;
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::{
Field, FieldChangeset, Grid, GridBlock, GridBlockChangeset, RepeatedFieldOrder, RepeatedRowOrder, Row,
CellMetaChangeset, Field, FieldChangeset, Grid, GridBlock, GridBlockChangeset, RepeatedFieldOrder,
RepeatedRowOrder, Row, RowMeta, RowMetaChangeset,
};
use std::collections::HashMap;
use crate::services::row::{
make_row_by_row_id, make_rows, row_meta_from_context, CreateRowContext, CreateRowContextBuilder,
};
use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
use lib_infra::future::FutureResult;
use lib_ot::core::PlainTextAttributes;
@ -73,44 +76,83 @@ impl ClientGridEditor {
Ok(())
}
pub async fn update_block(&self, change: GridBlockChangeset) -> FlowyResult<()> {
let _ = self.modify(|grid| Ok(grid.update_block(change)?)).await?;
pub async fn update_block(&self, changeset: GridBlockChangeset) -> FlowyResult<()> {
let _ = self.modify(|grid| Ok(grid.update_block(changeset)?)).await?;
Ok(())
}
pub async fn create_row(&self) -> FlowyResult<()> {
let fields = self.grid_meta_pad.read().await.get_fields(None)?;
let grid_block = match self.grid_meta_pad.read().await.get_blocks().last() {
None => Err(FlowyError::internal().context("There is no grid block in this grid")),
Some(grid_block) => Ok(grid_block.clone()),
}?;
let row_count = self.block_meta_manager.create_row(fields, &grid_block).await?;
let change = GridBlockChangeset::from_row_count(&grid_block.id, row_count);
let _ = self.update_block(change).await?;
let block_id = self.last_block_id().await?;
let row = row_meta_from_context(&block_id, CreateRowContextBuilder::new(&fields).build());
let row_count = self.block_meta_manager.create_row(row).await?;
let changeset = GridBlockChangeset::from_row_count(&block_id, row_count);
let _ = self.update_block(changeset).await?;
Ok(())
}
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<Vec<Row>> {
let fields = self.grid_meta_pad.read().await.get_fields(None)?;
let rows = self.block_meta_manager.get_rows(fields, row_orders).await?;
Ok(rows)
}
pub async fn insert_rows(&self, contexts: Vec<CreateRowContext>) -> FlowyResult<()> {
let block_id = self.last_block_id().await?;
let mut rows_by_block_id: HashMap<String, Vec<RowMeta>> = HashMap::new();
pub async fn get_all_rows(&self) -> FlowyResult<Vec<Row>> {
let fields = self.grid_meta_pad.read().await.get_fields(None)?;
let grid_blocks = self.grid_meta_pad.read().await.get_blocks();
self.block_meta_manager.get_all_rows(grid_blocks, fields).await
}
pub async fn delete_rows(&self, row_orders: Option<RepeatedRowOrder>) -> FlowyResult<()> {
let row_counts = self.block_meta_manager.delete_rows(row_orders).await?;
for (block_id, row_count) in row_counts {
let _ = self
.update_block(GridBlockChangeset::from_row_count(&block_id, row_count))
.await?;
for ctx in contexts {
let row_meta = row_meta_from_context(&block_id, ctx);
rows_by_block_id
.entry(block_id.clone())
.or_insert(Vec::new())
.push(row_meta);
}
let changesets = self.block_meta_manager.insert_row(rows_by_block_id).await?;
for changeset in changesets {
let _ = self.update_block(changeset).await?;
}
Ok(())
}
pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
self.block_meta_manager.update_row(changeset).await
}
pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> {
let row_changeset: RowMetaChangeset = changeset.into();
self.update_row(row_changeset).await
}
pub async fn get_rows(&self, row_orders: Option<RepeatedRowOrder>) -> FlowyResult<Vec<Row>> {
let row_metas = self.get_row_metas(&row_orders).await?;
let fields = self.grid_meta_pad.read().await.get_fields(None)?;
match row_orders {
None => Ok(make_rows(&fields, row_metas)),
Some(row_orders) => {
let mut row_map: HashMap<String, Row> = make_row_by_row_id(&fields, row_metas);
let rows = row_orders
.iter()
.flat_map(|row_order| row_map.remove(&row_order.row_id))
.collect::<Vec<_>>();
Ok(rows)
}
}
}
pub async fn get_row_metas(&self, row_orders: &Option<RepeatedRowOrder>) -> FlowyResult<Vec<RowMeta>> {
match row_orders {
None => {
let grid_blocks = self.grid_meta_pad.read().await.get_blocks();
let row_metas = self.block_meta_manager.get_all_rows(grid_blocks).await?;
Ok(row_metas)
}
Some(row_orders) => {
let row_metas = self.block_meta_manager.get_rows(row_orders).await?;
Ok(row_metas)
}
}
}
pub async fn delete_rows(&self, row_ids: Vec<String>) -> FlowyResult<()> {
let changesets = self.block_meta_manager.delete_rows(row_ids).await?;
for changeset in changesets {
let _ = self.update_block(changeset).await?;
}
Ok(())
}
@ -165,6 +207,13 @@ impl ClientGridEditor {
.await?;
Ok(())
}
async fn last_block_id(&self) -> FlowyResult<String> {
match self.grid_meta_pad.read().await.get_blocks().last() {
None => Err(FlowyError::internal().context("There is no grid block in this grid")),
Some(grid_block) => Ok(grid_block.id.clone()),
}
}
}
#[cfg(feature = "flowy_unit_test")]
@ -174,24 +223,6 @@ impl ClientGridEditor {
}
}
async fn load_all_fields(
grid_pad: &GridMetaPad,
kv_persistence: &Arc<GridKVPersistence>,
) -> FlowyResult<DashMap<String, Field>> {
let field_ids = grid_pad
.fields()
.iter()
.map(|field| field.id.clone())
.collect::<Vec<_>>();
let fields = kv_persistence.batch_get::<Field>(field_ids)?;
let map = DashMap::new();
for field in fields {
map.insert(field.id.clone(), field);
}
Ok(map)
}
pub struct GridPadBuilder();
impl RevisionObjectBuilder for GridPadBuilder {
type Output = GridMetaPad;

View File

@ -1,5 +1,5 @@
use crate::manager::GridUser;
use crate::services::row::{make_row_by_row_id, make_row_ids_per_block, make_rows, RowBuilder};
use crate::services::row::make_row_ids_per_block;
use bytes::Bytes;
use dashmap::DashMap;
@ -7,7 +7,9 @@ use flowy_collaboration::client_grid::{GridBlockMetaChange, GridBlockMetaPad};
use flowy_collaboration::entities::revision::Revision;
use flowy_collaboration::util::make_delta_from_revisions;
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::entities::{Field, GridBlock, RepeatedRowOrder, Row, RowMeta, RowMetaChangeset};
use flowy_grid_data_model::entities::{
GridBlock, GridBlockChangeset, RepeatedRowOrder, RowMeta, RowMetaChangeset, RowOrder,
};
use flowy_sync::disk::SQLiteGridBlockMetaRevisionPersistence;
use flowy_sync::{
RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
@ -16,19 +18,30 @@ use lib_infra::future::FutureResult;
use lib_ot::core::PlainTextAttributes;
use std::collections::HashMap;
use dashmap::mapref::one::Ref;
use std::sync::Arc;
use tokio::sync::RwLock;
type RowId = String;
type BlockId = String;
pub(crate) struct GridBlockMetaEditorManager {
user: Arc<dyn GridUser>,
editor_map: DashMap<String, Arc<ClientGridBlockMetaEditor>>,
block_id_by_row_id: DashMap<BlockId, RowId>,
}
impl GridBlockMetaEditorManager {
pub(crate) async fn new(user: &Arc<dyn GridUser>, blocks: Vec<GridBlock>) -> FlowyResult<Self> {
let editor_map = make_block_meta_editor_map(user, blocks).await?;
let user = user.clone();
let manager = Self { user, editor_map };
let block_id_by_row_id = DashMap::new();
let manager = Self {
user,
editor_map,
block_id_by_row_id,
};
Ok(manager)
}
@ -44,40 +57,98 @@ impl GridBlockMetaEditorManager {
}
}
pub(crate) async fn create_row(&self, fields: Vec<Field>, grid_block: &GridBlock) -> FlowyResult<i32> {
let row = RowBuilder::new(&fields, &grid_block.id).build();
let editor = self.get_editor(&grid_block.id).await?;
pub(crate) async fn create_row(&self, row: RowMeta) -> FlowyResult<i32> {
self.block_id_by_row_id.insert(row.id.clone(), row.block_id.clone());
let editor = self.get_editor(&row.block_id).await?;
editor.create_row(row).await
}
pub(crate) async fn delete_rows(&self, _row_orders: Option<RepeatedRowOrder>) -> FlowyResult<Vec<(String, i32)>> {
Ok(vec![("".to_owned(), 2)])
}
pub(crate) async fn get_all_rows(&self, grid_blocks: Vec<GridBlock>, fields: Vec<Field>) -> FlowyResult<Vec<Row>> {
let mut rows = vec![];
for grid_block in grid_blocks {
let editor = self.get_editor(&grid_block.id).await?;
let row_metas = editor.get_rows(None).await?;
rows.extend(make_rows(&fields, row_metas));
pub(crate) async fn insert_row(
&self,
rows_by_block_id: HashMap<String, Vec<RowMeta>>,
) -> FlowyResult<Vec<GridBlockChangeset>> {
let mut changesets = vec![];
for (block_id, rows) in rows_by_block_id {
let editor = self.get_editor(&block_id).await?;
let mut row_count = 0;
for row in rows {
self.block_id_by_row_id.insert(row.id.clone(), row.block_id.clone());
row_count = editor.create_row(row).await?;
}
changesets.push(GridBlockChangeset::from_row_count(&block_id, row_count));
}
Ok(rows)
Ok(changesets)
}
pub(crate) async fn get_rows(&self, fields: Vec<Field>, row_orders: RepeatedRowOrder) -> FlowyResult<Vec<Row>> {
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 {
row_id,
block_id: block_id.clone(),
}),
})
.collect::<Vec<RowOrder>>();
let mut changesets = vec![];
let row_ids_per_blocks = make_row_ids_per_block(&row_orders);
let mut row_map: HashMap<String, Row> = HashMap::new();
for row_ids_per_block in row_ids_per_blocks {
let editor = self.get_editor(&row_ids_per_block.block_id).await?;
let row_metas = editor.get_rows(Some(row_ids_per_block.row_ids)).await?;
row_map.extend(make_row_by_row_id(&fields, row_metas));
let row_count = editor.delete_rows(row_ids_per_block.row_ids).await?;
let changeset = GridBlockChangeset::from_row_count(&row_ids_per_block.block_id, row_count);
changesets.push(changeset);
}
let rows = row_orders
.iter()
.flat_map(|row_order| row_map.remove(&row_order.row_id))
.collect::<Vec<_>>();
Ok(rows)
Ok(changesets)
}
pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
match self.block_id_by_row_id.get(&changeset.row_id) {
None => {
let msg = format!(
"Update Row failed. Can't find the corresponding block with row_id: {}",
changeset.row_id
);
Err(FlowyError::internal().context(msg))
}
Some(block_id) => {
let editor = self.get_editor(&block_id).await?;
editor.update_row(changeset).await
}
}
}
pub(crate) async fn get_all_rows(&self, grid_blocks: Vec<GridBlock>) -> FlowyResult<Vec<RowMeta>> {
let mut row_metas = vec![];
for grid_block in grid_blocks {
let editor = self.get_editor(&grid_block.id).await?;
let new_row_metas = editor.get_rows(None).await?;
new_row_metas.iter().for_each(|row_meta| {
self.block_id_by_row_id
.insert(row_meta.id.clone(), row_meta.block_id.clone());
});
row_metas.extend(new_row_metas);
}
Ok(row_metas)
}
pub(crate) async fn get_rows(&self, row_orders: &RepeatedRowOrder) -> FlowyResult<Vec<RowMeta>> {
let row_ids_per_blocks = make_row_ids_per_block(row_orders);
let mut row_metas = vec![];
for row_ids_per_block in row_ids_per_blocks {
let editor = self.get_editor(&row_ids_per_block.block_id).await?;
let new_row_metas = editor.get_rows(Some(row_ids_per_block.row_ids)).await?;
new_row_metas.iter().for_each(|row_meta| {
self.block_id_by_row_id
.insert(row_meta.id.clone(), row_meta.block_id.clone());
});
row_metas.extend(new_row_metas);
}
Ok(row_metas)
}
}
@ -148,9 +219,16 @@ impl ClientGridBlockMetaEditor {
Ok(row_count)
}
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<()> {
let _ = self.modify(|pad| Ok(pad.delete_rows(&ids)?)).await?;
Ok(())
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<i32> {
let mut row_count = 0;
let _ = self
.modify(|pad| {
let changeset = pad.delete_rows(&ids)?;
row_count = pad.number_of_rows();
Ok(changeset)
})
.await?;
Ok(row_count)
}
pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {

View File

@ -1,5 +1,6 @@
mod util;
pub mod cell;
pub mod field;
pub mod grid_editor;
pub mod grid_meta_editor;

View File

@ -1,5 +1,4 @@
use crate::services::field::*;
use crate::services::cell::*;
use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{Field, FieldType};

View File

@ -1,24 +1,60 @@
use flowy_grid_data_model::entities::{CellMeta, Field, RowMeta};
use flowy_grid_data_model::entities::{CellMeta, Field, RowMeta, DEFAULT_ROW_HEIGHT};
use std::collections::HashMap;
pub struct RowBuilder<'a> {
fields: &'a Vec<Field>,
row: RowMeta,
pub struct CreateRowContextBuilder<'a> {
#[allow(dead_code)]
fields: &'a [Field],
ctx: CreateRowContext,
}
impl<'a> RowBuilder<'a> {
pub fn new(fields: &'a Vec<Field>, block_id: &'a String) -> Self {
let row = RowMeta::new(block_id);
Self { fields, row }
impl<'a> CreateRowContextBuilder<'a> {
pub fn new(fields: &'a [Field]) -> Self {
let ctx = CreateRowContext {
row_id: uuid::Uuid::new_v4().to_string(),
cell_by_field_id: Default::default(),
height: DEFAULT_ROW_HEIGHT,
visibility: true,
};
Self { fields, ctx }
}
#[allow(dead_code)]
pub fn add_cell(mut self, field_id: &str, data: String) -> Self {
let cell = CellMeta::new(field_id, data);
self.row.cell_by_field_id.insert(field_id.to_owned(), cell);
self.ctx.cell_by_field_id.insert(field_id.to_owned(), cell);
self
}
pub fn build(self) -> RowMeta {
self.row
#[allow(dead_code)]
pub fn height(mut self, height: i32) -> Self {
self.ctx.height = height;
self
}
#[allow(dead_code)]
pub fn visibility(mut self, visibility: bool) -> Self {
self.ctx.visibility = visibility;
self
}
pub fn build(self) -> CreateRowContext {
self.ctx
}
}
pub fn row_meta_from_context(block_id: &str, ctx: CreateRowContext) -> RowMeta {
RowMeta {
id: ctx.row_id,
block_id: block_id.to_owned(),
cell_by_field_id: ctx.cell_by_field_id,
height: ctx.height,
visibility: ctx.visibility,
}
}
pub struct CreateRowContext {
pub row_id: String,
pub cell_by_field_id: HashMap<String, CellMeta>,
pub height: i32,
pub visibility: bool,
}

View File

@ -1,5 +1,5 @@
use crate::services::row::stringify_deserialize;
use flowy_grid_data_model::entities::{Cell, CellMeta, Field, RepeatedRowOrder, Row, RowMeta};
use flowy_grid_data_model::entities::{Cell, CellMeta, Field, RepeatedRowOrder, Row, RowMeta, RowOrder};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::collections::HashMap;
@ -8,7 +8,7 @@ pub(crate) struct RowIdsPerBlock {
pub(crate) row_ids: Vec<String>,
}
pub(crate) fn make_row_ids_per_block(row_orders: &RepeatedRowOrder) -> Vec<RowIdsPerBlock> {
pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec<RowIdsPerBlock> {
let mut map: HashMap<String, RowIdsPerBlock> = HashMap::new();
row_orders.iter().for_each(|row_order| {
let block_id = row_order.block_id.clone();
@ -21,7 +21,7 @@ pub(crate) fn make_row_ids_per_block(row_orders: &RepeatedRowOrder) -> Vec<RowId
map.into_values().collect::<Vec<_>>()
}
pub(crate) fn make_rows(fields: &Vec<Field>, row_metas: Vec<RowMeta>) -> Vec<Row> {
pub(crate) fn make_rows(fields: &[Field], row_metas: Vec<RowMeta>) -> Vec<Row> {
let field_map = fields
.iter()
.map(|field| (&field.id, field))
@ -59,7 +59,7 @@ fn make_cell(field_map: &HashMap<&String, &Field>, field_id: String, raw_cell: C
}
}
pub(crate) fn make_row_by_row_id(fields: &Vec<Field>, row_metas: Vec<RowMeta>) -> HashMap<String, Row> {
pub(crate) fn make_row_by_row_id(fields: &[Field], row_metas: Vec<RowMeta>) -> HashMap<String, Row> {
let field_map = fields
.iter()
.map(|field| (&field.id, field))

View File

@ -1,4 +1,4 @@
use crate::services::field::MoneySymbol;
use crate::services::cell::MoneySymbol;
use flowy_error::FlowyError;
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
use lazy_static::lazy_static;
@ -99,31 +99,6 @@ fn crop_letters(s: &mut String, pos: usize) {
}
}
pub fn string_to_bool(bool_str: &str) -> bool {
let lower_case_str: &str = &bool_str.to_lowercase();
match lower_case_str {
"1" => true,
"true" => true,
"yes" => true,
"0" => false,
"false" => false,
"no" => false,
_ => false,
}
}
pub fn uuid() -> String {
uuid::Uuid::new_v4().to_string()
}
pub fn check_type_id(data: &AnyData, field: &Field) -> Result<(), FlowyError> {
let field_type = FieldType::from_type_id(&data.type_id).map_err(|e| FlowyError::internal().context(e))?;
if field_type != field.field_type {
tracing::error!(
"expected field type: {:?} but receive {:?} ",
field_type,
field.field_type
);
}
Ok(())
}

View File

@ -1,15 +1,16 @@
use crate::services::cell::*;
use crate::services::field::*;
use flowy_collaboration::client_grid::{BuildGridInfo, GridBuilder};
use flowy_grid_data_model::entities::FieldType;
pub fn make_default_grid(grid_id: &str) -> BuildGridInfo {
let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::new())
let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::default())
.name("Name")
.visibility(true)
.field_type(FieldType::RichText)
.build();
let single_select = SingleSelectTypeOptionsBuilder::new()
let single_select = SingleSelectTypeOptionsBuilder::default()
.option(SelectOption::new("Done"))
.option(SelectOption::new("Progress"));

View File

@ -1,7 +1,10 @@
use crate::grid::script::EditorScript::*;
use crate::grid::script::*;
use flowy_grid::services::field::{SelectOption, SingleSelectDescription};
use flowy_grid_data_model::entities::{FieldChangeset, GridBlock, GridBlockChangeset};
use flowy_grid::services::row::CreateRowContextBuilder;
use flowy_grid_data_model::entities::{
FieldChangeset, FieldType, GridBlock, GridBlockChangeset, Row, RowMetaChangeset,
};
#[tokio::test]
async fn default_grid_test() {
@ -55,7 +58,7 @@ async fn grid_create_duplicate_field() {
#[tokio::test]
async fn grid_update_field_with_empty_change() {
let single_select_field = create_single_select_field();
let change = FieldChangeset {
let changeset = FieldChangeset {
field_id: single_select_field.id.clone(),
name: None,
desc: None,
@ -70,7 +73,7 @@ async fn grid_update_field_with_empty_change() {
CreateField {
field: single_select_field.clone(),
},
UpdateField { change },
UpdateField { changeset },
AssertFieldEqual {
field_index: 2,
field: single_select_field,
@ -87,7 +90,7 @@ async fn grid_update_field() {
let mut single_select_type_options = SingleSelectDescription::from(&single_select_field);
single_select_type_options.options.push(SelectOption::new("Unknown"));
let change = FieldChangeset {
let changeset = FieldChangeset {
field_id: single_select_field.id.clone(),
name: None,
desc: None,
@ -106,7 +109,7 @@ async fn grid_update_field() {
CreateField {
field: single_select_field.clone(),
},
UpdateField { change },
UpdateField { changeset },
AssertFieldEqual {
field_index: 2,
field: cloned_field,
@ -145,7 +148,7 @@ async fn grid_create_block() {
async fn grid_update_block() {
let grid_block = GridBlock::new();
let mut cloned_grid_block = grid_block.clone();
let change = GridBlockChangeset {
let changeset = GridBlockChangeset {
block_id: grid_block.id.clone(),
start_row_index: Some(2),
row_count: Some(10),
@ -157,7 +160,7 @@ async fn grid_update_block() {
let scripts = vec![
AssertBlockCount(1),
CreateBlock { block: grid_block },
UpdateBlock { change },
UpdateBlock { changeset },
AssertBlockCount(2),
AssertBlockEqual {
block_index: 1,
@ -169,6 +172,96 @@ async fn grid_update_block() {
#[tokio::test]
async fn grid_create_row() {
let scripts = vec![AssertRowCount(3), CreateRow, CreateRow, AssertRowCount(5)];
let scripts = vec![AssertRowCount(3), CreateEmptyRow, CreateEmptyRow, AssertRowCount(5)];
GridEditorTest::new().await.run_scripts(scripts).await;
}
#[tokio::test]
async fn grid_create_row2() {
let mut test = GridEditorTest::new().await;
let create_row_context = CreateRowContextBuilder::new(&test.fields).build();
let scripts = vec![
AssertRowCount(3),
CreateRow {
context: create_row_context,
},
AssertRowCount(4),
];
test.run_scripts(scripts).await;
}
#[tokio::test]
async fn grid_update_row() {
let mut test = GridEditorTest::new().await;
let context = CreateRowContextBuilder::new(&test.fields).build();
let changeset = RowMetaChangeset {
row_id: context.row_id.clone(),
height: None,
visibility: None,
cell_by_field_id: Default::default(),
};
let scripts = vec![
AssertRowCount(3),
CreateRow { context },
UpdateRow {
changeset: changeset.clone(),
},
AssertRow { changeset },
AssertRowCount(4),
];
test.run_scripts(scripts).await;
}
#[tokio::test]
async fn grid_delete_row() {
let mut test = GridEditorTest::new().await;
let context_1 = CreateRowContextBuilder::new(&test.fields).build();
let context_2 = CreateRowContextBuilder::new(&test.fields).build();
let row_ids = vec![context_1.row_id.clone(), context_2.row_id.clone()];
let scripts = vec![
AssertRowCount(3),
CreateRow { context: context_1 },
CreateRow { context: context_2 },
AssertBlockCount(1),
AssertBlock {
block_index: 0,
row_count: 5,
start_row_index: 0,
},
DeleteRow { row_ids },
AssertBlock {
block_index: 0,
row_count: 3,
start_row_index: 0,
},
];
test.run_scripts(scripts).await;
}
#[tokio::test]
async fn grid_update_cell() {
let mut test = GridEditorTest::new().await;
let mut builder = CreateRowContextBuilder::new(&test.fields);
for field in &test.fields {
match field.field_type {
FieldType::RichText => {
builder = builder.add_cell(&field.id, "hello world".to_owned());
}
FieldType::Number => {
builder = builder.add_cell(&field.id, "123".to_owned());
}
FieldType::DateTime => {
builder = builder.add_cell(&field.id, "March 8, 2022".to_owned());
}
FieldType::SingleSelect => {}
FieldType::MultiSelect => {}
FieldType::Checkbox => {
builder = builder.add_cell(&field.id, "1".to_owned());
}
}
}
let context = builder.build();
let scripts = vec![AssertRowCount(3), CreateRow { context }];
test.run_scripts(scripts).await;
}

View File

@ -1,8 +1,11 @@
use flowy_grid::services::cell::*;
use flowy_grid::services::field::*;
use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
use flowy_grid_data_model::entities::{Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset};
use flowy_grid::services::row::CreateRowContext;
use flowy_grid_data_model::entities::{
CellMetaChangeset, Field, FieldChangeset, FieldType, GridBlock, GridBlockChangeset, Row, RowMeta, RowMetaChangeset,
};
use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS;
use flowy_test::helper::ViewTest;
use flowy_test::FlowySDKTest;
use std::sync::Arc;
@ -10,16 +13,52 @@ use std::time::Duration;
use tokio::time::sleep;
pub enum EditorScript {
CreateField { field: Field },
UpdateField { change: FieldChangeset },
DeleteField { field: Field },
CreateField {
field: Field,
},
UpdateField {
changeset: FieldChangeset,
},
DeleteField {
field: Field,
},
AssertFieldCount(usize),
AssertFieldEqual { field_index: usize, field: Field },
CreateBlock { block: GridBlock },
UpdateBlock { change: GridBlockChangeset },
AssertFieldEqual {
field_index: usize,
field: Field,
},
CreateBlock {
block: GridBlock,
},
UpdateBlock {
changeset: GridBlockChangeset,
},
AssertBlockCount(usize),
AssertBlockEqual { block_index: usize, block: GridBlock },
CreateRow,
AssertBlock {
block_index: usize,
row_count: i32,
start_row_index: i32,
},
AssertBlockEqual {
block_index: usize,
block: GridBlock,
},
CreateEmptyRow,
CreateRow {
context: CreateRowContext,
},
UpdateRow {
changeset: RowMetaChangeset,
},
AssertRow {
changeset: RowMetaChangeset,
},
DeleteRow {
row_ids: Vec<String>,
},
UpdateCell {
changeset: CellMetaChangeset,
},
AssertRowCount(usize),
// AssertRowEqual{ row_index: usize, row: RowMeta},
AssertGridMetaPad,
@ -29,6 +68,9 @@ pub struct GridEditorTest {
pub sdk: FlowySDKTest,
pub grid_id: String,
pub editor: Arc<ClientGridEditor>,
pub fields: Vec<Field>,
pub grid_blocks: Vec<GridBlock>,
pub row_metas: Vec<RowMeta>,
}
impl GridEditorTest {
@ -37,8 +79,19 @@ impl GridEditorTest {
let _ = sdk.init_user().await;
let test = ViewTest::new_grid_view(&sdk).await;
let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap();
let fields = editor.get_fields(None).await.unwrap();
let grid_blocks = editor.get_blocks().await.unwrap();
let row_metas = editor.get_row_metas(&None).await.unwrap();
let grid_id = test.view.id;
Self { sdk, grid_id, editor }
Self {
sdk,
grid_id,
editor,
fields,
grid_blocks,
row_metas,
}
}
pub async fn run_scripts(&mut self, scripts: Vec<EditorScript>) {
@ -56,16 +109,20 @@ impl GridEditorTest {
match script {
EditorScript::CreateField { field } => {
self.editor.create_field(field).await.unwrap();
self.fields = self.editor.get_fields(None).await.unwrap();
}
EditorScript::UpdateField { change } => {
EditorScript::UpdateField { changeset: change } => {
self.editor.update_field(change).await.unwrap();
self.fields = self.editor.get_fields(None).await.unwrap();
}
EditorScript::DeleteField { field } => {
self.editor.delete_field(&field.id).await.unwrap();
self.fields = self.editor.get_fields(None).await.unwrap();
}
EditorScript::AssertFieldCount(count) => {
assert_eq!(self.editor.get_fields(None).await.unwrap().len(), count);
}
EditorScript::AssertFieldEqual { field_index, field } => {
let repeated_fields = self.editor.get_fields(None).await.unwrap();
let compared_field = repeated_fields[field_index].clone();
@ -73,23 +130,60 @@ impl GridEditorTest {
}
EditorScript::CreateBlock { block } => {
self.editor.create_block(block).await.unwrap();
self.grid_blocks = self.editor.get_blocks().await.unwrap();
}
EditorScript::UpdateBlock { change } => {
EditorScript::UpdateBlock { changeset: change } => {
self.editor.update_block(change).await.unwrap();
}
EditorScript::AssertBlockCount(count) => {
assert_eq!(self.editor.get_blocks().await.unwrap().len(), count);
}
EditorScript::AssertBlock {
block_index,
row_count,
start_row_index,
} => {
assert_eq!(self.grid_blocks[block_index].row_count, row_count);
assert_eq!(self.grid_blocks[block_index].start_row_index, start_row_index);
}
EditorScript::AssertBlockEqual { block_index, block } => {
let blocks = self.editor.get_blocks().await.unwrap();
let compared_block = blocks[block_index].clone();
assert_eq!(compared_block, block);
}
EditorScript::CreateRow => {
EditorScript::CreateEmptyRow => {
self.editor.create_row().await.unwrap();
self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
self.grid_blocks = self.editor.get_blocks().await.unwrap();
}
EditorScript::CreateRow { context } => {
self.editor.insert_rows(vec![context]).await.unwrap();
self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
self.grid_blocks = self.editor.get_blocks().await.unwrap();
}
EditorScript::UpdateRow { changeset: change } => self.editor.update_row(change).await.unwrap(),
EditorScript::DeleteRow { row_ids } => {
self.editor.delete_rows(row_ids).await.unwrap();
self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
self.grid_blocks = self.editor.get_blocks().await.unwrap();
}
EditorScript::AssertRow { changeset } => {
let row = self.row_metas.iter().find(|row| row.id == changeset.row_id).unwrap();
if let Some(visibility) = changeset.visibility {
assert_eq!(row.visibility, visibility);
}
if let Some(height) = changeset.height {
assert_eq!(row.height, height);
}
}
EditorScript::UpdateCell { changeset } => {
self.editor.update_cell(changeset).await.unwrap();
self.row_metas = self.editor.get_row_metas(&None).await.unwrap();
}
EditorScript::AssertRowCount(count) => {
assert_eq!(self.editor.get_all_rows().await.unwrap().len(), count);
assert_eq!(self.editor.get_rows(None).await.unwrap().len(), count);
}
EditorScript::AssertGridMetaPad => {
sleep(Duration::from_millis(2 * REVISION_WRITE_INTERVAL_IN_MILLIS)).await;
@ -102,7 +196,7 @@ impl GridEditorTest {
}
pub fn create_text_field() -> Field {
FieldBuilder::new(RichTextTypeOptionsBuilder::new())
FieldBuilder::new(RichTextTypeOptionsBuilder::default())
.name("Name")
.visibility(true)
.field_type(FieldType::RichText)
@ -110,7 +204,7 @@ pub fn create_text_field() -> Field {
}
pub fn create_single_select_field() -> Field {
let single_select = SingleSelectTypeOptionsBuilder::new()
let single_select = SingleSelectTypeOptionsBuilder::default()
.option(SelectOption::new("Done"))
.option(SelectOption::new("Progress"));

View File

@ -33,6 +33,7 @@ impl GridBuilder {
pub fn add_empty_row(mut self) -> Self {
let row = RowMeta::new(&self.grid_block.id);
self.grid_block_meta.rows.push(row);
self.grid_block.row_count += 1;
self
}

View File

@ -82,41 +82,41 @@ impl GridMetaPad {
}
}
pub fn update_field(&mut self, change: FieldChangeset) -> CollaborateResult<Option<GridChange>> {
let field_id = change.field_id.clone();
pub fn update_field(&mut self, changeset: FieldChangeset) -> CollaborateResult<Option<GridChange>> {
let field_id = changeset.field_id.clone();
self.modify_field(&field_id, |field| {
let mut is_changed = None;
if let Some(name) = change.name {
if let Some(name) = changeset.name {
field.name = name;
is_changed = Some(())
}
if let Some(desc) = change.desc {
if let Some(desc) = changeset.desc {
field.desc = desc;
is_changed = Some(())
}
if let Some(field_type) = change.field_type {
if let Some(field_type) = changeset.field_type {
field.field_type = field_type;
is_changed = Some(())
}
if let Some(frozen) = change.frozen {
if let Some(frozen) = changeset.frozen {
field.frozen = frozen;
is_changed = Some(())
}
if let Some(visibility) = change.visibility {
if let Some(visibility) = changeset.visibility {
field.visibility = visibility;
is_changed = Some(())
}
if let Some(width) = change.width {
if let Some(width) = changeset.width {
field.width = width;
is_changed = Some(())
}
if let Some(type_options) = change.type_options {
if let Some(type_options) = changeset.type_options {
field.type_options = type_options;
is_changed = Some(())
}
@ -141,17 +141,17 @@ impl GridMetaPad {
self.grid_meta.blocks.clone()
}
pub fn update_block(&mut self, change: GridBlockChangeset) -> CollaborateResult<Option<GridChange>> {
let block_id = change.block_id.clone();
pub fn update_block(&mut self, changeset: GridBlockChangeset) -> CollaborateResult<Option<GridChange>> {
let block_id = changeset.block_id.clone();
self.modify_block(&block_id, |block| {
let mut is_changed = None;
if let Some(row_count) = change.row_count {
if let Some(row_count) = changeset.row_count {
block.row_count = row_count;
is_changed = Some(());
}
if let Some(start_row_index) = change.start_row_index {
if let Some(start_row_index) = changeset.start_row_index {
block.start_row_index = start_row_index;
is_changed = Some(());
}

View File

@ -297,3 +297,36 @@ impl CellMeta {
}
}
}
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct CellMetaChangeset {
#[pb(index = 1)]
pub row_id: String,
#[pb(index = 2)]
pub field_id: String,
#[pb(index = 3, one_of)]
pub data: Option<String>,
}
impl std::convert::From<CellMetaChangeset> for RowMetaChangeset {
fn from(changeset: CellMetaChangeset) -> Self {
let mut cell_by_field_id = HashMap::with_capacity(1);
if let Some(data) = changeset.data {
let field_id = changeset.field_id;
let cell_meta = CellMeta {
field_id: field_id.clone(),
data,
};
cell_by_field_id.insert(field_id, cell_meta);
}
RowMetaChangeset {
row_id: changeset.row_id,
height: None,
visibility: None,
cell_by_field_id,
}
}
}

View File

@ -2956,6 +2956,289 @@ impl ::protobuf::reflect::ProtobufValue for CellMeta {
}
}
#[derive(PartialEq,Clone,Default)]
pub struct CellMetaChangeset {
// message fields
pub row_id: ::std::string::String,
pub field_id: ::std::string::String,
// message oneof groups
pub one_of_data: ::std::option::Option<CellMetaChangeset_oneof_one_of_data>,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a CellMetaChangeset {
fn default() -> &'a CellMetaChangeset {
<CellMetaChangeset as ::protobuf::Message>::default_instance()
}
}
#[derive(Clone,PartialEq,Debug)]
pub enum CellMetaChangeset_oneof_one_of_data {
data(::std::string::String),
}
impl CellMetaChangeset {
pub fn new() -> CellMetaChangeset {
::std::default::Default::default()
}
// string row_id = 1;
pub fn get_row_id(&self) -> &str {
&self.row_id
}
pub fn clear_row_id(&mut self) {
self.row_id.clear();
}
// Param is passed by value, moved
pub fn set_row_id(&mut self, v: ::std::string::String) {
self.row_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_row_id(&mut self) -> &mut ::std::string::String {
&mut self.row_id
}
// Take field
pub fn take_row_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.row_id, ::std::string::String::new())
}
// string field_id = 2;
pub fn get_field_id(&self) -> &str {
&self.field_id
}
pub fn clear_field_id(&mut self) {
self.field_id.clear();
}
// Param is passed by value, moved
pub fn set_field_id(&mut self, v: ::std::string::String) {
self.field_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_field_id(&mut self) -> &mut ::std::string::String {
&mut self.field_id
}
// Take field
pub fn take_field_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.field_id, ::std::string::String::new())
}
// string data = 3;
pub fn get_data(&self) -> &str {
match self.one_of_data {
::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(ref v)) => v,
_ => "",
}
}
pub fn clear_data(&mut self) {
self.one_of_data = ::std::option::Option::None;
}
pub fn has_data(&self) -> bool {
match self.one_of_data {
::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(..)) => true,
_ => false,
}
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::string::String) {
self.one_of_data = ::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(v))
}
// Mutable pointer to the field.
pub fn mut_data(&mut self) -> &mut ::std::string::String {
if let ::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(_)) = self.one_of_data {
} else {
self.one_of_data = ::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(::std::string::String::new()));
}
match self.one_of_data {
::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(ref mut v)) => v,
_ => panic!(),
}
}
// Take field
pub fn take_data(&mut self) -> ::std::string::String {
if self.has_data() {
match self.one_of_data.take() {
::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(v)) => v,
_ => panic!(),
}
} else {
::std::string::String::new()
}
}
}
impl ::protobuf::Message for CellMetaChangeset {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.row_id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?;
},
3 => {
if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
self.one_of_data = ::std::option::Option::Some(CellMetaChangeset_oneof_one_of_data::data(is.read_string()?));
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.row_id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.row_id);
}
if !self.field_id.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.field_id);
}
if let ::std::option::Option::Some(ref v) = self.one_of_data {
match v {
&CellMetaChangeset_oneof_one_of_data::data(ref v) => {
my_size += ::protobuf::rt::string_size(3, &v);
},
};
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.row_id.is_empty() {
os.write_string(1, &self.row_id)?;
}
if !self.field_id.is_empty() {
os.write_string(2, &self.field_id)?;
}
if let ::std::option::Option::Some(ref v) = self.one_of_data {
match v {
&CellMetaChangeset_oneof_one_of_data::data(ref v) => {
os.write_string(3, v)?;
},
};
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> CellMetaChangeset {
CellMetaChangeset::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"row_id",
|m: &CellMetaChangeset| { &m.row_id },
|m: &mut CellMetaChangeset| { &mut m.row_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"field_id",
|m: &CellMetaChangeset| { &m.field_id },
|m: &mut CellMetaChangeset| { &mut m.field_id },
));
fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
"data",
CellMetaChangeset::has_data,
CellMetaChangeset::get_data,
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<CellMetaChangeset>(
"CellMetaChangeset",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static CellMetaChangeset {
static instance: ::protobuf::rt::LazyV2<CellMetaChangeset> = ::protobuf::rt::LazyV2::INIT;
instance.get(CellMetaChangeset::new)
}
}
impl ::protobuf::Clear for CellMetaChangeset {
fn clear(&mut self) {
self.row_id.clear();
self.field_id.clear();
self.one_of_data = ::std::option::Option::None;
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for CellMetaChangeset {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for CellMetaChangeset {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum FieldType {
RichText = 0,
@ -3059,10 +3342,13 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05\
value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"9\n\
\x08CellMeta\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\
\x12\n\x04data\x18\x02\x20\x01(\tR\x04data*d\n\tFieldType\x12\x0c\n\x08R\
ichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\
\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\
\x0c\n\x08Checkbox\x10\x05b\x06proto3\
\x12\n\x04data\x18\x02\x20\x01(\tR\x04data\"j\n\x11CellMetaChangeset\x12\
\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\
\x02\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x03\x20\x01(\tH\0R\x04\
dataB\r\n\x0bone_of_data*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\
\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingle\
Select\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\
\x10\x05b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -58,6 +58,11 @@ message CellMeta {
string field_id = 1;
string data = 2;
}
message CellMetaChangeset {
string row_id = 1;
string field_id = 2;
oneof one_of_data { string data = 3; };
}
enum FieldType {
RichText = 0;
Number = 1;