feat: add grid widget

This commit is contained in:
appflowy 2022-03-03 10:51:52 +08:00
parent 03f34b143d
commit 0bbf17f776
23 changed files with 1343 additions and 84 deletions

View File

@ -0,0 +1,135 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'grid_service.dart';
part 'grid_bloc.freezed.dart';
class GridBloc extends Bloc<GridEvent, GridState> {
final GridService service;
final View view;
late Grid _grid;
GridBloc({required this.view, required this.service}) : super(GridState.initial()) {
on<GridEvent>(
(event, emit) async {
await event.map(
initial: (Initial value) async {
await _initial(value, emit);
},
createRow: (_CreateRow value) {
service.createRow(gridId: view.id);
},
delete: (_Delete value) {},
rename: (_Rename value) {},
updateDesc: (_Desc value) {},
);
},
);
}
@override
Future<void> close() async {
return super.close();
}
Future<void> _initial(Initial value, Emitter<GridState> emit) async {
final result = await service.openGrid(gridId: view.id);
result.fold(
(grid) {
_grid = grid;
_loadGridInfo(emit);
},
(err) {
emit(state.copyWith(loadingState: GridLoadingState.finish(right(err))));
},
);
}
Future<void> _loadGridInfo(Emitter<GridState> emit) async {
emit(
state.copyWith(loadingState: GridLoadingState.finish(left(unit))),
);
}
}
@freezed
abstract class GridEvent with _$GridEvent {
const factory GridEvent.initial() = Initial;
const factory GridEvent.rename(String gridId, String name) = _Rename;
const factory GridEvent.updateDesc(String gridId, String desc) = _Desc;
const factory GridEvent.delete(String gridId) = _Delete;
const factory GridEvent.createRow() = _CreateRow;
}
@freezed
abstract class GridState with _$GridState {
const factory GridState({
required GridLoadingState loadingState,
required Option<Either<GridInfo, FlowyError>> gridInfo,
}) = _GridState;
factory GridState.initial() => GridState(
loadingState: const _Loading(),
gridInfo: none(),
);
}
@freezed
class GridLoadingState with _$GridLoadingState {
const factory GridLoadingState.loading() = _Loading;
const factory GridLoadingState.finish(Either<Unit, FlowyError> successOrFail) = _Finish;
}
typedef FieldById = Map<String, Field>;
typedef RowById = Map<String, Row>;
typedef CellById = Map<String, DisplayCell>;
class GridInfo {
List<RowOrder> rowOrders;
List<FieldOrder> fieldOrders;
RowById rowMap;
FieldById fieldMap;
GridInfo({
required this.rowOrders,
required this.fieldOrders,
required this.fieldMap,
required this.rowMap,
});
RowInfo rowInfoAtIndex(int index) {
final rowOrder = rowOrders[index];
final Row row = rowMap[rowOrder.rowId]!;
final cellMap = row.cellByFieldId;
final displayCellMap = <String, DisplayCell>{};
return RowInfo(
fieldOrders: fieldOrders,
fieldMap: fieldMap,
displayCellMap: displayCellMap,
);
}
int numberOfRows() {
return rowOrders.length;
}
}
class RowInfo {
List<FieldOrder> fieldOrders;
FieldById fieldMap;
CellById displayCellMap;
RowInfo({
required this.fieldOrders,
required this.fieldMap,
required this.displayCellMap,
});
}

View File

@ -0,0 +1,20 @@
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:dartz/dartz.dart';
class GridService {
Future<Either<Grid, FlowyError>> createGrid({required String name}) {
final payload = CreateGridPayload()..name = name;
return GridEventCreateGrid(payload).send();
}
Future<Either<Grid, FlowyError>> openGrid({required String gridId}) {
final payload = GridId(value: gridId);
return GridEventOpenGrid(payload).send();
}
Future<Either<void, FlowyError>> createRow({required String gridId}) {
throw UnimplementedError();
}
}

View File

