Browse Source

feat: get all databases (#1983)

Nathan.fooo 2 years ago
parent
commit
ad5213cfad
20 changed files with 234 additions and 189 deletions
  1. 11 11
      frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart
  2. 5 113
      frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart
  3. 121 0
      frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart
  4. 4 4
      frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_controller.dart
  5. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart
  6. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart
  7. 2 2
      frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart
  8. 12 3
      frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart
  9. 2 2
      frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart
  10. 1 1
      frontend/appflowy_flutter/test/bloc_test/board_test/util.dart
  11. 1 1
      frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart
  12. 1 1
      frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart
  13. 3 3
      frontend/rust-lib/flowy-database/src/entities/database_entities.rs
  14. 4 4
      frontend/rust-lib/flowy-database/src/event_handler.rs
  15. 2 1
      frontend/rust-lib/flowy-database/src/event_map.rs
  16. 9 4
      frontend/rust-lib/flowy-database/src/manager.rs
  17. 2 2
      frontend/rust-lib/flowy-database/src/services/database/database_editor.rs
  18. 6 3
      frontend/rust-lib/flowy-database/src/services/persistence/database_ref.rs
  19. 14 14
      frontend/rust-lib/flowy-database/tests/database/database_ref_test/script.rs
  20. 32 18
      frontend/rust-lib/flowy-database/tests/database/database_ref_test/test.rs

+ 11 - 11
frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart

@@ -12,7 +12,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
 import 'package:collection/collection.dart';
 import 'package:collection/collection.dart';
 import 'dart:async';
 import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'package:dartz/dartz.dart';
-import 'database_service.dart';
+import 'database_view_service.dart';
 import 'defines.dart';
 import 'defines.dart';
 import 'layout/layout_setting_listener.dart';
 import 'layout/layout_setting_listener.dart';
 import 'row/row_cache.dart';
 import 'row/row_cache.dart';
@@ -67,7 +67,7 @@ class DatabaseCallbacks {
 
 
 class DatabaseController {
 class DatabaseController {
   final String viewId;
   final String viewId;
-  final DatabaseBackendService _databaseBackendSvc;
+  final DatabaseViewBackendService _databaseViewBackendSvc;
   final FieldController fieldController;
   final FieldController fieldController;
   late DatabaseViewCache _viewCache;
   late DatabaseViewCache _viewCache;
   final LayoutTypePB layoutType;
   final LayoutTypePB layoutType;
@@ -87,7 +87,7 @@ class DatabaseController {
 
 
   DatabaseController({required ViewPB view, required this.layoutType})
   DatabaseController({required ViewPB view, required this.layoutType})
       : viewId = view.id,
       : viewId = view.id,
-        _databaseBackendSvc = DatabaseBackendService(viewId: view.id),
+        _databaseViewBackendSvc = DatabaseViewBackendService(viewId: view.id),
         fieldController = FieldController(viewId: view.id),
         fieldController = FieldController(viewId: view.id),
         groupListener = DatabaseGroupListener(view.id),
         groupListener = DatabaseGroupListener(view.id),
         layoutListener = DatabaseLayoutListener(view.id) {
         layoutListener = DatabaseLayoutListener(view.id) {
@@ -112,7 +112,7 @@ class DatabaseController {
   }
   }
 
 
   Future<Either<Unit, FlowyError>> open() async {
   Future<Either<Unit, FlowyError>> open() async {
-    return _databaseBackendSvc.openGrid().then((result) {
+    return _databaseViewBackendSvc.openGrid().then((result) {
       return result.fold(
       return result.fold(
         (database) async {
         (database) async {
           _databaseCallbacks?.onDatabaseChanged?.call(database);
           _databaseCallbacks?.onDatabaseChanged?.call(database);
@@ -152,7 +152,7 @@ class DatabaseController {
       cellDataByFieldId = rowBuilder.build();
       cellDataByFieldId = rowBuilder.build();
     }
     }
 
 
-    return _databaseBackendSvc.createRow(
+    return _databaseViewBackendSvc.createRow(
       startRowId: startRowId,
       startRowId: startRowId,
       groupId: groupId,
       groupId: groupId,
       cellDataByFieldId: cellDataByFieldId,
       cellDataByFieldId: cellDataByFieldId,
@@ -161,7 +161,7 @@ class DatabaseController {
 
 
   Future<Either<Unit, FlowyError>> moveRow(RowPB fromRow,
   Future<Either<Unit, FlowyError>> moveRow(RowPB fromRow,
       {RowPB? toRow, String? groupId}) {
       {RowPB? toRow, String? groupId}) {
-    return _databaseBackendSvc.moveRow(
+    return _databaseViewBackendSvc.moveRow(
       fromRowId: fromRow.id,
       fromRowId: fromRow.id,
       toGroupId: groupId,
       toGroupId: groupId,
       toRowId: toRow?.id,
       toRowId: toRow?.id,
@@ -170,7 +170,7 @@ class DatabaseController {
 
 
   Future<Either<Unit, FlowyError>> moveGroup(
   Future<Either<Unit, FlowyError>> moveGroup(
       {required String fromGroupId, required String toGroupId}) {
       {required String fromGroupId, required String toGroupId}) {
-    return _databaseBackendSvc.moveGroup(
+    return _databaseViewBackendSvc.moveGroup(
       fromGroupId: fromGroupId,
       fromGroupId: fromGroupId,
       toGroupId: toGroupId,
       toGroupId: toGroupId,
     );
     );
@@ -178,7 +178,7 @@ class DatabaseController {
 
 
   Future<void> updateCalenderLayoutSetting(
   Future<void> updateCalenderLayoutSetting(
       CalendarLayoutSettingsPB layoutSetting) async {
       CalendarLayoutSettingsPB layoutSetting) async {
-    await _databaseBackendSvc
+    await _databaseViewBackendSvc
         .updateLayoutSetting(calendarLayoutSetting: layoutSetting)
         .updateLayoutSetting(calendarLayoutSetting: layoutSetting)
         .then((result) {
         .then((result) {
       result.fold((l) => null, (r) => Log.error(r));
       result.fold((l) => null, (r) => Log.error(r));
@@ -186,13 +186,13 @@ class DatabaseController {
   }
   }
 
 
   Future<void> dispose() async {
   Future<void> dispose() async {
-    await _databaseBackendSvc.closeView();
+    await _databaseViewBackendSvc.closeView();
     await fieldController.dispose();
     await fieldController.dispose();
     await groupListener.stop();
     await groupListener.stop();
   }
   }
 
 
   Future<void> _loadGroups() async {
   Future<void> _loadGroups() async {
-    final result = await _databaseBackendSvc.loadGroups();
+    final result = await _databaseViewBackendSvc.loadGroups();
     return Future(
     return Future(
       () => result.fold(
       () => result.fold(
         (groups) {
         (groups) {
@@ -204,7 +204,7 @@ class DatabaseController {
   }
   }
 
 
   Future<void> _loadLayoutSetting() async {
   Future<void> _loadLayoutSetting() async {
-    _databaseBackendSvc.getLayoutSetting(layoutType).then((result) {
+    _databaseViewBackendSvc.getLayoutSetting(layoutType).then((result) {
       result.fold(
       result.fold(
         (l) {
         (l) {
           _layoutCallbacks?.onLoadLayout(l);
           _layoutCallbacks?.onLoadLayout(l);

+ 5 - 113
frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart

@@ -1,121 +1,13 @@
-import 'package:appflowy_backend/protobuf/flowy-database/calendar_entities.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/database_entities.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/group_changeset.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pb.dart';
-import 'package:dartz/dartz.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
 import 'package:appflowy_backend/dispatch/dispatch.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/database_entities.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/group.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
+import 'package:dartz/dartz.dart';
 
 
 class DatabaseBackendService {
 class DatabaseBackendService {
-  final String viewId;
-  DatabaseBackendService({
-    required this.viewId,
-  });
-
-  Future<Either<DatabasePB, FlowyError>> openGrid() async {
-    await FolderEventSetLatestView(ViewIdPB(value: viewId)).send();
-
-    final payload = DatabaseViewIdPB(value: viewId);
-    return DatabaseEventGetDatabase(payload).send();
-  }
-
-  Future<Either<RowPB, FlowyError>> createRow({
-    String? startRowId,
-    String? groupId,
-    Map<String, String>? cellDataByFieldId,
-  }) {
-    var payload = CreateRowPayloadPB.create()..viewId = viewId;
-    if (startRowId != null) {
-      payload.startRowId = startRowId;
-    }
-
-    if (groupId != null) {
-      payload.groupId = groupId;
-    }
-
-    if (cellDataByFieldId != null && cellDataByFieldId.isNotEmpty) {
-      payload.data = RowDataPB(cellDataByFieldId: cellDataByFieldId);
-    }
-
-    return DatabaseEventCreateRow(payload).send();
-  }
-
-  Future<Either<Unit, FlowyError>> moveRow({
-    required String fromRowId,
-    required String? toGroupId,
-    required String? toRowId,
-  }) {
-    var payload = MoveGroupRowPayloadPB.create()
-      ..viewId = viewId
-      ..fromRowId = fromRowId;
-    if (toGroupId != null) {
-      payload.toGroupId = toGroupId;
-    }
-
-    if (toRowId != null) {
-      payload.toRowId = toRowId;
-    }
-
-    return DatabaseEventMoveGroupRow(payload).send();
-  }
-
-  Future<Either<Unit, FlowyError>> moveGroup({
-    required String fromGroupId,
-    required String toGroupId,
-  }) {
-    final payload = MoveGroupPayloadPB.create()
-      ..viewId = viewId
-      ..fromGroupId = fromGroupId
-      ..toGroupId = toGroupId;
-
-    return DatabaseEventMoveGroup(payload).send();
-  }
-
-  Future<Either<List<FieldPB>, FlowyError>> getFields(
-      {List<FieldIdPB>? fieldIds}) {
-    var payload = GetFieldPayloadPB.create()..viewId = viewId;
-
-    if (fieldIds != null) {
-      payload.fieldIds = RepeatedFieldIdPB(items: fieldIds);
-    }
-    return DatabaseEventGetFields(payload).send().then((result) {
+  static Future<Either<List<DatabaseDescriptionPB>, FlowyError>>
+      getAllDatabase() {
+    return DatabaseEventGetDatabases().send().then((result) {
       return result.fold((l) => left(l.items), (r) => right(r));
       return result.fold((l) => left(l.items), (r) => right(r));
     });
     });
   }
   }
-
-  Future<Either<LayoutSettingPB, FlowyError>> getLayoutSetting(
-      LayoutTypePB layoutType) {
-    final payload = DatabaseLayoutIdPB.create()
-      ..viewId = viewId
-      ..layout = layoutType;
-    return DatabaseEventGetLayoutSetting(payload).send();
-  }
-
-  Future<Either<Unit, FlowyError>> updateLayoutSetting(
-      {CalendarLayoutSettingsPB? calendarLayoutSetting}) {
-    final layoutSetting = LayoutSettingPB.create();
-    if (calendarLayoutSetting != null) {
-      layoutSetting.calendar = calendarLayoutSetting;
-    }
-
-    final payload = UpdateLayoutSettingPB.create()
-      ..viewId = viewId
-      ..layoutSetting = layoutSetting;
-
-    return DatabaseEventSetLayoutSetting(payload).send();
-  }
-
-  Future<Either<Unit, FlowyError>> closeView() {
-    final request = ViewIdPB(value: viewId);
-    return FolderEventCloseView(request).send();
-  }
-
-  Future<Either<RepeatedGroupPB, FlowyError>> loadGroups() {
-    final payload = DatabaseViewIdPB(value: viewId);
-    return DatabaseEventGetGroups(payload).send();
-  }
 }
 }

+ 121 - 0
frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart

@@ -0,0 +1,121 @@
+import 'package:appflowy_backend/protobuf/flowy-database/calendar_entities.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/database_entities.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/group_changeset.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pb.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-folder/view.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/group.pb.dart';
+import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
+
+class DatabaseViewBackendService {
+  final String viewId;
+  DatabaseViewBackendService({
+    required this.viewId,
+  });
+
+  Future<Either<DatabasePB, FlowyError>> openGrid() async {
+    await FolderEventSetLatestView(ViewIdPB(value: viewId)).send();
+
+    final payload = DatabaseViewIdPB(value: viewId);
+    return DatabaseEventGetDatabase(payload).send();
+  }
+
+  Future<Either<RowPB, FlowyError>> createRow({
+    String? startRowId,
+    String? groupId,
+    Map<String, String>? cellDataByFieldId,
+  }) {
+    var payload = CreateRowPayloadPB.create()..viewId = viewId;
+    if (startRowId != null) {
+      payload.startRowId = startRowId;
+    }
+
+    if (groupId != null) {
+      payload.groupId = groupId;
+    }
+
+    if (cellDataByFieldId != null && cellDataByFieldId.isNotEmpty) {
+      payload.data = RowDataPB(cellDataByFieldId: cellDataByFieldId);
+    }
+
+    return DatabaseEventCreateRow(payload).send();
+  }
+
+  Future<Either<Unit, FlowyError>> moveRow({
+    required String fromRowId,
+    required String? toGroupId,
+    required String? toRowId,
+  }) {
+    var payload = MoveGroupRowPayloadPB.create()
+      ..viewId = viewId
+      ..fromRowId = fromRowId;
+    if (toGroupId != null) {
+      payload.toGroupId = toGroupId;
+    }
+
+    if (toRowId != null) {
+      payload.toRowId = toRowId;
+    }
+
+    return DatabaseEventMoveGroupRow(payload).send();
+  }
+
+  Future<Either<Unit, FlowyError>> moveGroup({
+    required String fromGroupId,
+    required String toGroupId,
+  }) {
+    final payload = MoveGroupPayloadPB.create()
+      ..viewId = viewId
+      ..fromGroupId = fromGroupId
+      ..toGroupId = toGroupId;
+
+    return DatabaseEventMoveGroup(payload).send();
+  }
+
+  Future<Either<List<FieldPB>, FlowyError>> getFields(
+      {List<FieldIdPB>? fieldIds}) {
+    var payload = GetFieldPayloadPB.create()..viewId = viewId;
+
+    if (fieldIds != null) {
+      payload.fieldIds = RepeatedFieldIdPB(items: fieldIds);
+    }
+    return DatabaseEventGetFields(payload).send().then((result) {
+      return result.fold((l) => left(l.items), (r) => right(r));
+    });
+  }
+
+  Future<Either<LayoutSettingPB, FlowyError>> getLayoutSetting(
+      LayoutTypePB layoutType) {
+    final payload = DatabaseLayoutIdPB.create()
+      ..viewId = viewId
+      ..layout = layoutType;
+    return DatabaseEventGetLayoutSetting(payload).send();
+  }
+
+  Future<Either<Unit, FlowyError>> updateLayoutSetting(
+      {CalendarLayoutSettingsPB? calendarLayoutSetting}) {
+    final layoutSetting = LayoutSettingPB.create();
+    if (calendarLayoutSetting != null) {
+      layoutSetting.calendar = calendarLayoutSetting;
+    }
+
+    final payload = UpdateLayoutSettingPB.create()
+      ..viewId = viewId
+      ..layoutSetting = layoutSetting;
+
+    return DatabaseEventSetLayoutSetting(payload).send();
+  }
+
+  Future<Either<Unit, FlowyError>> closeView() {
+    final request = ViewIdPB(value: viewId);
+    return FolderEventCloseView(request).send();
+  }
+
+  Future<Either<RepeatedGroupPB, FlowyError>> loadGroups() {
+    final payload = DatabaseViewIdPB(value: viewId);
+    return DatabaseEventGetGroups(payload).send();
+  }
+}

+ 4 - 4
frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_controller.dart

@@ -11,7 +11,7 @@ import 'package:appflowy_backend/protobuf/flowy-database/util.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/foundation.dart';
 import '../../grid/presentation/widgets/filter/filter_info.dart';
 import '../../grid/presentation/widgets/filter/filter_info.dart';
 import '../../grid/presentation/widgets/sort/sort_info.dart';
 import '../../grid/presentation/widgets/sort/sort_info.dart';
-import '../database_service.dart';
+import '../database_view_service.dart';
 import '../filter/filter_listener.dart';
 import '../filter/filter_listener.dart';
 import '../filter/filter_service.dart';
 import '../filter/filter_service.dart';
 import '../row/row_cache.dart';
 import '../row/row_cache.dart';
@@ -80,7 +80,7 @@ class FieldController {
   final SortsListener _sortsListener;
   final SortsListener _sortsListener;
 
 
   // FFI services
   // FFI services
-  final DatabaseBackendService _databaseBackendSvc;
+  final DatabaseViewBackendService _databaseViewBackendSvc;
   final SettingBackendService _settingBackendSvc;
   final SettingBackendService _settingBackendSvc;
   final FilterBackendService _filterBackendSvc;
   final FilterBackendService _filterBackendSvc;
   final SortBackendService _sortBackendSvc;
   final SortBackendService _sortBackendSvc;
@@ -152,7 +152,7 @@ class FieldController {
         _settingListener = DatabaseSettingListener(viewId: viewId),
         _settingListener = DatabaseSettingListener(viewId: viewId),
         _filterBackendSvc = FilterBackendService(viewId: viewId),
         _filterBackendSvc = FilterBackendService(viewId: viewId),
         _filtersListener = FiltersListener(viewId: viewId),
         _filtersListener = FiltersListener(viewId: viewId),
-        _databaseBackendSvc = DatabaseBackendService(viewId: viewId),
+        _databaseViewBackendSvc = DatabaseViewBackendService(viewId: viewId),
         _sortBackendSvc = SortBackendService(viewId: viewId),
         _sortBackendSvc = SortBackendService(viewId: viewId),
         _sortsListener = SortsListener(viewId: viewId),
         _sortsListener = SortsListener(viewId: viewId),
         _settingBackendSvc = SettingBackendService(viewId: viewId) {
         _settingBackendSvc = SettingBackendService(viewId: viewId) {
@@ -448,7 +448,7 @@ class FieldController {
   Future<Either<Unit, FlowyError>> loadFields({
   Future<Either<Unit, FlowyError>> loadFields({
     required List<FieldIdPB> fieldIds,
     required List<FieldIdPB> fieldIds,
   }) async {
   }) async {
-    final result = await _databaseBackendSvc.getFields(fieldIds: fieldIds);
+    final result = await _databaseViewBackendSvc.getFields(fieldIds: fieldIds);
     return Future(
     return Future(
       () => result.fold(
       () => result.fold(
         (newFields) {
         (newFields) {

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart

@@ -59,7 +59,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
           child: CircularProgressIndicator(),
           child: CircularProgressIndicator(),
         );
         );
       },
       },
-      future: AppService().getView(appID, gridID),
+      future: AppBackendService().getView(appID, gridID),
     );
     );
   }
   }
 
 

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart

@@ -169,7 +169,7 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> {
           );
           );
         }
         }
       },
       },
-      future: AppService().fetchViews(widget.layoutType),
+      future: AppBackendService().fetchViews(widget.layoutType),
     );
     );
   }
   }
 
 

+ 2 - 2
frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart

@@ -18,11 +18,11 @@ import 'package:dartz/dartz.dart';
 part 'app_bloc.freezed.dart';
 part 'app_bloc.freezed.dart';
 
 
 class AppBloc extends Bloc<AppEvent, AppState> {
 class AppBloc extends Bloc<AppEvent, AppState> {
-  final AppService appService;
+  final AppBackendService appService;
   final AppListener appListener;
   final AppListener appListener;
 
 
   AppBloc({required AppPB app})
   AppBloc({required AppPB app})
-      : appService = AppService(),
+      : appService = AppBackendService(),
         appListener = AppListener(appId: app.id),
         appListener = AppListener(appId: app.id),
         super(AppState.initial(app)) {
         super(AppState.initial(app)) {
     on<AppEvent>((event, emit) async {
     on<AppEvent>((event, emit) async {

+ 12 - 3
frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart

@@ -8,7 +8,7 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
 
 
-class AppService {
+class AppBackendService {
   Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
   Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
     final payload = AppIdPB.create()..value = appId;
     final payload = AppIdPB.create()..value = appId;
 
 
@@ -21,9 +21,18 @@ class AppService {
     String? desc,
     String? desc,
     required ViewLayoutTypePB layoutType,
     required ViewLayoutTypePB layoutType,
 
 
-    /// The initial data should be the JSON of the doucment
-    /// For example: {"document":{"type":"editor","children":[]}}
+    /// The initial data should be the JSON of the document.
+    /// Currently, only support create document with initial data.
+    ///
+    /// The initial data must be follow this format as shown below.
+    ///  {"document":{"type":"editor","children":[]}}
     String? initialData,
     String? initialData,
+
+    /// The [ext] is used to pass through the custom configuration
+    /// to the backend.
+    /// Linking the view to the existing database, it needs to pass
+    /// the database id. For example: "database_id": "xxx"
+    ///
     Map<String, String> ext = const {},
     Map<String, String> ext = const {},
   }) {
   }) {
     final payload = CreateViewPayloadPB.create()
     final payload = CreateViewPayloadPB.create()

+ 2 - 2
frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart

@@ -13,11 +13,11 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
   void Function()? _viewsListener;
   void Function()? _viewsListener;
   void Function()? _selectedViewlistener;
   void Function()? _selectedViewlistener;
   final AppViewDataContext _appViewData;
   final AppViewDataContext _appViewData;
-  late final AppService _appService;
+  late final AppBackendService _appService;
 
 
   ViewSectionBloc({
   ViewSectionBloc({
     required AppViewDataContext appViewData,
     required AppViewDataContext appViewData,
-  })  : _appService = AppService(),
+  })  : _appService = AppBackendService(),
         _appViewData = appViewData,
         _appViewData = appViewData,
         super(ViewSectionState.initial(appViewData)) {
         super(ViewSectionState.initial(appViewData)) {
     on<ViewSectionEvent>((event, emit) async {
     on<ViewSectionEvent>((event, emit) async {

+ 1 - 1
frontend/appflowy_flutter/test/bloc_test/board_test/util.dart

@@ -30,7 +30,7 @@ class AppFlowyBoardTest {
   Future<BoardTestContext> createTestBoard() async {
   Future<BoardTestContext> createTestBoard() async {
     final app = await unitTest.createTestApp();
     final app = await unitTest.createTestApp();
     final builder = BoardPluginBuilder();
     final builder = BoardPluginBuilder();
-    return AppService()
+    return AppBackendService()
         .createView(
         .createView(
       appId: app.id,
       appId: app.id,
       name: "Test Board",
       name: "Test Board",

+ 1 - 1
frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart

@@ -8,7 +8,7 @@ import '../util.dart';
 Future<GridTestContext> createTestFilterGrid(AppFlowyGridTest gridTest) async {
 Future<GridTestContext> createTestFilterGrid(AppFlowyGridTest gridTest) async {
   final app = await gridTest.unitTest.createTestApp();
   final app = await gridTest.unitTest.createTestApp();
   final builder = GridPluginBuilder();
   final builder = GridPluginBuilder();
-  final context = await AppService()
+  final context = await AppBackendService()
       .createView(
       .createView(
     appId: app.id,
     appId: app.id,
     name: "Filter Grid",
     name: "Filter Grid",

+ 1 - 1
frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart

@@ -165,7 +165,7 @@ class AppFlowyGridTest {
   Future<GridTestContext> createTestGrid() async {
   Future<GridTestContext> createTestGrid() async {
     final app = await unitTest.createTestApp();
     final app = await unitTest.createTestApp();
     final builder = GridPluginBuilder();
     final builder = GridPluginBuilder();
-    final context = await AppService()
+    final context = await AppBackendService()
         .createView(
         .createView(
       appId: app.id,
       appId: app.id,
       name: "Test Grid",
       name: "Test Grid",

+ 3 - 3
frontend/rust-lib/flowy-database/src/entities/database_entities.rs

@@ -155,7 +155,7 @@ impl TryInto<MoveGroupRowParams> for MoveGroupRowPayloadPB {
 }
 }
 
 
 #[derive(Debug, Default, ProtoBuf)]
 #[derive(Debug, Default, ProtoBuf)]
-pub struct DatabaseDescPB {
+pub struct DatabaseDescriptionPB {
   #[pb(index = 1)]
   #[pb(index = 1)]
   pub name: String,
   pub name: String,
 
 
@@ -164,9 +164,9 @@ pub struct DatabaseDescPB {
 }
 }
 
 
 #[derive(Debug, Default, ProtoBuf)]
 #[derive(Debug, Default, ProtoBuf)]
-pub struct RepeatedDatabaseDescPB {
+pub struct RepeatedDatabaseDescriptionPB {
   #[pb(index = 1)]
   #[pb(index = 1)]
-  pub items: Vec<DatabaseDescPB>,
+  pub items: Vec<DatabaseDescriptionPB>,
 }
 }
 
 
 #[derive(Debug, Clone, Default, ProtoBuf)]
 #[derive(Debug, Clone, Default, ProtoBuf)]

+ 4 - 4
frontend/rust-lib/flowy-database/src/event_handler.rs

@@ -575,17 +575,17 @@ pub(crate) async fn move_group_row_handler(
 #[tracing::instrument(level = "debug", skip(manager), err)]
 #[tracing::instrument(level = "debug", skip(manager), err)]
 pub(crate) async fn get_databases_handler(
 pub(crate) async fn get_databases_handler(
   manager: AFPluginState<Arc<DatabaseManager>>,
   manager: AFPluginState<Arc<DatabaseManager>>,
-) -> DataResult<RepeatedDatabaseDescPB, FlowyError> {
+) -> DataResult<RepeatedDatabaseDescriptionPB, FlowyError> {
   let items = manager
   let items = manager
     .get_databases()
     .get_databases()
     .await?
     .await?
     .into_iter()
     .into_iter()
-    .map(|database_info| DatabaseDescPB {
+    .map(|database_info| DatabaseDescriptionPB {
       name: database_info.name,
       name: database_info.name,
       database_id: database_info.database_id,
       database_id: database_info.database_id,
     })
     })
-    .collect::<Vec<DatabaseDescPB>>();
-  data_result_ok(RepeatedDatabaseDescPB { items })
+    .collect::<Vec<DatabaseDescriptionPB>>();
+  data_result_ok(RepeatedDatabaseDescriptionPB { items })
 }
 }
 
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 #[tracing::instrument(level = "debug", skip(data, manager), err)]

+ 2 - 1
frontend/rust-lib/flowy-database/src/event_map.rs

@@ -238,7 +238,8 @@ pub enum DatabaseEvent {
   #[event(input = "MoveGroupRowPayloadPB")]
   #[event(input = "MoveGroupRowPayloadPB")]
   GroupByField = 113,
   GroupByField = 113,
 
 
-  #[event(output = "RepeatedDatabaseDescPB")]
+  /// Returns all the databases
+  #[event(output = "RepeatedDatabaseDescriptionPB")]
   GetDatabases = 114,
   GetDatabases = 114,
 
 
   #[event(input = "UpdateLayoutSettingPB")]
   #[event(input = "UpdateLayoutSettingPB")]

+ 9 - 4
frontend/rust-lib/flowy-database/src/manager.rs

@@ -7,7 +7,9 @@ use crate::services::database_view::{
   make_database_view_rev_manager, make_database_view_revision_pad, DatabaseViewEditor,
   make_database_view_rev_manager, make_database_view_revision_pad, DatabaseViewEditor,
 };
 };
 use crate::services::persistence::block_index::BlockRowIndexer;
 use crate::services::persistence::block_index::BlockRowIndexer;
-use crate::services::persistence::database_ref::{DatabaseInfo, DatabaseRef, DatabaseRefIndexer};
+use crate::services::persistence::database_ref::{
+  DatabaseInfo, DatabaseRefIndexer, DatabaseViewRef,
+};
 use crate::services::persistence::kv::DatabaseKVPersistence;
 use crate::services::persistence::kv::DatabaseKVPersistence;
 use crate::services::persistence::migration::DatabaseMigration;
 use crate::services::persistence::migration::DatabaseMigration;
 use crate::services::persistence::rev_sqlite::{
 use crate::services::persistence::rev_sqlite::{
@@ -192,7 +194,10 @@ impl DatabaseManager {
     self.database_ref_indexer.get_all_databases()
     self.database_ref_indexer.get_all_databases()
   }
   }
 
 
-  pub async fn get_database_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseRef>> {
+  pub async fn get_database_ref_views(
+    &self,
+    database_id: &str,
+  ) -> FlowyResult<Vec<DatabaseViewRef>> {
     self
     self
       .database_ref_indexer
       .database_ref_indexer
       .get_ref_views_with_database(database_id)
       .get_ref_views_with_database(database_id)
@@ -425,13 +430,13 @@ pub async fn create_new_database(
 }
 }
 
 
 impl DatabaseRefIndexerQuery for DatabaseRefIndexer {
 impl DatabaseRefIndexerQuery for DatabaseRefIndexer {
-  fn get_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseRef>> {
+  fn get_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseViewRef>> {
     self.get_ref_views_with_database(database_id)
     self.get_ref_views_with_database(database_id)
   }
   }
 }
 }
 
 
 impl DatabaseRefIndexerQuery for Arc<DatabaseRefIndexer> {
 impl DatabaseRefIndexerQuery for Arc<DatabaseRefIndexer> {
-  fn get_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseRef>> {
+  fn get_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseViewRef>> {
     (**self).get_ref_views(database_id)
     (**self).get_ref_views(database_id)
   }
   }
 }
 }

+ 2 - 2
frontend/rust-lib/flowy-database/src/services/database/database_editor.rs

@@ -18,7 +18,7 @@ use crate::services::database_view::{
 };
 };
 use crate::services::filter::FilterType;
 use crate::services::filter::FilterType;
 use crate::services::persistence::block_index::BlockRowIndexer;
 use crate::services::persistence::block_index::BlockRowIndexer;
-use crate::services::persistence::database_ref::DatabaseRef;
+use crate::services::persistence::database_ref::DatabaseViewRef;
 use crate::services::row::{DatabaseBlockRow, DatabaseBlockRowRevision, RowRevisionBuilder};
 use crate::services::row::{DatabaseBlockRow, DatabaseBlockRowRevision, RowRevisionBuilder};
 use bytes::Bytes;
 use bytes::Bytes;
 use database_model::*;
 use database_model::*;
@@ -42,7 +42,7 @@ use std::sync::Arc;
 use tokio::sync::{broadcast, RwLock};
 use tokio::sync::{broadcast, RwLock};
 
 
 pub trait DatabaseRefIndexerQuery: Send + Sync + 'static {
 pub trait DatabaseRefIndexerQuery: Send + Sync + 'static {
-  fn get_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseRef>>;
+  fn get_ref_views(&self, database_id: &str) -> FlowyResult<Vec<DatabaseViewRef>>;
 }
 }
 
 
 pub struct DatabaseEditor {
 pub struct DatabaseEditor {

+ 6 - 3
frontend/rust-lib/flowy-database/src/services/persistence/database_ref.rs

@@ -45,7 +45,10 @@ impl DatabaseRefIndexer {
     Ok(())
     Ok(())
   }
   }
 
 
-  pub fn get_ref_views_with_database(&self, database_id: &str) -> FlowyResult<Vec<DatabaseRef>> {
+  pub fn get_ref_views_with_database(
+    &self,
+    database_id: &str,
+  ) -> FlowyResult<Vec<DatabaseViewRef>> {
     let conn = self.database.get_db_connection()?;
     let conn = self.database.get_db_connection()?;
     let views = dsl::database_refs
     let views = dsl::database_refs
       .filter(database_refs::database_id.like(database_id))
       .filter(database_refs::database_id.like(database_id))
@@ -93,12 +96,12 @@ struct DatabaseRefRecord {
   database_id: String,
   database_id: String,
 }
 }
 
 
-pub struct DatabaseRef {
+pub struct DatabaseViewRef {
   pub view_id: String,
   pub view_id: String,
   pub name: String,
   pub name: String,
   pub database_id: String,
   pub database_id: String,
 }
 }
-impl std::convert::From<DatabaseRefRecord> for DatabaseRef {
+impl std::convert::From<DatabaseRefRecord> for DatabaseViewRef {
   fn from(record: DatabaseRefRecord) -> Self {
   fn from(record: DatabaseRefRecord) -> Self {
     Self {
     Self {
       view_id: record.view_id,
       view_id: record.view_id,

+ 14 - 14
frontend/rust-lib/flowy-database/tests/database/database_ref_test/script.rs

@@ -2,12 +2,12 @@ use crate::database::block_test::util::DatabaseRowTestBuilder;
 use crate::database::database_editor::DatabaseEditorTest;
 use crate::database::database_editor::DatabaseEditorTest;
 use database_model::RowRevision;
 use database_model::RowRevision;
 use flowy_database::services::database::DatabaseEditor;
 use flowy_database::services::database::DatabaseEditor;
-use flowy_database::services::persistence::database_ref::{DatabaseInfo, DatabaseRef};
+use flowy_database::services::persistence::database_ref::{DatabaseInfo, DatabaseViewRef};
 use std::collections::HashMap;
 use std::collections::HashMap;
 use std::sync::Arc;
 use std::sync::Arc;
 
 
-pub enum DatabaseRefScript {
-  LinkGridToDatabase {
+pub enum LinkDatabaseTestScript {
+  CreateGridViewAndLinkToDatabase {
     database_id: String,
     database_id: String,
   },
   },
   #[allow(dead_code)]
   #[allow(dead_code)]
@@ -28,17 +28,17 @@ pub enum DatabaseRefScript {
   },
   },
 }
 }
 
 
-pub struct DatabaseRefTest {
+pub struct LinkDatabaseTest {
   inner: DatabaseEditorTest,
   inner: DatabaseEditorTest,
 }
 }
 
 
-impl DatabaseRefTest {
+impl LinkDatabaseTest {
   pub async fn new() -> Self {
   pub async fn new() -> Self {
     let inner = DatabaseEditorTest::new_grid().await;
     let inner = DatabaseEditorTest::new_grid().await;
     Self { inner }
     Self { inner }
   }
   }
 
 
-  pub async fn run_scripts(&mut self, scripts: Vec<DatabaseRefScript>) {
+  pub async fn run_scripts(&mut self, scripts: Vec<LinkDatabaseTestScript>) {
     for script in scripts {
     for script in scripts {
       self.run_script(script).await;
       self.run_script(script).await;
     }
     }
@@ -61,7 +61,7 @@ impl DatabaseRefTest {
       .unwrap()
       .unwrap()
   }
   }
 
 
-  pub async fn all_database_ref_views(&self, database_id: &str) -> Vec<DatabaseRef> {
+  pub async fn all_database_ref_views(&self, database_id: &str) -> Vec<DatabaseViewRef> {
     self
     self
       .inner
       .inner
       .sdk
       .sdk
@@ -87,9 +87,9 @@ impl DatabaseRefTest {
     DatabaseRowTestBuilder::new(self.block_id(view_id).await, field_revs)
     DatabaseRowTestBuilder::new(self.block_id(view_id).await, field_revs)
   }
   }
 
 
-  pub async fn run_script(&mut self, script: DatabaseRefScript) {
+  pub async fn run_script(&mut self, script: LinkDatabaseTestScript) {
     match script {
     match script {
-      DatabaseRefScript::LinkGridToDatabase { database_id } => {
+      LinkDatabaseTestScript::CreateGridViewAndLinkToDatabase { database_id } => {
         let mut ext = HashMap::new();
         let mut ext = HashMap::new();
         ext.insert("database_id".to_owned(), database_id);
         ext.insert("database_id".to_owned(), database_id);
         self
         self
@@ -99,7 +99,7 @@ impl DatabaseRefTest {
           .create_test_grid_view(&self.inner.app_id, "test link grid", ext)
           .create_test_grid_view(&self.inner.app_id, "test link grid", ext)
           .await;
           .await;
       },
       },
-      DatabaseRefScript::LinkBoardToDatabase { database_id } => {
+      LinkDatabaseTestScript::LinkBoardToDatabase { database_id } => {
         let mut ext = HashMap::new();
         let mut ext = HashMap::new();
         ext.insert("database_id".to_owned(), database_id);
         ext.insert("database_id".to_owned(), database_id);
         self
         self
@@ -109,7 +109,7 @@ impl DatabaseRefTest {
           .create_test_board_view(&self.inner.app_id, "test link board", ext)
           .create_test_board_view(&self.inner.app_id, "test link board", ext)
           .await;
           .await;
       },
       },
-      DatabaseRefScript::CreateNewGrid => {
+      LinkDatabaseTestScript::CreateNewGrid => {
         self
         self
           .inner
           .inner
           .sdk
           .sdk
@@ -117,15 +117,15 @@ impl DatabaseRefTest {
           .create_test_grid_view(&self.inner.app_id, "Create test grid", HashMap::new())
           .create_test_grid_view(&self.inner.app_id, "Create test grid", HashMap::new())
           .await;
           .await;
       },
       },
-      DatabaseRefScript::AssertNumberOfDatabase { expected } => {
+      LinkDatabaseTestScript::AssertNumberOfDatabase { expected } => {
         let databases = self.all_databases().await;
         let databases = self.all_databases().await;
         assert_eq!(databases.len(), expected);
         assert_eq!(databases.len(), expected);
       },
       },
-      DatabaseRefScript::CreateRow { view_id, row_rev } => {
+      LinkDatabaseTestScript::CreateRow { view_id, row_rev } => {
         let editor = self.get_database_editor(&view_id).await;
         let editor = self.get_database_editor(&view_id).await;
         let _ = editor.insert_rows(vec![row_rev]).await.unwrap();
         let _ = editor.insert_rows(vec![row_rev]).await.unwrap();
       },
       },
-      DatabaseRefScript::AssertNumberOfRows { view_id, expected } => {
+      LinkDatabaseTestScript::AssertNumberOfRows { view_id, expected } => {
         let editor = self.get_database_editor(&view_id).await;
         let editor = self.get_database_editor(&view_id).await;
         let rows = editor.get_all_row_revs(&view_id).await.unwrap();
         let rows = editor.get_all_row_revs(&view_id).await.unwrap();
         assert_eq!(rows.len(), expected);
         assert_eq!(rows.len(), expected);

+ 32 - 18
frontend/rust-lib/flowy-database/tests/database/database_ref_test/test.rs

@@ -1,11 +1,12 @@
-use crate::database::database_ref_test::script::DatabaseRefScript::*;
-use crate::database::database_ref_test::script::DatabaseRefTest;
+use crate::database::database_ref_test::script::LinkDatabaseTest;
+use crate::database::database_ref_test::script::LinkDatabaseTestScript::*;
 
 
 #[tokio::test]
 #[tokio::test]
-async fn database_ref_number_of_database_test() {
-  let mut test = DatabaseRefTest::new().await;
+async fn number_of_database_test() {
+  let mut test = LinkDatabaseTest::new().await;
   test
   test
     .run_scripts(vec![
     .run_scripts(vec![
+      // After the LinkDatabaseTest initialize, it will create a grid.
       AssertNumberOfDatabase { expected: 1 },
       AssertNumberOfDatabase { expected: 1 },
       CreateNewGrid,
       CreateNewGrid,
       AssertNumberOfDatabase { expected: 2 },
       AssertNumberOfDatabase { expected: 2 },
@@ -14,12 +15,12 @@ async fn database_ref_number_of_database_test() {
 }
 }
 
 
 #[tokio::test]
 #[tokio::test]
-async fn database_ref_link_with_existing_database_test() {
-  let mut test = DatabaseRefTest::new().await;
+async fn database_view_link_with_existing_database_test() {
+  let mut test = LinkDatabaseTest::new().await;
   let database = test.all_databases().await.pop().unwrap();
   let database = test.all_databases().await.pop().unwrap();
   test
   test
     .run_scripts(vec![
     .run_scripts(vec![
-      LinkGridToDatabase {
+      CreateGridViewAndLinkToDatabase {
         database_id: database.database_id,
         database_id: database.database_id,
       },
       },
       AssertNumberOfDatabase { expected: 1 },
       AssertNumberOfDatabase { expected: 1 },
@@ -28,36 +29,48 @@ async fn database_ref_link_with_existing_database_test() {
 }
 }
 
 
 #[tokio::test]
 #[tokio::test]
-async fn database_ref_link_with_existing_database_row_test() {
-  let mut test = DatabaseRefTest::new().await;
+async fn check_number_of_rows_in_linked_database_view() {
+  let mut test = LinkDatabaseTest::new().await;
   let database = test.all_databases().await.pop().unwrap();
   let database = test.all_databases().await.pop().unwrap();
+  let view = test
+    .all_database_ref_views(&database.database_id)
+    .await
+    .remove(0);
+
   test
   test
     .run_scripts(vec![
     .run_scripts(vec![
-      LinkGridToDatabase {
+      CreateGridViewAndLinkToDatabase {
         database_id: database.database_id,
         database_id: database.database_id,
       },
       },
-      AssertNumberOfDatabase { expected: 1 },
+      // The initial number of rows is 6
+      AssertNumberOfRows {
+        view_id: view.view_id.clone(),
+        expected: 6,
+      },
     ])
     ])
     .await;
     .await;
 }
 }
 
 
 #[tokio::test]
 #[tokio::test]
-async fn database_ref_create_new_row_test() {
-  let mut test = DatabaseRefTest::new().await;
+async fn multiple_views_share_database_rows() {
+  let mut test = LinkDatabaseTest::new().await;
+
+  // After the LinkDatabaseTest initialize, it will create a default database
+  // with Grid layout.
   let database = test.all_databases().await.pop().unwrap();
   let database = test.all_databases().await.pop().unwrap();
-  let database_views = test.all_database_ref_views(&database.database_id).await;
+  let mut database_views = test.all_database_ref_views(&database.database_id).await;
   assert_eq!(database_views.len(), 1);
   assert_eq!(database_views.len(), 1);
-  let view_id_1 = database_views.get(0).unwrap().view_id.clone();
+  let view = database_views.remove(0);
+
   test
   test
     .run_scripts(vec![
     .run_scripts(vec![
       AssertNumberOfRows {
       AssertNumberOfRows {
-        view_id: view_id_1.clone(),
+        view_id: view.view_id.clone(),
         expected: 6,
         expected: 6,
       },
       },
-      LinkGridToDatabase {
+      CreateGridViewAndLinkToDatabase {
         database_id: database.database_id.clone(),
         database_id: database.database_id.clone(),
       },
       },
-      AssertNumberOfDatabase { expected: 1 },
     ])
     ])
     .await;
     .await;
 
 
@@ -84,6 +97,7 @@ async fn database_ref_create_new_row_test() {
         view_id: view_id_2,
         view_id: view_id_2,
         expected: 7,
         expected: 7,
       },
       },
+      AssertNumberOfDatabase { expected: 1 },
     ])
     ])
     .await;
     .await;
 }
 }