chore: duplicate and hide field

This commit is contained in:
appflowy 2022-03-27 11:14:21 +08:00
parent c7bba01fe5
commit 8b7eee46bb
23 changed files with 835 additions and 287 deletions

View File

@ -62,6 +62,7 @@ class CreateFieldBloc extends Bloc<CreateFieldEvent, CreateFieldState> {
emit(state.copyWith(
field: Some(editContext.gridField),
typeOptionData: editContext.typeOptionData,
fieldName: editContext.gridField.name,
));
},
(err) => Log.error(err),

View File

@ -1,3 +1,4 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -18,9 +19,27 @@ class EditFieldBloc extends Bloc<EditFieldEvent, EditFieldState> {
updateFieldName: (_UpdateFieldName value) {
//
},
hideField: (_HideField value) {},
deleteField: (_DeleteField value) {},
duplicateField: (_DuplicateField value) {},
hideField: (_HideField value) async {
final result = await service.updateField(fieldId: value.fieldId, visibility: false);
result.fold(
(l) => null,
(err) => Log.error(err),
);
},
deleteField: (_DeleteField value) async {
final result = await service.deleteField(fieldId: value.fieldId);
result.fold(
(l) => null,
(err) => Log.error(err),
);
},
duplicateField: (_DuplicateField value) async {
final result = await service.duplicateField(fieldId: value.fieldId);
result.fold(
(l) => null,
(err) => Log.error(err),
);
},
saveField: (_SaveField value) {},
);
},
@ -37,9 +56,9 @@ class EditFieldBloc extends Bloc<EditFieldEvent, EditFieldState> {
class EditFieldEvent with _$EditFieldEvent {
const factory EditFieldEvent.initial() = _InitialField;
const factory EditFieldEvent.updateFieldName(String name) = _UpdateFieldName;
const factory EditFieldEvent.hideField() = _HideField;
const factory EditFieldEvent.duplicateField() = _DuplicateField;
const factory EditFieldEvent.deleteField() = _DeleteField;
const factory EditFieldEvent.hideField(String fieldId) = _HideField;
const factory EditFieldEvent.duplicateField(String fieldId) = _DuplicateField;
const factory EditFieldEvent.deleteField(String fieldId) = _DeleteField;
const factory EditFieldEvent.saveField() = _SaveField;
}

View File

@ -21,7 +21,7 @@ class FieldService {
}
Future<Either<Unit, FlowyError>> updateField({
required Field field,
required String fieldId,
String? name,
FieldType? fieldType,
bool? frozen,
@ -29,7 +29,9 @@ class FieldService {
double? width,
List<int>? typeOptionData,
}) {
var payload = FieldChangesetPayload.create()..gridId = gridId;
var payload = FieldChangesetPayload.create()
..gridId = gridId
..fieldId = fieldId;
if (name != null) {
payload.name = name;
@ -74,6 +76,26 @@ class FieldService {
return GridEventCreateField(payload).send();
}
Future<Either<Unit, FlowyError>> deleteField({
required String fieldId,
}) {
final payload = FieldIdentifierPayload.create()
..gridId = gridId
..fieldId = fieldId;
return GridEventDeleteField(payload).send();
}
Future<Either<Unit, FlowyError>> duplicateField({
required String fieldId,
}) {
final payload = FieldIdentifierPayload.create()
..gridId = gridId
..fieldId = fieldId;
return GridEventDuplicateField(payload).send();
}
}
class GridFieldData extends Equatable {

View File

@ -13,7 +13,7 @@ import 'layout/layout.dart';
import 'layout/sizes.dart';
import 'widgets/content/grid_row.dart';
import 'widgets/footer/grid_footer.dart';
import 'widgets/header/header.dart';
import 'widgets/header/grid_header.dart';
class GridPage extends StatefulWidget {
final View view;

View File

@ -2,7 +2,6 @@ import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -38,9 +37,7 @@ class EditFieldPannel extends StatelessWidget {
const VSpace(6),
const _FieldTypeSwitcher(),
const VSpace(6),
FieldOperationList(
onDismiss: () => FlowyOverlay.of(context).remove(identifier()),
),
_FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())),
],
),
),
@ -52,6 +49,27 @@ class EditFieldPannel extends StatelessWidget {
}
}
class _FieldOperationList extends StatelessWidget {
final GridFieldData fieldData;
final VoidCallback onDismissed;
const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final actions = FieldAction.values
.map(
(action) => FieldActionItem(
fieldId: fieldData.field.id,
action: action,
onTap: onDismissed,
),
)
.toList();
return FieldOperationList(actions: actions);
}
}
class _FieldTypeSwitcher extends StatelessWidget {
const _FieldTypeSwitcher({Key? key}) : super(key: key);

View File

@ -9,17 +9,11 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class FieldOperationList extends StatelessWidget {
final VoidCallback onDismiss;
const FieldOperationList({required this.onDismiss, Key? key}) : super(key: key);
final List<FieldActionItem> actions;
const FieldOperationList({required this.actions, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final children = FieldAction.values
.map((action) => FieldActionItem(
action: action,
onTap: onDismiss,
))
.toList();
return GridView(
// https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html
shrinkWrap: true,
@ -28,15 +22,22 @@ class FieldOperationList extends StatelessWidget {
childAspectRatio: 4.0,
mainAxisSpacing: 8,
),
children: children,
children: actions,
);
}
}
class FieldActionItem extends StatelessWidget {
final String fieldId;
final VoidCallback onTap;
final FieldAction action;
const FieldActionItem({required this.action, required this.onTap, Key? key}) : super(key: key);
const FieldActionItem({
required this.fieldId,
required this.action,
required this.onTap,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -45,7 +46,7 @@ class FieldActionItem extends StatelessWidget {
text: FlowyText.medium(action.title(), fontSize: 12),
hoverColor: theme.hover,
onTap: () {
action.run(context);
action.run(context, fieldId);
onTap();
},
leftIcon: svg(action.iconName(), color: theme.iconColor),
@ -82,16 +83,16 @@ extension _FieldActionExtension on FieldAction {
}
}
void run(BuildContext context) {
void run(BuildContext context, String fieldId) {
switch (this) {
case FieldAction.hide:
context.read<EditFieldBloc>().add(const EditFieldEvent.hideField());
context.read<EditFieldBloc>().add(EditFieldEvent.hideField(fieldId));
break;
case FieldAction.duplicate:
context.read<EditFieldBloc>().add(const EditFieldEvent.duplicateField());
context.read<EditFieldBloc>().add(EditFieldEvent.duplicateField(fieldId));
break;
case FieldAction.delete:
context.read<EditFieldBloc>().add(const EditFieldEvent.deleteField());
context.read<EditFieldBloc>().add(EditFieldEvent.deleteField(fieldId));
break;
}
}

View File

@ -1,123 +0,0 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/prelude.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'create_field_pannel.dart';
import 'header_cell.dart';
class GridHeaderDelegate extends SliverPersistentHeaderDelegate {
final String gridId;
final List<Field> fields;
GridHeaderDelegate({required this.gridId, required this.fields});
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields));
}
@override
double get maxExtent => GridSize.headerHeight;
@override
double get minExtent => GridSize.headerHeight;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
if (oldDelegate is GridHeaderDelegate) {
return fields != oldDelegate.fields;
}
return false;
}
}
class GridHeader extends StatelessWidget {
final List<Field> fields;
final String gridId;
const GridHeader({required this.gridId, required this.fields, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return BlocProvider(
create: (context) {
final bloc = getIt<GridHeaderBloc>(param1: gridId, param2: fields);
bloc.add(const GridHeaderEvent.initial());
return bloc;
},
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) {
final cells = state.fields.map(
(field) => HeaderCell(
GridFieldData(gridId: gridId, field: field),
),
);
final row = Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const _HeaderLeading(),
...cells,
_HeaderTrailing(gridId: gridId),
],
);
return Container(color: theme.surface, child: row);
},
),
);
}
}
class _HeaderLeading extends StatelessWidget {
const _HeaderLeading({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: GridSize.leadingHeaderPadding,
);
}
}
class _HeaderTrailing extends StatelessWidget {
final String gridId;
const _HeaderTrailing({required this.gridId, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final borderSide = BorderSide(color: theme.shader4, width: 0.4);
return Container(
width: GridSize.trailHeaderPadding,
decoration: BoxDecoration(
border: Border(top: borderSide, bottom: borderSide),
),
padding: GridSize.headerContentInsets,
child: CreateFieldButton(gridId: gridId),
);
}
}
class CreateFieldButton extends StatelessWidget {
final String gridId;
const CreateFieldButton({required this.gridId, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return FlowyButton(
text: const FlowyText.medium('New column', fontSize: 12),
hoverColor: theme.hover,
onTap: () => CreateFieldPannel(gridId: gridId).show(context, gridId),
leftIcon: svg("home/add"),
);
}
}

View File

@ -1,36 +0,0 @@
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'edit_field_pannel.dart';
class HeaderCell extends StatelessWidget {
final GridFieldData fieldData;
const HeaderCell(this.fieldData, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final button = FlowyButton(
hoverColor: theme.hover,
onTap: () => EditFieldPannel.show(context, fieldData),
rightIcon: svg("editor/details", color: theme.iconColor),
text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)),
);
final borderSide = BorderSide(color: theme.shader4, width: 0.4);
final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide));
return Container(
width: fieldData.field.width.toDouble(),
decoration: decoration,
padding: GridSize.headerContentInsets,
child: button,
);
}
}