@ -0,0 +1,73 @@
/// The data structor representing each selection of flowy table.
enum FlowyTableSelectionType {
item,
row,
col,
}
class FlowyTableSelectionItem {
final FlowyTableSelectionType type;
final int? row;
final int? column;
const FlowyTableSelectionItem({
required this.type,
this.row,
this.column,
});
@override
String toString() {
return '$type($row, $column)';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
return other is FlowyTableSelectionItem &&
type == other.type &&
row == other.row &&
column == other.column;
}
@override
int get hashCode => type.hashCode ^ row.hashCode ^ column.hashCode;
}
class FlowyTableSelection {
Set<FlowyTableSelectionItem> _items = {};
Set<FlowyTableSelectionItem> get items => _items;
FlowyTableSelection(
this._items,
);
FlowyTableSelection.combine(
FlowyTableSelection lhs, FlowyTableSelection rhs) {
this..combine(lhs)..combine(rhs);
}
FlowyTableSelection operator +(FlowyTableSelection other) {
return this..combine(other);
}
void combine(FlowyTableSelection other) {
var totalItems = items..union(other.items);
final rows = totalItems
.where((ele) => ele.type == FlowyTableSelectionType.row)
.map((e) => e.row)
.toSet();
final cols = totalItems
.where((ele) => ele.type == FlowyTableSelectionType.col)
.map((e) => e.column)
.toSet();
totalItems.removeWhere((ele) {
return ele.type == FlowyTableSelectionType.item &&
(rows.contains(ele.row) || cols.contains(ele.column));
});
_items = totalItems;
}
}

View File

@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
class GridScrollController {
final ScrollController _verticalController = ScrollController();
final ScrollController _horizontalController = ScrollController();
ScrollController get verticalController => _verticalController;
ScrollController get horizontalController => _horizontalController;
GridScrollController();
// final SelectionChangeCallback? onSelectionChanged;
// final ShouldApplySelection? shouldApplySelection;
// final ScrollCallback? onScroll;
void dispose() {
verticalController.dispose();
horizontalController.dispose();
}
}

View File

@ -0,0 +1,17 @@
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'grid_sizes.dart';
class GridLayout {
static double headerWidth(List<FieldOrder> fieldOrders) {
if (fieldOrders.isEmpty) return 0;
final fieldsWidth = fieldOrders
.map(
(fieldOrder) => fieldOrder.width.toDouble(),
)
.reduce((value, element) => value + element);
return fieldsWidth + GridSize.firstHeaderPadding;
}
}

View File

