mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add field builder
This commit is contained in:
parent
6579940dc8
commit
1e6d82c0ec
@ -1,3 +1,3 @@
|
||||
// Auto-generated, do not edit
|
||||
export './cell_data.pb.dart';
|
||||
export './type_options.pb.dart';
|
||||
export './event_map.pb.dart';
|
||||
|
@ -0,0 +1,458 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: type_options.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 'type_options.pbenum.dart';
|
||||
|
||||
export 'type_options.pbenum.dart';
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: type_options.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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -0,0 +1,125 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: type_options.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 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 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');
|
||||
@$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');
|
||||
@$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==');
|
||||
@$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');
|
||||
@$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=');
|
@ -0,0 +1,9 @@
|
||||
///
|
||||
// Generated code. Do not modify.
|
||||
// source: type_options.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 'type_options.pb.dart';
|
||||
|
2
frontend/rust-lib/Cargo.lock
generated
2
frontend/rust-lib/Cargo.lock
generated
@ -1059,8 +1059,10 @@ dependencies = [
|
||||
"flowy-database",
|
||||
"flowy-derive",
|
||||
"flowy-error",
|
||||
"flowy-grid",
|
||||
"flowy-grid-data-model",
|
||||
"flowy-sync",
|
||||
"flowy-test",
|
||||
"lazy_static",
|
||||
"lib-dispatch",
|
||||
"lib-infra",
|
||||
|
@ -39,7 +39,7 @@ impl ClientTextBlockEditor {
|
||||
rev_web_socket: Arc<dyn RevisionWebSocket>,
|
||||
cloud_service: Arc<dyn RevisionCloudService>,
|
||||
) -> FlowyResult<Arc<Self>> {
|
||||
let document_info = rev_manager.load::<TextBlockInfoBuilder>(cloud_service).await?;
|
||||
let document_info = rev_manager.load::<TextBlockInfoBuilder>(Some(cloud_service)).await?;
|
||||
let delta = document_info.delta()?;
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let doc_id = doc_id.to_string();
|
||||
@ -191,17 +191,9 @@ fn spawn_edit_queue(
|
||||
|
||||
#[cfg(feature = "flowy_unit_test")]
|
||||
impl ClientTextBlockEditor {
|
||||
pub async fn doc_json(&self) -> FlowyResult<String> {
|
||||
let (ret, rx) = oneshot::channel::<CollaborateResult<String>>();
|
||||
let msg = EditorCommand::ReadDeltaStr { ret };
|
||||
let _ = self.edit_cmd_tx.send(msg).await;
|
||||
let s = rx.await.map_err(internal_error)??;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub async fn doc_delta(&self) -> FlowyResult<RichTextDelta> {
|
||||
pub async fn text_block_delta(&self) -> FlowyResult<RichTextDelta> {
|
||||
let (ret, rx) = oneshot::channel::<CollaborateResult<RichTextDelta>>();
|
||||
let msg = EditorCommand::ReadBlockDelta { ret };
|
||||
let msg = EditorCommand::ReadDelta { ret };
|
||||
let _ = self.edit_cmd_tx.send(msg).await;
|
||||
let delta = rx.await.map_err(internal_error)??;
|
||||
Ok(delta)
|
||||
|
@ -166,7 +166,7 @@ impl EditBlockQueue {
|
||||
let data = self.document.read().await.delta_str();
|
||||
let _ = ret.send(Ok(data));
|
||||
}
|
||||
EditorCommand::ReadBlockDelta { ret } => {
|
||||
EditorCommand::ReadDelta { ret } => {
|
||||
let delta = self.document.read().await.delta().clone();
|
||||
let _ = ret.send(Ok(delta));
|
||||
}
|
||||
@ -256,7 +256,7 @@ pub(crate) enum EditorCommand {
|
||||
ret: Ret<String>,
|
||||
},
|
||||
#[allow(dead_code)]
|
||||
ReadBlockDelta {
|
||||
ReadDelta {
|
||||
ret: Ret<RichTextDelta>,
|
||||
},
|
||||
}
|
||||
@ -277,7 +277,7 @@ impl std::fmt::Debug for EditorCommand {
|
||||
EditorCommand::Undo { .. } => "Undo",
|
||||
EditorCommand::Redo { .. } => "Redo",
|
||||
EditorCommand::ReadDeltaStr { .. } => "ReadDeltaStr",
|
||||
EditorCommand::ReadBlockDelta { .. } => "ReadDocumentAsDelta",
|
||||
EditorCommand::ReadDelta { .. } => "ReadDocumentAsDelta",
|
||||
};
|
||||
f.write_str(s)
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
mod document_test;
|
||||
mod edit_script;
|
||||
mod script;
|
||||
mod text_block_test;
|
||||
|
@ -17,16 +17,16 @@ pub enum EditorScript {
|
||||
AssertJson(&'static str),
|
||||
}
|
||||
|
||||
pub struct EditorTest {
|
||||
pub struct TextBlockEditorTest {
|
||||
pub sdk: FlowySDKTest,
|
||||
pub editor: Arc<ClientTextBlockEditor>,
|
||||
}
|
||||
|
||||
impl EditorTest {
|
||||
impl TextBlockEditorTest {
|
||||
pub async fn new() -> Self {
|
||||
let sdk = FlowySDKTest::default();
|
||||
let _ = sdk.init_user().await;
|
||||
let test = ViewTest::new(&sdk).await;
|
||||
let test = ViewTest::new_grid_view(&sdk).await;
|
||||
let editor = sdk.text_block_manager.open_block(&test.view.id).await.unwrap();
|
||||
Self { sdk, editor }
|
||||
}
|
||||
@ -41,8 +41,6 @@ impl EditorTest {
|
||||
let rev_manager = self.editor.rev_manager();
|
||||
let cache = rev_manager.revision_cache().await;
|
||||
let _user_id = self.sdk.user_session.user_id().unwrap();
|
||||
// let ws_manager = self.sdk.ws_conn.clone();
|
||||
// let token = self.sdk.user_session.token().unwrap();
|
||||
|
||||
match script {
|
||||
EditorScript::InsertText(s, offset) => {
|
||||
@ -74,7 +72,7 @@ impl EditorTest {
|
||||
}
|
||||
EditorScript::AssertJson(expected) => {
|
||||
let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap();
|
||||
let delta = self.editor.doc_delta().await.unwrap();
|
||||
let delta = self.editor.text_block_delta().await.unwrap();
|
||||
if expected_delta != delta {
|
||||
eprintln!("✅ expect: {}", expected,);
|
||||
eprintln!("❌ receive: {}", delta.to_delta_str());
|
@ -1,9 +1,9 @@
|
||||
use crate::document::edit_script::{EditorScript::*, *};
|
||||
use crate::document::script::{EditorScript::*, *};
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use lib_ot::core::{count_utf16_code_units, Interval};
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_current_rev_id_check() {
|
||||
async fn text_block_sync_current_rev_id_check() {
|
||||
let scripts = vec![
|
||||
InsertText("1", 0),
|
||||
AssertCurrentRevId(1),
|
||||
@ -14,11 +14,11 @@ async fn document_sync_current_rev_id_check() {
|
||||
AssertNextSyncRevId(None),
|
||||
AssertJson(r#"[{"insert":"123\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_state_check() {
|
||||
async fn text_block_sync_state_check() {
|
||||
let scripts = vec![
|
||||
InsertText("1", 0),
|
||||
InsertText("2", 1),
|
||||
@ -28,11 +28,11 @@ async fn document_sync_state_check() {
|
||||
AssertRevisionState(3, RevisionState::Ack),
|
||||
AssertJson(r#"[{"insert":"123\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_insert_test() {
|
||||
async fn text_block_sync_insert_test() {
|
||||
let scripts = vec![
|
||||
InsertText("1", 0),
|
||||
InsertText("2", 1),
|
||||
@ -40,11 +40,11 @@ async fn document_sync_insert_test() {
|
||||
AssertJson(r#"[{"insert":"123\n"}]"#),
|
||||
AssertNextSyncRevId(None),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_insert_in_chinese() {
|
||||
async fn text_block_sync_insert_in_chinese() {
|
||||
let s = "好".to_owned();
|
||||
let offset = count_utf16_code_units(&s);
|
||||
let scripts = vec![
|
||||
@ -52,11 +52,11 @@ async fn document_sync_insert_in_chinese() {
|
||||
InsertText("好", offset),
|
||||
AssertJson(r#"[{"insert":"你好\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_insert_with_emoji() {
|
||||
async fn text_block_sync_insert_with_emoji() {
|
||||
let s = "😁".to_owned();
|
||||
let offset = count_utf16_code_units(&s);
|
||||
let scripts = vec![
|
||||
@ -64,11 +64,11 @@ async fn document_sync_insert_with_emoji() {
|
||||
InsertText("☺️", offset),
|
||||
AssertJson(r#"[{"insert":"😁☺️\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_delete_in_english() {
|
||||
async fn text_block_sync_delete_in_english() {
|
||||
let scripts = vec![
|
||||
InsertText("1", 0),
|
||||
InsertText("2", 1),
|
||||
@ -76,11 +76,11 @@ async fn document_sync_delete_in_english() {
|
||||
Delete(Interval::new(0, 2)),
|
||||
AssertJson(r#"[{"insert":"3\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_delete_in_chinese() {
|
||||
async fn text_block_sync_delete_in_chinese() {
|
||||
let s = "好".to_owned();
|
||||
let offset = count_utf16_code_units(&s);
|
||||
let scripts = vec![
|
||||
@ -89,11 +89,11 @@ async fn document_sync_delete_in_chinese() {
|
||||
Delete(Interval::new(0, offset)),
|
||||
AssertJson(r#"[{"insert":"好\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_sync_replace_test() {
|
||||
async fn text_block_sync_replace_test() {
|
||||
let scripts = vec![
|
||||
InsertText("1", 0),
|
||||
InsertText("2", 1),
|
||||
@ -101,5 +101,5 @@ async fn document_sync_replace_test() {
|
||||
Replace(Interval::new(0, 3), "abc"),
|
||||
AssertJson(r#"[{"insert":"abc\n"}]"#),
|
||||
];
|
||||
EditorTest::new().await.run_scripts(scripts).await;
|
||||
TextBlockEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
@ -38,7 +38,7 @@ impl ClientFolderEditor {
|
||||
let cloud = Arc::new(FolderRevisionCloudService {
|
||||
token: token.to_string(),
|
||||
});
|
||||
let folder = Arc::new(RwLock::new(rev_manager.load::<FolderPadBuilder>(cloud).await?));
|
||||
let folder = Arc::new(RwLock::new(rev_manager.load::<FolderPadBuilder>(Some(cloud)).await?));
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let ws_manager = make_folder_ws_manager(
|
||||
user_id,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
|
||||
|
||||
use flowy_folder::entities::workspace::CreateWorkspacePayload;
|
||||
use flowy_folder_data_model::entities::view::ViewDataType;
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
|
||||
@ -136,10 +137,12 @@ async fn app_create_with_view() {
|
||||
CreateView {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
},
|
||||
CreateView {
|
||||
name: "View B".to_owned(),
|
||||
desc: "View B description".to_owned(),
|
||||
name: "Grid".to_owned(),
|
||||
desc: "Grid description".to_owned(),
|
||||
data_type: ViewDataType::Grid,
|
||||
},
|
||||
ReadApp(app.id),
|
||||
])
|
||||
@ -148,7 +151,7 @@ async fn app_create_with_view() {
|
||||
app = test.app.clone();
|
||||
assert_eq!(app.belongings.len(), 3);
|
||||
assert_eq!(app.belongings[1].name, "View A");
|
||||
assert_eq!(app.belongings[2].name, "View B")
|
||||
assert_eq!(app.belongings[2].name, "Grid")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@ -198,10 +201,12 @@ async fn view_delete_all() {
|
||||
CreateView {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
},
|
||||
CreateView {
|
||||
name: "View B".to_owned(),
|
||||
desc: "View B description".to_owned(),
|
||||
name: "Grid".to_owned(),
|
||||
desc: "Grid description".to_owned(),
|
||||
data_type: ViewDataType::Grid,
|
||||
},
|
||||
ReadApp(app.id.clone()),
|
||||
])
|
||||
@ -229,6 +234,7 @@ async fn view_delete_all_permanent() {
|
||||
CreateView {
|
||||
name: "View A".to_owned(),
|
||||
desc: "View A description".to_owned(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
},
|
||||
ReadApp(app.id.clone()),
|
||||
])
|
||||
@ -327,6 +333,7 @@ async fn folder_sync_revision_with_new_view() {
|
||||
CreateView {
|
||||
name: view_name.clone(),
|
||||
desc: view_desc.clone(),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
},
|
||||
AssertCurrentRevId(3),
|
||||
AssertNextSyncRevId(Some(3)),
|
||||
|
@ -1,212 +0,0 @@
|
||||
use flowy_collaboration::entities::text_block_info::TextBlockInfo;
|
||||
use flowy_folder::event_map::FolderEvent::*;
|
||||
use flowy_folder_data_model::entities::view::{RepeatedViewId, ViewId};
|
||||
use flowy_folder_data_model::entities::workspace::WorkspaceId;
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{App, AppId, CreateAppPayload, UpdateAppPayload},
|
||||
trash::{RepeatedTrash, TrashId, TrashType},
|
||||
view::{CreateViewPayload, UpdateViewPayload, View, ViewDataType},
|
||||
workspace::{CreateWorkspacePayload, RepeatedWorkspace, Workspace},
|
||||
};
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
|
||||
pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspace {
|
||||
let request = CreateWorkspacePayload {
|
||||
name: name.to_owned(),
|
||||
desc: desc.to_owned(),
|
||||
};
|
||||
|
||||
let workspace = FolderEventBuilder::new(sdk.clone())
|
||||
.event(CreateWorkspace)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<Workspace>();
|
||||
workspace
|
||||
}
|
||||
|
||||
pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) -> Vec<Workspace> {
|
||||
let request = WorkspaceId { value: workspace_id };
|
||||
let repeated_workspace = FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadWorkspaces)
|
||||
.payload(request.clone())
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedWorkspace>();
|
||||
|
||||
let workspaces;
|
||||
if let Some(workspace_id) = &request.value {
|
||||
workspaces = repeated_workspace
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.filter(|workspace| &workspace.id == workspace_id)
|
||||
.collect::<Vec<Workspace>>();
|
||||
debug_assert_eq!(workspaces.len(), 1);
|
||||
} else {
|
||||
workspaces = repeated_workspace.items;
|
||||
}
|
||||
|
||||
workspaces
|
||||
}
|
||||
|
||||
pub async fn create_app(sdk: &FlowySDKTest, workspace_id: &str, name: &str, desc: &str) -> App {
|
||||
let create_app_request = CreateAppPayload {
|
||||
workspace_id: workspace_id.to_owned(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
color_style: Default::default(),
|
||||
};
|
||||
|
||||
let app = FolderEventBuilder::new(sdk.clone())
|
||||
.event(CreateApp)
|
||||
.payload(create_app_request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<App>();
|
||||
app
|
||||
}
|
||||
|
||||
pub async fn read_app(sdk: &FlowySDKTest, app_id: &str) -> App {
|
||||
let request = AppId {
|
||||
value: app_id.to_owned(),
|
||||
};
|
||||
|
||||
let app = FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadApp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<App>();
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
pub async fn update_app(sdk: &FlowySDKTest, app_id: &str, name: Option<String>, desc: Option<String>) {
|
||||
let request = UpdateAppPayload {
|
||||
app_id: app_id.to_string(),
|
||||
name,
|
||||
desc,
|
||||
color_style: None,
|
||||
is_trash: None,
|
||||
};
|
||||
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(UpdateApp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
|
||||
let request = AppId {
|
||||
value: app_id.to_string(),
|
||||
};
|
||||
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteApp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, data_type: ViewDataType) -> View {
|
||||
let request = CreateViewPayload {
|
||||
belong_to_id: app_id.to_string(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
thumbnail: None,
|
||||
data_type,
|
||||
ext_data: "".to_string(),
|
||||
plugin_type: 0,
|
||||
};
|
||||
let view = FolderEventBuilder::new(sdk.clone())
|
||||
.event(CreateView)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<View>();
|
||||
view
|
||||
}
|
||||
|
||||
pub async fn read_view(sdk: &FlowySDKTest, view_id: &str) -> View {
|
||||
let view_id: ViewId = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadView)
|
||||
.payload(view_id)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<View>()
|
||||
}
|
||||
|
||||
pub async fn update_view(sdk: &FlowySDKTest, view_id: &str, name: Option<String>, desc: Option<String>) {
|
||||
let request = UpdateViewPayload {
|
||||
view_id: view_id.to_string(),
|
||||
name,
|
||||
desc,
|
||||
thumbnail: None,
|
||||
};
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(UpdateView)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec<String>) {
|
||||
let request = RepeatedViewId { items: view_ids };
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteView)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn set_latest_view(sdk: &FlowySDKTest, view_id: &str) -> TextBlockInfo {
|
||||
let view_id: ViewId = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(SetLatestView)
|
||||
.payload(view_id)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<TextBlockInfo>()
|
||||
}
|
||||
|
||||
pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrash {
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadTrash)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedTrash>()
|
||||
}
|
||||
|
||||
pub async fn restore_app_from_trash(sdk: &FlowySDKTest, app_id: &str) {
|
||||
let id = TrashId {
|
||||
id: app_id.to_owned(),
|
||||
ty: TrashType::TrashApp,
|
||||
};
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(PutbackTrash)
|
||||
.payload(id)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn restore_view_from_trash(sdk: &FlowySDKTest, view_id: &str) {
|
||||
let id = TrashId {
|
||||
id: view_id.to_owned(),
|
||||
ty: TrashType::TrashView,
|
||||
};
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(PutbackTrash)
|
||||
.payload(id)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn delete_all_trash(sdk: &FlowySDKTest) {
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteAllTrash)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
@ -1,3 +1,2 @@
|
||||
mod folder_test;
|
||||
mod helper;
|
||||
mod script;
|
||||
|
@ -1,39 +1,63 @@
|
||||
use crate::helper::*;
|
||||
|
||||
use flowy_collaboration::entities::text_block_info::TextBlockInfo;
|
||||
use flowy_folder::event_map::FolderEvent::*;
|
||||
use flowy_folder::{errors::ErrorCode, services::folder_editor::ClientFolderEditor};
|
||||
use flowy_folder_data_model::entities::view::{RepeatedViewId, ViewId};
|
||||
use flowy_folder_data_model::entities::workspace::WorkspaceId;
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{App, RepeatedApp},
|
||||
trash::Trash,
|
||||
view::{RepeatedView, View, ViewDataType},
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{AppId, CreateAppPayload, UpdateAppPayload},
|
||||
trash::{RepeatedTrash, TrashId, TrashType},
|
||||
view::{CreateViewPayload, UpdateViewPayload},
|
||||
workspace::{CreateWorkspacePayload, RepeatedWorkspace},
|
||||
};
|
||||
use flowy_sync::disk::RevisionState;
|
||||
use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS;
|
||||
use flowy_test::FlowySDKTest;
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::time::sleep;
|
||||
|
||||
pub enum FolderScript {
|
||||
// Workspace
|
||||
ReadAllWorkspaces,
|
||||
CreateWorkspace { name: String, desc: String },
|
||||
CreateWorkspace {
|
||||
name: String,
|
||||
desc: String,
|
||||
},
|
||||
AssertWorkspaceJson(String),
|
||||
AssertWorkspace(Workspace),
|
||||
ReadWorkspace(Option<String>),
|
||||
|
||||
// App
|
||||
CreateApp { name: String, desc: String },
|
||||
CreateApp {
|
||||
name: String,
|
||||
desc: String,
|
||||
},
|
||||
AssertAppJson(String),
|
||||
AssertApp(App),
|
||||
ReadApp(String),
|
||||
UpdateApp { name: Option<String>, desc: Option<String> },
|
||||
UpdateApp {
|
||||
name: Option<String>,
|
||||
desc: Option<String>,
|
||||
},
|
||||
DeleteApp,
|
||||
|
||||
// View
|
||||
CreateView { name: String, desc: String },
|
||||
CreateView {
|
||||
name: String,
|
||||
desc: String,
|
||||
data_type: ViewDataType,
|
||||
},
|
||||
AssertView(View),
|
||||
ReadView(String),
|
||||
UpdateView { name: Option<String>, desc: Option<String> },
|
||||
UpdateView {
|
||||
name: Option<String>,
|
||||
desc: Option<String>,
|
||||
},
|
||||
DeleteView,
|
||||
DeleteViews(Vec<String>),
|
||||
|
||||
@ -46,7 +70,10 @@ pub enum FolderScript {
|
||||
// Sync
|
||||
AssertCurrentRevId(i64),
|
||||
AssertNextSyncRevId(Option<i64>),
|
||||
AssertRevisionState { rev_id: i64, state: RevisionState },
|
||||
AssertRevisionState {
|
||||
rev_id: i64,
|
||||
state: RevisionState,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct FolderTest {
|
||||
@ -148,8 +175,8 @@ impl FolderTest {
|
||||
delete_app(sdk, &self.app.id).await;
|
||||
}
|
||||
|
||||
FolderScript::CreateView { name, desc } => {
|
||||
let view = create_view(sdk, &self.app.id, &name, &desc, ViewDataType::TextBlock).await;
|
||||
FolderScript::CreateView { name, desc, data_type } => {
|
||||
let view = create_view(sdk, &self.app.id, &name, &desc, data_type).await;
|
||||
self.view = view;
|
||||
}
|
||||
FolderScript::AssertView(view) => {
|
||||
@ -216,3 +243,204 @@ pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
|
||||
("1234".repeat(100), ErrorCode::WorkspaceNameTooLong),
|
||||
]
|
||||
}
|
||||
|
||||
pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspace {
|
||||
let request = CreateWorkspacePayload {
|
||||
name: name.to_owned(),
|
||||
desc: desc.to_owned(),
|
||||
};
|
||||
|
||||
let workspace = FolderEventBuilder::new(sdk.clone())
|
||||
.event(CreateWorkspace)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<Workspace>();
|
||||
workspace
|
||||
}
|
||||
|
||||
pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) -> Vec<Workspace> {
|
||||
let request = WorkspaceId { value: workspace_id };
|
||||
let repeated_workspace = FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadWorkspaces)
|
||||
.payload(request.clone())
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedWorkspace>();
|
||||
|
||||
let workspaces;
|
||||
if let Some(workspace_id) = &request.value {
|
||||
workspaces = repeated_workspace
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.filter(|workspace| &workspace.id == workspace_id)
|
||||
.collect::<Vec<Workspace>>();
|
||||
debug_assert_eq!(workspaces.len(), 1);
|
||||
} else {
|
||||
workspaces = repeated_workspace.items;
|
||||
}
|
||||
|
||||
workspaces
|
||||
}
|
||||
|
||||
pub async fn create_app(sdk: &FlowySDKTest, workspace_id: &str, name: &str, desc: &str) -> App {
|
||||
let create_app_request = CreateAppPayload {
|
||||
workspace_id: workspace_id.to_owned(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
color_style: Default::default(),
|
||||
};
|
||||
|
||||
let app = FolderEventBuilder::new(sdk.clone())
|
||||
.event(CreateApp)
|
||||
.payload(create_app_request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<App>();
|
||||
app
|
||||
}
|
||||
|
||||
pub async fn read_app(sdk: &FlowySDKTest, app_id: &str) -> App {
|
||||
let request = AppId {
|
||||
value: app_id.to_owned(),
|
||||
};
|
||||
|
||||
let app = FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadApp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<App>();
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
pub async fn update_app(sdk: &FlowySDKTest, app_id: &str, name: Option<String>, desc: Option<String>) {
|
||||
let request = UpdateAppPayload {
|
||||
app_id: app_id.to_string(),
|
||||
name,
|
||||
desc,
|
||||
color_style: None,
|
||||
is_trash: None,
|
||||
};
|
||||
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(UpdateApp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
|
||||
let request = AppId {
|
||||
value: app_id.to_string(),
|
||||
};
|
||||
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteApp)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, data_type: ViewDataType) -> View {
|
||||
let request = CreateViewPayload {
|
||||
belong_to_id: app_id.to_string(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
thumbnail: None,
|
||||
data_type,
|
||||
ext_data: "".to_string(),
|
||||
plugin_type: 0,
|
||||
};
|
||||
let view = FolderEventBuilder::new(sdk.clone())
|
||||
.event(CreateView)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<View>();
|
||||
view
|
||||
}
|
||||
|
||||
pub async fn read_view(sdk: &FlowySDKTest, view_id: &str) -> View {
|
||||
let view_id: ViewId = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadView)
|
||||
.payload(view_id)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<View>()
|
||||
}
|
||||
|
||||
pub async fn update_view(sdk: &FlowySDKTest, view_id: &str, name: Option<String>, desc: Option<String>) {
|
||||
let request = UpdateViewPayload {
|
||||
view_id: view_id.to_string(),
|
||||
name,
|
||||
desc,
|
||||
thumbnail: None,
|
||||
};
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(UpdateView)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec<String>) {
|
||||
let request = RepeatedViewId { items: view_ids };
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteView)
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn set_latest_view(sdk: &FlowySDKTest, view_id: &str) -> TextBlockInfo {
|
||||
let view_id: ViewId = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(SetLatestView)
|
||||
.payload(view_id)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<TextBlockInfo>()
|
||||
}
|
||||
|
||||
pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrash {
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadTrash)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedTrash>()
|
||||
}
|
||||
|
||||
pub async fn restore_app_from_trash(sdk: &FlowySDKTest, app_id: &str) {
|
||||
let id = TrashId {
|
||||
id: app_id.to_owned(),
|
||||
ty: TrashType::TrashApp,
|
||||
};
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(PutbackTrash)
|
||||
.payload(id)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn restore_view_from_trash(sdk: &FlowySDKTest, view_id: &str) {
|
||||
let id = TrashId {
|
||||
id: view_id.to_owned(),
|
||||
ty: TrashType::TrashView,
|
||||
};
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(PutbackTrash)
|
||||
.payload(id)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn delete_all_trash(sdk: &FlowySDKTest) {
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteAllTrash)
|
||||
.async_send()
|
||||
.await;
|
||||
}
|
||||
|
@ -34,10 +34,15 @@ tokio = {version = "1", features = ["sync"]}
|
||||
rayon = "1.5"
|
||||
parking_lot = "0.11"
|
||||
|
||||
[dev-dependencies]
|
||||
flowy-test = { path = "../flowy-test" }
|
||||
flowy-grid = { path = "../flowy-grid", features = ["flowy_unit_test"]}
|
||||
|
||||
[build-dependencies]
|
||||
lib-infra = { path = "../../../shared-lib/lib-infra", features = ["protobuf_file_gen", "proto_gen"] }
|
||||
|
||||
|
||||
[features]
|
||||
default = []
|
||||
dart = ["lib-infra/dart"]
|
||||
dart = ["lib-infra/dart"]
|
||||
flowy_unit_test = ["flowy-sync/flowy_unit_test"]
|
@ -1,3 +1,3 @@
|
||||
|
||||
proto_crates = ["src/event_map.rs", "src/services/cell_data.rs"]
|
||||
proto_crates = ["src/event_map.rs", "src/services/field/type_options.rs"]
|
||||
event_files = ["src/event_map.rs"]
|
@ -7,3 +7,4 @@ pub mod manager;
|
||||
|
||||
mod protobuf;
|
||||
pub mod services;
|
||||
pub mod util;
|
||||
|
@ -1,29 +1,17 @@
|
||||
#[macro_export]
|
||||
macro_rules! impl_any_data {
|
||||
macro_rules! impl_from_and_to_type_option {
|
||||
($target: ident, $field_type:expr) => {
|
||||
impl_field_type_data_from_field!($target);
|
||||
impl_field_type_data_from_field_type_option!($target);
|
||||
impl_type_option_from_field_data!($target, $field_type);
|
||||
impl_from_field_type_option!($target);
|
||||
impl_to_field_type_option!($target, $field_type);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_field_type_data_from_field {
|
||||
macro_rules! impl_from_field_type_option {
|
||||
($target: ident) => {
|
||||
impl std::convert::From<&Field> for $target {
|
||||
fn from(field: &Field) -> $target {
|
||||
$target::from(&field.type_options)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_field_type_data_from_field_type_option {
|
||||
($target: ident) => {
|
||||
impl std::convert::From<&AnyData> for $target {
|
||||
fn from(any_data: &AnyData) -> $target {
|
||||
match $target::try_from(Bytes::from(any_data.value.clone())) {
|
||||
match $target::try_from(Bytes::from(field.type_options.value.clone())) {
|
||||
Ok(obj) => obj,
|
||||
Err(err) => {
|
||||
tracing::error!("{} convert from any data failed, {:?}", stringify!($target), err);
|
||||
@ -36,26 +24,27 @@ macro_rules! impl_field_type_data_from_field_type_option {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_type_option_from_field_data {
|
||||
macro_rules! impl_to_field_type_option {
|
||||
($target: ident, $field_type:expr) => {
|
||||
impl $target {
|
||||
pub fn field_type() -> FieldType {
|
||||
pub fn field_type(&self) -> FieldType {
|
||||
$field_type
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<$target> for AnyData {
|
||||
fn from(field_data: $target) -> Self {
|
||||
match field_data.try_into() {
|
||||
fn from(field_description: $target) -> Self {
|
||||
let field_type = field_description.field_type();
|
||||
match field_description.try_into() {
|
||||
Ok(bytes) => {
|
||||
let bytes: Bytes = bytes;
|
||||
AnyData::from_bytes(&$target::field_type(), bytes)
|
||||
AnyData::from_bytes(field_type, bytes)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Field type data convert to AnyData fail, error: {:?}", e);
|
||||
// it's impossible to fail when unwrapping the default field type data
|
||||
let default_bytes: Bytes = $target::default().try_into().unwrap();
|
||||
AnyData::from_bytes(&$target::field_type(), default_bytes)
|
||||
AnyData::from_bytes(field_type, default_bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ impl GridManager {
|
||||
Ok(grid_editor)
|
||||
}
|
||||
|
||||
fn make_grid_rev_manager(&self, grid_id: &str, pool: Arc<ConnectionPool>) -> FlowyResult<RevisionManager> {
|
||||
pub fn make_grid_rev_manager(&self, grid_id: &str, pool: Arc<ConnectionPool>) -> FlowyResult<RevisionManager> {
|
||||
let user_id = self.grid_user.user_id()?;
|
||||
|
||||
let disk_cache = Arc::new(SQLiteGridRevisionPersistence::new(&user_id, pool));
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
// Auto-generated, do not edit
|
||||
|
||||
mod cell_data;
|
||||
pub use cell_data::*;
|
||||
mod type_options;
|
||||
pub use type_options::*;
|
||||
|
||||
mod event_map;
|
||||
pub use event_map::*;
|
||||
|
@ -17,7 +17,7 @@
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_results)]
|
||||
//! Generated file from `cell_data.proto`
|
||||
//! Generated file from `type_options.proto`
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
@ -514,7 +514,7 @@ impl ::protobuf::reflect::ProtobufValue for DateDescription {
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct SingleSelect {
|
||||
pub struct SingleSelectDescription {
|
||||
// message fields
|
||||
pub options: ::protobuf::RepeatedField<SelectOption>,
|
||||
pub disable_color: bool,
|
||||
@ -523,14 +523,14 @@ pub struct SingleSelect {
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a SingleSelect {
|
||||
fn default() -> &'a SingleSelect {
|
||||
<SingleSelect as ::protobuf::Message>::default_instance()
|
||||
impl<'a> ::std::default::Default for &'a SingleSelectDescription {
|
||||
fn default() -> &'a SingleSelectDescription {
|
||||
<SingleSelectDescription as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl SingleSelect {
|
||||
pub fn new() -> SingleSelect {
|
||||
impl SingleSelectDescription {
|
||||
pub fn new() -> SingleSelectDescription {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
@ -575,7 +575,7 @@ impl SingleSelect {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for SingleSelect {
|
||||
impl ::protobuf::Message for SingleSelectDescription {
|
||||
fn is_initialized(&self) -> bool {
|
||||
for v in &self.options {
|
||||
if !v.is_initialized() {
|
||||
@ -662,8 +662,8 @@ impl ::protobuf::Message for SingleSelect {
|
||||
Self::descriptor_static()
|
||||
}
|
||||
|
||||
fn new() -> SingleSelect {
|
||||
SingleSelect::new()
|
||||
fn new() -> SingleSelectDescription {
|
||||
SingleSelectDescription::new()
|
||||
}
|
||||
|
||||
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||
@ -672,29 +672,29 @@ impl ::protobuf::Message for SingleSelect {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<SelectOption>>(
|
||||
"options",
|
||||
|m: &SingleSelect| { &m.options },
|
||||
|m: &mut SingleSelect| { &mut m.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: &SingleSelect| { &m.disable_color },
|
||||
|m: &mut SingleSelect| { &mut m.disable_color },
|
||||
|m: &SingleSelectDescription| { &m.disable_color },
|
||||
|m: &mut SingleSelectDescription| { &mut m.disable_color },
|
||||
));
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<SingleSelect>(
|
||||
"SingleSelect",
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<SingleSelectDescription>(
|
||||
"SingleSelectDescription",
|
||||
fields,
|
||||
file_descriptor_proto()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static SingleSelect {
|
||||
static instance: ::protobuf::rt::LazyV2<SingleSelect> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(SingleSelect::new)
|
||||
fn default_instance() -> &'static SingleSelectDescription {
|
||||
static instance: ::protobuf::rt::LazyV2<SingleSelectDescription> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(SingleSelectDescription::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Clear for SingleSelect {
|
||||
impl ::protobuf::Clear for SingleSelectDescription {
|
||||
fn clear(&mut self) {
|
||||
self.options.clear();
|
||||
self.disable_color = false;
|
||||
@ -702,20 +702,20 @@ impl ::protobuf::Clear for SingleSelect {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for SingleSelect {
|
||||
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 SingleSelect {
|
||||
impl ::protobuf::reflect::ProtobufValue for SingleSelectDescription {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct MultiSelect {
|
||||
pub struct MultiSelectDescription {
|
||||
// message fields
|
||||
pub options: ::protobuf::RepeatedField<SelectOption>,
|
||||
pub disable_color: bool,
|
||||
@ -724,14 +724,14 @@ pub struct MultiSelect {
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a MultiSelect {
|
||||
fn default() -> &'a MultiSelect {
|
||||
<MultiSelect as ::protobuf::Message>::default_instance()
|
||||
impl<'a> ::std::default::Default for &'a MultiSelectDescription {
|
||||
fn default() -> &'a MultiSelectDescription {
|
||||
<MultiSelectDescription as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiSelect {
|
||||
pub fn new() -> MultiSelect {
|
||||
impl MultiSelectDescription {
|
||||
pub fn new() -> MultiSelectDescription {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
@ -776,7 +776,7 @@ impl MultiSelect {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for MultiSelect {
|
||||
impl ::protobuf::Message for MultiSelectDescription {
|
||||
fn is_initialized(&self) -> bool {
|
||||
for v in &self.options {
|
||||
if !v.is_initialized() {
|
||||
@ -863,8 +863,8 @@ impl ::protobuf::Message for MultiSelect {
|
||||
Self::descriptor_static()
|
||||
}
|
||||
|
||||
fn new() -> MultiSelect {
|
||||
MultiSelect::new()
|
||||
fn new() -> MultiSelectDescription {
|
||||
MultiSelectDescription::new()
|
||||
}
|
||||
|
||||
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||
@ -873,29 +873,29 @@ impl ::protobuf::Message for MultiSelect {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<SelectOption>>(
|
||||
"options",
|
||||
|m: &MultiSelect| { &m.options },
|
||||
|m: &mut MultiSelect| { &mut m.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: &MultiSelect| { &m.disable_color },
|
||||
|m: &mut MultiSelect| { &mut m.disable_color },
|
||||
|m: &MultiSelectDescription| { &m.disable_color },
|
||||
|m: &mut MultiSelectDescription| { &mut m.disable_color },
|
||||
));
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<MultiSelect>(
|
||||
"MultiSelect",
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<MultiSelectDescription>(
|
||||
"MultiSelectDescription",
|
||||
fields,
|
||||
file_descriptor_proto()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static MultiSelect {
|
||||
static instance: ::protobuf::rt::LazyV2<MultiSelect> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(MultiSelect::new)
|
||||
fn default_instance() -> &'static MultiSelectDescription {
|
||||
static instance: ::protobuf::rt::LazyV2<MultiSelectDescription> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(MultiSelectDescription::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Clear for MultiSelect {
|
||||
impl ::protobuf::Clear for MultiSelectDescription {
|
||||
fn clear(&mut self) {
|
||||
self.options.clear();
|
||||
self.disable_color = false;
|
||||
@ -903,13 +903,13 @@ impl ::protobuf::Clear for MultiSelect {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for MultiSelect {
|
||||
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 MultiSelect {
|
||||
impl ::protobuf::reflect::ProtobufValue for MultiSelectDescription {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||
}
|
||||
@ -1161,7 +1161,7 @@ impl ::protobuf::reflect::ProtobufValue for SelectOption {
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct NumberDescription {
|
||||
// message fields
|
||||
pub money: FlowyMoney,
|
||||
pub money: MoneySymbol,
|
||||
pub scale: u32,
|
||||
pub symbol: ::std::string::String,
|
||||
pub sign_positive: bool,
|
||||
@ -1182,18 +1182,18 @@ impl NumberDescription {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
// .FlowyMoney money = 1;
|
||||
// .MoneySymbol money = 1;
|
||||
|
||||
|
||||
pub fn get_money(&self) -> FlowyMoney {
|
||||
pub fn get_money(&self) -> MoneySymbol {
|
||||
self.money
|
||||
}
|
||||
pub fn clear_money(&mut self) {
|
||||
self.money = FlowyMoney::CNY;
|
||||
self.money = MoneySymbol::CNY;
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_money(&mut self, v: FlowyMoney) {
|
||||
pub fn set_money(&mut self, v: MoneySymbol) {
|
||||
self.money = v;
|
||||
}
|
||||
|
||||
@ -1324,7 +1324,7 @@ impl ::protobuf::Message for NumberDescription {
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u32 {
|
||||
let mut my_size = 0;
|
||||
if self.money != FlowyMoney::CNY {
|
||||
if self.money != MoneySymbol::CNY {
|
||||
my_size += ::protobuf::rt::enum_size(1, self.money);
|
||||
}
|
||||
if self.scale != 0 {
|
||||
@ -1345,7 +1345,7 @@ impl ::protobuf::Message for NumberDescription {
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||
if self.money != FlowyMoney::CNY {
|
||||
if self.money != MoneySymbol::CNY {
|
||||
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.money))?;
|
||||
}
|
||||
if self.scale != 0 {
|
||||
@ -1398,7 +1398,7 @@ impl ::protobuf::Message for NumberDescription {
|
||||
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||
descriptor.get(|| {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<FlowyMoney>>(
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<MoneySymbol>>(
|
||||
"money",
|
||||
|m: &NumberDescription| { &m.money },
|
||||
|m: &mut NumberDescription| { &mut m.money },
|
||||
@ -1439,7 +1439,7 @@ impl ::protobuf::Message for NumberDescription {
|
||||
|
||||
impl ::protobuf::Clear for NumberDescription {
|
||||
fn clear(&mut self) {
|
||||
self.money = FlowyMoney::CNY;
|
||||
self.money = MoneySymbol::CNY;
|
||||
self.scale = 0;
|
||||
self.symbol.clear();
|
||||
self.sign_positive = false;
|
||||
@ -1567,31 +1567,31 @@ impl ::protobuf::reflect::ProtobufValue for TimeFormat {
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||
pub enum FlowyMoney {
|
||||
pub enum MoneySymbol {
|
||||
CNY = 0,
|
||||
EUR = 1,
|
||||
USD = 2,
|
||||
}
|
||||
|
||||
impl ::protobuf::ProtobufEnum for FlowyMoney {
|
||||
impl ::protobuf::ProtobufEnum for MoneySymbol {
|
||||
fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
|
||||
fn from_i32(value: i32) -> ::std::option::Option<FlowyMoney> {
|
||||
fn from_i32(value: i32) -> ::std::option::Option<MoneySymbol> {
|
||||
match value {
|
||||
0 => ::std::option::Option::Some(FlowyMoney::CNY),
|
||||
1 => ::std::option::Option::Some(FlowyMoney::EUR),
|
||||
2 => ::std::option::Option::Some(FlowyMoney::USD),
|
||||
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 [FlowyMoney] = &[
|
||||
FlowyMoney::CNY,
|
||||
FlowyMoney::EUR,
|
||||
FlowyMoney::USD,
|
||||
static values: &'static [MoneySymbol] = &[
|
||||
MoneySymbol::CNY,
|
||||
MoneySymbol::EUR,
|
||||
MoneySymbol::USD,
|
||||
];
|
||||
values
|
||||
}
|
||||
@ -1599,47 +1599,48 @@ impl ::protobuf::ProtobufEnum for FlowyMoney {
|
||||
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::<FlowyMoney>("FlowyMoney", file_descriptor_proto())
|
||||
::protobuf::reflect::EnumDescriptor::new_pb_name::<MoneySymbol>("MoneySymbol", file_descriptor_proto())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::marker::Copy for FlowyMoney {
|
||||
impl ::std::marker::Copy for MoneySymbol {
|
||||
}
|
||||
|
||||
impl ::std::default::Default for FlowyMoney {
|
||||
impl ::std::default::Default for MoneySymbol {
|
||||
fn default() -> Self {
|
||||
FlowyMoney::CNY
|
||||
MoneySymbol::CNY
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for FlowyMoney {
|
||||
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\x0fcell_data.proto\"-\n\x13RichTextDescription\x12\x16\n\x06format\
|
||||
\n\x12type_options.proto\"-\n\x13RichTextDescription\x12\x16\n\x06format\
|
||||
\x18\x01\x20\x01(\tR\x06format\"6\n\x13CheckboxDescription\x12\x1f\n\x0b\
|
||||
is_selected\x18\x01\x20\x01(\x08R\nisSelected\"m\n\x0fDateDescription\
|
||||
\x12,\n\x0bdate_format\x18\x01\x20\x01(\x0e2\x0b.DateFormatR\ndateFormat\
|
||||
\x12,\n\x0btime_format\x18\x02\x20\x01(\x0e2\x0b.TimeFormatR\ntimeFormat\
|
||||
\"\\\n\x0cSingleSelect\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.SelectO\
|
||||
ptionR\x07options\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisable\
|
||||
Color\"[\n\x0bMultiSelect\x12'\n\x07options\x18\x01\x20\x03(\x0b2\r.Sele\
|
||||
ctOptionR\x07options\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\x0cdisa\
|
||||
bleColor\"H\n\x0cSelectOption\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\x05color\"\x9d\x01\n\x11NumberDescription\x12!\n\x05mon\
|
||||
ey\x18\x01\x20\x01(\x0e2\x0b.FlowyMoneyR\x05money\x12\x14\n\x05scale\x18\
|
||||
\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\tR\x06sym\
|
||||
bol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositive\x12\x12\
|
||||
\n\x04name\x18\x05\x20\x01(\tR\x04name*6\n\nDateFormat\x12\t\n\x05Local\
|
||||
\x10\0\x12\x06\n\x02US\x10\x01\x12\x07\n\x03ISO\x10\x02\x12\x0c\n\x08Fri\
|
||||
endly\x10\x03*0\n\nTimeFormat\x12\x0e\n\nTwelveHour\x10\0\x12\x12\n\x0eT\
|
||||
wentyFourHour\x10\x01*'\n\nFlowyMoney\x12\x07\n\x03CNY\x10\0\x12\x07\n\
|
||||
\x03EUR\x10\x01\x12\x07\n\x03USD\x10\x02b\x06proto3\
|
||||
\"g\n\x17SingleSelectDescription\x12'\n\x07options\x18\x01\x20\x03(\x0b2\
|
||||
\r.SelectOptionR\x07options\x12#\n\rdisable_color\x18\x02\x20\x01(\x08R\
|
||||
\x0cdisableColor\"f\n\x16MultiSelectDescription\x12'\n\x07options\x18\
|
||||
\x01\x20\x03(\x0b2\r.SelectOptionR\x07options\x12#\n\rdisable_color\x18\
|
||||
\x02\x20\x01(\x08R\x0cdisableColor\"H\n\x0cSelectOption\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\x05color\"\x9e\x01\n\x11NumberDe\
|
||||
scription\x12\"\n\x05money\x18\x01\x20\x01(\x0e2\x0c.MoneySymbolR\x05mon\
|
||||
ey\x12\x14\n\x05scale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\
|
||||
\x18\x03\x20\x01(\tR\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\
|
||||
\x08R\x0csignPositive\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04name*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\x01*(\n\x0bMoneySymbo\
|
||||
l\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;
|
@ -10,11 +10,11 @@ message DateDescription {
|
||||
DateFormat date_format = 1;
|
||||
TimeFormat time_format = 2;
|
||||
}
|
||||
message SingleSelect {
|
||||
message SingleSelectDescription {
|
||||
repeated SelectOption options = 1;
|
||||
bool disable_color = 2;
|
||||
}
|
||||
message MultiSelect {
|
||||
message MultiSelectDescription {
|
||||
repeated SelectOption options = 1;
|
||||
bool disable_color = 2;
|
||||
}
|
||||
@ -24,7 +24,7 @@ message SelectOption {
|
||||
string color = 3;
|
||||
}
|
||||
message NumberDescription {
|
||||
FlowyMoney money = 1;
|
||||
MoneySymbol money = 1;
|
||||
uint32 scale = 2;
|
||||
string symbol = 3;
|
||||
bool sign_positive = 4;
|
||||
@ -40,7 +40,7 @@ enum TimeFormat {
|
||||
TwelveHour = 0;
|
||||
TwentyFourHour = 1;
|
||||
}
|
||||
enum FlowyMoney {
|
||||
enum MoneySymbol {
|
||||
CNY = 0;
|
||||
EUR = 1;
|
||||
USD = 2;
|
@ -0,0 +1,34 @@
|
||||
use crate::services::field::*;
|
||||
use crate::services::util::*;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
|
||||
|
||||
pub trait StringifyCellData {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String;
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError>;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn stringify_serialize(field: &Field, s: &str) -> Result<AnyData, FlowyError> {
|
||||
match field.field_type {
|
||||
FieldType::RichText => RichTextDescription::from(field).str_to_cell_data(s),
|
||||
FieldType::Number => NumberDescription::from(field).str_to_cell_data(s),
|
||||
FieldType::DateTime => DateDescription::from(field).str_to_cell_data(s),
|
||||
FieldType::SingleSelect => SingleSelectDescription::from(field).str_to_cell_data(s),
|
||||
FieldType::MultiSelect => MultiSelectDescription::from(field).str_to_cell_data(s),
|
||||
FieldType::Checkbox => CheckboxDescription::from(field).str_to_cell_data(s),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn stringify_deserialize(data: AnyData, field: &Field) -> Result<String, FlowyError> {
|
||||
let _ = check_type_id(&data, field)?;
|
||||
let s = match field.field_type {
|
||||
FieldType::RichText => RichTextDescription::from(field).str_from_cell_data(data),
|
||||
FieldType::Number => NumberDescription::from(field).str_from_cell_data(data),
|
||||
FieldType::DateTime => DateDescription::from(field).str_from_cell_data(data),
|
||||
FieldType::SingleSelect => SingleSelectDescription::from(field).str_from_cell_data(data),
|
||||
FieldType::MultiSelect => MultiSelectDescription::from(field).str_from_cell_data(data),
|
||||
FieldType::Checkbox => CheckboxDescription::from(field).str_from_cell_data(data),
|
||||
};
|
||||
Ok(s)
|
||||
}
|
217
frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs
Normal file
217
frontend/rust-lib/flowy-grid/src/services/field/field_builder.rs
Normal file
@ -0,0 +1,217 @@
|
||||
use crate::services::field::{
|
||||
CheckboxDescription, DateDescription, DateFormat, MoneySymbol, MultiSelectDescription, NumberDescription,
|
||||
RichTextDescription, SelectOption, SingleSelectDescription, TimeFormat,
|
||||
};
|
||||
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
|
||||
|
||||
pub struct FieldBuilder {
|
||||
field: Field,
|
||||
type_options_builder: Box<dyn TypeOptionsBuilder>,
|
||||
}
|
||||
|
||||
impl FieldBuilder {
|
||||
pub fn new<T: TypeOptionsBuilder + 'static>(type_options_builder: T) -> Self {
|
||||
let field = Field::new("Name", "", FieldType::RichText);
|
||||
Self {
|
||||
field,
|
||||
type_options_builder: Box::new(type_options_builder),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(mut self, name: &str) -> Self {
|
||||
self.field.name = name.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn desc(mut self, desc: &str) -> Self {
|
||||
self.field.desc = desc.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn field_type(mut self, field_type: FieldType) -> Self {
|
||||
self.field.field_type = field_type;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn visibility(mut self, visibility: bool) -> Self {
|
||||
self.field.visibility = visibility;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn width(mut self, width: i32) -> Self {
|
||||
self.field.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn frozen(mut self, frozen: bool) -> Self {
|
||||
self.field.frozen = frozen;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(mut self) -> Field {
|
||||
assert_eq!(self.field.field_type, self.type_options_builder.field_type());
|
||||
|
||||
let type_options = self.type_options_builder.build();
|
||||
self.field.type_options = type_options;
|
||||
self.field
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TypeOptionsBuilder {
|
||||
fn field_type(&self) -> FieldType;
|
||||
fn build(&self) -> AnyData;
|
||||
}
|
||||
|
||||
// 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) -> AnyData {
|
||||
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) -> AnyData {
|
||||
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) -> AnyData {
|
||||
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) -> AnyData {
|
||||
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) -> AnyData {
|
||||
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) -> AnyData {
|
||||
self.0.clone().into()
|
||||
}
|
||||
}
|
7
frontend/rust-lib/flowy-grid/src/services/field/mod.rs
Normal file
7
frontend/rust-lib/flowy-grid/src/services/field/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
mod cell_stringify;
|
||||
mod field_builder;
|
||||
mod type_options;
|
||||
|
||||
pub use cell_stringify::*;
|
||||
pub use field_builder::*;
|
||||
pub use type_options::*;
|
@ -1,5 +1,6 @@
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
use crate::impl_any_data;
|
||||
use crate::impl_from_and_to_type_option;
|
||||
use crate::services::field::StringifyCellData;
|
||||
use crate::services::util::*;
|
||||
use bytes::Bytes;
|
||||
use chrono::format::strftime::StrftimeItems;
|
||||
@ -15,63 +16,42 @@ use rusty_money::{
|
||||
use std::str::FromStr;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
pub trait StringifyAnyData {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String;
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError>;
|
||||
}
|
||||
|
||||
pub trait DisplayCell {
|
||||
fn display_content(&self, s: &str) -> String;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, ProtoBuf, Default)]
|
||||
pub struct RichTextDescription {
|
||||
#[pb(index = 1)]
|
||||
pub format: String,
|
||||
}
|
||||
impl_any_data!(RichTextDescription, FieldType::RichText);
|
||||
impl_from_and_to_type_option!(RichTextDescription, FieldType::RichText);
|
||||
|
||||
impl StringifyAnyData for RichTextDescription {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String {
|
||||
impl StringifyCellData for RichTextDescription {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String {
|
||||
data.to_string()
|
||||
}
|
||||
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
Ok(AnyData::from_str(&RichTextDescription::field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayCell for RichTextDescription {
|
||||
fn display_content(&self, s: &str) -> String {
|
||||
s.to_string()
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
Ok(AnyData::from_str(self.field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
// Checkbox
|
||||
#[derive(Debug, ProtoBuf, Default)]
|
||||
#[derive(Debug, Clone, ProtoBuf, Default)]
|
||||
pub struct CheckboxDescription {
|
||||
#[pb(index = 1)]
|
||||
pub is_selected: bool,
|
||||
}
|
||||
impl_any_data!(CheckboxDescription, FieldType::Checkbox);
|
||||
impl_from_and_to_type_option!(CheckboxDescription, FieldType::Checkbox);
|
||||
|
||||
impl StringifyAnyData for CheckboxDescription {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String {
|
||||
impl StringifyCellData for CheckboxDescription {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String {
|
||||
data.to_string()
|
||||
}
|
||||
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
let s = match string_to_bool(s) {
|
||||
true => "1",
|
||||
false => "0",
|
||||
};
|
||||
Ok(AnyData::from_str(&CheckboxDescription::field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayCell for CheckboxDescription {
|
||||
fn display_content(&self, s: &str) -> String {
|
||||
s.to_string()
|
||||
Ok(AnyData::from_str(self.field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +64,7 @@ pub struct DateDescription {
|
||||
#[pb(index = 2)]
|
||||
pub time_format: TimeFormat,
|
||||
}
|
||||
impl_any_data!(DateDescription, FieldType::DateTime);
|
||||
impl_from_and_to_type_option!(DateDescription, FieldType::DateTime);
|
||||
|
||||
impl DateDescription {
|
||||
fn date_time_format_str(&self) -> String {
|
||||
@ -107,23 +87,8 @@ impl DateDescription {
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayCell for DateDescription {
|
||||
fn display_content(&self, s: &str) -> String {
|
||||
match s.parse::<i64>() {
|
||||
Ok(timestamp) => {
|
||||
let native = NaiveDateTime::from_timestamp(timestamp, 0);
|
||||
self.today_from_native(native)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::debug!("DateDescription format {} fail. error: {:?}", s, e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StringifyAnyData for DateDescription {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String {
|
||||
impl StringifyCellData for DateDescription {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String {
|
||||
match String::from_utf8(data.value) {
|
||||
Ok(s) => match s.parse::<i64>() {
|
||||
Ok(timestamp) => {
|
||||
@ -142,14 +107,11 @@ impl StringifyAnyData for DateDescription {
|
||||
}
|
||||
}
|
||||
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
let timestamp = s
|
||||
.parse::<i64>()
|
||||
.map_err(|e| FlowyError::internal().context(format!("Parse {} to i64 failed: {}", s, e)))?;
|
||||
Ok(AnyData::from_str(
|
||||
&DateDescription::field_type(),
|
||||
&format!("{}", timestamp),
|
||||
))
|
||||
Ok(AnyData::from_str(self.field_type(), &format!("{}", timestamp)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,54 +199,42 @@ impl std::default::Default for TimeFormat {
|
||||
|
||||
// Single select
|
||||
#[derive(Clone, Debug, ProtoBuf, Default)]
|
||||
pub struct SingleSelect {
|
||||
pub struct SingleSelectDescription {
|
||||
#[pb(index = 1)]
|
||||
pub options: Vec<SelectOption>,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub disable_color: bool,
|
||||
}
|
||||
impl_any_data!(SingleSelect, FieldType::SingleSelect);
|
||||
impl_from_and_to_type_option!(SingleSelectDescription, FieldType::SingleSelect);
|
||||
|
||||
impl StringifyAnyData for SingleSelect {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String {
|
||||
impl StringifyCellData for SingleSelectDescription {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String {
|
||||
data.to_string()
|
||||
}
|
||||
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
Ok(AnyData::from_str(&SingleSelect::field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayCell for SingleSelect {
|
||||
fn display_content(&self, s: &str) -> String {
|
||||
s.to_string()
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
Ok(AnyData::from_str(self.field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
// Multiple select
|
||||
#[derive(Clone, Debug, ProtoBuf, Default)]
|
||||
pub struct MultiSelect {
|
||||
pub struct MultiSelectDescription {
|
||||
#[pb(index = 1)]
|
||||
pub options: Vec<SelectOption>,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub disable_color: bool,
|
||||
}
|
||||
impl_any_data!(MultiSelect, FieldType::MultiSelect);
|
||||
impl StringifyAnyData for MultiSelect {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String {
|
||||
impl_from_and_to_type_option!(MultiSelectDescription, FieldType::MultiSelect);
|
||||
impl StringifyCellData for MultiSelectDescription {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String {
|
||||
data.to_string()
|
||||
}
|
||||
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
Ok(AnyData::from_str(&MultiSelect::field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayCell for MultiSelect {
|
||||
fn display_content(&self, s: &str) -> String {
|
||||
s.to_string()
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
Ok(AnyData::from_str(self.field_type(), s))
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +264,7 @@ impl SelectOption {
|
||||
#[derive(Clone, Debug, ProtoBuf)]
|
||||
pub struct NumberDescription {
|
||||
#[pb(index = 1)]
|
||||
pub money: FlowyMoney,
|
||||
pub money: MoneySymbol,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub scale: u32,
|
||||
@ -328,24 +278,26 @@ pub struct NumberDescription {
|
||||
#[pb(index = 5)]
|
||||
pub name: String,
|
||||
}
|
||||
impl_any_data!(NumberDescription, FieldType::Number);
|
||||
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: FlowyMoney::default(),
|
||||
money,
|
||||
scale: 0,
|
||||
symbol: String::new(),
|
||||
symbol,
|
||||
sign_positive: true,
|
||||
name: String::new(),
|
||||
name: "Number".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NumberDescription {
|
||||
pub fn set_money(&mut self, money: FlowyMoney) {
|
||||
self.money = money;
|
||||
self.symbol = money.symbol();
|
||||
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> {
|
||||
@ -368,17 +320,8 @@ impl NumberDescription {
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayCell for NumberDescription {
|
||||
fn display_content(&self, s: &str) -> String {
|
||||
match self.money_from_str(s) {
|
||||
Some(money_str) => money_str,
|
||||
None => String::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StringifyAnyData for NumberDescription {
|
||||
fn stringify_any_data(&self, data: AnyData) -> String {
|
||||
impl StringifyCellData for NumberDescription {
|
||||
fn str_from_cell_data(&self, data: AnyData) -> String {
|
||||
match String::from_utf8(data.value) {
|
||||
Ok(s) => match self.money_from_str(&s) {
|
||||
Some(money_str) => money_str,
|
||||
@ -391,47 +334,47 @@ impl StringifyAnyData for NumberDescription {
|
||||
}
|
||||
}
|
||||
|
||||
fn str_to_any_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
fn str_to_cell_data(&self, s: &str) -> Result<AnyData, FlowyError> {
|
||||
let strip_symbol_money = strip_money_symbol(s);
|
||||
let decimal = Decimal::from_str(&strip_symbol_money).map_err(|err| FlowyError::internal().context(err))?;
|
||||
let money_str = decimal.to_string();
|
||||
Ok(AnyData::from_str(&NumberDescription::field_type(), &money_str))
|
||||
Ok(AnyData::from_str(self.field_type(), &money_str))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, EnumIter, ProtoBuf_Enum)]
|
||||
pub enum FlowyMoney {
|
||||
pub enum MoneySymbol {
|
||||
CNY = 0,
|
||||
EUR = 1,
|
||||
USD = 2,
|
||||
}
|
||||
|
||||
impl std::default::Default for FlowyMoney {
|
||||
impl std::default::Default for MoneySymbol {
|
||||
fn default() -> Self {
|
||||
FlowyMoney::USD
|
||||
MoneySymbol::USD
|
||||
}
|
||||
}
|
||||
|
||||
impl FlowyMoney {
|
||||
impl MoneySymbol {
|
||||
// Currency list https://docs.rs/rusty-money/0.4.0/rusty_money/iso/index.html
|
||||
pub fn from_symbol_str(s: &str) -> FlowyMoney {
|
||||
pub fn from_symbol_str(s: &str) -> MoneySymbol {
|
||||
match s {
|
||||
"CNY" => FlowyMoney::CNY,
|
||||
"EUR" => FlowyMoney::EUR,
|
||||
"USD" => FlowyMoney::USD,
|
||||
_ => FlowyMoney::CNY,
|
||||
"CNY" => MoneySymbol::CNY,
|
||||
"EUR" => MoneySymbol::EUR,
|
||||
"USD" => MoneySymbol::USD,
|
||||
_ => MoneySymbol::CNY,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_money(money: &rusty_money::Money<Currency>) -> FlowyMoney {
|
||||
FlowyMoney::from_symbol_str(&money.currency().symbol.to_string())
|
||||
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 {
|
||||
FlowyMoney::CNY => CNY,
|
||||
FlowyMoney::EUR => EUR,
|
||||
FlowyMoney::USD => USD,
|
||||
MoneySymbol::CNY => CNY,
|
||||
MoneySymbol::EUR => EUR,
|
||||
MoneySymbol::USD => USD,
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,7 +385,7 @@ impl FlowyMoney {
|
||||
self.currency().iso_alpha_code.to_string()
|
||||
}
|
||||
|
||||
pub fn symbol(&self) -> String {
|
||||
pub fn symbol_str(&self) -> String {
|
||||
self.currency().symbol.to_string()
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ impl ClientGridEditor {
|
||||
) -> FlowyResult<Arc<Self>> {
|
||||
let token = user.token()?;
|
||||
let cloud = Arc::new(GridRevisionCloudService { token });
|
||||
let grid_pad = rev_manager.load::<GridPadBuilder>(cloud).await?;
|
||||
let grid_pad = rev_manager.load::<GridPadBuilder>(Some(cloud)).await?;
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let grid_meta_pad = Arc::new(RwLock::new(grid_pad));
|
||||
|
||||
@ -55,12 +55,12 @@ impl ClientGridEditor {
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn create_field(&mut self, field: Field) -> FlowyResult<()> {
|
||||
pub async fn create_field(&self, field: Field) -> FlowyResult<()> {
|
||||
let _ = self.modify(|grid| Ok(grid.create_field(field)?)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn delete_field(&mut self, field_id: &str) -> FlowyResult<()> {
|
||||
pub async fn delete_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||
let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?;
|
||||
Ok(())
|
||||
}
|
||||
@ -125,6 +125,13 @@ impl ClientGridEditor {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "flowy_unit_test")]
|
||||
impl ClientGridEditor {
|
||||
pub fn rev_manager(&self) -> Arc<RevisionManager> {
|
||||
self.rev_manager.clone()
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_all_fields(
|
||||
grid_pad: &GridMetaPad,
|
||||
kv_persistence: &Arc<GridKVPersistence>,
|
||||
@ -143,7 +150,7 @@ async fn load_all_fields(
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
struct GridPadBuilder();
|
||||
pub struct GridPadBuilder();
|
||||
impl RevisionObjectBuilder for GridPadBuilder {
|
||||
type Output = GridMetaPad;
|
||||
|
||||
|
@ -27,7 +27,7 @@ impl ClientGridBlockMetaEditor {
|
||||
let cloud = Arc::new(GridBlockMetaRevisionCloudService {
|
||||
token: token.to_owned(),
|
||||
});
|
||||
let block_meta_pad = rev_manager.load::<GridBlockMetaPadBuilder>(cloud).await?;
|
||||
let block_meta_pad = rev_manager.load::<GridBlockMetaPadBuilder>(Some(cloud)).await?;
|
||||
let meta_pad = Arc::new(RwLock::new(block_meta_pad));
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let user_id = user_id.to_owned();
|
||||
|
@ -1,7 +1,6 @@
|
||||
mod util;
|
||||
|
||||
pub mod cell_data;
|
||||
pub mod field;
|
||||
pub mod grid_editor;
|
||||
pub mod grid_meta_editor;
|
||||
pub mod kv_persistence;
|
||||
pub mod stringify;
|
||||
|
@ -1,29 +0,0 @@
|
||||
use crate::services::cell_data::*;
|
||||
use crate::services::util::*;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn stringify_serialize(field: &Field, s: &str) -> Result<AnyData, FlowyError> {
|
||||
match field.field_type {
|
||||
FieldType::RichText => RichTextDescription::from(field).str_to_any_data(s),
|
||||
FieldType::Number => NumberDescription::from(field).str_to_any_data(s),
|
||||
FieldType::DateTime => DateDescription::from(field).str_to_any_data(s),
|
||||
FieldType::SingleSelect => SingleSelect::from(field).str_to_any_data(s),
|
||||
FieldType::MultiSelect => MultiSelect::from(field).str_to_any_data(s),
|
||||
FieldType::Checkbox => CheckboxDescription::from(field).str_to_any_data(s),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn stringify_deserialize(data: AnyData, field: &Field) -> Result<String, FlowyError> {
|
||||
let _ = check_type_id(&data, field)?;
|
||||
let s = match field.field_type {
|
||||
FieldType::RichText => RichTextDescription::from(field).stringify_any_data(data),
|
||||
FieldType::Number => NumberDescription::from(field).stringify_any_data(data),
|
||||
FieldType::DateTime => DateDescription::from(field).stringify_any_data(data),
|
||||
FieldType::SingleSelect => SingleSelect::from(field).stringify_any_data(data),
|
||||
FieldType::MultiSelect => MultiSelect::from(field).stringify_any_data(data),
|
||||
FieldType::Checkbox => CheckboxDescription::from(field).stringify_any_data(data),
|
||||
};
|
||||
Ok(s)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::services::cell_data::FlowyMoney;
|
||||
use crate::services::field::MoneySymbol;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
|
||||
use lazy_static::lazy_static;
|
||||
@ -16,8 +16,8 @@ lazy_static! {
|
||||
fn generate_currency_by_symbol() -> HashMap<String, &'static Currency> {
|
||||
let mut map: HashMap<String, &'static Currency> = HashMap::new();
|
||||
|
||||
for money in FlowyMoney::iter() {
|
||||
map.insert(money.symbol(), money.currency());
|
||||
for money in MoneySymbol::iter() {
|
||||
map.insert(money.symbol_str(), money.currency());
|
||||
}
|
||||
map
|
||||
}
|
||||
@ -25,7 +25,7 @@ fn generate_currency_by_symbol() -> HashMap<String, &'static Currency> {
|
||||
#[allow(dead_code)]
|
||||
pub fn string_to_money(money_str: &str) -> Option<Money<Currency>> {
|
||||
let mut process_money_str = String::from(money_str);
|
||||
let default_currency = FlowyMoney::from_symbol_str("CNY").currency();
|
||||
let default_currency = MoneySymbol::from_symbol_str("CNY").currency();
|
||||
|
||||
if process_money_str.is_empty() {
|
||||
return None;
|
||||
@ -65,7 +65,7 @@ pub fn money_from_str(s: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
decimal.set_sign_positive(true);
|
||||
Some(FlowyMoney::USD.with_decimal(decimal).to_string())
|
||||
Some(MoneySymbol::USD.with_decimal(decimal).to_string())
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::debug!("Format {} to money failed, {:?}", s, e);
|
||||
|
30
frontend/rust-lib/flowy-grid/src/util.rs
Normal file
30
frontend/rust-lib/flowy-grid/src/util.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use crate::services::field::*;
|
||||
use flowy_collaboration::client_grid::{BuildGridInfo, GridBuilder};
|
||||
use flowy_grid_data_model::entities::{Field, FieldType};
|
||||
|
||||
pub fn make_default_grid(grid_id: &str) -> BuildGridInfo {
|
||||
let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::new())
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.field_type(FieldType::RichText)
|
||||
.build();
|
||||
|
||||
let single_select = SingleSelectTypeOptionsBuilder::new()
|
||||
.option(SelectOption::new("Done"))
|
||||
.option(SelectOption::new("Progress"));
|
||||
|
||||
let single_select_field = FieldBuilder::new(single_select)
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.field_type(FieldType::SingleSelect)
|
||||
.build();
|
||||
|
||||
GridBuilder::new(grid_id)
|
||||
.add_field(text_field)
|
||||
.add_field(single_select_field)
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
16
frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs
Normal file
16
frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use crate::grid::script::EditorScript::*;
|
||||
use crate::grid::script::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_creat_field_test() {
|
||||
let scripts = vec![
|
||||
CreateField {
|
||||
field: create_text_field(),
|
||||
},
|
||||
CreateField {
|
||||
field: create_single_select_field(),
|
||||
},
|
||||
AssertGridMetaPad,
|
||||
];
|
||||
GridEditorTest::new().await.run_scripts(scripts).await;
|
||||
}
|
2
frontend/rust-lib/flowy-grid/tests/grid/mod.rs
Normal file
2
frontend/rust-lib/flowy-grid/tests/grid/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
mod grid_test;
|
||||
mod script;
|
75
frontend/rust-lib/flowy-grid/tests/grid/script.rs
Normal file
75
frontend/rust-lib/flowy-grid/tests/grid/script.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use flowy_grid::services::field::*;
|
||||
use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder};
|
||||
use flowy_grid_data_model::entities::{AnyData, Field, FieldType};
|
||||
use flowy_test::event_builder::FolderEventBuilder;
|
||||
use flowy_test::helper::ViewTest;
|
||||
use flowy_test::FlowySDKTest;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub enum EditorScript {
|
||||
CreateField { field: Field },
|
||||
CreateRow,
|
||||
AssertGridMetaPad,
|
||||
}
|
||||
|
||||
pub struct GridEditorTest {
|
||||
pub sdk: FlowySDKTest,
|
||||
pub grid_id: String,
|
||||
pub editor: Arc<ClientGridEditor>,
|
||||
}
|
||||
|
||||
impl GridEditorTest {
|
||||
pub async fn new() -> Self {
|
||||
let sdk = FlowySDKTest::default();
|
||||
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 grid_id = test.view.id;
|
||||
Self { sdk, grid_id, editor }
|
||||
}
|
||||
|
||||
pub async fn run_scripts(&mut self, scripts: Vec<EditorScript>) {
|
||||
for script in scripts {
|
||||
self.run_script(script).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_script(&mut self, script: EditorScript) {
|
||||
let grid_manager = self.sdk.grid_manager.clone();
|
||||
let pool = self.sdk.user_session.db_pool().unwrap();
|
||||
let rev_manager = self.editor.rev_manager();
|
||||
let cache = rev_manager.revision_cache().await;
|
||||
|
||||
match script {
|
||||
EditorScript::CreateField { field } => {
|
||||
self.editor.create_field(field).await.unwrap();
|
||||
}
|
||||
EditorScript::CreateRow => {}
|
||||
EditorScript::AssertGridMetaPad => {
|
||||
let mut grid_rev_manager = grid_manager.make_grid_rev_manager(&self.grid_id, pool.clone()).unwrap();
|
||||
let grid_pad = grid_rev_manager.load::<GridPadBuilder>(None).await.unwrap();
|
||||
println!("{}", grid_pad.delta_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_text_field() -> Field {
|
||||
FieldBuilder::new(RichTextTypeOptionsBuilder::new())
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.field_type(FieldType::RichText)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub fn create_single_select_field() -> Field {
|
||||
let single_select = SingleSelectTypeOptionsBuilder::new()
|
||||
.option(SelectOption::new("Done"))
|
||||
.option(SelectOption::new("Progress"));
|
||||
|
||||
FieldBuilder::new(single_select)
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.field_type(FieldType::SingleSelect)
|
||||
.build()
|
||||
}
|
1
frontend/rust-lib/flowy-grid/tests/main.rs
Normal file
1
frontend/rust-lib/flowy-grid/tests/main.rs
Normal file
@ -0,0 +1 @@
|
||||
mod grid;
|
@ -1,7 +1,6 @@
|
||||
use bytes::Bytes;
|
||||
use flowy_block::TextBlockManager;
|
||||
use flowy_collaboration::client_document::default::initial_quill_delta_string;
|
||||
use flowy_collaboration::client_grid::make_default_grid;
|
||||
use flowy_collaboration::entities::revision::{RepeatedRevision, Revision};
|
||||
use flowy_collaboration::entities::ws_data::ClientRevisionWSData;
|
||||
use flowy_database::ConnectionPool;
|
||||
@ -13,6 +12,7 @@ use flowy_folder::{
|
||||
manager::FolderManager,
|
||||
};
|
||||
use flowy_grid::manager::GridManager;
|
||||
use flowy_grid::util::make_default_grid;
|
||||
use flowy_net::ClientServerConfiguration;
|
||||
use flowy_net::{
|
||||
http_server::folder::FolderHttpCloudService, local_server::LocalServer, ws::connection::FlowyWebSocketConnect,
|
||||
|
@ -67,14 +67,14 @@ impl RevisionManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn load<B>(&mut self, cloud: Arc<dyn RevisionCloudService>) -> FlowyResult<B::Output>
|
||||
pub async fn load<B>(&mut self, cloud: Option<Arc<dyn RevisionCloudService>>) -> FlowyResult<B::Output>
|
||||
where
|
||||
B: RevisionObjectBuilder,
|
||||
{
|
||||
let (revisions, rev_id) = RevisionLoader {
|
||||
object_id: self.object_id.clone(),
|
||||
user_id: self.user_id.clone(),
|
||||
cloud: Some(cloud),
|
||||
cloud,
|
||||
rev_persistence: self.rev_persistence.clone(),
|
||||
}
|
||||
.load()
|
||||
|
@ -25,11 +25,12 @@ pub struct ViewTest {
|
||||
}
|
||||
|
||||
impl ViewTest {
|
||||
pub async fn new(sdk: &FlowySDKTest) -> Self {
|
||||
#[allow(dead_code)]
|
||||
pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataType) -> Self {
|
||||
let workspace = create_workspace(sdk, "Workspace", "").await;
|
||||
open_workspace(sdk, &workspace.id).await;
|
||||
let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await;
|
||||
let view = create_view(sdk, &app.id).await;
|
||||
let view = create_view(sdk, &app.id, data_type).await;
|
||||
Self {
|
||||
sdk: sdk.clone(),
|
||||
workspace,
|
||||
@ -37,6 +38,16 @@ impl ViewTest {
|
||||
view,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn new_grid_view(sdk: &FlowySDKTest) -> Self {
|
||||
Self::new(sdk, ViewDataType::Grid).await
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self {
|
||||
Self::new(sdk, ViewDataType::TextBlock).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspace {
|
||||
@ -82,13 +93,13 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s
|
||||
app
|
||||
}
|
||||
|
||||
async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View {
|
||||
async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataType) -> View {
|
||||
let request = CreateViewPayload {
|
||||
belong_to_id: app_id.to_string(),
|
||||
name: "View A".to_string(),
|
||||
desc: "".to_string(),
|
||||
thumbnail: Some("http://1.png".to_string()),
|
||||
data_type: ViewDataType::TextBlock,
|
||||
data_type,
|
||||
ext_data: "".to_string(),
|
||||
plugin_type: 0,
|
||||
};
|
||||
|
@ -25,8 +25,7 @@ impl GridBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_field(mut self, name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||
let field = Field::new(name, desc, field_type);
|
||||
pub fn add_field(mut self, field: Field) -> Self {
|
||||
self.fields.push(field);
|
||||
self
|
||||
}
|
||||
@ -74,27 +73,16 @@ fn check_rows(fields: &[Field], rows: &[RowMeta]) -> CollaborateResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make_default_grid(grid_id: &str) -> BuildGridInfo {
|
||||
GridBuilder::new(grid_id)
|
||||
.add_field("Name", "", FieldType::RichText)
|
||||
.add_field("Tags", "", FieldType::SingleSelect)
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::client_grid::GridBuilder;
|
||||
use flowy_grid_data_model::entities::{FieldType, GridBlockMeta, GridMeta};
|
||||
use flowy_grid_data_model::entities::{Field, FieldType, GridBlockMeta, GridMeta};
|
||||
|
||||
#[test]
|
||||
fn create_default_grid_test() {
|
||||
let info = GridBuilder::new("1")
|
||||
.add_field("Name", "", FieldType::RichText)
|
||||
.add_field("Tags", "", FieldType::SingleSelect)
|
||||
.add_field(Field::new("Name", "", FieldType::RichText))
|
||||
.add_field(Field::new("Tags", "", FieldType::SingleSelect))
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
|
@ -163,8 +163,19 @@ impl std::default::Default for FieldType {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<FieldType> for FieldType {
|
||||
fn as_ref(&self) -> &FieldType {
|
||||
&self
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<FieldType> for &FieldType {
|
||||
fn into(self) -> FieldType {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl FieldType {
|
||||
#[allow(dead_code)]
|
||||
pub fn type_id(&self) -> String {
|
||||
let ty = self.clone();
|
||||
format!("{}", ty as u8)
|
||||
@ -193,13 +204,13 @@ pub struct AnyData {
|
||||
}
|
||||
|
||||
impl AnyData {
|
||||
pub fn from_str(field_type: &FieldType, s: &str) -> AnyData {
|
||||
pub fn from_str<F: Into<FieldType>>(field_type: F, s: &str) -> AnyData {
|
||||
Self::from_bytes(field_type, s.as_bytes().to_vec())
|
||||
}
|
||||
|
||||
pub fn from_bytes<T: AsRef<[u8]>>(field_type: &FieldType, bytes: T) -> AnyData {
|
||||
pub fn from_bytes<T: AsRef<[u8]>, F: Into<FieldType>>(field_type: F, bytes: T) -> AnyData {
|
||||
AnyData {
|
||||
type_id: field_type.type_id(),
|
||||
type_id: field_type.into().type_id(),
|
||||
value: bytes.as_ref().to_vec(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user