mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: config row detail page
This commit is contained in:
parent
f40e0c18e6
commit
eeba6884ce
6
frontend/app_flowy/assets/images/grid/expander.svg
Normal file
6
frontend/app_flowy/assets/images/grid/expander.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 13H3V10" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10 3H13V6" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M3 13L7 9" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M13 3L9 7" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 449 B |
@ -0,0 +1,73 @@
|
||||
import 'dart:collection';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
import 'row_service.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
part 'row_detail_bloc.freezed.dart';
|
||||
|
||||
class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
||||
final GridRow rowData;
|
||||
final GridRowCache _rowCache;
|
||||
void Function()? _rowListenFn;
|
||||
|
||||
RowDetailBloc({
|
||||
required this.rowData,
|
||||
required GridRowCache rowCache,
|
||||
}) : _rowCache = rowCache,
|
||||
super(RowDetailState.initial()) {
|
||||
on<RowDetailEvent>(
|
||||
(event, emit) async {
|
||||
await event.map(
|
||||
initial: (_Initial value) async {
|
||||
await _startListening();
|
||||
},
|
||||
didReceiveCellDatas: (_DidReceiveCellDatas value) {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
if (_rowListenFn != null) {
|
||||
_rowCache.removeRowListener(_rowListenFn!);
|
||||
}
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
_rowListenFn = _rowCache.addRowListener(
|
||||
rowId: rowData.rowId,
|
||||
onUpdated: (cellDatas) => add(RowDetailEvent.didReceiveCellDatas(cellDatas)),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadRow(Emitter<RowDetailState> emit) async {
|
||||
final data = _rowCache.loadCellData(rowData.rowId);
|
||||
data.foldRight(null, (cellDatas, _) {
|
||||
if (!isClosed) {
|
||||
add(RowDetailEvent.didReceiveCellDatas(cellDatas));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowDetailEvent with _$RowDetailEvent {
|
||||
const factory RowDetailEvent.initial() = _Initial;
|
||||
const factory RowDetailEvent.didReceiveCellDatas(CellDataMap cellData) = _DidReceiveCellDatas;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowDetailState with _$RowDetailState {
|
||||
const factory RowDetailState({
|
||||
required Option<CellDataMap> cellDataMap,
|
||||
}) = _RowDetailState;
|
||||
|
||||
factory RowDetailState.initial() => RowDetailState(
|
||||
cellDataMap: none(),
|
||||
);
|
||||
}
|
@ -42,9 +42,9 @@ class GridRowCache {
|
||||
result.fold(
|
||||
(changesets) {
|
||||
for (final changeset in changesets) {
|
||||
_deleteRows(changeset.deletedRows);
|
||||
_insertRows(changeset.insertedRows);
|
||||
_updateRows(changeset.updatedRows);
|
||||
_rowNotifier.deleteRows(changeset.deletedRows);
|
||||
_rowNotifier.insertRows(changeset.insertedRows);
|
||||
_rowNotifier.updateRows(changeset.updatedRows);
|
||||
}
|
||||
},
|
||||
(err) => Log.error(err),
|
||||
@ -63,13 +63,15 @@ class GridRowCache {
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
_rowNotifier.addListener(() {
|
||||
if (onChanged == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (onChanged != null) {
|
||||
onChanged(clonedRows, _rowNotifier._changeReason);
|
||||
}
|
||||
onChanged(clonedRows, _rowNotifier._changeReason);
|
||||
});
|
||||
}
|
||||
|
||||
@ -136,18 +138,6 @@ class GridRowCache {
|
||||
final rowOrders = blocks.expand((block) => block.rowOrders).toList();
|
||||
_rowNotifier.reset(rowOrders);
|
||||
}
|
||||
|
||||
void _deleteRows(List<RowOrder> deletedRows) {
|
||||
_rowNotifier.deleteRows(deletedRows);
|
||||
}
|
||||
|
||||
void _insertRows(List<IndexRowOrder> createdRows) {
|
||||
_rowNotifier.insertRows(createdRows);
|
||||
}
|
||||
|
||||
void _updateRows(List<RowOrder> rowOrders) {
|
||||
_rowNotifier.updateRows(rowOrders);
|
||||
}
|
||||
}
|
||||
|
||||
class RowsNotifier extends ChangeNotifier {
|
||||
@ -173,7 +163,7 @@ class RowsNotifier extends ChangeNotifier {
|
||||
|
||||
final List<GridRow> newRows = [];
|
||||
final DeletedIndexs deletedIndex = [];
|
||||
final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
|
||||
final Map<String, RowOrder> deletedRowMap = {for (var e in deletedRows) e.rowId: e};
|
||||
|
||||
_rows.asMap().forEach((index, row) {
|
||||
if (deletedRowMap[row.rowId] == null) {
|
||||
@ -192,12 +182,14 @@ class RowsNotifier extends ChangeNotifier {
|
||||
}
|
||||
|
||||
InsertedIndexs insertIndexs = [];
|
||||
final List<GridRow> newRows = _rows;
|
||||
final List<GridRow> newRows = clonedRows;
|
||||
for (final createdRow in createdRows) {
|
||||
final rowOrder = createdRow.rowOrder;
|
||||
final insertIndex = InsertedIndex(index: createdRow.index, rowId: rowOrder.rowId);
|
||||
final insertIndex = InsertedIndex(
|
||||
index: createdRow.index,
|
||||
rowId: createdRow.rowOrder.rowId,
|
||||
);
|
||||
insertIndexs.add(insertIndex);
|
||||
newRows.insert(createdRow.index, (rowBuilder(rowOrder)));
|
||||
newRows.insert(createdRow.index, (rowBuilder(createdRow.rowOrder)));
|
||||
}
|
||||
_update(newRows, GridRowChangeReason.insert(insertIndexs));
|
||||
}
|
||||
@ -208,15 +200,15 @@ class RowsNotifier extends ChangeNotifier {
|
||||
}
|
||||
|
||||
final UpdatedIndexs updatedIndexs = UpdatedIndexs();
|
||||
final List<GridRow> newRows = _rows;
|
||||
final List<GridRow> newRows = clonedRows;
|
||||
for (final rowOrder in updatedRows) {
|
||||
final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId);
|
||||
if (index != -1) {
|
||||
newRows.removeAt(index);
|
||||
// Remove the old row data, the data will be filled if the loadRow method gets called.
|
||||
_rowDataMap.remove(rowOrder.rowId);
|
||||
newRows.insert(index, rowBuilder(rowOrder));
|
||||
|
||||
newRows.removeAt(index);
|
||||
newRows.insert(index, rowBuilder(rowOrder));
|
||||
updatedIndexs[rowOrder.rowId] = UpdatedIndex(index: index, rowId: rowOrder.rowId);
|
||||
}
|
||||
}
|
||||
|
@ -231,10 +231,8 @@ class _GridRowsState extends State<_GridRows> {
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: GridRowWidget(
|
||||
blocBuilder: () => RowBloc(
|
||||
rowData: rowData,
|
||||
rowCache: rowCache,
|
||||
),
|
||||
rowData: rowData,
|
||||
rowCache: rowCache,
|
||||
key: ValueKey(rowData.rowId),
|
||||
),
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d
|
||||
|
||||
class CellStateNotifier extends ChangeNotifier {
|
||||
bool _isFocus = false;
|
||||
bool _onEnter = false;
|
||||
|
||||
set isFocus(bool value) {
|
||||
if (_isFocus != value) {
|
||||
@ -14,38 +15,56 @@ class CellStateNotifier extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
set onEnter(bool value) {
|
||||
if (_onEnter != value) {
|
||||
_onEnter = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
bool get isFocus => _isFocus;
|
||||
|
||||
bool get onEnter => _onEnter;
|
||||
}
|
||||
|
||||
class CellContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
final Widget? expander;
|
||||
final double width;
|
||||
const CellContainer({
|
||||
Key? key,
|
||||
required this.child,
|
||||
required this.width,
|
||||
this.expander,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProvider(
|
||||
create: (_) => CellStateNotifier(),
|
||||
child: Consumer<CellStateNotifier>(
|
||||
builder: (context, state, _) {
|
||||
child: Selector<CellStateNotifier, bool>(
|
||||
selector: (context, notifier) => notifier.isFocus,
|
||||
builder: (context, isFocus, _) {
|
||||
Widget container = Center(child: child);
|
||||
|
||||
if (expander != null) {
|
||||
container = _CellEnterRegion(child: container, expander: expander!);
|
||||
}
|
||||
|
||||
return Container(
|
||||
constraints: BoxConstraints(maxWidth: width),
|
||||
decoration: _makeBoxDecoration(context, state),
|
||||
decoration: _makeBoxDecoration(context, isFocus),
|
||||
padding: GridSize.cellContentInsets,
|
||||
child: Center(child: child),
|
||||
child: container,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
BoxDecoration _makeBoxDecoration(BuildContext context, CellStateNotifier state) {
|
||||
BoxDecoration _makeBoxDecoration(BuildContext context, bool isFocus) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
if (state.isFocus) {
|
||||
if (isFocus) {
|
||||
final borderSide = BorderSide(color: theme.main1, width: 1.0);
|
||||
return BoxDecoration(border: Border.fromBorderSide(borderSide));
|
||||
} else {
|
||||
@ -55,6 +74,35 @@ class CellContainer extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _CellEnterRegion extends StatelessWidget {
|
||||
final Widget expander;
|
||||
final Widget child;
|
||||
const _CellEnterRegion({required this.expander, required this.child, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<CellStateNotifier, bool>(
|
||||
selector: (context, notifier) => notifier.onEnter,
|
||||
builder: (context, onEnter, _) {
|
||||
List<Widget> children = [child];
|
||||
if (onEnter) {
|
||||
children.add(expander);
|
||||
}
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (p) => Provider.of<CellStateNotifier>(context, listen: false).onEnter = true,
|
||||
onExit: (p) => Provider.of<CellStateNotifier>(context, listen: false).onEnter = false,
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class GridCellWidget extends StatefulWidget {
|
||||
const GridCellWidget({Key? key}) : super(key: key);
|
||||
|
||||
|
@ -90,16 +90,6 @@ class _FieldOperationList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final actions = FieldAction.values
|
||||
.map(
|
||||
(action) => FieldActionCell(
|
||||
fieldId: fieldData.field.id,
|
||||
action: action,
|
||||
onTap: onDismissed,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
return GridView(
|
||||
// https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html
|
||||
shrinkWrap: true,
|
||||
@ -108,20 +98,44 @@ class _FieldOperationList extends StatelessWidget {
|
||||
childAspectRatio: 4.0,
|
||||
mainAxisSpacing: 8,
|
||||
),
|
||||
children: actions,
|
||||
children: buildCells(),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> buildCells() {
|
||||
return FieldAction.values.map(
|
||||
(action) {
|
||||
bool enable = true;
|
||||
switch (action) {
|
||||
case FieldAction.delete:
|
||||
enable = !fieldData.field.isPrimary;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FieldActionCell(
|
||||
fieldId: fieldData.field.id,
|
||||
action: action,
|
||||
onTap: onDismissed,
|
||||
enable: enable,
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
}
|
||||
|
||||
class FieldActionCell extends StatelessWidget {
|
||||
final String fieldId;
|
||||
final VoidCallback onTap;
|
||||
final FieldAction action;
|
||||
final bool enable;
|
||||
|
||||
const FieldActionCell({
|
||||
required this.fieldId,
|
||||
required this.action,
|
||||
required this.onTap,
|
||||
required this.enable,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -129,11 +143,13 @@ class FieldActionCell extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return FlowyButton(
|
||||
text: FlowyText.medium(action.title(), fontSize: 12),
|
||||
text: FlowyText.medium(action.title(), fontSize: 12, color: enable ? null : theme.shader4),
|
||||
hoverColor: theme.hover,
|
||||
onTap: () {
|
||||
action.run(context);
|
||||
onTap();
|
||||
if (enable) {
|
||||
action.run(context);
|
||||
onTap();
|
||||
}
|
||||
},
|
||||
leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
|
||||
);
|
||||
|
@ -8,12 +8,17 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'row_action_sheet.dart';
|
||||
import 'package:dartz/dartz.dart' show Option;
|
||||
|
||||
import 'row_detail.dart';
|
||||
|
||||
class GridRowWidget extends StatefulWidget {
|
||||
final RowBloc Function() blocBuilder;
|
||||
final GridRow rowData;
|
||||
final GridRowCache rowCache;
|
||||
|
||||
const GridRowWidget({
|
||||
required this.blocBuilder,
|
||||
required this.rowData,
|
||||
required this.rowCache,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -23,13 +28,14 @@ class GridRowWidget extends StatefulWidget {
|
||||
|
||||
class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
late RowBloc _rowBloc;
|
||||
late _RegionStateNotifier _rowStateNotifier;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_rowBloc = widget.blocBuilder();
|
||||
_rowBloc = RowBloc(
|
||||
rowData: widget.rowData,
|
||||
rowCache: widget.rowCache,
|
||||
);
|
||||
_rowBloc.add(const RowEvent.initial());
|
||||
_rowStateNotifier = _RegionStateNotifier();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@ -37,29 +43,24 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider.value(
|
||||
value: _rowBloc,
|
||||
child: ChangeNotifierProvider.value(
|
||||
value: _rowStateNotifier,
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (p) => _rowStateNotifier.onEnter = true,
|
||||
onExit: (p) => _rowStateNotifier.onEnter = false,
|
||||
child: BlocBuilder<RowBloc, RowState>(
|
||||
buildWhen: (p, c) => p.rowData.height != c.rowData.height,
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
height: 42,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: const [
|
||||
_RowLeading(),
|
||||
_RowCells(),
|
||||
_RowTrailing(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
child: _RowEnterRegion(
|
||||
child: BlocBuilder<RowBloc, RowState>(
|
||||
buildWhen: (p, c) => p.rowData.height != c.rowData.height,
|
||||
builder: (context, state) {
|
||||
final children = [
|
||||
const _RowLeading(),
|
||||
_RowCells(onExpand: () => onExpandCell(context)),
|
||||
const _RowTrailing(),
|
||||
];
|
||||
|
||||
final child = Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: children,
|
||||
);
|
||||
|
||||
return SizedBox(height: 42, child: child);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -68,9 +69,13 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
_rowBloc.close();
|
||||
_rowStateNotifier.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void onExpandCell(BuildContext context) {
|
||||
final page = RowDetailPage(rowData: widget.rowData, rowCache: widget.rowCache);
|
||||
page.show(context);
|
||||
}
|
||||
}
|
||||
|
||||
class _RowLeading extends StatelessWidget {
|
||||
@ -142,32 +147,41 @@ class _DeleteRowButton extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _RowCells extends StatelessWidget {
|
||||
const _RowCells({Key? key}) : super(key: key);
|
||||
final VoidCallback onExpand;
|
||||
const _RowCells({required this.onExpand, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<RowBloc, RowState>(
|
||||
buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap,
|
||||
builder: (context, state) {
|
||||
final List<Widget> children = state.cellDataMap.fold(() => [], _toCells);
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: children,
|
||||
children: _makeCells(state.cellDataMap),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _toCells(CellDataMap dataMap) {
|
||||
return dataMap.values.map(
|
||||
(cellData) {
|
||||
return CellContainer(
|
||||
width: cellData.field.width.toDouble(),
|
||||
child: buildGridCell(cellData),
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
List<Widget> _makeCells(Option<CellDataMap> data) {
|
||||
return data.fold(
|
||||
() => [],
|
||||
(cellDataMap) => cellDataMap.values.map(
|
||||
(cellData) {
|
||||
Widget? expander;
|
||||
if (cellData.field.isPrimary) {
|
||||
expander = _CellExpander(onExpand: onExpand);
|
||||
}
|
||||
|
||||
return CellContainer(
|
||||
width: cellData.field.width.toDouble(),
|
||||
child: buildGridCell(cellData),
|
||||
expander: expander,
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,3 +197,57 @@ class _RegionStateNotifier extends ChangeNotifier {
|
||||
|
||||
bool get onEnter => _onEnter;
|
||||
}
|
||||
|
||||
class _CellExpander extends StatelessWidget {
|
||||
final VoidCallback onExpand;
|
||||
const _CellExpander({required this.onExpand, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return FlowyIconButton(
|
||||
width: 20,
|
||||
onPressed: onExpand,
|
||||
iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
|
||||
icon: svgWidget("grid/expander", color: theme.main1),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RowEnterRegion extends StatefulWidget {
|
||||
final Widget child;
|
||||
const _RowEnterRegion({required this.child, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<_RowEnterRegion> createState() => _RowEnterRegionState();
|
||||
}
|
||||
|
||||
class _RowEnterRegionState extends State<_RowEnterRegion> {
|
||||
late _RegionStateNotifier _rowStateNotifier;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_rowStateNotifier = _RegionStateNotifier();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProvider.value(
|
||||
value: _rowStateNotifier,
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (p) => _rowStateNotifier.onEnter = true,
|
||||
onExit: (p) => _rowStateNotifier.onEnter = false,
|
||||
child: widget.child,
|
||||
),
|
||||
);
|
||||
;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
_rowStateNotifier.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_detail_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
|
||||
class RowDetailPage extends StatelessWidget with FlowyOverlayDelegate {
|
||||
final GridRow rowData;
|
||||
final GridRowCache rowCache;
|
||||
|
||||
const RowDetailPage({
|
||||
required this.rowData,
|
||||
required this.rowCache,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => RowDetailBloc(rowData: rowData, rowCache: rowCache),
|
||||
child: Container(),
|
||||
);
|
||||
}
|
||||
|
||||
void show(BuildContext context) async {
|
||||
FlowyOverlay.of(context).remove(identifier());
|
||||
|
||||
const size = Size(460, 400);
|
||||
final window = await getWindowInfo();
|
||||
FlowyOverlay.of(context).insertWithRect(
|
||||
widget: OverlayContainer(
|
||||
child: this,
|
||||
constraints: BoxConstraints.tight(const Size(460, 400)),
|
||||
),
|
||||
identifier: identifier(),
|
||||
anchorPosition: Offset(-size.width / 2.0, -size.height / 2.0),
|
||||
anchorSize: window.frame.size,
|
||||
anchorDirection: AnchorDirection.center,
|
||||
style: FlowyOverlayStyle(blur: false),
|
||||
delegate: this,
|
||||
);
|
||||
}
|
||||
|
||||
static String identifier() {
|
||||
return (RowDetailPage).toString();
|
||||
}
|
||||
}
|
@ -67,7 +67,7 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate {
|
||||
}
|
||||
|
||||
String identifier() {
|
||||
return toString();
|
||||
return (GridPropertyList).toString();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -85,6 +85,7 @@ class Field extends $pb.GeneratedMessage {
|
||||
..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen')
|
||||
..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility')
|
||||
..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3)
|
||||
..aOB(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isPrimary')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@ -97,6 +98,7 @@ class Field extends $pb.GeneratedMessage {
|
||||
$core.bool? frozen,
|
||||
$core.bool? visibility,
|
||||
$core.int? width,
|
||||
$core.bool? isPrimary,
|
||||
}) {
|
||||
final _result = create();
|
||||
if (id != null) {
|
||||
@ -120,6 +122,9 @@ class Field extends $pb.GeneratedMessage {
|
||||
if (width != null) {
|
||||
_result.width = width;
|
||||
}
|
||||
if (isPrimary != null) {
|
||||
_result.isPrimary = isPrimary;
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
factory Field.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
@ -205,6 +210,15 @@ class Field extends $pb.GeneratedMessage {
|
||||
$core.bool hasWidth() => $_has(6);
|
||||
@$pb.TagNumber(7)
|
||||
void clearWidth() => clearField(7);
|
||||
|
||||
@$pb.TagNumber(8)
|
||||
$core.bool get isPrimary => $_getBF(7);
|
||||
@$pb.TagNumber(8)
|
||||
set isPrimary($core.bool v) { $_setBool(7, v); }
|
||||
@$pb.TagNumber(8)
|
||||
$core.bool hasIsPrimary() => $_has(7);
|
||||
@$pb.TagNumber(8)
|
||||
void clearIsPrimary() => clearField(8);
|
||||
}
|
||||
|
||||
class FieldOrder extends $pb.GeneratedMessage {
|
||||
|
@ -57,11 +57,12 @@ const Field$json = const {
|
||||
const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '10': 'frozen'},
|
||||
const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '10': 'visibility'},
|
||||
const {'1': 'width', '3': 7, '4': 1, '5': 5, '10': 'width'},
|
||||
const {'1': 'is_primary', '3': 8, '4': 1, '5': 8, '10': 'isPrimary'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `Field`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aA==');
|
||||
final $typed_data.Uint8List fieldDescriptor = $convert.base64Decode('CgVGaWVsZBIOCgJpZBgBIAEoCVICaWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEikKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVSCWZpZWxkVHlwZRIWCgZmcm96ZW4YBSABKAhSBmZyb3plbhIeCgp2aXNpYmlsaXR5GAYgASgIUgp2aXNpYmlsaXR5EhQKBXdpZHRoGAcgASgFUgV3aWR0aBIdCgppc19wcmltYXJ5GAggASgIUglpc1ByaW1hcnk=');
|
||||
@$core.Deprecated('Use fieldOrderDescriptor instead')
|
||||
const FieldOrder$json = const {
|
||||
'1': 'FieldOrder',
|
||||
|
@ -13,7 +13,7 @@ pub type BoxTypeOptionBuilder = Box<dyn TypeOptionBuilder + 'static>;
|
||||
impl FieldBuilder {
|
||||
pub fn new<T: Into<BoxTypeOptionBuilder>>(type_option_builder: T) -> Self {
|
||||
let type_option_builder = type_option_builder.into();
|
||||
let field_meta = FieldMeta::new("", "", type_option_builder.field_type());
|
||||
let field_meta = FieldMeta::new("", "", type_option_builder.field_type(), false);
|
||||
Self {
|
||||
field_meta,
|
||||
type_option_builder,
|
||||
@ -35,6 +35,7 @@ impl FieldBuilder {
|
||||
visibility: field.visibility,
|
||||
width: field.width,
|
||||
type_options: IndexMap::default(),
|
||||
is_primary: field.is_primary,
|
||||
};
|
||||
Self {
|
||||
field_meta,
|
||||
@ -52,6 +53,11 @@ impl FieldBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn primary(mut self, is_primary: bool) -> Self {
|
||||
self.field_meta.is_primary = is_primary;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn visibility(mut self, visibility: bool) -> Self {
|
||||
self.field_meta.visibility = visibility;
|
||||
self
|
||||
|
@ -1,10 +1,9 @@
|
||||
use crate::dart_notification::{send_dart_notification, GridNotification};
|
||||
use crate::manager::GridUser;
|
||||
use crate::services::block_meta_manager::GridBlockMetaEditorManager;
|
||||
use crate::services::entities::{CellIdentifier, CreateSelectOptionParams};
|
||||
use crate::services::entities::CellIdentifier;
|
||||
use crate::services::field::{
|
||||
default_type_option_builder_from_type, select_option_operation, type_option_builder_from_bytes, FieldBuilder,
|
||||
SelectOption,
|
||||
default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder, SelectOption,
|
||||
};
|
||||
use crate::services::persistence::block_index::BlockIndexPersistence;
|
||||
use crate::services::row::*;
|
||||
|
@ -7,6 +7,7 @@ pub fn make_default_grid() -> BuildGridContext {
|
||||
let text_field = FieldBuilder::new(RichTextTypeOptionBuilder::default())
|
||||
.name("Name")
|
||||
.visibility(true)
|
||||
.primary(true)
|
||||
.build();
|
||||
|
||||
// single select
|
||||
|
@ -271,6 +271,7 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldMeta) {
|
||||
frozen: field_meta.frozen,
|
||||
visibility: field_meta.visibility,
|
||||
width: field_meta.width,
|
||||
is_primary: false,
|
||||
};
|
||||
|
||||
let params = InsertFieldParams {
|
||||
@ -303,6 +304,7 @@ pub fn create_single_select_field(grid_id: &str) -> (InsertFieldParams, FieldMet
|
||||
frozen: field_meta.frozen,
|
||||
visibility: field_meta.visibility,
|
||||
width: field_meta.width,
|
||||
is_primary: false,
|
||||
};
|
||||
|
||||
let params = InsertFieldParams {
|
||||
|
@ -42,6 +42,9 @@ pub struct Field {
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub width: i32,
|
||||
|
||||
#[pb(index = 8)]
|
||||
pub is_primary: bool,
|
||||
}
|
||||
|
||||
impl std::convert::From<FieldMeta> for Field {
|
||||
@ -54,6 +57,7 @@ impl std::convert::From<FieldMeta> for Field {
|
||||
frozen: field_meta.frozen,
|
||||
visibility: field_meta.visibility,
|
||||
width: field_meta.width,
|
||||
is_primary: field_meta.is_primary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,13 +98,21 @@ pub struct FieldMeta {
|
||||
// #[pb(index = 8)]
|
||||
/// type_options contains key/value pairs
|
||||
/// key: id of the FieldType
|
||||
/// value: type option data string
|
||||
/// value: type option data that can be parsed into specified TypeOptionStruct.
|
||||
/// For example, CheckboxTypeOption, MultiSelectTypeOption etc.
|
||||
#[serde(with = "indexmap::serde_seq")]
|
||||
pub type_options: IndexMap<String, String>,
|
||||
|
||||
#[serde(default = "default_is_primary")]
|
||||
pub is_primary: bool,
|
||||
}
|
||||
|
||||
fn default_is_primary() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
impl FieldMeta {
|
||||
pub fn new(name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||
pub fn new(name: &str, desc: &str, field_type: FieldType, is_primary: bool) -> Self {
|
||||
let width = field_type.default_cell_width();
|
||||
Self {
|
||||
id: gen_field_id(),
|
||||
@ -115,6 +123,7 @@ impl FieldMeta {
|
||||
visibility: true,
|
||||
width,
|
||||
type_options: Default::default(),
|
||||
is_primary,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,6 +290,7 @@ pub struct Field {
|
||||
pub frozen: bool,
|
||||
pub visibility: bool,
|
||||
pub width: i32,
|
||||
pub is_primary: bool,
|
||||
// special fields
|
||||
pub unknown_fields: ::protobuf::UnknownFields,
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
@ -443,6 +444,21 @@ impl Field {
|
||||
pub fn set_width(&mut self, v: i32) {
|
||||
self.width = v;
|
||||
}
|
||||
|
||||
// bool is_primary = 8;
|
||||
|
||||
|
||||
pub fn get_is_primary(&self) -> bool {
|
||||
self.is_primary
|
||||
}
|
||||
pub fn clear_is_primary(&mut self) {
|
||||
self.is_primary = false;
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_is_primary(&mut self, v: bool) {
|
||||
self.is_primary = v;
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for Field {
|
||||
@ -487,6 +503,13 @@ impl ::protobuf::Message for Field {
|
||||
let tmp = is.read_int32()?;
|
||||
self.width = tmp;
|
||||
},
|
||||
8 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
let tmp = is.read_bool()?;
|
||||
self.is_primary = tmp;
|
||||
},
|
||||
_ => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||
},
|
||||
@ -520,6 +543,9 @@ impl ::protobuf::Message for Field {
|
||||
if self.width != 0 {
|
||||
my_size += ::protobuf::rt::value_size(7, self.width, ::protobuf::wire_format::WireTypeVarint);
|
||||
}
|
||||
if self.is_primary != false {
|
||||
my_size += 2;
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||
self.cached_size.set(my_size);
|
||||
my_size
|
||||
@ -547,6 +573,9 @@ impl ::protobuf::Message for Field {
|
||||
if self.width != 0 {
|
||||
os.write_int32(7, self.width)?;
|
||||
}
|
||||
if self.is_primary != false {
|
||||
os.write_bool(8, self.is_primary)?;
|
||||
}
|
||||
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
@ -620,6 +649,11 @@ impl ::protobuf::Message for Field {
|
||||
|m: &Field| { &m.width },
|
||||
|m: &mut Field| { &mut m.width },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>(
|
||||
"is_primary",
|
||||
|m: &Field| { &m.is_primary },
|
||||
|m: &mut Field| { &mut m.is_primary },
|
||||
));
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<Field>(
|
||||
"Field",
|
||||
fields,
|
||||
@ -643,6 +677,7 @@ impl ::protobuf::Clear for Field {
|
||||
self.frozen = false;
|
||||
self.visibility = false;
|
||||
self.width = 0;
|
||||
self.is_primary = false;
|
||||
self.unknown_fields.clear();
|
||||
}
|
||||
}
|
||||
@ -7770,93 +7805,94 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\ngrid.proto\"z\n\x04Grid\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\
|
||||
\x12.\n\x0cfield_orders\x18\x02\x20\x03(\x0b2\x0b.FieldOrderR\x0bfieldOr\
|
||||
ders\x122\n\x0cblock_orders\x18\x03\x20\x03(\x0b2\x0f.GridBlockOrderR\
|
||||
\x0bblockOrders\"\xb8\x01\n\x05Field\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\
|
||||
\x0bblockOrders\"\xd7\x01\n\x05Field\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\
|
||||
\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\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\x06froze\
|
||||
n\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\x12\x14\n\x05w\
|
||||
idth\x18\x07\x20\x01(\x05R\x05width\"'\n\nFieldOrder\x12\x19\n\x08field_\
|
||||
id\x18\x01\x20\x01(\tR\x07fieldId\"\xc6\x01\n\x12GridFieldChangeset\x12\
|
||||
\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x124\n\x0finserted_field\
|
||||
s\x18\x02\x20\x03(\x0b2\x0b.IndexFieldR\x0einsertedFields\x122\n\x0edele\
|
||||
ted_fields\x18\x03\x20\x03(\x0b2\x0b.FieldOrderR\rdeletedFields\x12-\n\
|
||||
\x0eupdated_fields\x18\x04\x20\x03(\x0b2\x06.FieldR\rupdatedFields\"@\n\
|
||||
\nIndexField\x12\x1c\n\x05field\x18\x01\x20\x01(\x0b2\x06.FieldR\x05fiel\
|
||||
d\x12\x14\n\x05index\x18\x02\x20\x01(\x05R\x05index\"\x90\x01\n\x1aGetEd\
|
||||
itFieldContextPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\
|
||||
\x12\x1b\n\x08field_id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_t\
|
||||
ype\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field\
|
||||
_id\"q\n\x10EditFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||
\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\n\
|
||||
field_type\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFie\
|
||||
ldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngri\
|
||||
d_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_optio\
|
||||
n_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\"U\n\x0eGridBlockOrder\
|
||||
\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\
|
||||
\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"_\n\rIndexRowOrder\x12&\n\
|
||||
\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\n\x05i\
|
||||
ndex\x18\x02\x20\x01(\x05H\0R\x05indexB\x0e\n\x0cone_of_index\"\xbf\x01\
|
||||
\n\x11GridRowsChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blo\
|
||||
ckId\x123\n\rinserted_rows\x18\x02\x20\x03(\x0b2\x0e.IndexRowOrderR\x0ci\
|
||||
nsertedRows\x12,\n\x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOrderR\x0b\
|
||||
deletedRows\x12,\n\x0cupdated_rows\x18\x04\x20\x03(\x0b2\t.RowOrderR\x0b\
|
||||
updatedRows\"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\"\x8f\x01\n\x14CellNotificati\
|
||||
onData\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08f\
|
||||
ield_id\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06row_id\x18\x03\x20\
|
||||
\x01(\tR\x05rowId\x12\x1a\n\x07content\x18\x04\x20\x01(\tH\0R\x07content\
|
||||
B\x10\n\x0eone_of_content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\
|
||||
\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\x11CreateGridPayload\x12\x12\
|
||||
\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\x05va\
|
||||
lue\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\nstartRowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12Ins\
|
||||
ertFieldPayload\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_fie\
|
||||
ld_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_fiel\
|
||||
d_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.RepeatedFiel\
|
||||
dOrderR\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\"\xa8\x03\n\x15FieldChangesetPa\
|
||||
yload\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07\
|
||||
grid_id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\x04name\x18\x03\x20\x01(\
|
||||
\tH\0R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\
|
||||
\nfield_type\x18\x05\x20\x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\
|
||||
\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06frozen\x12\x20\n\nvisibility\
|
||||
\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\x16\n\x05width\x18\x08\x20\
|
||||
\x01(\x05H\x05R\x05width\x12*\n\x10type_option_data\x18\t\x20\x01(\x0cH\
|
||||
\x06R\x0etypeOptionDataB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\
|
||||
\x11one_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one_of_visibilityB\
|
||||
\x0e\n\x0cone_of_widthB\x19\n\x17one_of_type_option_data\"\x9c\x01\n\x0f\
|
||||
MoveItemPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\
|
||||
\x17\n\x07item_id\x18\x02\x20\x01(\tR\x06itemId\x12\x1d\n\nfrom_index\
|
||||
\x18\x03\x20\x01(\x05R\tfromIndex\x12\x19\n\x08to_index\x18\x04\x20\x01(\
|
||||
\x05R\x07toIndex\x12\x1d\n\x02ty\x18\x05\x20\x01(\x0e2\r.MoveItemTypeR\
|
||||
\x02ty\"\x7f\n\rCellChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||
\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\
|
||||
\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\
|
||||
\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data**\n\x0cMoveItemType\x12\r\n\
|
||||
\tMoveField\x10\0\x12\x0b\n\x07MoveRow\x10\x01*d\n\tFieldType\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\x0bMultiSelect\x10\x04\
|
||||
\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\
|
||||
idth\x18\x07\x20\x01(\x05R\x05width\x12\x1d\n\nis_primary\x18\x08\x20\
|
||||
\x01(\x08R\tisPrimary\"'\n\nFieldOrder\x12\x19\n\x08field_id\x18\x01\x20\
|
||||
\x01(\tR\x07fieldId\"\xc6\x01\n\x12GridFieldChangeset\x12\x17\n\x07grid_\
|
||||
id\x18\x01\x20\x01(\tR\x06gridId\x124\n\x0finserted_fields\x18\x02\x20\
|
||||
\x03(\x0b2\x0b.IndexFieldR\x0einsertedFields\x122\n\x0edeleted_fields\
|
||||
\x18\x03\x20\x03(\x0b2\x0b.FieldOrderR\rdeletedFields\x12-\n\x0eupdated_\
|
||||
fields\x18\x04\x20\x03(\x0b2\x06.FieldR\rupdatedFields\"@\n\nIndexField\
|
||||
\x12\x1c\n\x05field\x18\x01\x20\x01(\x0b2\x06.FieldR\x05field\x12\x14\n\
|
||||
\x05index\x18\x02\x20\x01(\x05R\x05index\"\x90\x01\n\x1aGetEditFieldCont\
|
||||
extPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1b\n\
|
||||
\x08field_id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_type\x18\
|
||||
\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field_id\"q\
|
||||
\n\x10EditFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridI\
|
||||
d\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\nfield_typ\
|
||||
e\x18\x03\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\
|
||||
\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12RepeatedFiel\
|
||||
dOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05items\"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\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.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.Cel\
|
||||
lR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\x20\
|
||||
\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05item\
|
||||
s\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"U\n\x0eGridBlockOrder\x12\
|
||||
\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\x18\
|
||||
\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"_\n\rIndexRowOrder\x12&\n\tro\
|
||||
w_order\x18\x01\x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\n\x05index\
|
||||
\x18\x02\x20\x01(\x05H\0R\x05indexB\x0e\n\x0cone_of_index\"\xbf\x01\n\
|
||||
\x11GridRowsChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07block\
|
||||
Id\x123\n\rinserted_rows\x18\x02\x20\x03(\x0b2\x0e.IndexRowOrderR\x0cins\
|
||||
ertedRows\x12,\n\x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOrderR\x0bde\
|
||||
letedRows\x12,\n\x0cupdated_rows\x18\x04\x20\x03(\x0b2\t.RowOrderR\x0bup\
|
||||
datedRows\"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\x07conte\
|
||||
nt\x18\x02\x20\x01(\tR\x07content\"\x8f\x01\n\x14CellNotificationData\
|
||||
\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_i\
|
||||
d\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\
|
||||
\x05rowId\x12\x1a\n\x07content\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\
|
||||
\x0eone_of_content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\
|
||||
\x03(\x0b2\x05.CellR\x05items\"'\n\x11CreateGridPayload\x12\x12\n\x04nam\
|
||||
e\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\0\
|
||||
R\nstartRowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12InsertFieldPa\
|
||||
yload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05fi\
|
||||
eld\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\"\xa8\x03\n\x15FieldChangesetPayload\
|
||||
\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_\
|
||||
id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0\
|
||||
R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfie\
|
||||
ld_type\x18\x05\x20\x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06\
|
||||
frozen\x18\x06\x20\x01(\x08H\x03R\x06frozen\x12\x20\n\nvisibility\x18\
|
||||
\x07\x20\x01(\x08H\x04R\nvisibility\x12\x16\n\x05width\x18\x08\x20\x01(\
|
||||
\x05H\x05R\x05width\x12*\n\x10type_option_data\x18\t\x20\x01(\x0cH\x06R\
|
||||
\x0etypeOptionDataB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\x11one\
|
||||
_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one_of_visibilityB\x0e\n\
|
||||
\x0cone_of_widthB\x19\n\x17one_of_type_option_data\"\x9c\x01\n\x0fMoveIt\
|
||||
emPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x17\n\
|
||||
\x07item_id\x18\x02\x20\x01(\tR\x06itemId\x12\x1d\n\nfrom_index\x18\x03\
|
||||
\x20\x01(\x05R\tfromIndex\x12\x19\n\x08to_index\x18\x04\x20\x01(\x05R\
|
||||
\x07toIndex\x12\x1d\n\x02ty\x18\x05\x20\x01(\x0e2\r.MoveItemTypeR\x02ty\
|
||||
\"\x7f\n\rCellChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06grid\
|
||||
Id\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_i\
|
||||
d\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0\
|
||||
R\x04dataB\r\n\x0bone_of_data**\n\x0cMoveItemType\x12\r\n\tMoveField\x10\
|
||||
\0\x12\x0b\n\x07MoveRow\x10\x01*d\n\tFieldType\x12\x0c\n\x08RichText\x10\
|
||||
\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0c\
|
||||
SingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Check\
|
||||
box\x10\x05b\x06proto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
@ -13,6 +13,7 @@ message Field {
|
||||
bool frozen = 5;
|
||||
bool visibility = 6;
|
||||
int32 width = 7;
|
||||
bool is_primary = 8;
|
||||
}
|
||||
message FieldOrder {
|
||||
string field_id = 1;
|
||||
|
@ -47,8 +47,8 @@ mod tests {
|
||||
fn create_default_grid_test() {
|
||||
let grid_id = "1".to_owned();
|
||||
let build_context = GridBuilder::default()
|
||||
.add_field(FieldMeta::new("Name", "", FieldType::RichText))
|
||||
.add_field(FieldMeta::new("Tags", "", FieldType::SingleSelect))
|
||||
.add_field(FieldMeta::new("Name", "", FieldType::RichText, true))
|
||||
.add_field(FieldMeta::new("Tags", "", FieldType::SingleSelect, false))
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
.add_empty_row()
|
||||
|
Loading…
Reference in New Issue
Block a user