@ -0,0 +1,150 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/grid/grid_bloc.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/controller/grid_scroll.dart';
import 'package:styled_widget/styled_widget.dart';
import 'grid_layout.dart';
import 'grid_sizes.dart';
import 'widgets/grid_content/grid_row.dart';
import 'widgets/grid_footer/grid_footer.dart';
import 'widgets/grid_header/header.dart';
class GridPage extends StatefulWidget {
final View view;
GridPage({Key? key, required this.view}) : super(key: ValueKey(view.id));
@override
State<GridPage> createState() => _GridPageState();
}
class _GridPageState extends State<GridPage> {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<GridBloc>(create: (context) => getIt<GridBloc>()),
],
child: BlocBuilder<GridBloc, GridState>(
builder: (context, state) {
return state.loadingState.map(
loading: (_) => const Center(child: CircularProgressIndicator.adaptive()),
finish: (result) => result.successOrFail.fold(
(_) => const GridBody(),
(err) => FlowyErrorPage(err.toString()),
),
);
},
),
);
}
@override
void dispose() {
super.dispose();
}
@override
void deactivate() {
super.deactivate();
}
@override
void didUpdateWidget(covariant GridPage oldWidget) {
super.didUpdateWidget(oldWidget);
}
}
class GridBody extends StatefulWidget {
const GridBody({Key? key}) : super(key: key);
@override
_GridBodyState createState() => _GridBodyState();
}
class _GridBodyState extends State<GridBody> {
final _scrollController = GridScrollController();
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<GridBloc, GridState>(
builder: (context, state) {
return state.gridInfo.fold(
() => const Center(child: CircularProgressIndicator.adaptive()),
(some) => some.fold(
(gridInfo) => _renderGrid(context, gridInfo),
(err) => FlowyErrorPage(err.toString()),
),
);
},
);
}
Widget _renderGrid(BuildContext context, GridInfo gridInfo) {
return Stack(
children: [
StyledSingleChildScrollView(
controller: _scrollController.horizontalController,
axis: Axis.horizontal,
child: SizedBox(
width: GridLayout.headerWidth(gridInfo.fieldOrders),
child: CustomScrollView(
physics: StyledScrollPhysics(),
controller: _scrollController.verticalController,
slivers: <Widget>[
_buildHeader(gridInfo.fieldOrders, gridInfo.fieldMap),
_buildRows(gridInfo),
_builderFooter(context),
],
),
),
),
ScrollbarListStack(
axis: Axis.vertical,
controller: _scrollController.verticalController,
barSize: GridSize.scrollBarSize,
child: Container(),
).padding(right: 0, top: GridSize.headerHeight, bottom: GridSize.scrollBarSize),
],
);
}
Widget _buildHeader(List<FieldOrder> fieldOrders, FieldById fieldById) {
return SliverPersistentHeader(
delegate: GridHeaderDelegate(fieldOrders, fieldById),
floating: true,
pinned: true,
);
}
Widget _buildRows(GridInfo gridInfo) {
return SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
final rowInfo = gridInfo.rowInfoAtIndex(index);
return RepaintBoundary(child: GridRow(rowInfo));
}, childCount: gridInfo.numberOfRows()),
);
}
Widget _builderFooter(BuildContext context) {
return GridFooter(
onAddRow: () {
context.read<GridBloc>().add(const GridEvent.createRow());
},
);
}
}

View File

@ -0,0 +1,16 @@
class GridInsets {
static double scale = 1;
static double get horizontal => 6 * scale;
static double get vertical => 6 * scale;
}
class GridSize {
static double scale = 1;
static double get scrollBarSize => 12 * scale;
static double get headerHeight => 50 * scale;
static double get rowHeight => 50 * scale;
static double get footerHeight => 40 * scale;
static double get firstHeaderPadding => 20 * scale;
}

View File

@ -0,0 +1,17 @@
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'grid_cell.dart';
class GridCellBuilder {
static GridCell buildCell(Field? field, DisplayCell? cell) {
if (field == null || cell == null) {
return BlankCell();
}
switch (field.fieldType) {
case FieldType.RichText:
return GridTextCell(cell.content);
default:
return BlankCell();
}
}
}

View File

@ -0,0 +1,34 @@
import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'cell_decoration.dart';
import 'grid_cell.dart';
class CellContainer extends StatelessWidget {
final GridCell child;
final double width;
const CellContainer({Key? key, required this.child, required this.width}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
// context
// .read<HomeBloc>()
// .add(HomeEvent.setEditPannel(CellEditPannelContext()));
},
child: MouseHoverBuilder(
builder: (_, isHovered) => Container(
width: width,
decoration: CellDecoration.box(
color: isHovered ? Colors.red.withOpacity(.1) : Colors.transparent,
),
padding: EdgeInsets.symmetric(vertical: GridInsets.vertical, horizontal: GridInsets.horizontal),
child: child,
),
),
);
}
}

View File

@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
class CellDecoration {
static BoxDecoration box({required Color color}) {
return BoxDecoration(
border: Border.all(color: Colors.black26, width: 0.2),
color: color,
);
}
}