View File

@ -40,10 +40,9 @@ class FlowyButton extends StatelessWidget {
children.add(const HSpace(6));
}
children.add(text);
children.add(Expanded(child: text));
if (rightIcon != null) {
children.add(const Spacer());
children.add(SizedBox.fromSize(size: const Size.square(16), child: rightIcon!));
children.add(const HSpace(6));
}

View File

@ -53,7 +53,7 @@ class GridEventGetFields {
}
class GridEventUpdateField {
FieldChangeset request;
FieldChangesetPayload request;
GridEventUpdateField(this.request);
Future<Either<Unit, FlowyError>> send() {
@ -87,7 +87,7 @@ class GridEventCreateField {
}
class GridEventDeleteField {
FieldOrder request;
FieldIdentifierPayload request;
GridEventDeleteField(this.request);
Future<Either<Unit, FlowyError>> send() {
@ -103,6 +103,23 @@ class GridEventDeleteField {
}
}
class GridEventDuplicateField {
FieldIdentifierPayload request;
GridEventDuplicateField(this.request);
Future<Either<Unit, FlowyError>> send() {
final request = FFIRequest.create()
..event = GridEvent.DuplicateField.toString()
..payload = requestToBytes(this.request);
return Dispatch.asyncRequest(request)
.then((bytesResult) => bytesResult.fold(
(bytes) => left(unit),
(errBytes) => right(FlowyError.fromBuffer(errBytes)),
));
}
}
class GridEventCreateEditFieldContext {
CreateEditFieldContextParams request;
GridEventCreateEditFieldContext(this.request);

View File

@ -205,6 +205,128 @@ class Field extends $pb.GeneratedMessage {
void clearWidth() => clearField(7);
}
class FieldIdentifierPayload extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierPayload', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
..hasRequiredFields = false
;
FieldIdentifierPayload._() : super();
factory FieldIdentifierPayload({
$core.String? fieldId,
$core.String? gridId,
}) {
final _result = create();
if (fieldId != null) {
_result.fieldId = fieldId;
}
if (gridId != null) {
_result.gridId = gridId;
}
return _result;
}
factory FieldIdentifierPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory FieldIdentifierPayload.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')
FieldIdentifierPayload clone() => FieldIdentifierPayload()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
FieldIdentifierPayload copyWith(void Function(FieldIdentifierPayload) updates) => super.copyWith((message) => updates(message as FieldIdentifierPayload)) as FieldIdentifierPayload; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static FieldIdentifierPayload create() => FieldIdentifierPayload._();
FieldIdentifierPayload createEmptyInstance() => create();
static $pb.PbList<FieldIdentifierPayload> createRepeated() => $pb.PbList<FieldIdentifierPayload>();
@$core.pragma('dart2js:noInline')
static FieldIdentifierPayload getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldIdentifierPayload>(create);
static FieldIdentifierPayload? _defaultInstance;
@$pb.TagNumber(1)
$core.String get fieldId => $_getSZ(0);
@$pb.TagNumber(1)
set fieldId($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasFieldId() => $_has(0);
@$pb.TagNumber(1)
void clearFieldId() => clearField(1);
@$pb.TagNumber(2)
$core.String get gridId => $_getSZ(1);
@$pb.TagNumber(2)
set gridId($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasGridId() => $_has(1);
@$pb.TagNumber(2)
void clearGridId() => clearField(2);
}
class FieldIdentifierParams extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldIdentifierParams', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
..hasRequiredFields = false
;
FieldIdentifierParams._() : super();
factory FieldIdentifierParams({
$core.String? fieldId,
$core.String? gridId,
}) {
final _result = create();
if (fieldId != null) {
_result.fieldId = fieldId;
}
if (gridId != null) {
_result.gridId = gridId;
}
return _result;
}
factory FieldIdentifierParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory FieldIdentifierParams.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')
FieldIdentifierParams clone() => FieldIdentifierParams()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
FieldIdentifierParams copyWith(void Function(FieldIdentifierParams) updates) => super.copyWith((message) => updates(message as FieldIdentifierParams)) as FieldIdentifierParams; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static FieldIdentifierParams create() => FieldIdentifierParams._();
FieldIdentifierParams createEmptyInstance() => create();
static $pb.PbList<FieldIdentifierParams> createRepeated() => $pb.PbList<FieldIdentifierParams>();
@$core.pragma('dart2js:noInline')
static FieldIdentifierParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldIdentifierParams>(create);
static FieldIdentifierParams? _defaultInstance;
@$pb.TagNumber(1)
$core.String get fieldId => $_getSZ(0);
@$pb.TagNumber(1)
set fieldId($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasFieldId() => $_has(0);
@$pb.TagNumber(1)
void clearFieldId() => clearField(1);
@$pb.TagNumber(2)
$core.String get gridId => $_getSZ(1);
@$pb.TagNumber(2)
set gridId($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasGridId() => $_has(1);
@$pb.TagNumber(2)
void clearGridId() => clearField(2);
}
class FieldOrder extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldOrder', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')

View File

@ -36,6 +36,28 @@ const Field$json = const {
/// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aA==');
@$core.Deprecated('Use fieldIdentifierPayloadDescriptor instead')
const FieldIdentifierPayload$json = const {
'1': 'FieldIdentifierPayload',
'2': const [
const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'},
const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'},
],
};
/// Descriptor for `FieldIdentifierPayload`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List fieldIdentifierPayloadDescriptor = $convert.base64Decode('ChZGaWVsZElkZW50aWZpZXJQYXlsb2FkEhkKCGZpZWxkX2lkGAEgASgJUgdmaWVsZElkEhcKB2dyaWRfaWQYAiABKAlSBmdyaWRJZA==');
@$core.Deprecated('Use fieldIdentifierParamsDescriptor instead')
const FieldIdentifierParams$json = const {
'1': 'FieldIdentifierParams',
'2': const [
const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'},
const {'1': 'grid_id', '3': 2, '4': 1, '5': 9, '10': 'gridId'},
],
};
/// Descriptor for `FieldIdentifierParams`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List fieldIdentifierParamsDescriptor = $convert.base64Decode('ChVGaWVsZElkZW50aWZpZXJQYXJhbXMSGQoIZmllbGRfaWQYASABKAlSB2ZpZWxkSWQSFwoHZ3JpZF9pZBgCIAEoCVIGZ3JpZElk');
@$core.Deprecated('Use fieldOrderDescriptor instead')
const FieldOrder$json = const {
'1': 'FieldOrder',

View File

@ -16,7 +16,8 @@ class GridEvent extends $pb.ProtobufEnum {
static const GridEvent UpdateField = GridEvent._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateField');
static const GridEvent CreateField = GridEvent._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateField');
static const GridEvent DeleteField = GridEvent._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteField');
static const GridEvent CreateEditFieldContext = GridEvent._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext');
static const GridEvent DuplicateField = GridEvent._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateField');
static const GridEvent CreateEditFieldContext = GridEvent._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateEditFieldContext');
static const GridEvent CreateRow = GridEvent._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
static const GridEvent GetRow = GridEvent._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
static const GridEvent UpdateCell = GridEvent._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
@ -28,6 +29,7 @@ class GridEvent extends $pb.ProtobufEnum {
UpdateField,
CreateField,
DeleteField,
DuplicateField,
CreateEditFieldContext,
CreateRow,
GetRow,

View File

@ -18,7 +18,8 @@ const GridEvent$json = const {
const {'1': 'UpdateField', '2': 11},
const {'1': 'CreateField', '2': 12},
const {'1': 'DeleteField', '2': 13},
const {'1': 'CreateEditFieldContext', '2': 14},
const {'1': 'DuplicateField', '2': 15},
const {'1': 'CreateEditFieldContext', '2': 16},
const {'1': 'CreateRow', '2': 21},
const {'1': 'GetRow', '2': 22},
const {'1': 'UpdateCell', '2': 30},
@ -26,4 +27,4 @@ const GridEvent$json = const {
};
/// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SGgoWQ3JlYXRlRWRpdEZpZWxkQ29udGV4dBAOEg0KCUNyZWF0ZVJvdxAVEgoKBkdldFJvdxAWEg4KClVwZGF0ZUNlbGwQHg==');
final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEgoORHVwbGljYXRlRmllbGQQDxIaChZDcmVhdGVFZGl0RmllbGRDb250ZXh0EBASDQoJQ3JlYXRlUm93EBUSCgoGR2V0Um93EBYSDgoKVXBkYXRlQ2VsbBAe');

View File

@ -68,12 +68,23 @@ pub(crate) async fn create_field_handler(
#[tracing::instrument(level = "debug", skip(data, manager), err)]
pub(crate) async fn delete_field_handler(
data: Data<FieldOrder>,
data: Data<FieldIdentifierPayload>,
manager: AppData<Arc<GridManager>>,
) -> Result<(), FlowyError> {
let field_order: FieldOrder = data.into_inner();
let params: FieldIdentifierParams = data.into_inner().try_into()?;
let editor = manager.get_grid_editor(&params.grid_id)?;
let _ = editor.delete_field(&field_order.field_id).await?;
let _ = editor.delete_field(&params.field_id).await?;
Ok(())
}
#[tracing::instrument(level = "debug", skip(data, manager), err)]
pub(crate) async fn duplicate_field_handler(
data: Data<FieldIdentifierPayload>,
manager: AppData<Arc<GridManager>>,
) -> Result<(), FlowyError> {
let params: FieldIdentifierParams = data.into_inner().try_into()?;
let editor = manager.get_grid_editor(&params.grid_id)?;
let _ = editor.duplicate_field(&params.field_id).await?;
Ok(())
}

View File

@ -13,7 +13,8 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
.event(GridEvent::GetFields, get_fields_handler)
.event(GridEvent::UpdateField, update_field_handler)
.event(GridEvent::CreateField, create_field_handler)
.event(GridEvent::DeleteField, create_field_handler)
.event(GridEvent::DeleteField, delete_field_handler)
.event(GridEvent::DuplicateField, duplicate_field_handler)
.event(GridEvent::CreateEditFieldContext, create_edit_field_context_handler)
.event(GridEvent::CreateRow, create_row_handler)
.event(GridEvent::GetRow, get_row_handler)
@ -34,17 +35,20 @@ pub enum GridEvent {
#[event(input = "QueryFieldPayload", output = "RepeatedField")]
GetFields = 10,
#[event(input = "FieldChangeset")]
#[event(input = "FieldChangesetPayload")]
UpdateField = 11,
#[event(input = "CreateFieldPayload")]
CreateField = 12,
#[event(input = "FieldOrder")]
#[event(input = "FieldIdentifierPayload")]
DeleteField = 13,
#[event(input = "FieldIdentifierPayload")]
DuplicateField = 15,
#[event(input = "CreateEditFieldContextParams", output = "EditFieldContext")]
CreateEditFieldContext = 14,
CreateEditFieldContext = 16,
#[event(input = "CreateRowPayload", output = "Row")]
CreateRow = 21,

View File

@ -31,7 +31,8 @@ pub enum GridEvent {
UpdateField = 11,
CreateField = 12,
DeleteField = 13,
CreateEditFieldContext = 14,
DuplicateField = 15,
CreateEditFieldContext = 16,
CreateRow = 21,
GetRow = 22,
UpdateCell = 30,
@ -50,7 +51,8 @@ impl ::protobuf::ProtobufEnum for GridEvent {
11 => ::std::option::Option::Some(GridEvent::UpdateField),
12 => ::std::option::Option::Some(GridEvent::CreateField),
13 => ::std::option::Option::Some(GridEvent::DeleteField),
14 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext),
15 => ::std::option::Option::Some(GridEvent::DuplicateField),
16 => ::std::option::Option::Some(GridEvent::CreateEditFieldContext),
21 => ::std::option::Option::Some(GridEvent::CreateRow),
22 => ::std::option::Option::Some(GridEvent::GetRow),
30 => ::std::option::Option::Some(GridEvent::UpdateCell),
@ -66,6 +68,7 @@ impl ::protobuf::ProtobufEnum for GridEvent {
GridEvent::UpdateField,
GridEvent::CreateField,
GridEvent::DeleteField,
GridEvent::DuplicateField,
GridEvent::CreateEditFieldContext,
GridEvent::CreateRow,
GridEvent::GetRow,
@ -98,12 +101,12 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0fevent_map.proto*\xb8\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
\n\x0fevent_map.proto*\xcc\x01\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
\0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\
\x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\
leteField\x10\r\x12\x1a\n\x16CreateEditFieldContext\x10\x0e\x12\r\n\tCre\
ateRow\x10\x15\x12\n\n\x06GetRow\x10\x16\x12\x0e\n\nUpdateCell\x10\x1eb\
\x06proto3\
leteField\x10\r\x12\x12\n\x0eDuplicateField\x10\x0f\x12\x1a\n\x16CreateE\
ditFieldContext\x10\x10\x12\r\n\tCreateRow\x10\x15\x12\n\n\x06GetRow\x10\
\x16\x12\x0e\n\nUpdateCell\x10\x1eb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -7,7 +7,8 @@ enum GridEvent {
UpdateField = 11;
CreateField = 12;
DeleteField = 13;
CreateEditFieldContext = 14;
DuplicateField = 15;
CreateEditFieldContext = 16;
CreateRow = 21;
GetRow = 22;
UpdateCell = 30;

View File

@ -110,6 +110,12 @@ impl ClientGridEditor {
Ok(())
}
pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> {
let _ = self.modify(|grid| Ok(grid.duplicate_field(field_id)?)).await?;
let _ = self.notify_did_update_fields().await?;
Ok(())
}
pub async fn create_block(&self, grid_block: GridBlockMeta) -> FlowyResult<()> {
let _ = self.modify(|grid| Ok(grid.create_block(grid_block)?)).await?;
Ok(())
@ -254,8 +260,9 @@ impl ClientGridEditor {
}
pub async fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> FlowyResult<Vec<FieldMeta>> {
let field_meta = self.pad.read().await.get_field_metas(field_orders)?;
Ok(field_meta)
let mut field_metas = self.pad.read().await.get_field_metas(field_orders)?;
field_metas.retain(|field_meta| field_meta.visibility);
Ok(field_metas)
}
pub async fn get_block_meta_data_vec(

View File

@ -55,6 +55,37 @@ impl std::convert::From<FieldMeta> for Field {
}
}
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct FieldIdentifierPayload {
#[pb(index = 1)]
pub field_id: String,
#[pb(index = 2)]
pub grid_id: String,
}
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct FieldIdentifierParams {
#[pb(index = 1)]
pub field_id: String,
#[pb(index = 2)]
pub grid_id: String,
}
impl TryInto<FieldIdentifierParams> for FieldIdentifierPayload {
type Error = ErrorCode;
fn try_into(self) -> Result<FieldIdentifierParams, Self::Error> {
let grid_id = NotEmptyUuid::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
let field_id = NotEmptyUuid::parse(self.field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?;
Ok(FieldIdentifierParams {
grid_id: grid_id.0,
field_id: field_id.0,
})
}
}
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct FieldOrder {
#[pb(index = 1)]

View File

@ -659,6 +659,408 @@ impl ::protobuf::reflect::ProtobufValue for Field {
}
}
#[derive(PartialEq,Clone,Default)]
pub struct FieldIdentifierPayload {
// message fields
pub field_id: ::std::string::String,
pub grid_id: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a FieldIdentifierPayload {
fn default() -> &'a FieldIdentifierPayload {
<FieldIdentifierPayload as ::protobuf::Message>::default_instance()
}
}
impl FieldIdentifierPayload {
pub fn new() -> FieldIdentifierPayload {
::std::default::Default::default()
}
// string field_id = 1;
pub fn get_field_id(&self) -> &str {
&self.field_id
}
pub fn clear_field_id(&mut self) {
self.field_id.clear();
}
// Param is passed by value, moved
pub fn set_field_id(&mut self, v: ::std::string::String) {
self.field_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_field_id(&mut self) -> &mut ::std::string::String {
&mut self.field_id
}
// Take field
pub fn take_field_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.field_id, ::std::string::String::new())
}
// string grid_id = 2;
pub fn get_grid_id(&self) -> &str {
&self.grid_id
}
pub fn clear_grid_id(&mut self) {
self.grid_id.clear();
}
// Param is passed by value, moved
pub fn set_grid_id(&mut self, v: ::std::string::String) {
self.grid_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_grid_id(&mut self) -> &mut ::std::string::String {
&mut self.grid_id
}
// Take field
pub fn take_grid_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.grid_id, ::std::string::String::new())
}
}
impl ::protobuf::Message for FieldIdentifierPayload {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.field_id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.field_id);
}
if !self.grid_id.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.grid_id);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.field_id.is_empty() {
os.write_string(1, &self.field_id)?;
}
if !self.grid_id.is_empty() {
os.write_string(2, &self.grid_id)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> FieldIdentifierPayload {
FieldIdentifierPayload::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"field_id",
|m: &FieldIdentifierPayload| { &m.field_id },
|m: &mut FieldIdentifierPayload| { &mut m.field_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"grid_id",
|m: &FieldIdentifierPayload| { &m.grid_id },
|m: &mut FieldIdentifierPayload| { &mut m.grid_id },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldIdentifierPayload>(
"FieldIdentifierPayload",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static FieldIdentifierPayload {
static instance: ::protobuf::rt::LazyV2<FieldIdentifierPayload> = ::protobuf::rt::LazyV2::INIT;
instance.get(FieldIdentifierPayload::new)
}
}
impl ::protobuf::Clear for FieldIdentifierPayload {
fn clear(&mut self) {
self.field_id.clear();
self.grid_id.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for FieldIdentifierPayload {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for FieldIdentifierPayload {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct FieldIdentifierParams {
// message fields
pub field_id: ::std::string::String,
pub grid_id: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a FieldIdentifierParams {
fn default() -> &'a FieldIdentifierParams {
<FieldIdentifierParams as ::protobuf::Message>::default_instance()
}
}
impl FieldIdentifierParams {
pub fn new() -> FieldIdentifierParams {
::std::default::Default::default()
}
// string field_id = 1;
pub fn get_field_id(&self) -> &str {
&self.field_id
}
pub fn clear_field_id(&mut self) {
self.field_id.clear();
}
// Param is passed by value, moved
pub fn set_field_id(&mut self, v: ::std::string::String) {
self.field_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_field_id(&mut self) -> &mut ::std::string::String {
&mut self.field_id
}
// Take field
pub fn take_field_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.field_id, ::std::string::String::new())
}
// string grid_id = 2;
pub fn get_grid_id(&self) -> &str {
&self.grid_id
}
pub fn clear_grid_id(&mut self) {
self.grid_id.clear();
}
// Param is passed by value, moved
pub fn set_grid_id(&mut self, v: ::std::string::String) {
self.grid_id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_grid_id(&mut self) -> &mut ::std::string::String {
&mut self.grid_id
}
// Take field
pub fn take_grid_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.grid_id, ::std::string::String::new())
}
}
impl ::protobuf::Message for FieldIdentifierParams {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.grid_id)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.field_id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.field_id);
}
if !self.grid_id.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.grid_id);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.field_id.is_empty() {
os.write_string(1, &self.field_id)?;
}
if !self.grid_id.is_empty() {
os.write_string(2, &self.grid_id)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> FieldIdentifierParams {
FieldIdentifierParams::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"field_id",
|m: &FieldIdentifierParams| { &m.field_id },
|m: &mut FieldIdentifierParams| { &mut m.field_id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"grid_id",
|m: &FieldIdentifierParams| { &m.grid_id },
|m: &mut FieldIdentifierParams| { &mut m.grid_id },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldIdentifierParams>(
"FieldIdentifierParams",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static FieldIdentifierParams {
static instance: ::protobuf::rt::LazyV2<FieldIdentifierParams> = ::protobuf::rt::LazyV2::INIT;
instance.get(FieldIdentifierParams::new)
}
}
impl ::protobuf::Clear for FieldIdentifierParams {
fn clear(&mut self) {
self.field_id.clear();
self.grid_id.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for FieldIdentifierParams {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for FieldIdentifierParams {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct FieldOrder {
// message fields
@ -4865,48 +5267,51 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\
\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\
\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\
\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\
\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFiel\
dContextParams\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\
\nfield_type\x18\x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditF\
ieldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ng\
rid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_opt\
ion_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\
\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\
edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\
ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\
\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\
t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\
\x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\
\x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\
\x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\
\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\
.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\
\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\
items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\
\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\
\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\
\x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\
\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\
\x07content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b\
2\x05.CellR\x05items\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\
\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\
\x01(\tR\x05value\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01\
(\tR\x05value\"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\
\x01(\tR\x06gridId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstart\
RowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\
\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\
\x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\
\x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\
\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\
\x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\
\x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\
\x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\
\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\
\x0f.GridBlockOrderR\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\
\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\
\x20\x01(\tR\x07blockId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\
b\x06proto3\
\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\"L\n\x16FieldIdentifi\
erPayload\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\
\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\"K\n\x15FieldIdentifierParams\
\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_\
id\x18\x02\x20\x01(\tR\x06gridId\"'\n\nFieldOrder\x12\x19\n\x08field_id\
\x18\x01\x20\x01(\tR\x07fieldId\"b\n\x1cCreateEditFieldContextParams\x12\
\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12)\n\nfield_type\x18\
\x02\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFieldContext\x12\
\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngrid_field\x18\
\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_option_data\x18\
\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\x1c\n\x05it\
ems\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFieldOrder\
\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"T\n\x08\
RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08b\
lock_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06height\x18\x03\x20\
\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\
\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\x17.Row.CellB\
yFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\
\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01\
(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\
\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\
\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05items\x18\x01\
\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\x12\x19\n\
\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\x12\x0e\n\
\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\
2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\
\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07content\
\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\
\x05items\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\t\
R\x04name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05va\
lue\"#\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\
\"f\n\x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gr\
idId\x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\
\x13one_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07g\
rid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\
\x0b2\x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\
\x0cR\x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\
\x0cstartFieldIdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPaylo\
ad\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_or\
ders\x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\
\x16QueryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06g\
ridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\
\x0bblockOrders\"\\\n\x0fQueryRowPayload\x12\x17\n\x07grid_id\x18\x01\
\x20\x01(\tR\x06gridId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07bloc\
kId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowIdb\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -15,6 +15,14 @@ message Field {
bool visibility = 6;
int32 width = 7;
}
message FieldIdentifierPayload {
string field_id = 1;
string grid_id = 2;
}
message FieldIdentifierParams {
string field_id = 1;
string grid_id = 2;
}
message FieldOrder {
string field_id = 1;
}

View File

@ -72,42 +72,17 @@ impl GridMetaPad {
})
}
pub fn contain_field(&self, field_id: &str) -> bool {
self.grid_meta.fields.iter().any(|field| field.id == field_id)
}
pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> {
self.grid_meta.fields.iter().find(|field| field.id == field_id)
}
pub fn get_field_orders(&self) -> Vec<FieldOrder> {
self.grid_meta.fields.iter().map(FieldOrder::from).collect()
}
pub fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> CollaborateResult<Vec<FieldMeta>> {
match field_orders {
None => Ok(self.grid_meta.fields.clone()),
Some(field_orders) => {
let field_by_field_id = self
.grid_meta
.fields
.iter()
.map(|field| (&field.id, field))
.collect::<HashMap<&String, &FieldMeta>>();
let fields = field_orders
.iter()
.flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
None => {
tracing::error!("Can't find the field with id: {}", field_order.field_id);
None
}
Some(field) => Some((*field).clone()),
})
.collect::<Vec<FieldMeta>>();
Ok(fields)
pub fn duplicate_field(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) {
None => Ok(None),
Some(index) => {
let mut duplicate_field_meta = grid.fields[index].clone();
duplicate_field_meta.id = uuid();
duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name);
grid.fields.insert(index + 1, duplicate_field_meta);
Ok(Some(()))
}
}
})
}
pub fn update_field(&mut self, changeset: FieldChangesetParams) -> CollaborateResult<Option<GridChangeset>> {
@ -160,6 +135,44 @@ impl GridMetaPad {
})
}
pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> {
self.grid_meta.fields.iter().find(|field| field.id == field_id)
}
pub fn contain_field(&self, field_id: &str) -> bool {
self.grid_meta.fields.iter().any(|field| field.id == field_id)
}
pub fn get_field_orders(&self) -> Vec<FieldOrder> {
self.grid_meta.fields.iter().map(FieldOrder::from).collect()
}
pub fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> CollaborateResult<Vec<FieldMeta>> {
match field_orders {
None => Ok(self.grid_meta.fields.clone()),
Some(field_orders) => {
let field_by_field_id = self
.grid_meta
.fields
.iter()
.map(|field| (&field.id, field))
.collect::<HashMap<&String, &FieldMeta>>();
let fields = field_orders
.iter()
.flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
None => {
tracing::error!("Can't find the field with id: {}", field_order.field_id);
None
}
Some(field) => Some((*field).clone()),
})
.collect::<Vec<FieldMeta>>();
Ok(fields)
}
}
}
pub fn create_block(&mut self, block: GridBlockMeta) -> CollaborateResult<Option<GridChangeset>> {
self.modify_grid(|grid| {
if grid.block_metas.iter().any(|b| b.block_id == block.block_id) {