mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: move database domain code to its own folder (#4556)
This commit is contained in:
@ -0,0 +1,53 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
import '../application/row/row_service.dart';
|
||||
|
||||
typedef UpdateFieldNotifiedValue = FlowyResult<void, FlowyError>;
|
||||
|
||||
class CellListener {
|
||||
CellListener({required this.rowId, required this.fieldId});
|
||||
|
||||
final RowId rowId;
|
||||
final String fieldId;
|
||||
|
||||
PublishNotifier<UpdateFieldNotifiedValue>? _updateCellNotifier =
|
||||
PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({required void Function(UpdateFieldNotifiedValue) onCellChanged}) {
|
||||
_updateCellNotifier?.addPublishListener(onCellChanged);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: "$rowId:$fieldId",
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateCell:
|
||||
result.fold(
|
||||
(payload) => _updateCellNotifier?.value = FlowyResult.success(null),
|
||||
(error) => _updateCellNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_updateCellNotifier?.dispose();
|
||||
_updateCellNotifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
import '../application/cell/cell_controller.dart';
|
||||
|
||||
class CellBackendService {
|
||||
CellBackendService();
|
||||
|
||||
static Future<FlowyResult<void, FlowyError>> updateCell({
|
||||
required String viewId,
|
||||
required CellContext cellContext,
|
||||
required String data,
|
||||
}) {
|
||||
final payload = CellChangesetPB()
|
||||
..viewId = viewId
|
||||
..fieldId = cellContext.fieldId
|
||||
..rowId = cellContext.rowId
|
||||
..cellChangeset = data;
|
||||
return DatabaseEventUpdateCell(payload).send();
|
||||
}
|
||||
|
||||
static Future<FlowyResult<CellPB, FlowyError>> getCell({
|
||||
required String viewId,
|
||||
required CellContext cellContext,
|
||||
}) {
|
||||
final payload = CellIdPB()
|
||||
..viewId = viewId
|
||||
..fieldId = cellContext.fieldId
|
||||
..rowId = cellContext.rowId;
|
||||
return DatabaseEventGetCell(payload).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/checklist_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
|
||||
class ChecklistCellBackendService {
|
||||
ChecklistCellBackendService({
|
||||
required this.viewId,
|
||||
required this.fieldId,
|
||||
required this.rowId,
|
||||
});
|
||||
|
||||
final String viewId;
|
||||
final String fieldId;
|
||||
final String rowId;
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> create({
|
||||
required String name,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId
|
||||
..insertOptions.add(name);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> delete({
|
||||
required List<String> optionIds,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId
|
||||
..deleteOptionIds.addAll(optionIds);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> select({
|
||||
required String optionId,
|
||||
}) {
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId
|
||||
..selectedOptionIds.add(optionId);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> updateName({
|
||||
required SelectOptionPB option,
|
||||
required name,
|
||||
}) {
|
||||
option.freeze();
|
||||
final newOption = option.rebuild((option) {
|
||||
option.name = name;
|
||||
});
|
||||
final payload = ChecklistCellDataChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId
|
||||
..updateOptions.add(newOption);
|
||||
|
||||
return DatabaseEventUpdateChecklistCell(payload).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class DatabaseBackendService {
|
||||
static Future<FlowyResult<List<DatabaseDescriptionPB>, FlowyError>>
|
||||
getAllDatabases() {
|
||||
return DatabaseEventGetDatabases().send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l.items),
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
import 'layout_service.dart';
|
||||
|
||||
class DatabaseViewBackendService {
|
||||
DatabaseViewBackendService({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
/// Returns the database id associated with the view.
|
||||
Future<FlowyResult<String, FlowyError>> getDatabaseId() async {
|
||||
final payload = DatabaseViewIdPB(value: viewId);
|
||||
return DatabaseEventGetDatabaseId(payload)
|
||||
.send()
|
||||
.then((value) => value.map((l) => l.value));
|
||||
}
|
||||
|
||||
static Future<FlowyResult<ViewPB, FlowyError>> updateLayout({
|
||||
required String viewId,
|
||||
required DatabaseLayoutPB layout,
|
||||
}) {
|
||||
final payload = UpdateViewPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..layout = viewLayoutFromDatabaseLayout(layout);
|
||||
|
||||
return FolderEventUpdateView(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<DatabasePB, FlowyError>> openDatabase() async {
|
||||
final payload = DatabaseViewIdPB(value: viewId);
|
||||
return DatabaseEventGetDatabase(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> moveGroupRow({
|
||||
required RowId fromRowId,
|
||||
required String fromGroupId,
|
||||
required String toGroupId,
|
||||
RowId? toRowId,
|
||||
}) {
|
||||
final payload = MoveGroupRowPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..fromRowId = fromRowId
|
||||
..fromGroupId = fromGroupId
|
||||
..toGroupId = toGroupId;
|
||||
|
||||
if (toRowId != null) {
|
||||
payload.toRowId = toRowId;
|
||||
}
|
||||
|
||||
return DatabaseEventMoveGroupRow(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> moveRow({
|
||||
required String fromRowId,
|
||||
required String toRowId,
|
||||
}) {
|
||||
final payload = MoveRowPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..fromRowId = fromRowId
|
||||
..toRowId = toRowId;
|
||||
|
||||
return DatabaseEventMoveRow(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> moveGroup({
|
||||
required String fromGroupId,
|
||||
required String toGroupId,
|
||||
}) {
|
||||
final payload = MoveGroupPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..fromGroupId = fromGroupId
|
||||
..toGroupId = toGroupId;
|
||||
|
||||
return DatabaseEventMoveGroup(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<List<FieldPB>, FlowyError>> getFields({
|
||||
List<FieldIdPB>? fieldIds,
|
||||
}) {
|
||||
final payload = GetFieldPayloadPB.create()..viewId = viewId;
|
||||
|
||||
if (fieldIds != null) {
|
||||
payload.fieldIds = RepeatedFieldIdPB(items: fieldIds);
|
||||
}
|
||||
return DatabaseEventGetFields(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l.items),
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<DatabaseLayoutSettingPB, FlowyError>> getLayoutSetting(
|
||||
DatabaseLayoutPB layoutType,
|
||||
) {
|
||||
final payload = DatabaseLayoutMetaPB.create()
|
||||
..viewId = viewId
|
||||
..layout = layoutType;
|
||||
return DatabaseEventGetLayoutSetting(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> updateLayoutSetting({
|
||||
required DatabaseLayoutPB layoutType,
|
||||
BoardLayoutSettingPB? boardLayoutSetting,
|
||||
CalendarLayoutSettingPB? calendarLayoutSetting,
|
||||
}) {
|
||||
final payload = LayoutSettingChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..layoutType = layoutType;
|
||||
|
||||
if (boardLayoutSetting != null) {
|
||||
payload.board = boardLayoutSetting;
|
||||
}
|
||||
|
||||
if (calendarLayoutSetting != null) {
|
||||
payload.calendar = calendarLayoutSetting;
|
||||
}
|
||||
|
||||
return DatabaseEventSetLayoutSetting(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> closeView() {
|
||||
final request = ViewIdPB(value: viewId);
|
||||
return FolderEventCloseView(request).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<RepeatedGroupPB, FlowyError>> loadGroups() {
|
||||
final payload = DatabaseViewIdPB(value: viewId);
|
||||
return DatabaseEventGetGroups(payload).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/cell_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
|
||||
final class DateCellBackendService {
|
||||
DateCellBackendService({
|
||||
required String viewId,
|
||||
required String fieldId,
|
||||
required String rowId,
|
||||
}) : cellId = CellIdPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId;
|
||||
|
||||
final CellIdPB cellId;
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> update({
|
||||
required bool includeTime,
|
||||
required bool isRange,
|
||||
DateTime? date,
|
||||
String? time,
|
||||
DateTime? endDate,
|
||||
String? endTime,
|
||||
String? reminderId,
|
||||
}) {
|
||||
final payload = DateCellChangesetPB.create()
|
||||
..cellId = cellId
|
||||
..includeTime = includeTime
|
||||
..isRange = isRange;
|
||||
|
||||
if (date != null) {
|
||||
final dateTimestamp = date.millisecondsSinceEpoch ~/ 1000;
|
||||
payload.date = Int64(dateTimestamp);
|
||||
}
|
||||
if (time != null) {
|
||||
payload.time = time;
|
||||
}
|
||||
if (endDate != null) {
|
||||
final dateTimestamp = endDate.millisecondsSinceEpoch ~/ 1000;
|
||||
payload.endDate = Int64(dateTimestamp);
|
||||
}
|
||||
if (endTime != null) {
|
||||
payload.endTime = endTime;
|
||||
}
|
||||
if (reminderId != null) {
|
||||
payload.reminderId = reminderId;
|
||||
}
|
||||
|
||||
return DatabaseEventUpdateDateCell(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> clear() {
|
||||
final payload = DateCellChangesetPB.create()
|
||||
..cellId = cellId
|
||||
..clearFlag = true;
|
||||
|
||||
return DatabaseEventUpdateDateCell(payload).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
import 'package:appflowy/plugins/database/domain/field_service.dart';
|
||||
import 'package:appflowy/plugins/database/domain/field_settings_service.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
|
||||
// This class is used for combining the
|
||||
// 1. FieldBackendService
|
||||
// 2. FieldSettingsBackendService
|
||||
// 3. TypeOptionBackendService
|
||||
//
|
||||
// including,
|
||||
// hide, delete, duplicated,
|
||||
// insertLeft, insertRight,
|
||||
// updateName
|
||||
class FieldServices {
|
||||
FieldServices({
|
||||
required this.viewId,
|
||||
required this.fieldId,
|
||||
}) : fieldBackendService = FieldBackendService(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
),
|
||||
fieldSettingsService = FieldSettingsBackendService(
|
||||
viewId: viewId,
|
||||
);
|
||||
|
||||
final String viewId;
|
||||
final String fieldId;
|
||||
|
||||
final FieldBackendService fieldBackendService;
|
||||
final FieldSettingsBackendService fieldSettingsService;
|
||||
|
||||
Future<void> hide() async {
|
||||
await fieldSettingsService.updateFieldSettings(
|
||||
fieldId: fieldId,
|
||||
fieldVisibility: FieldVisibility.AlwaysHidden,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> show() async {
|
||||
await fieldSettingsService.updateFieldSettings(
|
||||
fieldId: fieldId,
|
||||
fieldVisibility: FieldVisibility.AlwaysShown,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> delete() async {
|
||||
await fieldBackendService.delete();
|
||||
}
|
||||
|
||||
Future<void> duplicate() async {
|
||||
await fieldBackendService.duplicate();
|
||||
}
|
||||
|
||||
Future<void> insertLeft() async {
|
||||
await FieldBackendService.createField(
|
||||
viewId: viewId,
|
||||
position: OrderObjectPositionPB(
|
||||
position: OrderObjectPositionTypePB.Before,
|
||||
objectId: fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> insertRight() async {
|
||||
await FieldBackendService.createField(
|
||||
viewId: viewId,
|
||||
position: OrderObjectPositionPB(
|
||||
position: OrderObjectPositionTypePB.After,
|
||||
objectId: fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateName(String name) async {
|
||||
await fieldBackendService.updateField(
|
||||
name: name,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
typedef UpdateFieldNotifiedValue = FieldPB;
|
||||
|
||||
class SingleFieldListener {
|
||||
SingleFieldListener({required this.fieldId});
|
||||
|
||||
final String fieldId;
|
||||
|
||||
void Function(UpdateFieldNotifiedValue)? _updateFieldNotifier;
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(UpdateFieldNotifiedValue) onFieldChanged,
|
||||
}) {
|
||||
_updateFieldNotifier = onFieldChanged;
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: fieldId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateField:
|
||||
result.fold(
|
||||
(payload) => _updateFieldNotifier?.call(FieldPB.fromBuffer(payload)),
|
||||
(error) => Log.error(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_updateFieldNotifier = null;
|
||||
}
|
||||
}
|
||||
|
||||
typedef UpdateFieldsNotifiedValue
|
||||
= FlowyResult<DatabaseFieldChangesetPB, FlowyError>;
|
||||
|
||||
class FieldsListener {
|
||||
FieldsListener({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
PublishNotifier<UpdateFieldsNotifiedValue>? updateFieldsNotifier =
|
||||
PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(UpdateFieldsNotifiedValue) onFieldsChanged,
|
||||
}) {
|
||||
updateFieldsNotifier?.addPublishListener(onFieldsChanged);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateFields:
|
||||
result.fold(
|
||||
(payload) => updateFieldsNotifier?.value =
|
||||
FlowyResult.success(DatabaseFieldChangesetPB.fromBuffer(payload)),
|
||||
(error) => updateFieldsNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
updateFieldsNotifier?.dispose();
|
||||
updateFieldsNotifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
/// FieldService provides many field-related interfaces event functions. Check out
|
||||
/// `rust-lib/flowy-database/event_map.rs` for a list of events and their
|
||||
/// implementations.
|
||||
class FieldBackendService {
|
||||
FieldBackendService({required this.viewId, required this.fieldId});
|
||||
|
||||
final String viewId;
|
||||
final String fieldId;
|
||||
|
||||
/// Create a field in a database view. The position will only be applicable
|
||||
/// in this view; for other views it will be appended to the end
|
||||
static Future<FlowyResult<FieldPB, FlowyError>> createField({
|
||||
required String viewId,
|
||||
FieldType fieldType = FieldType.RichText,
|
||||
String? fieldName,
|
||||
Uint8List? typeOptionData,
|
||||
OrderObjectPositionPB? position,
|
||||
}) {
|
||||
final payload = CreateFieldPayloadPB(
|
||||
viewId: viewId,
|
||||
fieldType: fieldType,
|
||||
fieldName: fieldName,
|
||||
typeOptionData: typeOptionData,
|
||||
fieldPosition: position,
|
||||
);
|
||||
|
||||
return DatabaseEventCreateField(payload).send();
|
||||
}
|
||||
|
||||
/// Reorder a field within a database view
|
||||
static Future<FlowyResult<void, FlowyError>> moveField({
|
||||
required String viewId,
|
||||
required String fromFieldId,
|
||||
required String toFieldId,
|
||||
}) {
|
||||
final payload = MoveFieldPayloadPB(
|
||||
viewId: viewId,
|
||||
fromFieldId: fromFieldId,
|
||||
toFieldId: toFieldId,
|
||||
);
|
||||
|
||||
return DatabaseEventMoveField(payload).send();
|
||||
}
|
||||
|
||||
/// Delete a field
|
||||
static Future<FlowyResult<void, FlowyError>> deleteField({
|
||||
required String viewId,
|
||||
required String fieldId,
|
||||
}) {
|
||||
final payload = DeleteFieldPayloadPB(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
|
||||
return DatabaseEventDeleteField(payload).send();
|
||||
}
|
||||
|
||||
/// Duplicate a field
|
||||
static Future<FlowyResult<void, FlowyError>> duplicateField({
|
||||
required String viewId,
|
||||
required String fieldId,
|
||||
}) {
|
||||
final payload = DuplicateFieldPayloadPB(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
|
||||
return DatabaseEventDuplicateField(payload).send();
|
||||
}
|
||||
|
||||
/// Update a field's properties
|
||||
Future<FlowyResult<void, FlowyError>> updateField({
|
||||
String? name,
|
||||
bool? frozen,
|
||||
}) {
|
||||
final payload = FieldChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId;
|
||||
|
||||
if (name != null) {
|
||||
payload.name = name;
|
||||
}
|
||||
|
||||
if (frozen != null) {
|
||||
payload.frozen = frozen;
|
||||
}
|
||||
|
||||
return DatabaseEventUpdateField(payload).send();
|
||||
}
|
||||
|
||||
/// Change a field's type
|
||||
static Future<FlowyResult<void, FlowyError>> updateFieldType({
|
||||
required String viewId,
|
||||
required String fieldId,
|
||||
required FieldType fieldType,
|
||||
}) {
|
||||
final payload = UpdateFieldTypePayloadPB()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..fieldType = fieldType;
|
||||
|
||||
return DatabaseEventUpdateFieldType(payload).send();
|
||||
}
|
||||
|
||||
/// Update a field's type option data
|
||||
static Future<FlowyResult<void, FlowyError>> updateFieldTypeOption({
|
||||
required String viewId,
|
||||
required String fieldId,
|
||||
required List<int> typeOptionData,
|
||||
}) {
|
||||
final payload = TypeOptionChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..typeOptionData = typeOptionData;
|
||||
|
||||
return DatabaseEventUpdateFieldTypeOption(payload).send();
|
||||
}
|
||||
|
||||
/// Returns the primary field of the view.
|
||||
static Future<FlowyResult<FieldPB, FlowyError>> getPrimaryField({
|
||||
required String viewId,
|
||||
}) {
|
||||
final payload = DatabaseViewIdPB.create()..value = viewId;
|
||||
return DatabaseEventGetPrimaryField(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<FieldPB, FlowyError>> createBefore({
|
||||
FieldType fieldType = FieldType.RichText,
|
||||
String? fieldName,
|
||||
Uint8List? typeOptionData,
|
||||
}) {
|
||||
return createField(
|
||||
viewId: viewId,
|
||||
fieldType: fieldType,
|
||||
fieldName: fieldName,
|
||||
typeOptionData: typeOptionData,
|
||||
position: OrderObjectPositionPB(
|
||||
position: OrderObjectPositionTypePB.Before,
|
||||
objectId: fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<FieldPB, FlowyError>> createAfter({
|
||||
FieldType fieldType = FieldType.RichText,
|
||||
String? fieldName,
|
||||
Uint8List? typeOptionData,
|
||||
}) {
|
||||
return createField(
|
||||
viewId: viewId,
|
||||
fieldType: fieldType,
|
||||
fieldName: fieldName,
|
||||
typeOptionData: typeOptionData,
|
||||
position: OrderObjectPositionPB(
|
||||
position: OrderObjectPositionTypePB.After,
|
||||
objectId: fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> updateType({
|
||||
required FieldType fieldType,
|
||||
}) =>
|
||||
updateFieldType(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
fieldType: fieldType,
|
||||
);
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> delete() =>
|
||||
deleteField(viewId: viewId, fieldId: fieldId);
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> duplicate() =>
|
||||
duplicateField(viewId: viewId, fieldId: fieldId);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
typedef FieldSettingsValue = FlowyResult<FieldSettingsPB, FlowyError>;
|
||||
|
||||
class FieldSettingsListener {
|
||||
FieldSettingsListener({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
PublishNotifier<FieldSettingsValue>? _fieldSettingsNotifier =
|
||||
PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(FieldSettingsValue) onFieldSettingsChanged,
|
||||
}) {
|
||||
_fieldSettingsNotifier?.addPublishListener(onFieldSettingsChanged);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateFieldSettings:
|
||||
result.fold(
|
||||
(payload) => _fieldSettingsNotifier?.value =
|
||||
FlowyResult.success(FieldSettingsPB.fromBuffer(payload)),
|
||||
(error) => _fieldSettingsNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_fieldSettingsNotifier?.dispose();
|
||||
_fieldSettingsNotifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class FieldSettingsBackendService {
|
||||
FieldSettingsBackendService({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
Future<FlowyResult<FieldSettingsPB, FlowyError>> getFieldSettings(
|
||||
String fieldId,
|
||||
) {
|
||||
final id = FieldIdPB(fieldId: fieldId);
|
||||
final ids = RepeatedFieldIdPB()..items.add(id);
|
||||
final payload = FieldIdsPB()
|
||||
..viewId = viewId
|
||||
..fieldIds = ids;
|
||||
|
||||
return DatabaseEventGetFieldSettings(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(repeatedFieldSettings) {
|
||||
final fieldSetting = repeatedFieldSettings.items.first;
|
||||
if (!fieldSetting.hasVisibility()) {
|
||||
fieldSetting.visibility = FieldVisibility.AlwaysShown;
|
||||
}
|
||||
|
||||
return FlowyResult.success(fieldSetting);
|
||||
},
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<List<FieldSettingsPB>, FlowyError>> getAllFieldSettings() {
|
||||
final payload = DatabaseViewIdPB()..value = viewId;
|
||||
|
||||
return DatabaseEventGetAllFieldSettings(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(repeatedFieldSettings) {
|
||||
final fieldSettings = <FieldSettingsPB>[];
|
||||
|
||||
for (final fieldSetting in repeatedFieldSettings.items) {
|
||||
if (!fieldSetting.hasVisibility()) {
|
||||
fieldSetting.visibility = FieldVisibility.AlwaysShown;
|
||||
}
|
||||
fieldSettings.add(fieldSetting);
|
||||
}
|
||||
|
||||
return FlowyResult.success(fieldSettings);
|
||||
},
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> updateFieldSettings({
|
||||
required String fieldId,
|
||||
FieldVisibility? fieldVisibility,
|
||||
double? width,
|
||||
}) {
|
||||
final FieldSettingsChangesetPB payload = FieldSettingsChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId;
|
||||
|
||||
if (fieldVisibility != null) {
|
||||
payload.visibility = fieldVisibility;
|
||||
}
|
||||
|
||||
if (width != null) {
|
||||
payload.width = width.round();
|
||||
}
|
||||
|
||||
return DatabaseEventUpdateFieldSettings(payload).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/filter_changeset.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
typedef UpdateFilterNotifiedValue
|
||||
= FlowyResult<FilterChangesetNotificationPB, FlowyError>;
|
||||
|
||||
class FiltersListener {
|
||||
FiltersListener({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
PublishNotifier<UpdateFilterNotifiedValue>? _filterNotifier =
|
||||
PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(UpdateFilterNotifiedValue) onFilterChanged,
|
||||
}) {
|
||||
_filterNotifier?.addPublishListener(onFilterChanged);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateFilter:
|
||||
result.fold(
|
||||
(payload) => _filterNotifier?.value = FlowyResult.success(
|
||||
FilterChangesetNotificationPB.fromBuffer(payload),
|
||||
),
|
||||
(error) => _filterNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_filterNotifier?.dispose();
|
||||
_filterNotifier = null;
|
||||
}
|
||||
}
|
||||
|
||||
class FilterListener {
|
||||
FilterListener({required this.viewId, required this.filterId});
|
||||
|
||||
final String viewId;
|
||||
final String filterId;
|
||||
|
||||
PublishNotifier<FilterPB>? _onDeleteNotifier = PublishNotifier();
|
||||
PublishNotifier<FilterPB>? _onUpdateNotifier = PublishNotifier();
|
||||
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
void Function()? onDeleted,
|
||||
void Function(FilterPB)? onUpdated,
|
||||
}) {
|
||||
_onDeleteNotifier?.addPublishListener((_) {
|
||||
onDeleted?.call();
|
||||
});
|
||||
|
||||
_onUpdateNotifier?.addPublishListener((filter) {
|
||||
onUpdated?.call(filter);
|
||||
});
|
||||
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void handleChangeset(FilterChangesetNotificationPB changeset) {
|
||||
// check the delete filter
|
||||
final deletedIndex = changeset.deleteFilters.indexWhere(
|
||||
(element) => element.id == filterId,
|
||||
);
|
||||
if (deletedIndex != -1) {
|
||||
_onDeleteNotifier?.value = changeset.deleteFilters[deletedIndex];
|
||||
}
|
||||
|
||||
// check the updated filter
|
||||
final updatedIndex = changeset.updateFilters.indexWhere(
|
||||
(element) => element.filter.id == filterId,
|
||||
);
|
||||
if (updatedIndex != -1) {
|
||||
_onUpdateNotifier?.value = changeset.updateFilters[updatedIndex].filter;
|
||||
}
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateFilter:
|
||||
result.fold(
|
||||
(payload) => handleChangeset(
|
||||
FilterChangesetNotificationPB.fromBuffer(payload),
|
||||
),
|
||||
(error) {},
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_onDeleteNotifier?.dispose();
|
||||
_onDeleteNotifier = null;
|
||||
|
||||
_onUpdateNotifier?.dispose();
|
||||
_onUpdateNotifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,231 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbserver.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/date_filter.pbserver.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/number_filter.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pbserver.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/text_filter.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||
|
||||
class FilterBackendService {
|
||||
const FilterBackendService({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
Future<FlowyResult<List<FilterPB>, FlowyError>> getAllFilters() {
|
||||
final payload = DatabaseViewIdPB()..value = viewId;
|
||||
|
||||
return DatabaseEventGetAllFilters(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(repeated) => FlowyResult.success(repeated.items),
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertTextFilter({
|
||||
required String fieldId,
|
||||
String? filterId,
|
||||
required TextFilterConditionPB condition,
|
||||
required String content,
|
||||
}) {
|
||||
final filter = TextFilterPB()
|
||||
..condition = condition
|
||||
..content = content;
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: FieldType.RichText,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertCheckboxFilter({
|
||||
required String fieldId,
|
||||
String? filterId,
|
||||
required CheckboxFilterConditionPB condition,
|
||||
}) {
|
||||
final filter = CheckboxFilterPB()..condition = condition;
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: FieldType.Checkbox,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertNumberFilter({
|
||||
required String fieldId,
|
||||
String? filterId,
|
||||
required NumberFilterConditionPB condition,
|
||||
String content = "",
|
||||
}) {
|
||||
final filter = NumberFilterPB()
|
||||
..condition = condition
|
||||
..content = content;
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: FieldType.Number,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertDateFilter({
|
||||
required String fieldId,
|
||||
String? filterId,
|
||||
required DateFilterConditionPB condition,
|
||||
required FieldType fieldType,
|
||||
int? start,
|
||||
int? end,
|
||||
int? timestamp,
|
||||
}) {
|
||||
assert(
|
||||
[
|
||||
FieldType.DateTime,
|
||||
FieldType.LastEditedTime,
|
||||
FieldType.CreatedTime,
|
||||
].contains(fieldType),
|
||||
);
|
||||
|
||||
final filter = DateFilterPB();
|
||||
if (timestamp != null) {
|
||||
filter.timestamp = $fixnum.Int64(timestamp);
|
||||
} else {
|
||||
if (start != null && end != null) {
|
||||
filter.start = $fixnum.Int64(start);
|
||||
filter.end = $fixnum.Int64(end);
|
||||
} else {
|
||||
throw Exception(
|
||||
"Start and end should not be null if the timestamp is null",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: fieldType,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertURLFilter({
|
||||
required String fieldId,
|
||||
String? filterId,
|
||||
required TextFilterConditionPB condition,
|
||||
String content = "",
|
||||
}) {
|
||||
final filter = TextFilterPB()
|
||||
..condition = condition
|
||||
..content = content;
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: FieldType.URL,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertSelectOptionFilter({
|
||||
required String fieldId,
|
||||
required FieldType fieldType,
|
||||
required SelectOptionConditionPB condition,
|
||||
String? filterId,
|
||||
List<String> optionIds = const [],
|
||||
}) {
|
||||
final filter = SelectOptionFilterPB()
|
||||
..condition = condition
|
||||
..optionIds.addAll(optionIds);
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: fieldType,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertChecklistFilter({
|
||||
required String fieldId,
|
||||
required ChecklistFilterConditionPB condition,
|
||||
String? filterId,
|
||||
List<String> optionIds = const [],
|
||||
}) {
|
||||
final filter = ChecklistFilterPB()..condition = condition;
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: FieldType.Checklist,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertFilter({
|
||||
required String fieldId,
|
||||
String? filterId,
|
||||
required FieldType fieldType,
|
||||
required List<int> data,
|
||||
}) {
|
||||
final insertFilterPayload = UpdateFilterPayloadPB.create()
|
||||
..fieldId = fieldId
|
||||
..fieldType = fieldType
|
||||
..viewId = viewId
|
||||
..data = data;
|
||||
|
||||
if (filterId != null) {
|
||||
insertFilterPayload.filterId = filterId;
|
||||
}
|
||||
|
||||
final payload = DatabaseSettingChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..updateFilter = insertFilterPayload;
|
||||
return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l),
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyResult.failure(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> deleteFilter({
|
||||
required String fieldId,
|
||||
required String filterId,
|
||||
required FieldType fieldType,
|
||||
}) {
|
||||
final deleteFilterPayload = DeleteFilterPayloadPB.create()
|
||||
..fieldId = fieldId
|
||||
..filterId = filterId
|
||||
..viewId = viewId
|
||||
..fieldType = fieldType;
|
||||
|
||||
final payload = DatabaseSettingChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..deleteFilter = deleteFilterPayload;
|
||||
|
||||
return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l),
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyResult.failure(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/group_changeset.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
typedef GroupConfigurationUpdateValue
|
||||
= FlowyResult<List<GroupSettingPB>, FlowyError>;
|
||||
typedef GroupUpdateValue = FlowyResult<GroupChangesPB, FlowyError>;
|
||||
typedef GroupByNewFieldValue = FlowyResult<List<GroupPB>, FlowyError>;
|
||||
|
||||
class DatabaseGroupListener {
|
||||
DatabaseGroupListener(this.viewId);
|
||||
|
||||
final String viewId;
|
||||
|
||||
PublishNotifier<GroupUpdateValue>? _numOfGroupsNotifier = PublishNotifier();
|
||||
PublishNotifier<GroupByNewFieldValue>? _groupByFieldNotifier =
|
||||
PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(GroupUpdateValue) onNumOfGroupsChanged,
|
||||
required void Function(GroupByNewFieldValue) onGroupByNewField,
|
||||
}) {
|
||||
_numOfGroupsNotifier?.addPublishListener(onNumOfGroupsChanged);
|
||||
_groupByFieldNotifier?.addPublishListener(onGroupByNewField);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateNumOfGroups:
|
||||
result.fold(
|
||||
(payload) => _numOfGroupsNotifier?.value =
|
||||
FlowyResult.success(GroupChangesPB.fromBuffer(payload)),
|
||||
(error) => _numOfGroupsNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
case DatabaseNotification.DidGroupByField:
|
||||
result.fold(
|
||||
(payload) => _groupByFieldNotifier?.value = FlowyResult.success(
|
||||
GroupChangesPB.fromBuffer(payload).initialGroups,
|
||||
),
|
||||
(error) => _groupByFieldNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_numOfGroupsNotifier?.dispose();
|
||||
_numOfGroupsNotifier = null;
|
||||
|
||||
_groupByFieldNotifier?.dispose();
|
||||
_groupByFieldNotifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class GroupBackendService {
|
||||
GroupBackendService(this.viewId);
|
||||
|
||||
final String viewId;
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> groupByField({
|
||||
required String fieldId,
|
||||
}) {
|
||||
final payload = GroupByFieldPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId;
|
||||
|
||||
return DatabaseEventSetGroupByField(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> updateGroup({
|
||||
required String groupId,
|
||||
required String fieldId,
|
||||
String? name,
|
||||
bool? visible,
|
||||
}) {
|
||||
final payload = UpdateGroupPB.create()
|
||||
..fieldId = fieldId
|
||||
..viewId = viewId
|
||||
..groupId = groupId;
|
||||
|
||||
if (name != null) {
|
||||
payload.name = name;
|
||||
}
|
||||
if (visible != null) {
|
||||
payload.visible = visible;
|
||||
}
|
||||
return DatabaseEventUpdateGroup(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> createGroup({
|
||||
required String name,
|
||||
String groupConfigId = "",
|
||||
}) {
|
||||
final payload = CreateGroupPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..name = name;
|
||||
|
||||
return DatabaseEventCreateGroup(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> deleteGroup({
|
||||
required String groupId,
|
||||
}) {
|
||||
final payload = DeleteGroupPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..groupId = groupId;
|
||||
|
||||
return DatabaseEventDeleteGroup(payload).send();
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
|
||||
ViewLayoutPB viewLayoutFromDatabaseLayout(DatabaseLayoutPB databaseLayout) {
|
||||
switch (databaseLayout) {
|
||||
case DatabaseLayoutPB.Board:
|
||||
return ViewLayoutPB.Board;
|
||||
case DatabaseLayoutPB.Calendar:
|
||||
return ViewLayoutPB.Calendar;
|
||||
case DatabaseLayoutPB.Grid:
|
||||
return ViewLayoutPB.Grid;
|
||||
default:
|
||||
throw UnimplementedError;
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseLayoutPB databaseLayoutFromViewLayout(ViewLayoutPB viewLayout) {
|
||||
switch (viewLayout) {
|
||||
case ViewLayoutPB.Board:
|
||||
return DatabaseLayoutPB.Board;
|
||||
case ViewLayoutPB.Calendar:
|
||||
return DatabaseLayoutPB.Calendar;
|
||||
case ViewLayoutPB.Grid:
|
||||
return DatabaseLayoutPB.Grid;
|
||||
default:
|
||||
throw UnimplementedError;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
typedef LayoutSettingsValue<T> = FlowyResult<T, FlowyError>;
|
||||
|
||||
class DatabaseLayoutSettingListener {
|
||||
DatabaseLayoutSettingListener(this.viewId);
|
||||
|
||||
final String viewId;
|
||||
|
||||
PublishNotifier<LayoutSettingsValue<DatabaseLayoutSettingPB>>?
|
||||
_settingNotifier = PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(LayoutSettingsValue<DatabaseLayoutSettingPB>)
|
||||
onLayoutChanged,
|
||||
}) {
|
||||
_settingNotifier?.addPublishListener(onLayoutChanged);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateLayoutSettings:
|
||||
result.fold(
|
||||
(payload) => _settingNotifier?.value =
|
||||
FlowyResult.success(DatabaseLayoutSettingPB.fromBuffer(payload)),
|
||||
(error) => _settingNotifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_settingNotifier?.dispose();
|
||||
_settingNotifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
typedef DidFetchRowCallback = void Function(DidFetchRowPB);
|
||||
typedef RowMetaCallback = void Function(RowMetaPB);
|
||||
|
||||
class RowListener {
|
||||
RowListener(this.rowId);
|
||||
|
||||
final String rowId;
|
||||
|
||||
DidFetchRowCallback? _onRowFetchedCallback;
|
||||
RowMetaCallback? _onMetaChangedCallback;
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
/// OnMetaChanged will be called when the row meta is changed.
|
||||
/// OnRowFetched will be called when the row is fetched from remote storage
|
||||
void start({
|
||||
RowMetaCallback? onMetaChanged,
|
||||
DidFetchRowCallback? onRowFetched,
|
||||
}) {
|
||||
_onMetaChangedCallback = onMetaChanged;
|
||||
_onRowFetchedCallback = onRowFetched;
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: rowId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateRowMeta:
|
||||
result.fold(
|
||||
(payload) {
|
||||
if (_onMetaChangedCallback != null) {
|
||||
_onMetaChangedCallback!(RowMetaPB.fromBuffer(payload));
|
||||
}
|
||||
},
|
||||
(error) => Log.error(error),
|
||||
);
|
||||
break;
|
||||
case DatabaseNotification.DidFetchRow:
|
||||
result.fold(
|
||||
(payload) {
|
||||
if (_onRowFetchedCallback != null) {
|
||||
_onRowFetchedCallback!(DidFetchRowPB.fromBuffer(payload));
|
||||
}
|
||||
},
|
||||
(error) => Log.error(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_onMetaChangedCallback = null;
|
||||
_onRowFetchedCallback = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
typedef RowMetaCallback = void Function(RowMetaPB);
|
||||
|
||||
class RowMetaListener {
|
||||
RowMetaListener(this.rowId);
|
||||
|
||||
final String rowId;
|
||||
|
||||
RowMetaCallback? _callback;
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({required RowMetaCallback callback}) {
|
||||
_callback = callback;
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: rowId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateRowMeta:
|
||||
result.fold(
|
||||
(payload) {
|
||||
if (_callback != null) {
|
||||
_callback!(RowMetaPB.fromBuffer(payload));
|
||||
}
|
||||
},
|
||||
(error) => Log.error(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_callback = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
import 'type_option_service.dart';
|
||||
|
||||
class SelectOptionCellBackendService {
|
||||
SelectOptionCellBackendService({
|
||||
required this.viewId,
|
||||
required this.fieldId,
|
||||
required this.rowId,
|
||||
});
|
||||
|
||||
final String viewId;
|
||||
final String fieldId;
|
||||
final String rowId;
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> create({
|
||||
required String name,
|
||||
bool isSelected = true,
|
||||
}) {
|
||||
return TypeOptionBackendService(viewId: viewId, fieldId: fieldId)
|
||||
.newOption(name: name)
|
||||
.then(
|
||||
(result) {
|
||||
return result.fold(
|
||||
(option) {
|
||||
final payload = RepeatedSelectOptionPayload()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId
|
||||
..items.add(option);
|
||||
|
||||
return DatabaseEventInsertOrUpdateSelectOption(payload).send();
|
||||
},
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> update({
|
||||
required SelectOptionPB option,
|
||||
}) {
|
||||
final payload = RepeatedSelectOptionPayload()
|
||||
..items.add(option)
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId;
|
||||
|
||||
return DatabaseEventInsertOrUpdateSelectOption(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> delete({
|
||||
required Iterable<SelectOptionPB> options,
|
||||
}) {
|
||||
final payload = RepeatedSelectOptionPayload()
|
||||
..items.addAll(options)
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId;
|
||||
|
||||
return DatabaseEventDeleteSelectOption(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<SelectOptionCellDataPB, FlowyError>> getCellData() {
|
||||
final payload = CellIdPB()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId;
|
||||
|
||||
return DatabaseEventGetSelectOptionCellData(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> select({
|
||||
required Iterable<String> optionIds,
|
||||
}) {
|
||||
final payload = SelectOptionCellChangesetPB()
|
||||
..cellIdentifier = _cellIdentifier()
|
||||
..insertOptionIds.addAll(optionIds);
|
||||
|
||||
return DatabaseEventUpdateSelectOptionCell(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> unSelect({
|
||||
required Iterable<String> optionIds,
|
||||
}) {
|
||||
final payload = SelectOptionCellChangesetPB()
|
||||
..cellIdentifier = _cellIdentifier()
|
||||
..deleteOptionIds.addAll(optionIds);
|
||||
|
||||
return DatabaseEventUpdateSelectOptionCell(payload).send();
|
||||
}
|
||||
|
||||
CellIdPB _cellIdentifier() {
|
||||
return CellIdPB()
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/grid_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
|
||||
typedef SortNotifiedValue
|
||||
= FlowyResult<SortChangesetNotificationPB, FlowyError>;
|
||||
|
||||
class SortsListener {
|
||||
SortsListener({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
PublishNotifier<SortNotifiedValue>? _notifier = PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
|
||||
void start({
|
||||
required void Function(SortNotifiedValue) onSortChanged,
|
||||
}) {
|
||||
_notifier?.addPublishListener(onSortChanged);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateSort:
|
||||
result.fold(
|
||||
(payload) => _notifier?.value = FlowyResult.success(
|
||||
SortChangesetNotificationPB.fromBuffer(payload),
|
||||
),
|
||||
(error) => _notifier?.value = FlowyResult.failure(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_notifier?.dispose();
|
||||
_notifier = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class SortBackendService {
|
||||
SortBackendService({required this.viewId});
|
||||
|
||||
final String viewId;
|
||||
|
||||
Future<FlowyResult<List<SortPB>, FlowyError>> getAllSorts() {
|
||||
final payload = DatabaseViewIdPB()..value = viewId;
|
||||
|
||||
return DatabaseEventGetAllSorts(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(repeated) => FlowyResult.success(repeated.items),
|
||||
(r) => FlowyResult.failure(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> updateSort({
|
||||
required String sortId,
|
||||
required String fieldId,
|
||||
required SortConditionPB condition,
|
||||
}) {
|
||||
final insertSortPayload = UpdateSortPayloadPB.create()
|
||||
..viewId = viewId
|
||||
..sortId = sortId
|
||||
..fieldId = fieldId
|
||||
..condition = condition;
|
||||
|
||||
final payload = DatabaseSettingChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..updateSort = insertSortPayload;
|
||||
return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l),
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyResult.failure(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> insertSort({
|
||||
required String fieldId,
|
||||
required SortConditionPB condition,
|
||||
}) {
|
||||
final insertSortPayload = UpdateSortPayloadPB.create()
|
||||
..fieldId = fieldId
|
||||
..viewId = viewId
|
||||
..condition = condition;
|
||||
|
||||
final payload = DatabaseSettingChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..updateSort = insertSortPayload;
|
||||
return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l),
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyResult.failure(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> reorderSort({
|
||||
required String fromSortId,
|
||||
required String toSortId,
|
||||
}) {
|
||||
final payload = DatabaseSettingChangesetPB()
|
||||
..viewId = viewId
|
||||
..reorderSort = (ReorderSortPayloadPB()
|
||||
..viewId = viewId
|
||||
..fromSortId = fromSortId
|
||||
..toSortId = toSortId);
|
||||
|
||||
return DatabaseEventUpdateDatabaseSetting(payload).send();
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> deleteSort({
|
||||
required String fieldId,
|
||||
required String sortId,
|
||||
}) {
|
||||
final deleteSortPayload = DeleteSortPayloadPB.create()
|
||||
..sortId = sortId
|
||||
..viewId = viewId;
|
||||
|
||||
final payload = DatabaseSettingChangesetPB.create()
|
||||
..viewId = viewId
|
||||
..deleteSort = deleteSortPayload;
|
||||
|
||||
return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l),
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyResult.failure(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<FlowyResult<void, FlowyError>> deleteAllSorts() {
|
||||
final payload = DatabaseViewIdPB(value: viewId);
|
||||
return DatabaseEventDeleteAllSorts(payload).send().then((result) {
|
||||
return result.fold(
|
||||
(l) => FlowyResult.success(l),
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyResult.failure(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class TypeOptionBackendService {
|
||||
TypeOptionBackendService({
|
||||
required this.viewId,
|
||||
required this.fieldId,
|
||||
});
|
||||
|
||||
final String viewId;
|
||||
final String fieldId;
|
||||
|
||||
Future<FlowyResult<SelectOptionPB, FlowyError>> newOption({
|
||||
required String name,
|
||||
}) {
|
||||
final payload = CreateSelectOptionPayloadPB.create()
|
||||
..optionName = name
|
||||
..viewId = viewId
|
||||
..fieldId = fieldId;
|
||||
|
||||
return DatabaseEventCreateSelectOption(payload).send();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user