View File

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
// ignore: import_of_legacy_library_into_null_safe
/// The interface of base cell.
abstract class GridCell extends StatelessWidget {
final canSelect = true;
const GridCell({Key? key}) : super(key: key);
}
class GridTextCell extends GridCell {
final String content;
const GridTextCell(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(content);
}
}
class DateCell extends GridCell {
final String content;
const DateCell(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(content);
}
}
class NumberCell extends GridCell {
final String content;
const NumberCell(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(content);
}
}
class SingleSelectCell extends GridCell {
final String content;
const SingleSelectCell(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(content);
}
}
class MultiSelectCell extends GridCell {
final String content;
const MultiSelectCell(this.content, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(content);
}
}
class BlankCell extends GridCell {
const BlankCell({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}

View File

@ -0,0 +1,64 @@
import 'package:app_flowy/workspace/application/grid/grid_bloc.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
import 'package:flutter/material.dart';
import 'cell_builder.dart';
import 'cell_container.dart';
import 'grid_row_leading.dart';
class GridRowContext {
final RepeatedFieldOrder fieldOrders;
final Map<String, Field> fieldById;
final Map<String, DisplayCell> cellByFieldId;
GridRowContext(this.fieldOrders, this.fieldById, this.cellByFieldId);
}
class GridRow extends StatelessWidget {
final RowInfo rowInfo;
final Function(bool)? onHoverChange;
const GridRow(this.rowInfo, {Key? key, this.onHoverChange}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: GridSize.rowHeight,
child: _buildRowBody(),
);
}
Widget _buildRowBody() {
Widget rowWidget = Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _buildCells(),
);
if (onHoverChange != null) {
rowWidget = MouseRegion(
onEnter: (event) => onHoverChange!(true),
onExit: (event) => onHoverChange!(false),
cursor: MouseCursor.uncontrolled,
child: rowWidget,
);
}
return rowWidget;
}
List<Widget> _buildCells() {
var cells = List<Widget>.empty(growable: true);
cells.add(const RowLeading());
rowInfo.fieldOrders.where((element) => element.visibility).forEach((fieldOrder) {
final field = rowInfo.fieldMap[fieldOrder.fieldId];
final data = rowInfo.displayCellMap[fieldOrder.fieldId];
final cell = CellContainer(
width: fieldOrder.width.toDouble(),
child: GridCellBuilder.buildCell(field, data),
);
cells.add(cell);
});
return cells;
}
}

View File

@ -0,0 +1,14 @@
import 'package:flutter/material.dart';
class GridUnknownError extends StatelessWidget {
const GridUnknownError({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
}

View File

@ -0,0 +1,46 @@
import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/widgets/grid_content/cell_decoration.dart';
import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
import 'package:flutter/material.dart';
class GridFooter extends StatelessWidget {
final VoidCallback? onAddRow;
const GridFooter({Key? key, required this.onAddRow}) : super(key: key);
@override
Widget build(BuildContext context) {
return SliverToBoxAdapter(
child: SizedBox(
height: GridSize.footerHeight,
child: Row(
children: [
AddRowButton(onTap: onAddRow),
],
),
),
);
}
}
class AddRowButton extends StatelessWidget {
final VoidCallback? onTap;
const AddRowButton({Key? key, required this.onTap}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: onTap,
child: MouseHoverBuilder(
builder: (_, isHovered) => Container(
width: GridSize.firstHeaderPadding,
height: GridSize.footerHeight,
decoration: CellDecoration.box(
color: isHovered ? Colors.red.withOpacity(.1) : Colors.white,
),
child: const Icon(Icons.add, size: 16),
),
),
);
}
}

View File

@ -0,0 +1,5 @@
import 'package:flutter/material.dart';
class GridHeaderConstants {
static Color get backgroundColor => Colors.grey;
}

View File

@ -0,0 +1,52 @@
import 'package:app_flowy/workspace/presentation/plugins/grid/grid_sizes.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' hide Row;
import 'package:flutter/material.dart';
import 'constants.dart';
class HeaderCell extends StatelessWidget {
final Field field;
const HeaderCell(this.field, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
field.name,
style: const TextStyle(fontSize: 15.0, color: Colors.black),
);
}
}
class HeaderCellContainer extends StatelessWidget {
final HeaderCell child;
final double width;
const HeaderCellContainer({Key? key, required this.child, required this.width}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {},
child: Container(
width: width,
decoration: BoxDecoration(
border: Border.all(color: Colors.black26, width: 0.5),
color: GridHeaderConstants.backgroundColor,
),
padding: EdgeInsets.symmetric(vertical: GridInsets.vertical, horizontal: GridInsets.horizontal),
child: child,
),
);
}
}
class HeaderCellLeading extends StatelessWidget {
const HeaderCellLeading({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: GridSize.firstHeaderPadding,
color: GridHeaderConstants.backgroundColor,
);
}
}

