mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: disable edit primary field (#2695)
* refactor: field editor * chore: disable edit type option of primary field
This commit is contained in:
parent
edd58ede45
commit
bec8122178
@ -1,6 +1,6 @@
|
||||
part of 'cell_service.dart';
|
||||
|
||||
typedef CellByFieldId = LinkedHashMap<String, CellIdentifier>;
|
||||
typedef CellContextByFieldId = LinkedHashMap<String, DatabaseCellContext>;
|
||||
|
||||
class DatabaseCell {
|
||||
dynamic object;
|
||||
|
@ -22,7 +22,7 @@ import 'cell_service.dart';
|
||||
///
|
||||
// ignore: must_be_immutable
|
||||
class CellController<T, D> extends Equatable {
|
||||
final CellIdentifier cellId;
|
||||
final DatabaseCellContext cellContext;
|
||||
final CellCache _cellCache;
|
||||
final CellCacheKey _cacheKey;
|
||||
final FieldBackendService _fieldBackendSvc;
|
||||
@ -37,37 +37,37 @@ class CellController<T, D> extends Equatable {
|
||||
Timer? _loadDataOperation;
|
||||
Timer? _saveDataOperation;
|
||||
|
||||
String get viewId => cellId.viewId;
|
||||
String get viewId => cellContext.viewId;
|
||||
|
||||
RowId get rowId => cellId.rowId;
|
||||
RowId get rowId => cellContext.rowId;
|
||||
|
||||
String get fieldId => cellId.fieldInfo.id;
|
||||
String get fieldId => cellContext.fieldInfo.id;
|
||||
|
||||
FieldInfo get fieldInfo => cellId.fieldInfo;
|
||||
FieldInfo get fieldInfo => cellContext.fieldInfo;
|
||||
|
||||
FieldType get fieldType => cellId.fieldInfo.fieldType;
|
||||
FieldType get fieldType => cellContext.fieldInfo.fieldType;
|
||||
|
||||
CellController({
|
||||
required this.cellId,
|
||||
required this.cellContext,
|
||||
required CellCache cellCache,
|
||||
required CellDataLoader<T> cellDataLoader,
|
||||
required CellDataPersistence<D> cellDataPersistence,
|
||||
}) : _cellCache = cellCache,
|
||||
_cellDataLoader = cellDataLoader,
|
||||
_cellDataPersistence = cellDataPersistence,
|
||||
_fieldListener = SingleFieldListener(fieldId: cellId.fieldId),
|
||||
_fieldListener = SingleFieldListener(fieldId: cellContext.fieldId),
|
||||
_fieldBackendSvc = FieldBackendService(
|
||||
viewId: cellId.viewId,
|
||||
fieldId: cellId.fieldInfo.id,
|
||||
viewId: cellContext.viewId,
|
||||
fieldId: cellContext.fieldInfo.id,
|
||||
),
|
||||
_cacheKey = CellCacheKey(
|
||||
rowId: cellId.rowId,
|
||||
fieldId: cellId.fieldInfo.id,
|
||||
rowId: cellContext.rowId,
|
||||
fieldId: cellContext.fieldInfo.id,
|
||||
) {
|
||||
_cellDataNotifier = CellDataNotifier(value: _cellCache.get(_cacheKey));
|
||||
_cellListener = CellListener(
|
||||
rowId: cellId.rowId,
|
||||
fieldId: cellId.fieldInfo.id,
|
||||
rowId: cellContext.rowId,
|
||||
fieldId: cellContext.fieldInfo.id,
|
||||
);
|
||||
|
||||
/// 1.Listen on user edit event and load the new cell data if needed.
|
||||
@ -195,8 +195,10 @@ class CellController<T, D> extends Equatable {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props =>
|
||||
[_cellCache.get(_cacheKey) ?? "", cellId.rowId + cellId.fieldInfo.id];
|
||||
List<Object> get props => [
|
||||
_cellCache.get(_cacheKey) ?? "",
|
||||
cellContext.rowId + cellContext.fieldInfo.id
|
||||
];
|
||||
}
|
||||
|
||||
class CellDataNotifier<T> extends ChangeNotifier {
|
||||
|
@ -17,104 +17,111 @@ typedef DateCellController = CellController<DateCellDataPB, DateCellData>;
|
||||
typedef URLCellController = CellController<URLCellDataPB, String>;
|
||||
|
||||
class CellControllerBuilder {
|
||||
final CellIdentifier _cellId;
|
||||
final DatabaseCellContext _cellContext;
|
||||
final CellCache _cellCache;
|
||||
|
||||
CellControllerBuilder({
|
||||
required CellIdentifier cellId,
|
||||
required DatabaseCellContext cellContext,
|
||||
required CellCache cellCache,
|
||||
}) : _cellCache = cellCache,
|
||||
_cellId = cellId;
|
||||
_cellContext = cellContext;
|
||||
|
||||
CellController build() {
|
||||
switch (_cellId.fieldType) {
|
||||
switch (_cellContext.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: StringCellDataParser(),
|
||||
);
|
||||
return TextCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
TextCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
case FieldType.DateTime:
|
||||
case FieldType.LastEditedTime:
|
||||
case FieldType.CreatedTime:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: DateCellDataParser(),
|
||||
reloadOnFieldChanged: true,
|
||||
);
|
||||
|
||||
return DateCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: DateCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
DateCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
case FieldType.Number:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: NumberCellDataParser(),
|
||||
reloadOnFieldChanged: true,
|
||||
);
|
||||
return NumberCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
TextCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
case FieldType.RichText:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: StringCellDataParser(),
|
||||
);
|
||||
return TextCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
TextCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
case FieldType.MultiSelect:
|
||||
case FieldType.SingleSelect:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: SelectOptionCellDataParser(),
|
||||
reloadOnFieldChanged: true,
|
||||
);
|
||||
|
||||
return SelectOptionCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
TextCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
|
||||
case FieldType.Checklist:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: ChecklistCellDataParser(),
|
||||
reloadOnFieldChanged: true,
|
||||
);
|
||||
|
||||
return ChecklistCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
TextCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
case FieldType.URL:
|
||||
final cellDataLoader = CellDataLoader(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
parser: URLCellDataParser(),
|
||||
);
|
||||
return URLCellController(
|
||||
cellId: _cellId,
|
||||
cellContext: _cellContext,
|
||||
cellCache: _cellCache,
|
||||
cellDataLoader: cellDataLoader,
|
||||
cellDataPersistence: TextCellDataPersistence(cellId: _cellId),
|
||||
cellDataPersistence:
|
||||
TextCellDataPersistence(cellContext: _cellContext),
|
||||
);
|
||||
}
|
||||
throw UnimplementedError;
|
||||
|
@ -11,18 +11,18 @@ abstract class CellDataParser<T> {
|
||||
|
||||
class CellDataLoader<T> {
|
||||
final CellBackendService service = CellBackendService();
|
||||
final CellIdentifier cellId;
|
||||
final DatabaseCellContext cellContext;
|
||||
final CellDataParser<T> parser;
|
||||
final bool reloadOnFieldChanged;
|
||||
|
||||
CellDataLoader({
|
||||
required this.cellId,
|
||||
required this.cellContext,
|
||||
required this.parser,
|
||||
this.reloadOnFieldChanged = false,
|
||||
});
|
||||
|
||||
Future<T?> loadData() {
|
||||
final fut = service.getCell(cellId: cellId);
|
||||
final fut = service.getCell(cellContext: cellContext);
|
||||
return fut.then(
|
||||
(result) => result.fold(
|
||||
(CellPB cell) {
|
||||
|
@ -7,16 +7,17 @@ abstract class CellDataPersistence<D> {
|
||||
}
|
||||
|
||||
class TextCellDataPersistence implements CellDataPersistence<String> {
|
||||
final CellIdentifier cellId;
|
||||
final DatabaseCellContext cellContext;
|
||||
final _cellBackendSvc = CellBackendService();
|
||||
|
||||
TextCellDataPersistence({
|
||||
required this.cellId,
|
||||
required this.cellContext,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Option<FlowyError>> save(String data) async {
|
||||
final fut = _cellBackendSvc.updateCell(cellId: cellId, data: data);
|
||||
final fut =
|
||||
_cellBackendSvc.updateCell(cellContext: cellContext, data: data);
|
||||
return fut.then((result) {
|
||||
return result.fold(
|
||||
(l) => none(),
|
||||
@ -36,14 +37,15 @@ class DateCellData with _$DateCellData {
|
||||
}
|
||||
|
||||
class DateCellDataPersistence implements CellDataPersistence<DateCellData> {
|
||||
final CellIdentifier cellId;
|
||||
final DatabaseCellContext cellContext;
|
||||
DateCellDataPersistence({
|
||||
required this.cellId,
|
||||
required this.cellContext,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Option<FlowyError>> save(DateCellData data) {
|
||||
var payload = DateChangesetPB.create()..cellPath = _makeCellPath(cellId);
|
||||
var payload = DateChangesetPB.create()
|
||||
..cellPath = _makeCellPath(cellContext);
|
||||
if (data.dateTime != null) {
|
||||
final date = (data.dateTime!.millisecondsSinceEpoch ~/ 1000).toString();
|
||||
payload.date = date;
|
||||
@ -62,7 +64,7 @@ class DateCellDataPersistence implements CellDataPersistence<DateCellData> {
|
||||
}
|
||||
}
|
||||
|
||||
CellIdPB _makeCellPath(CellIdentifier cellId) {
|
||||
CellIdPB _makeCellPath(DatabaseCellContext cellId) {
|
||||
return CellIdPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldId
|
||||
|
@ -25,40 +25,39 @@ class CellBackendService {
|
||||
CellBackendService();
|
||||
|
||||
Future<Either<void, FlowyError>> updateCell({
|
||||
required CellIdentifier cellId,
|
||||
required DatabaseCellContext cellContext,
|
||||
required String data,
|
||||
}) {
|
||||
final payload = CellChangesetPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldId
|
||||
..rowId = cellId.rowId
|
||||
..viewId = cellContext.viewId
|
||||
..fieldId = cellContext.fieldId
|
||||
..rowId = cellContext.rowId
|
||||
..cellChangeset = data;
|
||||
return DatabaseEventUpdateCell(payload).send();
|
||||
}
|
||||
|
||||
Future<Either<CellPB, FlowyError>> getCell({
|
||||
required CellIdentifier cellId,
|
||||
required DatabaseCellContext cellContext,
|
||||
}) {
|
||||
final payload = CellIdPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldId
|
||||
..rowId = cellId.rowId;
|
||||
..viewId = cellContext.viewId
|
||||
..fieldId = cellContext.fieldId
|
||||
..rowId = cellContext.rowId;
|
||||
return DatabaseEventGetCell(payload).send();
|
||||
}
|
||||
}
|
||||
|
||||
/// Id of the cell
|
||||
/// We can locate the cell by using database + rowId + field.id.
|
||||
@freezed
|
||||
class CellIdentifier with _$CellIdentifier {
|
||||
const factory CellIdentifier({
|
||||
class DatabaseCellContext with _$DatabaseCellContext {
|
||||
const factory DatabaseCellContext({
|
||||
required String viewId,
|
||||
required RowId rowId,
|
||||
required FieldInfo fieldInfo,
|
||||
}) = _CellIdentifier;
|
||||
}) = _DatabaseCellContext;
|
||||
|
||||
// ignore: unused_element
|
||||
const CellIdentifier._();
|
||||
const DatabaseCellContext._();
|
||||
|
||||
String get fieldId => fieldInfo.id;
|
||||
|
||||
|
@ -7,17 +7,17 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
class ChecklistCellBackendService {
|
||||
final CellIdentifier cellId;
|
||||
final DatabaseCellContext cellContext;
|
||||
|
||||
ChecklistCellBackendService({required this.cellId});
|
||||
ChecklistCellBackendService({required this.cellContext});
|
||||
|
||||
Future<Either<Unit, FlowyError>> create({
|
||||
required String name,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldInfo.id
|
||||
..rowId = cellId.rowId
|
||||
..viewId = cellContext.viewId
|
||||
..fieldId = cellContext.fieldInfo.id
|
||||
..rowId = cellContext.rowId
|
||||
..insertOptions.add(name);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
@ -27,9 +27,9 @@ class ChecklistCellBackendService {
|
||||
required List<String> optionIds,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldInfo.id
|
||||
..rowId = cellId.rowId
|
||||
..viewId = cellContext.viewId
|
||||
..fieldId = cellContext.fieldInfo.id
|
||||
..rowId = cellContext.rowId
|
||||
..deleteOptionIds.addAll(optionIds);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
@ -39,9 +39,9 @@ class ChecklistCellBackendService {
|
||||
required String optionId,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldInfo.id
|
||||
..rowId = cellId.rowId
|
||||
..viewId = cellContext.viewId
|
||||
..fieldId = cellContext.fieldInfo.id
|
||||
..rowId = cellContext.rowId
|
||||
..selectedOptionIds.add(optionId);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
@ -51,9 +51,9 @@ class ChecklistCellBackendService {
|
||||
required SelectOptionPB option,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = cellId.viewId
|
||||
..fieldId = cellId.fieldInfo.id
|
||||
..rowId = cellId.rowId
|
||||
..viewId = cellContext.viewId
|
||||
..fieldId = cellContext.fieldInfo.id
|
||||
..rowId = cellContext.rowId
|
||||
..updateOptions.add(option);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
@ -61,10 +61,10 @@ class ChecklistCellBackendService {
|
||||
|
||||
Future<Either<ChecklistCellDataPB, FlowyError>> getCellData() {
|
||||
final payload = CellIdPB.create()
|
||||
..fieldId = cellId.fieldInfo.id
|
||||
..viewId = cellId.viewId
|
||||
..rowId = cellId.rowId
|
||||
..rowId = cellId.rowId;
|
||||
..fieldId = cellContext.fieldInfo.id
|
||||
..viewId = cellContext.viewId
|
||||
..rowId = cellContext.rowId
|
||||
..rowId = cellContext.rowId;
|
||||
|
||||
return DatabaseEventGetChecklistCellData(payload).send();
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/cell_entities.pb.dart';
|
||||
|
||||
class SelectOptionCellBackendService {
|
||||
final CellIdentifier cellId;
|
||||
SelectOptionCellBackendService({required this.cellId});
|
||||
final DatabaseCellContext cellContext;
|
||||
SelectOptionCellBackendService({required this.cellContext});
|
||||
|
||||
String get viewId => cellId.viewId;
|
||||
String get fieldId => cellId.fieldInfo.id;
|
||||
RowId get rowId => cellId.rowId;
|
||||
String get viewId => cellContext.viewId;
|
||||
String get fieldId => cellContext.fieldInfo.id;
|
||||
RowId get rowId => cellContext.rowId;
|
||||
|
||||
Future<Either<Unit, FlowyError>> create({
|
||||
required String name,
|
||||
|
@ -10,7 +10,7 @@ class FieldActionSheetBloc
|
||||
extends Bloc<FieldActionSheetEvent, FieldActionSheetState> {
|
||||
final FieldBackendService fieldService;
|
||||
|
||||
FieldActionSheetBloc({required FieldCellContext fieldCellContext})
|
||||
FieldActionSheetBloc({required FieldContext fieldCellContext})
|
||||
: fieldService = FieldBackendService(
|
||||
viewId: fieldCellContext.viewId,
|
||||
fieldId: fieldCellContext.field.id,
|
||||
|
@ -14,7 +14,7 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
||||
final FieldBackendService _fieldBackendSvc;
|
||||
|
||||
FieldCellBloc({
|
||||
required FieldCellContext cellContext,
|
||||
required FieldContext cellContext,
|
||||
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.field.id),
|
||||
_fieldBackendSvc = FieldBackendService(
|
||||
viewId: cellContext.viewId,
|
||||
@ -83,8 +83,7 @@ class FieldCellState with _$FieldCellState {
|
||||
required double width,
|
||||
}) = _FieldCellState;
|
||||
|
||||
factory FieldCellState.initial(FieldCellContext cellContext) =>
|
||||
FieldCellState(
|
||||
factory FieldCellState.initial(FieldContext cellContext) => FieldCellState(
|
||||
viewId: cellContext.viewId,
|
||||
field: cellContext.field,
|
||||
width: cellContext.field.width.toDouble(),
|
||||
|
@ -12,12 +12,20 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
||||
final TypeOptionController dataController;
|
||||
|
||||
FieldEditorBloc({
|
||||
required String viewId,
|
||||
required String fieldName,
|
||||
required bool isGroupField,
|
||||
required ITypeOptionLoader loader,
|
||||
}) : dataController = TypeOptionController(viewId: viewId, loader: loader),
|
||||
super(FieldEditorState.initial(viewId, fieldName, isGroupField)) {
|
||||
required FieldPB field,
|
||||
required FieldTypeOptionLoader loader,
|
||||
}) : dataController = TypeOptionController(
|
||||
field: field,
|
||||
loader: loader,
|
||||
),
|
||||
super(
|
||||
FieldEditorState.initial(
|
||||
loader.viewId,
|
||||
loader.field.name,
|
||||
isGroupField,
|
||||
),
|
||||
) {
|
||||
on<FieldEditorEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
@ -27,7 +35,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
||||
add(FieldEditorEvent.didReceiveFieldChanged(field));
|
||||
}
|
||||
});
|
||||
await dataController.loadTypeOptionData();
|
||||
await dataController.reloadTypeOption();
|
||||
add(FieldEditorEvent.didReceiveFieldChanged(dataController.field));
|
||||
},
|
||||
updateName: (name) {
|
||||
@ -50,7 +58,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
||||
() => null,
|
||||
(field) {
|
||||
final fieldService = FieldBackendService(
|
||||
viewId: viewId,
|
||||
viewId: loader.viewId,
|
||||
fieldId: field.id,
|
||||
);
|
||||
fieldService.deleteField();
|
||||
|
@ -107,8 +107,8 @@ class FieldBackendService {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class FieldCellContext with _$FieldCellContext {
|
||||
const factory FieldCellContext({
|
||||
class FieldContext with _$FieldContext {
|
||||
const factory FieldContext({
|
||||
required String viewId,
|
||||
required FieldPB field,
|
||||
}) = _FieldCellContext;
|
||||
|
@ -113,7 +113,7 @@ class TypeOptionContext<T extends GeneratedMessage> {
|
||||
required TypeOptionController dataController,
|
||||
}) : _dataController = dataController;
|
||||
|
||||
String get viewId => _dataController.viewId;
|
||||
String get viewId => _dataController.loader.viewId;
|
||||
|
||||
String get fieldId => _dataController.field.id;
|
||||
|
||||
@ -121,7 +121,7 @@ class TypeOptionContext<T extends GeneratedMessage> {
|
||||
void Function(T)? onCompleted,
|
||||
required void Function(FlowyError) onError,
|
||||
}) async {
|
||||
await _dataController.loadTypeOptionData().then((result) {
|
||||
await _dataController.reloadTypeOption().then((result) {
|
||||
result.fold((l) => null, (err) => onError(err));
|
||||
});
|
||||
|
||||
@ -153,54 +153,12 @@ abstract class TypeOptionFieldDelegate {
|
||||
abstract class ITypeOptionLoader {
|
||||
String get viewId;
|
||||
String get fieldName;
|
||||
|
||||
Future<Either<TypeOptionPB, FlowyError>> initialize();
|
||||
}
|
||||
|
||||
/// Uses when creating a new field
|
||||
class NewFieldTypeOptionLoader extends ITypeOptionLoader {
|
||||
TypeOptionPB? fieldTypeOption;
|
||||
|
||||
@override
|
||||
final String viewId;
|
||||
NewFieldTypeOptionLoader({
|
||||
required this.viewId,
|
||||
});
|
||||
|
||||
/// Creates the field type option if the fieldTypeOption is null.
|
||||
/// Otherwise, it loads the type option data from the backend.
|
||||
@override
|
||||
Future<Either<TypeOptionPB, FlowyError>> initialize() {
|
||||
if (fieldTypeOption != null) {
|
||||
final payload = TypeOptionPathPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldTypeOption!.field_2.id
|
||||
..fieldType = fieldTypeOption!.field_2.fieldType;
|
||||
|
||||
return DatabaseEventGetTypeOption(payload).send();
|
||||
} else {
|
||||
final payload = CreateFieldPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..fieldType = FieldType.RichText;
|
||||
|
||||
return DatabaseEventCreateTypeOption(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(newFieldTypeOption) {
|
||||
fieldTypeOption = newFieldTypeOption;
|
||||
return left(newFieldTypeOption);
|
||||
},
|
||||
(err) => right(err),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String get fieldName => fieldTypeOption?.field_2.name ?? '';
|
||||
}
|
||||
|
||||
/// Uses when editing a existing field
|
||||
class FieldTypeOptionLoader extends ITypeOptionLoader {
|
||||
@override
|
||||
class FieldTypeOptionLoader {
|
||||
final String viewId;
|
||||
final FieldPB field;
|
||||
|
||||
@ -209,8 +167,7 @@ class FieldTypeOptionLoader extends ITypeOptionLoader {
|
||||
required this.field,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<TypeOptionPB, FlowyError>> initialize() {
|
||||
Future<Either<TypeOptionPB, FlowyError>> load() {
|
||||
final payload = TypeOptionPathPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = field.id
|
||||
@ -218,7 +175,4 @@ class FieldTypeOptionLoader extends ITypeOptionLoader {
|
||||
|
||||
return DatabaseEventGetTypeOption(payload).send();
|
||||
}
|
||||
|
||||
@override
|
||||
String get fieldName => field.name;
|
||||
}
|
||||
|
@ -11,31 +11,27 @@ import '../field_service.dart';
|
||||
import 'type_option_context.dart';
|
||||
|
||||
class TypeOptionController {
|
||||
final String viewId;
|
||||
late TypeOptionPB _typeOption;
|
||||
final ITypeOptionLoader loader;
|
||||
final FieldTypeOptionLoader loader;
|
||||
final PublishNotifier<FieldPB> _fieldNotifier = PublishNotifier();
|
||||
|
||||
/// Returns a [TypeOptionController] used to modify the specified
|
||||
/// [FieldPB]'s data
|
||||
///
|
||||
/// Should call [loadTypeOptionData] if the passed-in [FieldInfo]
|
||||
/// Should call [reloadTypeOption] if the passed-in [FieldInfo]
|
||||
/// is null
|
||||
///
|
||||
TypeOptionController({
|
||||
required this.viewId,
|
||||
required this.loader,
|
||||
FieldInfo? fieldInfo,
|
||||
required FieldPB field,
|
||||
}) {
|
||||
if (fieldInfo != null) {
|
||||
_typeOption = TypeOptionPB.create()
|
||||
..viewId = viewId
|
||||
..field_2 = fieldInfo.field;
|
||||
}
|
||||
_typeOption = TypeOptionPB.create()
|
||||
..viewId = loader.viewId
|
||||
..field_2 = field;
|
||||
}
|
||||
|
||||
Future<Either<TypeOptionPB, FlowyError>> loadTypeOptionData() async {
|
||||
final result = await loader.initialize();
|
||||
Future<Either<TypeOptionPB, FlowyError>> reloadTypeOption() async {
|
||||
final result = await loader.load();
|
||||
return result.fold(
|
||||
(data) {
|
||||
data.freeze();
|
||||
@ -67,7 +63,7 @@ class TypeOptionController {
|
||||
|
||||
_fieldNotifier.value = _typeOption.field_2;
|
||||
|
||||
FieldBackendService(viewId: viewId, fieldId: field.id)
|
||||
FieldBackendService(viewId: loader.viewId, fieldId: field.id)
|
||||
.updateField(name: name);
|
||||
}
|
||||
|
||||
@ -79,7 +75,7 @@ class TypeOptionController {
|
||||
});
|
||||
|
||||
FieldBackendService.updateFieldTypeOption(
|
||||
viewId: viewId,
|
||||
viewId: loader.viewId,
|
||||
fieldId: field.id,
|
||||
typeOptionData: typeOptionData,
|
||||
);
|
||||
@ -87,7 +83,7 @@ class TypeOptionController {
|
||||
|
||||
Future<void> switchToField(FieldType newFieldType) async {
|
||||
final payload = UpdateFieldTypePayloadPB.create()
|
||||
..viewId = viewId
|
||||
..viewId = loader.viewId
|
||||
..fieldId = field.id
|
||||
..fieldType = newFieldType;
|
||||
|
||||
@ -97,7 +93,7 @@ class TypeOptionController {
|
||||
// Should load the type-option data after switching to a new field.
|
||||
// After loading the type-option data, the editor widget that uses
|
||||
// the type-option data will be rebuild.
|
||||
loadTypeOptionData();
|
||||
reloadTypeOption();
|
||||
},
|
||||
(err) => Future(() => Log.error(err)),
|
||||
);
|
||||
|
@ -1,8 +1,7 @@
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/cell_entities.pb.dart';
|
||||
|
||||
class TypeOptionBackendService {
|
||||
final String viewId;
|
||||
@ -23,4 +22,15 @@ class TypeOptionBackendService {
|
||||
|
||||
return DatabaseEventCreateSelectOption(payload).send();
|
||||
}
|
||||
|
||||
static Future<Either<TypeOptionPB, FlowyError>> createFieldTypeOption({
|
||||
required String viewId,
|
||||
FieldType fieldType = FieldType.RichText,
|
||||
}) {
|
||||
final payload = CreateFieldPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..fieldType = FieldType.RichText;
|
||||
|
||||
return DatabaseEventCreateTypeOption(payload).send();
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class RowCache {
|
||||
|
||||
RowUpdateCallback addListener({
|
||||
required RowId rowId,
|
||||
void Function(CellByFieldId, RowsChangedReason)? onCellUpdated,
|
||||
void Function(CellContextByFieldId, RowsChangedReason)? onCellUpdated,
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
listenerHandler() async {
|
||||
@ -197,7 +197,7 @@ class RowCache {
|
||||
if (onCellUpdated != null) {
|
||||
final rowInfo = _rowList.get(rowId);
|
||||
if (rowInfo != null) {
|
||||
final CellByFieldId cellDataMap =
|
||||
final CellContextByFieldId cellDataMap =
|
||||
_makeGridCells(rowId, rowInfo.rowPB);
|
||||
onCellUpdated(cellDataMap, _rowChangeReasonNotifier.reason);
|
||||
}
|
||||
@ -220,7 +220,7 @@ class RowCache {
|
||||
_rowChangeReasonNotifier.removeListener(callback);
|
||||
}
|
||||
|
||||
CellByFieldId loadGridCells(RowId rowId) {
|
||||
CellContextByFieldId loadGridCells(RowId rowId) {
|
||||
final RowPB? data = _rowList.get(rowId)?.rowPB;
|
||||
if (data == null) {
|
||||
_loadRow(rowId);
|
||||
@ -240,12 +240,12 @@ class RowCache {
|
||||
);
|
||||
}
|
||||
|
||||
CellByFieldId _makeGridCells(RowId rowId, RowPB? row) {
|
||||
CellContextByFieldId _makeGridCells(RowId rowId, RowPB? row) {
|
||||
// ignore: prefer_collection_literals
|
||||
var cellDataMap = CellByFieldId();
|
||||
var cellDataMap = CellContextByFieldId();
|
||||
for (final field in _delegate.fields) {
|
||||
if (field.visibility) {
|
||||
cellDataMap[field.id] = CellIdentifier(
|
||||
cellDataMap[field.id] = DatabaseCellContext(
|
||||
rowId: rowId,
|
||||
viewId: viewId,
|
||||
fieldInfo: field,
|
||||
|
@ -3,7 +3,7 @@ import '../cell/cell_service.dart';
|
||||
import 'row_cache.dart';
|
||||
import 'row_service.dart';
|
||||
|
||||
typedef OnRowChanged = void Function(CellByFieldId, RowsChangedReason);
|
||||
typedef OnRowChanged = void Function(CellContextByFieldId, RowsChangedReason);
|
||||
|
||||
class RowController {
|
||||
final RowId rowId;
|
||||
@ -21,7 +21,7 @@ class RowController {
|
||||
this.groupId,
|
||||
}) : _rowCache = rowCache;
|
||||
|
||||
CellByFieldId loadData() {
|
||||
CellContextByFieldId loadData() {
|
||||
return _rowCache.loadGridCells(rowId);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class RowEvent with _$RowEvent {
|
||||
const factory RowEvent.initial() = _InitialRow;
|
||||
const factory RowEvent.createRow() = _CreateRow;
|
||||
const factory RowEvent.didReceiveCells(
|
||||
CellByFieldId cellsByFieldId,
|
||||
CellContextByFieldId cellsByFieldId,
|
||||
RowsChangedReason reason,
|
||||
) = _DidReceiveCells;
|
||||
}
|
||||
@ -79,12 +79,15 @@ class RowEvent with _$RowEvent {
|
||||
class RowState with _$RowState {
|
||||
const factory RowState({
|
||||
required RowInfo rowInfo,
|
||||
required CellByFieldId cellByFieldId,
|
||||
required CellContextByFieldId cellByFieldId,
|
||||
required UnmodifiableListView<GridCellEquatable> cells,
|
||||
RowsChangedReason? changeReason,
|
||||
}) = _RowState;
|
||||
|
||||
factory RowState.initial(RowInfo rowInfo, CellByFieldId cellByFieldId) =>
|
||||
factory RowState.initial(
|
||||
RowInfo rowInfo,
|
||||
CellContextByFieldId cellByFieldId,
|
||||
) =>
|
||||
RowState(
|
||||
rowInfo: rowInfo,
|
||||
cellByFieldId: cellByFieldId,
|
||||
|
@ -88,14 +88,14 @@ class RowDetailEvent with _$RowDetailEvent {
|
||||
const factory RowDetailEvent.duplicateRow(String rowId, String? groupId) =
|
||||
_DuplicateRow;
|
||||
const factory RowDetailEvent.didReceiveCellDatas(
|
||||
List<CellIdentifier> gridCells,
|
||||
List<DatabaseCellContext> gridCells,
|
||||
) = _DidReceiveCellDatas;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowDetailState with _$RowDetailState {
|
||||
const factory RowDetailState({
|
||||
required List<CellIdentifier> gridCells,
|
||||
required List<DatabaseCellContext> gridCells,
|
||||
}) = _RowDetailState;
|
||||
|
||||
factory RowDetailState.initial() => RowDetailState(
|
||||
|
@ -14,7 +14,7 @@ import 'field_cell_action_sheet.dart';
|
||||
import 'field_type_extension.dart';
|
||||
|
||||
class GridFieldCell extends StatefulWidget {
|
||||
final FieldCellContext cellContext;
|
||||
final FieldContext cellContext;
|
||||
const GridFieldCell({
|
||||
Key? key,
|
||||
required this.cellContext,
|
||||
|
@ -19,7 +19,7 @@ import '../../layout/sizes.dart';
|
||||
import 'field_editor.dart';
|
||||
|
||||
class GridFieldCellActionSheet extends StatefulWidget {
|
||||
final FieldCellContext cellContext;
|
||||
final FieldContext cellContext;
|
||||
const GridFieldCellActionSheet({required this.cellContext, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@ -69,7 +69,7 @@ class _GridFieldCellActionSheetState extends State<GridFieldCellActionSheet> {
|
||||
}
|
||||
|
||||
class _EditFieldButton extends StatelessWidget {
|
||||
final FieldCellContext cellContext;
|
||||
final FieldContext cellContext;
|
||||
final void Function()? onTap;
|
||||
const _EditFieldButton({required this.cellContext, Key? key, this.onTap})
|
||||
: super(key: key);
|
||||
@ -95,7 +95,7 @@ class _EditFieldButton extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _FieldOperationList extends StatelessWidget {
|
||||
final FieldCellContext fieldInfo;
|
||||
final FieldContext fieldInfo;
|
||||
const _FieldOperationList(this.fieldInfo, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -138,7 +138,7 @@ class _FieldOperationList extends StatelessWidget {
|
||||
}
|
||||
|
||||
class FieldActionCell extends StatelessWidget {
|
||||
final FieldCellContext fieldInfo;
|
||||
final FieldContext fieldInfo;
|
||||
final FieldAction action;
|
||||
final bool enable;
|
||||
|
||||
@ -203,7 +203,7 @@ extension _FieldActionExtension on FieldAction {
|
||||
}
|
||||
}
|
||||
|
||||
void run(BuildContext context, FieldCellContext fieldInfo) {
|
||||
void run(BuildContext context, FieldContext fieldInfo) {
|
||||
switch (this) {
|
||||
case FieldAction.hide:
|
||||
context
|
||||
|
@ -19,7 +19,7 @@ class FieldEditor extends StatefulWidget {
|
||||
final bool isGroupingField;
|
||||
final Function(String)? onDeleted;
|
||||
final Function(String)? onHidden;
|
||||
final ITypeOptionLoader typeOptionLoader;
|
||||
final FieldTypeOptionLoader typeOptionLoader;
|
||||
|
||||
const FieldEditor({
|
||||
required this.viewId,
|
||||
@ -53,22 +53,25 @@ class _FieldEditorState extends State<FieldEditor> {
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> children = [
|
||||
_FieldNameTextField(popoverMutex: popoverMutex),
|
||||
const VSpace(10),
|
||||
if (widget.onDeleted != null) _addDeleteFieldButton(),
|
||||
if (widget.onHidden != null) _addHideFieldButton(),
|
||||
_FieldTypeOptionCell(popoverMutex: popoverMutex),
|
||||
if (!widget.typeOptionLoader.field.isPrimary)
|
||||
_FieldTypeOptionCell(popoverMutex: popoverMutex),
|
||||
];
|
||||
return BlocProvider(
|
||||
create: (context) => FieldEditorBloc(
|
||||
viewId: widget.viewId,
|
||||
fieldName: widget.typeOptionLoader.fieldName,
|
||||
isGroupField: widget.isGroupingField,
|
||||
loader: widget.typeOptionLoader,
|
||||
)..add(const FieldEditorEvent.initial()),
|
||||
child: ListView.builder(
|
||||
create: (context) {
|
||||
return FieldEditorBloc(
|
||||
isGroupField: widget.isGroupingField,
|
||||
loader: widget.typeOptionLoader,
|
||||
field: widget.typeOptionLoader.field,
|
||||
)..add(const FieldEditorEvent.initial());
|
||||
},
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemCount: children.length,
|
||||
itemBuilder: (context, index) => children[index],
|
||||
separatorBuilder: (context, index) =>
|
||||
VSpace(GridSize.typeOptionSeparatorHeight),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
),
|
||||
);
|
||||
|
@ -4,6 +4,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_service.d
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
import 'package:appflowy/plugins/database_view/grid/application/grid_header_bloc.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
@ -13,6 +14,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:reorderables/reorderables.dart';
|
||||
import '../../../../application/field/type_option/type_option_service.dart';
|
||||
import '../../layout/sizes.dart';
|
||||
import 'field_editor.dart';
|
||||
import 'field_cell.dart';
|
||||
@ -101,8 +103,10 @@ class _GridHeaderState extends State<_GridHeader> {
|
||||
final cells = state.fields
|
||||
.where((field) => field.visibility)
|
||||
.map(
|
||||
(field) =>
|
||||
FieldCellContext(viewId: widget.viewId, field: field.field),
|
||||
(field) => FieldContext(
|
||||
viewId: widget.viewId,
|
||||
field: field.field,
|
||||
),
|
||||
)
|
||||
.map(
|
||||
(ctx) => GridFieldCell(
|
||||
@ -177,28 +181,52 @@ class _CellTrailing extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class CreateFieldButton extends StatelessWidget {
|
||||
class CreateFieldButton extends StatefulWidget {
|
||||
final String viewId;
|
||||
const CreateFieldButton({required this.viewId, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CreateFieldButton> createState() => _CreateFieldButtonState();
|
||||
}
|
||||
|
||||
class _CreateFieldButtonState extends State<CreateFieldButton> {
|
||||
final popoverController = PopoverController();
|
||||
late TypeOptionPB typeOption;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppFlowyPopover(
|
||||
controller: popoverController,
|
||||
direction: PopoverDirection.bottomWithRightAligned,
|
||||
asBarrier: true,
|
||||
margin: EdgeInsets.zero,
|
||||
constraints: BoxConstraints.loose(const Size(240, 600)),
|
||||
triggerActions: PopoverTriggerFlags.none,
|
||||
child: FlowyButton(
|
||||
radius: BorderRadius.zero,
|
||||
text: FlowyText.medium(LocaleKeys.grid_field_newProperty.tr()),
|
||||
hoverColor: AFThemeExtension.of(context).greyHover,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
final result = await TypeOptionBackendService.createFieldTypeOption(
|
||||
viewId: widget.viewId,
|
||||
);
|
||||
result.fold(
|
||||
(l) {
|
||||
typeOption = l;
|
||||
popoverController.show();
|
||||
},
|
||||
(r) => Log.error("Failed to create field type option: $r"),
|
||||
);
|
||||
},
|
||||
leftIcon: const FlowySvg(name: 'home/add'),
|
||||
),
|
||||
popupBuilder: (BuildContext popover) {
|
||||
return FieldEditor(
|
||||
viewId: viewId,
|
||||
typeOptionLoader: NewFieldTypeOptionLoader(viewId: viewId),
|
||||
viewId: widget.viewId,
|
||||
typeOptionLoader: FieldTypeOptionLoader(
|
||||
viewId: widget.viewId,
|
||||
field: typeOption.field_2,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -60,7 +60,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
|
||||
required TypeOptionController dataController,
|
||||
required PopoverMutex popoverMutex,
|
||||
}) {
|
||||
final viewId = dataController.viewId;
|
||||
final viewId = dataController.loader.viewId;
|
||||
final fieldType = dataController.field.fieldType;
|
||||
|
||||
switch (dataController.field.fieldType) {
|
||||
@ -146,9 +146,8 @@ TypeOptionContext<T> makeTypeOptionContext<T extends GeneratedMessage>({
|
||||
}) {
|
||||
final loader = FieldTypeOptionLoader(viewId: viewId, field: fieldInfo.field);
|
||||
final dataController = TypeOptionController(
|
||||
viewId: viewId,
|
||||
loader: loader,
|
||||
fieldInfo: fieldInfo,
|
||||
field: fieldInfo.field,
|
||||
);
|
||||
return makeTypeOptionContextWithDataController(
|
||||
viewId: viewId,
|
||||
@ -180,8 +179,8 @@ TypeOptionContext<T> makeSelectTypeOptionContext<T extends GeneratedMessage>({
|
||||
field: fieldPB,
|
||||
);
|
||||
final dataController = TypeOptionController(
|
||||
viewId: viewId,
|
||||
loader: loader,
|
||||
field: fieldPB,
|
||||
);
|
||||
final typeOptionContext = makeTypeOptionContextWithDataController<T>(
|
||||
viewId: viewId,
|
||||
|
@ -255,7 +255,10 @@ class RowContent extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _makeCells(BuildContext context, CellByFieldId cellByFieldId) {
|
||||
List<Widget> _makeCells(
|
||||
BuildContext context,
|
||||
CellContextByFieldId cellByFieldId,
|
||||
) {
|
||||
return cellByFieldId.values.map(
|
||||
(cellId) {
|
||||
final GridCellWidget child = builder.build(cellId);
|
||||
|
@ -194,7 +194,7 @@ class _RowCardState<T> extends State<RowCard<T>> {
|
||||
class _CardContent<CustomCardData> extends StatelessWidget {
|
||||
final CardCellBuilder<CustomCardData> cellBuilder;
|
||||
final EditableRowNotifier rowNotifier;
|
||||
final List<CellIdentifier> cells;
|
||||
final List<DatabaseCellContext> cells;
|
||||
final RowCardRenderHook<CustomCardData>? renderHook;
|
||||
final CustomCardData? cardData;
|
||||
final RowCardStyleConfiguration styleConfiguration;
|
||||
@ -233,28 +233,28 @@ class _CardContent<CustomCardData> extends StatelessWidget {
|
||||
|
||||
List<Widget> _makeCells(
|
||||
BuildContext context,
|
||||
List<CellIdentifier> cells,
|
||||
List<DatabaseCellContext> cells,
|
||||
) {
|
||||
final List<Widget> children = [];
|
||||
// Remove all the cell listeners.
|
||||
rowNotifier.unbind();
|
||||
|
||||
cells.asMap().forEach(
|
||||
(int index, CellIdentifier cell) {
|
||||
(int index, DatabaseCellContext cellContext) {
|
||||
final isEditing = index == 0 ? rowNotifier.isEditing.value : false;
|
||||
final cellNotifier = EditableCardNotifier(isEditing: isEditing);
|
||||
|
||||
if (index == 0) {
|
||||
// Only use the first cell to receive user's input when click the edit
|
||||
// button
|
||||
rowNotifier.bindCell(cell, cellNotifier);
|
||||
rowNotifier.bindCell(cellContext, cellNotifier);
|
||||
}
|
||||
|
||||
final child = Padding(
|
||||
key: cell.key(),
|
||||
key: cellContext.key(),
|
||||
padding: styleConfiguration.cellPadding,
|
||||
child: cellBuilder.buildCell(
|
||||
cellId: cell,
|
||||
cellContext: cellContext,
|
||||
cellNotifier: cellNotifier,
|
||||
renderHook: renderHook,
|
||||
cardData: cardData,
|
||||
|
@ -87,11 +87,11 @@ class CardBloc extends Bloc<RowCardEvent, RowCardState> {
|
||||
}
|
||||
}
|
||||
|
||||
List<CellIdentifier> _makeCells(
|
||||
List<DatabaseCellContext> _makeCells(
|
||||
String? groupFieldId,
|
||||
CellByFieldId originalCellMap,
|
||||
CellContextByFieldId originalCellMap,
|
||||
) {
|
||||
List<CellIdentifier> cells = [];
|
||||
List<DatabaseCellContext> cells = [];
|
||||
for (final entry in originalCellMap.entries) {
|
||||
// Filter out the cell if it's fieldId equal to the groupFieldId
|
||||
if (groupFieldId != null) {
|
||||
@ -110,7 +110,7 @@ class RowCardEvent with _$RowCardEvent {
|
||||
const factory RowCardEvent.initial() = _InitialRow;
|
||||
const factory RowCardEvent.setIsEditing(bool isEditing) = _IsEditing;
|
||||
const factory RowCardEvent.didReceiveCells(
|
||||
List<CellIdentifier> cells,
|
||||
List<DatabaseCellContext> cells,
|
||||
RowsChangedReason reason,
|
||||
) = _DidReceiveCells;
|
||||
}
|
||||
@ -119,14 +119,14 @@ class RowCardEvent with _$RowCardEvent {
|
||||
class RowCardState with _$RowCardState {
|
||||
const factory RowCardState({
|
||||
required RowPB rowPB,
|
||||
required List<CellIdentifier> cells,
|
||||
required List<DatabaseCellContext> cells,
|
||||
required bool isEditing,
|
||||
RowsChangedReason? changeReason,
|
||||
}) = _RowCardState;
|
||||
|
||||
factory RowCardState.initial(
|
||||
RowPB rowPB,
|
||||
List<CellIdentifier> cells,
|
||||
List<DatabaseCellContext> cells,
|
||||
bool isEditing,
|
||||
) =>
|
||||
RowCardState(
|
||||
|
@ -21,18 +21,18 @@ class CardCellBuilder<CustomCardData> {
|
||||
|
||||
Widget buildCell({
|
||||
CustomCardData? cardData,
|
||||
required CellIdentifier cellId,
|
||||
required DatabaseCellContext cellContext,
|
||||
EditableCardNotifier? cellNotifier,
|
||||
RowCardRenderHook<CustomCardData>? renderHook,
|
||||
}) {
|
||||
final cellControllerBuilder = CellControllerBuilder(
|
||||
cellId: cellId,
|
||||
cellContext: cellContext,
|
||||
cellCache: cellCache,
|
||||
);
|
||||
|
||||
final key = cellId.key();
|
||||
final style = styles?[cellId.fieldType];
|
||||
switch (cellId.fieldType) {
|
||||
final key = cellContext.key();
|
||||
final style = styles?[cellContext.fieldType];
|
||||
switch (cellContext.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
return CheckboxCardCell(
|
||||
cellControllerBuilder: cellControllerBuilder,
|
||||
|
@ -106,7 +106,7 @@ class EditableRowNotifier {
|
||||
: isEditing = ValueNotifier(isEditing);
|
||||
|
||||
void bindCell(
|
||||
CellIdentifier cellIdentifier,
|
||||
DatabaseCellContext cellIdentifier,
|
||||
EditableCardNotifier notifier,
|
||||
) {
|
||||
assert(
|
||||
@ -171,7 +171,8 @@ class EditableCellId {
|
||||
|
||||
EditableCellId(this.rowId, this.fieldId);
|
||||
|
||||
factory EditableCellId.from(CellIdentifier cellIdentifier) => EditableCellId(
|
||||
factory EditableCellId.from(DatabaseCellContext cellIdentifier) =>
|
||||
EditableCellId(
|
||||
cellIdentifier.rowId,
|
||||
cellIdentifier.fieldId,
|
||||
);
|
||||
|
@ -20,14 +20,17 @@ class GridCellBuilder {
|
||||
required this.cellCache,
|
||||
});
|
||||
|
||||
GridCellWidget build(CellIdentifier cellId, {GridCellStyle? style}) {
|
||||
GridCellWidget build(
|
||||
DatabaseCellContext cellContext, {
|
||||
GridCellStyle? style,
|
||||
}) {
|
||||
final cellControllerBuilder = CellControllerBuilder(
|
||||
cellId: cellId,
|
||||
cellContext: cellContext,
|
||||
cellCache: cellCache,
|
||||
);
|
||||
|
||||
final key = cellId.key();
|
||||
switch (cellId.fieldType) {
|
||||
final key = cellContext.key();
|
||||
switch (cellContext.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
return GridCheckboxCell(
|
||||
cellControllerBuilder: cellControllerBuilder,
|
||||
|
@ -15,8 +15,9 @@ class ChecklistCardCellBloc
|
||||
void Function()? _onCellChangedFn;
|
||||
ChecklistCardCellBloc({
|
||||
required this.cellController,
|
||||
}) : _checklistCellSvc =
|
||||
ChecklistCellBackendService(cellId: cellController.cellId),
|
||||
}) : _checklistCellSvc = ChecklistCellBackendService(
|
||||
cellContext: cellController.cellContext,
|
||||
),
|
||||
super(ChecklistCellState.initial(cellController)) {
|
||||
on<ChecklistCellEvent>(
|
||||
(event, emit) async {
|
||||
|
@ -18,8 +18,9 @@ class ChecklistCellEditorBloc
|
||||
|
||||
ChecklistCellEditorBloc({
|
||||
required this.cellController,
|
||||
}) : _checklistCellService =
|
||||
ChecklistCellBackendService(cellId: cellController.cellId),
|
||||
}) : _checklistCellService = ChecklistCellBackendService(
|
||||
cellContext: cellController.cellContext,
|
||||
),
|
||||
super(ChecklistCellEditorState.initial(cellController)) {
|
||||
on<ChecklistCellEditorEvent>(
|
||||
(event, emit) async {
|
||||
|
@ -16,8 +16,9 @@ class SelectOptionCellEditorBloc
|
||||
|
||||
SelectOptionCellEditorBloc({
|
||||
required this.cellController,
|
||||
}) : _selectOptionService =
|
||||
SelectOptionCellBackendService(cellId: cellController.cellId),
|
||||
}) : _selectOptionService = SelectOptionCellBackendService(
|
||||
cellContext: cellController.cellContext,
|
||||
),
|
||||
super(SelectOptionEditorState.initial(cellController)) {
|
||||
on<SelectOptionEditorEvent>(
|
||||
(event, emit) async {
|
||||
|
@ -1,8 +1,10 @@
|
||||
import 'package:appflowy/plugins/database_view/application/cell/cell_service.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_service.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/row/row_data_controller.dart';
|
||||
import 'package:appflowy/plugins/database_view/grid/application/row/row_detail_bloc.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
@ -134,7 +136,7 @@ class _PropertyColumn extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_RowTitle(
|
||||
cellId: state.gridCells
|
||||
cellContext: state.gridCells
|
||||
.firstWhereOrNull((e) => e.fieldInfo.isPrimary),
|
||||
cellBuilder: cellBuilder,
|
||||
),
|
||||
@ -145,7 +147,7 @@ class _PropertyColumn extends StatelessWidget {
|
||||
(cell) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: _PropertyCell(
|
||||
cellId: cell,
|
||||
cellContext: cell,
|
||||
cellBuilder: cellBuilder,
|
||||
),
|
||||
),
|
||||
@ -161,14 +163,14 @@ class _PropertyColumn extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _RowTitle extends StatelessWidget {
|
||||
final CellIdentifier? cellId;
|
||||
final DatabaseCellContext? cellContext;
|
||||
final GridCellBuilder cellBuilder;
|
||||
const _RowTitle({this.cellId, required this.cellBuilder, Key? key})
|
||||
const _RowTitle({this.cellContext, required this.cellBuilder, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (cellId == null) {
|
||||
if (cellContext == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
final style = GridTextCellStyle(
|
||||
@ -176,7 +178,7 @@ class _RowTitle extends StatelessWidget {
|
||||
textStyle: Theme.of(context).textTheme.titleLarge,
|
||||
autofocus: true,
|
||||
);
|
||||
return cellBuilder.build(cellId!, style: style);
|
||||
return cellBuilder.build(cellContext!, style: style);
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,6 +196,7 @@ class _CreatePropertyButton extends StatefulWidget {
|
||||
|
||||
class _CreatePropertyButtonState extends State<_CreatePropertyButton> {
|
||||
late PopoverController popoverController;
|
||||
late TypeOptionPB typeOption;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -207,6 +210,7 @@ class _CreatePropertyButtonState extends State<_CreatePropertyButton> {
|
||||
constraints: BoxConstraints.loose(const Size(240, 200)),
|
||||
controller: popoverController,
|
||||
direction: PopoverDirection.topWithLeftAligned,
|
||||
triggerActions: PopoverTriggerFlags.none,
|
||||
margin: EdgeInsets.zero,
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
@ -216,7 +220,18 @@ class _CreatePropertyButtonState extends State<_CreatePropertyButton> {
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
),
|
||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||
onTap: () {},
|
||||
onTap: () async {
|
||||
final result = await TypeOptionBackendService.createFieldTypeOption(
|
||||
viewId: widget.viewId,
|
||||
);
|
||||
result.fold(
|
||||
(l) {
|
||||
typeOption = l;
|
||||
popoverController.show();
|
||||
},
|
||||
(r) => Log.error("Failed to create field type option: $r"),
|
||||
);
|
||||
},
|
||||
leftIcon: svgWidget(
|
||||
"home/add",
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
@ -226,7 +241,10 @@ class _CreatePropertyButtonState extends State<_CreatePropertyButton> {
|
||||
popupBuilder: (BuildContext popOverContext) {
|
||||
return FieldEditor(
|
||||
viewId: widget.viewId,
|
||||
typeOptionLoader: NewFieldTypeOptionLoader(viewId: widget.viewId),
|
||||
typeOptionLoader: FieldTypeOptionLoader(
|
||||
viewId: widget.viewId,
|
||||
field: typeOption.field_2,
|
||||
),
|
||||
onDeleted: (fieldId) {
|
||||
popoverController.close();
|
||||
NavigatorAlertDialog(
|
||||
@ -245,10 +263,10 @@ class _CreatePropertyButtonState extends State<_CreatePropertyButton> {
|
||||
}
|
||||
|
||||
class _PropertyCell extends StatefulWidget {
|
||||
final CellIdentifier cellId;
|
||||
final DatabaseCellContext cellContext;
|
||||
final GridCellBuilder cellBuilder;
|
||||
const _PropertyCell({
|
||||
required this.cellId,
|
||||
required this.cellContext,
|
||||
required this.cellBuilder,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
@ -262,8 +280,8 @@ class _PropertyCellState extends State<_PropertyCell> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final style = _customCellStyle(widget.cellId.fieldType);
|
||||
final cell = widget.cellBuilder.build(widget.cellId, style: style);
|
||||
final style = _customCellStyle(widget.cellContext.fieldType);
|
||||
final cell = widget.cellBuilder.build(widget.cellContext, style: style);
|
||||
|
||||
final gesture = GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
@ -290,7 +308,7 @@ class _PropertyCellState extends State<_PropertyCell> {
|
||||
child: SizedBox(
|
||||
width: 150,
|
||||
child: FieldCellButton(
|
||||
field: widget.cellId.fieldInfo.field,
|
||||
field: widget.cellContext.fieldInfo.field,
|
||||
onTap: () => popover.show(),
|
||||
radius: BorderRadius.circular(6),
|
||||
),
|
||||
@ -306,11 +324,11 @@ class _PropertyCellState extends State<_PropertyCell> {
|
||||
|
||||
Widget buildFieldEditor() {
|
||||
return FieldEditor(
|
||||
viewId: widget.cellId.viewId,
|
||||
isGroupingField: widget.cellId.fieldInfo.isGroupField,
|
||||
viewId: widget.cellContext.viewId,
|
||||
isGroupingField: widget.cellContext.fieldInfo.isGroupField,
|
||||
typeOptionLoader: FieldTypeOptionLoader(
|
||||
viewId: widget.cellId.viewId,
|
||||
field: widget.cellId.fieldInfo.field,
|
||||
viewId: widget.cellContext.viewId,
|
||||
field: widget.cellContext.fieldInfo.field,
|
||||
),
|
||||
onHidden: (fieldId) {
|
||||
popover.close();
|
||||
|
@ -171,7 +171,7 @@ void _resolveGridDeps(GetIt getIt) {
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactoryParam<FieldActionSheetBloc, FieldCellContext, void>(
|
||||
getIt.registerFactoryParam<FieldActionSheetBloc, FieldContext, void>(
|
||||
(data, _) => FieldActionSheetBloc(fieldCellContext: data),
|
||||
);
|
||||
|
||||
|
@ -35,10 +35,9 @@ void main() {
|
||||
);
|
||||
|
||||
final editorBloc = FieldEditorBloc(
|
||||
viewId: context.gridView.id,
|
||||
fieldName: fieldInfo.name,
|
||||
isGroupField: fieldInfo.isGroupField,
|
||||
loader: loader,
|
||||
field: fieldInfo.field,
|
||||
)..add(const FieldEditorEvent.initial());
|
||||
await boardResponseFuture();
|
||||
|
||||
|
@ -15,7 +15,7 @@ void main() {
|
||||
boardTest = await AppFlowyBoardTest.ensureInitialized();
|
||||
context = await boardTest.createTestBoard();
|
||||
final fieldInfo = context.singleSelectFieldContext();
|
||||
editorBloc = context.createFieldEditor(
|
||||
editorBloc = context.makeFieldEditor(
|
||||
fieldInfo: fieldInfo,
|
||||
)..add(const FieldEditorEvent.initial());
|
||||
|
||||
|
@ -76,22 +76,18 @@ class BoardTestContext {
|
||||
return _boardDataController.fieldController;
|
||||
}
|
||||
|
||||
FieldEditorBloc createFieldEditor({
|
||||
FieldInfo? fieldInfo,
|
||||
FieldEditorBloc makeFieldEditor({
|
||||
required FieldInfo fieldInfo,
|
||||
}) {
|
||||
ITypeOptionLoader loader;
|
||||
if (fieldInfo == null) {
|
||||
loader = NewFieldTypeOptionLoader(viewId: gridView.id);
|
||||
} else {
|
||||
loader =
|
||||
FieldTypeOptionLoader(viewId: gridView.id, field: fieldInfo.field);
|
||||
}
|
||||
final loader = FieldTypeOptionLoader(
|
||||
viewId: gridView.id,
|
||||
field: fieldInfo.field,
|
||||
);
|
||||
|
||||
final editorBloc = FieldEditorBloc(
|
||||
fieldName: fieldInfo?.name ?? '',
|
||||
isGroupField: fieldInfo?.isGroupField ?? false,
|
||||
isGroupField: fieldInfo.isGroupField,
|
||||
loader: loader,
|
||||
viewId: gridView.id,
|
||||
field: fieldInfo.field,
|
||||
);
|
||||
return editorBloc;
|
||||
}
|
||||
@ -120,13 +116,13 @@ class BoardTestContext {
|
||||
await gridResponseFuture();
|
||||
|
||||
return CellControllerBuilder(
|
||||
cellId: rowBloc.state.cellByFieldId[fieldId]!,
|
||||
cellContext: rowBloc.state.cellByFieldId[fieldId]!,
|
||||
cellCache: rowCache.cellCache,
|
||||
);
|
||||
}
|
||||
|
||||
Future<FieldEditorBloc> createField(FieldType fieldType) async {
|
||||
final editorBloc = createFieldEditor()
|
||||
final editorBloc = await createFieldEditor(viewId: gridView.id)
|
||||
..add(const FieldEditorEvent.initial());
|
||||
await gridResponseFuture();
|
||||
editorBloc.add(FieldEditorEvent.switchToField(fieldType));
|
||||
@ -140,9 +136,9 @@ class BoardTestContext {
|
||||
return fieldInfo;
|
||||
}
|
||||
|
||||
FieldCellContext singleSelectFieldCellContext() {
|
||||
FieldContext singleSelectFieldCellContext() {
|
||||
final field = singleSelectFieldContext().field;
|
||||
return FieldCellContext(viewId: gridView.id, field: field);
|
||||
return FieldContext(viewId: gridView.id, field: field);
|
||||
}
|
||||
|
||||
FieldInfo textFieldContext() {
|
||||
|
@ -13,10 +13,9 @@ Future<FieldEditorBloc> createEditorBloc(AppFlowyGridTest gridTest) async {
|
||||
);
|
||||
|
||||
return FieldEditorBloc(
|
||||
viewId: context.gridView.id,
|
||||
fieldName: fieldInfo.name,
|
||||
isGroupField: fieldInfo.isGroupField,
|
||||
loader: loader,
|
||||
field: fieldInfo.field,
|
||||
)..add(const FieldEditorEvent.initial());
|
||||
}
|
||||
|
||||
@ -83,10 +82,9 @@ Future<FieldEditorBloc> makeEditorBloc(AppFlowyGridTest gridTest) async {
|
||||
);
|
||||
|
||||
final editorBloc = FieldEditorBloc(
|
||||
viewId: context.gridView.id,
|
||||
fieldName: fieldInfo.name,
|
||||
isGroupField: fieldInfo.isGroupField,
|
||||
loader: loader,
|
||||
field: fieldInfo.field,
|
||||
)..add(const FieldEditorEvent.initial());
|
||||
|
||||
await gridResponseFuture();
|
||||
|
@ -41,10 +41,9 @@ void main() {
|
||||
);
|
||||
|
||||
final editorBloc = FieldEditorBloc(
|
||||
viewId: context.gridView.id,
|
||||
fieldName: textField.field.name,
|
||||
isGroupField: false,
|
||||
loader: loader,
|
||||
field: textField.field,
|
||||
)..add(const FieldEditorEvent.initial());
|
||||
await gridResponseFuture();
|
||||
|
||||
|
@ -4,6 +4,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_service.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/row/row_cache.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/row/row_data_controller.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/database_controller.dart';
|
||||
@ -38,26 +39,6 @@ class GridTestContext {
|
||||
return gridController.createRow();
|
||||
}
|
||||
|
||||
FieldEditorBloc createFieldEditor({
|
||||
FieldInfo? fieldInfo,
|
||||
}) {
|
||||
ITypeOptionLoader loader;
|
||||
if (fieldInfo == null) {
|
||||
loader = NewFieldTypeOptionLoader(viewId: gridView.id);
|
||||
} else {
|
||||
loader =
|
||||
FieldTypeOptionLoader(viewId: gridView.id, field: fieldInfo.field);
|
||||
}
|
||||
|
||||
final editorBloc = FieldEditorBloc(
|
||||
fieldName: fieldInfo?.name ?? '',
|
||||
isGroupField: fieldInfo?.isGroupField ?? false,
|
||||
loader: loader,
|
||||
viewId: gridView.id,
|
||||
);
|
||||
return editorBloc;
|
||||
}
|
||||
|
||||
Future<CellController> makeCellController(
|
||||
String fieldId,
|
||||
int rowIndex,
|
||||
@ -86,13 +67,13 @@ class GridTestContext {
|
||||
await gridResponseFuture();
|
||||
|
||||
return CellControllerBuilder(
|
||||
cellId: rowBloc.state.cellByFieldId[fieldId]!,
|
||||
cellContext: rowBloc.state.cellByFieldId[fieldId]!,
|
||||
cellCache: rowCache.cellCache,
|
||||
);
|
||||
}
|
||||
|
||||
Future<FieldEditorBloc> createField(FieldType fieldType) async {
|
||||
final editorBloc = createFieldEditor()
|
||||
final editorBloc = await createFieldEditor(viewId: gridView.id)
|
||||
..add(const FieldEditorEvent.initial());
|
||||
await gridResponseFuture();
|
||||
editorBloc.add(FieldEditorEvent.switchToField(fieldType));
|
||||
@ -106,9 +87,9 @@ class GridTestContext {
|
||||
return fieldInfo;
|
||||
}
|
||||
|
||||
FieldCellContext singleSelectFieldCellContext() {
|
||||
FieldContext singleSelectFieldCellContext() {
|
||||
final field = singleSelectFieldContext().field;
|
||||
return FieldCellContext(viewId: gridView.id, field: field);
|
||||
return FieldContext(viewId: gridView.id, field: field);
|
||||
}
|
||||
|
||||
FieldInfo textFieldContext() {
|
||||
@ -155,6 +136,28 @@ class GridTestContext {
|
||||
}
|
||||
}
|
||||
|
||||
Future<FieldEditorBloc> createFieldEditor({
|
||||
required String viewId,
|
||||
}) async {
|
||||
final result = await TypeOptionBackendService.createFieldTypeOption(
|
||||
viewId: viewId,
|
||||
);
|
||||
return result.fold(
|
||||
(data) {
|
||||
final loader = FieldTypeOptionLoader(
|
||||
viewId: viewId,
|
||||
field: data.field_2,
|
||||
);
|
||||
return FieldEditorBloc(
|
||||
isGroupField: FieldInfo(field: data.field_2).isGroupField,
|
||||
loader: loader,
|
||||
field: data.field_2,
|
||||
);
|
||||
},
|
||||
(err) => throw Exception(err),
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a empty Grid for test
|
||||
class AppFlowyGridTest {
|
||||
final AppFlowyUnitTest unitTest;
|
||||
|
@ -196,16 +196,27 @@ impl DatabaseEditor {
|
||||
}
|
||||
|
||||
pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> {
|
||||
let is_primary = self
|
||||
.database
|
||||
.lock()
|
||||
.fields
|
||||
.get_field(¶ms.field_id)
|
||||
.map(|field| field.is_primary)
|
||||
.unwrap_or(false);
|
||||
self
|
||||
.database
|
||||
.lock()
|
||||
.fields
|
||||
.update_field(¶ms.field_id, |update| {
|
||||
update
|
||||
.update_field(¶ms.field_id, |mut update| {
|
||||
update = update
|
||||
.set_name_if_not_none(params.name)
|
||||
.set_field_type_if_not_none(params.field_type.map(|field_type| field_type.into()))
|
||||
.set_width_at_if_not_none(params.width.map(|value| value as i64))
|
||||
.set_visibility_if_not_none(params.visibility);
|
||||
if is_primary {
|
||||
tracing::warn!("Cannot update primary field type");
|
||||
} else {
|
||||
update.set_field_type_if_not_none(params.field_type.map(|field_type| field_type.into()));
|
||||
}
|
||||
});
|
||||
self
|
||||
.notify_did_update_database_field(¶ms.field_id)
|
||||
@ -238,10 +249,15 @@ impl DatabaseEditor {
|
||||
.lock()
|
||||
.fields
|
||||
.update_field(field_id, |update| {
|
||||
update.update_type_options(|type_options_update| {
|
||||
type_options_update.insert(&field_type.to_string(), type_option_data);
|
||||
});
|
||||
if old_field.is_primary {
|
||||
tracing::warn!("Cannot update primary field type");
|
||||
} else {
|
||||
update.update_type_options(|type_options_update| {
|
||||
type_options_update.insert(&field_type.to_string(), type_option_data);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
self
|
||||
.database_views
|
||||
.did_update_field_type_option(view_id, field_id, &old_field)
|
||||
|
@ -43,7 +43,7 @@ async fn update_at_field_test() {
|
||||
.unwrap();
|
||||
let old_updated_at = DateCellData::from(&cell).timestamp.unwrap();
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||
tokio::time::sleep(Duration::from_millis(1000)).await;
|
||||
test
|
||||
.run_script(UpdateTextCell {
|
||||
row_id: row.id.clone(),
|
||||
|
Loading…
Reference in New Issue
Block a user