View File

@ -9,6 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-net/event.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/event_map.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/event_map.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/event_map.pb.dart';
import 'package:isolates/isolates.dart';
import 'package:isolates/ports.dart';
import 'package:ffi/ffi.dart';
@ -21,6 +22,7 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart';
import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-collaboration/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/protobuf.dart';
// ignore: unused_import
import 'package:protobuf/protobuf.dart';
@ -30,6 +32,7 @@ import 'error.dart';
part 'dart_event/flowy-folder/dart_event.dart';
part 'dart_event/flowy-net/dart_event.dart';
part 'dart_event/flowy-user/dart_event.dart';
part 'dart_event/flowy-grid/dart_event.dart';
enum FFIException {
RequestIsEmpty,

View File

@ -725,7 +725,6 @@ class Cell extends $pb.GeneratedMessage {
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowId')
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
..aOM<AnyData>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', subBuilder: AnyData.create)
..hasRequiredFields = false
;
@ -734,7 +733,6 @@ class Cell extends $pb.GeneratedMessage {
$core.String? id,
$core.String? rowId,
$core.String? fieldId,
AnyData? data,
}) {
final _result = create();
if (id != null) {
@ -746,9 +744,6 @@ class Cell extends $pb.GeneratedMessage {
if (fieldId != null) {
_result.fieldId = fieldId;
}
if (data != null) {
_result.data = data;
}
return _result;
}
factory Cell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@ -798,17 +793,130 @@ class Cell extends $pb.GeneratedMessage {
$core.bool hasFieldId() => $_has(2);
@$pb.TagNumber(3)
void clearFieldId() => clearField(3);
}
@$pb.TagNumber(4)
AnyData get data => $_getN(3);
@$pb.TagNumber(4)
set data(AnyData v) { setField(4, v); }
@$pb.TagNumber(4)
$core.bool hasData() => $_has(3);
@$pb.TagNumber(4)
void clearData() => clearField(4);
@$pb.TagNumber(4)
AnyData ensureData() => $_ensure(3);
class DisplayCell extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DisplayCell', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'content')
..hasRequiredFields = false
;
DisplayCell._() : super();
factory DisplayCell({
$core.String? id,
$core.String? content,
}) {
final _result = create();
if (id != null) {
_result.id = id;
}
if (content != null) {
_result.content = content;
}
return _result;
}
factory DisplayCell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory DisplayCell.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')
DisplayCell clone() => DisplayCell()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
DisplayCell copyWith(void Function(DisplayCell) updates) => super.copyWith((message) => updates(message as DisplayCell)) as DisplayCell; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static DisplayCell create() => DisplayCell._();
DisplayCell createEmptyInstance() => create();
static $pb.PbList<DisplayCell> createRepeated() => $pb.PbList<DisplayCell>();
@$core.pragma('dart2js:noInline')
static DisplayCell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<DisplayCell>(create);
static DisplayCell? _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 content => $_getSZ(1);
@$pb.TagNumber(2)
set content($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasContent() => $_has(1);
@$pb.TagNumber(2)
void clearContent() => clearField(2);
}
class RawCell extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RawCell', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
..aOM<AnyData>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', subBuilder: AnyData.create)
..hasRequiredFields = false
;
RawCell._() : super();
factory RawCell({
$core.String? id,
AnyData? data,
}) {
final _result = create();
if (id != null) {
_result.id = id;
}
if (data != null) {
_result.data = data;
}
return _result;
}
factory RawCell.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory RawCell.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')
RawCell clone() => RawCell()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
RawCell copyWith(void Function(RawCell) updates) => super.copyWith((message) => updates(message as RawCell)) as RawCell; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static RawCell create() => RawCell._();
RawCell createEmptyInstance() => create();
static $pb.PbList<RawCell> createRepeated() => $pb.PbList<RawCell>();
@$core.pragma('dart2js:noInline')
static RawCell getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<RawCell>(create);
static RawCell? _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)
AnyData get data => $_getN(1);
@$pb.TagNumber(2)
set data(AnyData v) { setField(2, v); }
@$pb.TagNumber(2)
$core.bool hasData() => $_has(1);
@$pb.TagNumber(2)
void clearData() => clearField(2);
@$pb.TagNumber(2)
AnyData ensureData() => $_ensure(1);
}
class CreateGridPayload extends $pb.GeneratedMessage {

View File

@ -159,12 +159,33 @@ const Cell$json = const {
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'row_id', '3': 2, '4': 1, '5': 9, '10': 'rowId'},
const {'1': 'field_id', '3': 3, '4': 1, '5': 9, '10': 'fieldId'},
const {'1': 'data', '3': 4, '4': 1, '5': 11, '6': '.AnyData', '10': 'data'},
],
};
/// Descriptor for `Cell`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEg4KAmlkGAEgASgJUgJpZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAMgASgJUgdmaWVsZElkEhwKBGRhdGEYBCABKAsyCC5BbnlEYXRhUgRkYXRh');
final $typed_data.Uint8List cellDescriptor = $convert.base64Decode('CgRDZWxsEg4KAmlkGAEgASgJUgJpZBIVCgZyb3dfaWQYAiABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAMgASgJUgdmaWVsZElk');
@$core.Deprecated('Use displayCellDescriptor instead')
const DisplayCell$json = const {
'1': 'DisplayCell',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'content', '3': 2, '4': 1, '5': 9, '10': 'content'},
],
};
/// Descriptor for `DisplayCell`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List displayCellDescriptor = $convert.base64Decode('CgtEaXNwbGF5Q2VsbBIOCgJpZBgBIAEoCVICaWQSGAoHY29udGVudBgCIAEoCVIHY29udGVudA==');
@$core.Deprecated('Use rawCellDescriptor instead')
const RawCell$json = const {
'1': 'RawCell',
'2': const [
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
const {'1': 'data', '3': 2, '4': 1, '5': 11, '6': '.AnyData', '10': 'data'},
],
};
/// Descriptor for `RawCell`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List rawCellDescriptor = $convert.base64Decode('CgdSYXdDZWxsEg4KAmlkGAEgASgJUgJpZBIcCgRkYXRhGAIgASgLMgguQW55RGF0YVIEZGF0YQ==');
@$core.Deprecated('Use createGridPayloadDescriptor instead')
const CreateGridPayload$json = const {
'1': 'CreateGridPayload',

View File

@ -142,8 +142,23 @@ pub struct Cell {
#[pb(index = 3)]
pub field_id: String,
}
#[pb(index = 4)]
#[derive(Debug, Default, ProtoBuf)]
pub struct DisplayCell {
#[pb(index = 1)]
pub id: String,
#[pb(index = 2)]
pub content: String,
}
#[derive(Debug, Default, ProtoBuf)]
pub struct RawCell {
#[pb(index = 1)]
pub id: String,
#[pb(index = 2)]
pub data: AnyData,
}

View File

@ -2405,7 +2405,6 @@ pub struct Cell {
pub id: ::std::string::String,
pub row_id: ::std::string::String,
pub field_id: ::std::string::String,
pub data: ::protobuf::SingularPtrField<AnyData>,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
@ -2499,48 +2498,10 @@ impl Cell {
pub fn take_field_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.field_id, ::std::string::String::new())
}
// .AnyData data = 4;
pub fn get_data(&self) -> &AnyData {
self.data.as_ref().unwrap_or_else(|| <AnyData as ::protobuf::Message>::default_instance())
}
pub fn clear_data(&mut self) {
self.data.clear();
}
pub fn has_data(&self) -> bool {
self.data.is_some()
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: AnyData) {
self.data = ::protobuf::SingularPtrField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut AnyData {
if self.data.is_none() {
self.data.set_default();
}
self.data.as_mut().unwrap()
}
// Take field
pub fn take_data(&mut self) -> AnyData {
self.data.take().unwrap_or_else(|| AnyData::new())
}
}
impl ::protobuf::Message for Cell {
fn is_initialized(&self) -> bool {
for v in &self.data {
if !v.is_initialized() {
return false;
}
};
true
}
@ -2557,9 +2518,6 @@ impl ::protobuf::Message for Cell {
3 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?;
},
4 => {
::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
@ -2581,10 +2539,6 @@ impl ::protobuf::Message for Cell {
if !self.field_id.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.field_id);
}
if let Some(ref v) = self.data.as_ref() {
let len = v.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
@ -2600,11 +2554,6 @@ impl ::protobuf::Message for Cell {
if !self.field_id.is_empty() {
os.write_string(3, &self.field_id)?;
}
if let Some(ref v) = self.data.as_ref() {
os.write_tag(4, ::protobuf::wire_format::WireTypeLengthDelimited)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
@ -2658,11 +2607,6 @@ impl ::protobuf::Message for Cell {
|m: &Cell| { &m.field_id },
|m: &mut Cell| { &mut m.field_id },
));
fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<AnyData>>(
"data",
|m: &Cell| { &m.data },
|m: &mut Cell| { &mut m.data },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<Cell>(
"Cell",
fields,
@ -2682,7 +2626,6 @@ impl ::protobuf::Clear for Cell {
self.id.clear();
self.row_id.clear();
self.field_id.clear();
self.data.clear();
self.unknown_fields.clear();
}
}
@ -2699,6 +2642,423 @@ impl ::protobuf::reflect::ProtobufValue for Cell {
}
}
#[derive(PartialEq,Clone,Default)]
pub struct DisplayCell {
// message fields
pub id: ::std::string::String,
pub content: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a DisplayCell {
fn default() -> &'a DisplayCell {
<DisplayCell as ::protobuf::Message>::default_instance()
}
}
impl DisplayCell {
pub fn new() -> DisplayCell {
::std::default::Default::default()
}
// string id = 1;
pub fn get_id(&self) -> &str {
&self.id
}
pub fn clear_id(&mut self) {
self.id.clear();
}
// Param is passed by value, moved
pub fn set_id(&mut self, v: ::std::string::String) {
self.id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_id(&mut self) -> &mut ::std::string::String {
&mut self.id
}
// Take field
pub fn take_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// string content = 2;
pub fn get_content(&self) -> &str {
&self.content
}
pub fn clear_content(&mut self) {
self.content.clear();
}
// Param is passed by value, moved
pub fn set_content(&mut self, v: ::std::string::String) {
self.content = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_content(&mut self) -> &mut ::std::string::String {
&mut self.content
}
// Take field
pub fn take_content(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.content, ::std::string::String::new())
}
}
impl ::protobuf::Message for DisplayCell {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.content)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if !self.content.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.content);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.id.is_empty() {
os.write_string(1, &self.id)?;
}
if !self.content.is_empty() {
os.write_string(2, &self.content)?;
}
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() -> DisplayCell {
DisplayCell::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"id",
|m: &DisplayCell| { &m.id },
|m: &mut DisplayCell| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"content",
|m: &DisplayCell| { &m.content },
|m: &mut DisplayCell| { &mut m.content },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<DisplayCell>(
"DisplayCell",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static DisplayCell {
static instance: ::protobuf::rt::LazyV2<DisplayCell> = ::protobuf::rt::LazyV2::INIT;
instance.get(DisplayCell::new)
}
}
impl ::protobuf::Clear for DisplayCell {
fn clear(&mut self) {
self.id.clear();
self.content.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for DisplayCell {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for DisplayCell {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct RawCell {
// message fields
pub id: ::std::string::String,
pub data: ::protobuf::SingularPtrField<AnyData>,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a RawCell {
fn default() -> &'a RawCell {
<RawCell as ::protobuf::Message>::default_instance()
}
}
impl RawCell {
pub fn new() -> RawCell {
::std::default::Default::default()
}
// string id = 1;
pub fn get_id(&self) -> &str {
&self.id
}
pub fn clear_id(&mut self) {
self.id.clear();
}
// Param is passed by value, moved
pub fn set_id(&mut self, v: ::std::string::String) {
self.id = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_id(&mut self) -> &mut ::std::string::String {
&mut self.id
}
// Take field
pub fn take_id(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.id, ::std::string::String::new())
}
// .AnyData data = 2;
pub fn get_data(&self) -> &AnyData {
self.data.as_ref().unwrap_or_else(|| <AnyData as ::protobuf::Message>::default_instance())
}
pub fn clear_data(&mut self) {
self.data.clear();
}
pub fn has_data(&self) -> bool {
self.data.is_some()
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: AnyData) {
self.data = ::protobuf::SingularPtrField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut AnyData {
if self.data.is_none() {
self.data.set_default();
}
self.data.as_mut().unwrap()
}
// Take field
pub fn take_data(&mut self) -> AnyData {
self.data.take().unwrap_or_else(|| AnyData::new())
}
}
impl ::protobuf::Message for RawCell {
fn is_initialized(&self) -> bool {
for v in &self.data {
if !v.is_initialized() {
return false;
}
};
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?;
},
2 => {
::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.id.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.id);
}
if let Some(ref v) = self.data.as_ref() {
let len = v.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.id.is_empty() {
os.write_string(1, &self.id)?;
}
if let Some(ref v) = self.data.as_ref() {
os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
}
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() -> RawCell {
RawCell::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"id",
|m: &RawCell| { &m.id },
|m: &mut RawCell| { &mut m.id },
));
fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<AnyData>>(
"data",
|m: &RawCell| { &m.data },
|m: &mut RawCell| { &mut m.data },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<RawCell>(
"RawCell",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static RawCell {
static instance: ::protobuf::rt::LazyV2<RawCell> = ::protobuf::rt::LazyV2::INIT;
instance.get(RawCell::new)
}
}
impl ::protobuf::Clear for RawCell {
fn clear(&mut self) {
self.id.clear();
self.data.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for RawCell {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RawCell {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(PartialEq,Clone,Default)]
pub struct CreateGridPayload {
// message fields
@ -3107,15 +3467,17 @@ static file_descriptor_proto_data: &'static [u8] = b"\
difiedTime\x12@\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2\x17.Row.Cell\
ByFieldIdEntryR\rcellByFieldId\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\"f\n\x04Cell\x12\x0e\n\x02id\x18\x01\
\x0b2\x05.CellR\x05value:\x028\x01\"H\n\x04Cell\x12\x0e\n\x02id\x18\x01\
\x20\x01(\tR\x02id\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\
\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x1c\n\x04data\x18\
\x04\x20\x01(\x0b2\x08.AnyDataR\x04data\"'\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*d\n\tFieldType\x12\x0c\n\x08RichT\
ext\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\
\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\
\n\x08Checkbox\x10\x05b\x06proto3\
\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\"7\n\x0bDisplayCell\
\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x18\n\x07content\x18\x02\
\x20\x01(\tR\x07content\"7\n\x07RawCell\x12\x0e\n\x02id\x18\x01\x20\x01(\
\tR\x02id\x12\x1c\n\x04data\x18\x02\x20\x01(\x0b2\x08.AnyDataR\x04data\"\
'\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*d\n\tFi\
eldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\
\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMult\
iSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -52,7 +52,14 @@ message Cell {
string id = 1;
string row_id = 2;
string field_id = 3;
AnyData data = 4;
}
message DisplayCell {
string id = 1;
string content = 2;
}
message RawCell {
string id = 1;
AnyData data = 2;
}
message CreateGridPayload {
string name = 1;