From 6bbdc7ceff0f0320342f9d6479dfa3c1a76e2db7 Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Sun, 28 May 2023 22:54:03 +0800 Subject: [PATCH] refactor: group event (#2640) * refactor: group event * fix: tauri build --- .../application/filter/filter_service.dart | 4 +- .../application/group/group_listener.dart | 8 +- .../application/group/group_service.dart | 37 ++++ .../application/setting/group_bloc.dart | 9 +- .../application/setting/setting_service.dart | 17 -- .../application/sort/sort_service.dart | 8 +- .../effects/database/group/group_observer.ts | 23 ++- .../src/entities/filter_entities/util.rs | 12 +- .../src/entities/group_entities/group.rs | 161 ++++++++++-------- .../group_entities/group_changeset.rs | 4 +- .../src/entities/setting_entities.rs | 38 ++--- .../src/entities/sort_entities.rs | 10 +- .../flowy-database2/src/event_handler.rs | 49 ++++-- .../rust-lib/flowy-database2/src/event_map.rs | 22 ++- .../flowy-database2/src/notification.rs | 2 +- .../src/services/database/database_editor.rs | 73 ++++---- .../src/services/database_view/notifier.rs | 6 +- .../src/services/database_view/view_editor.rs | 104 ++++++----- .../src/services/database_view/view_group.rs | 2 - .../src/services/database_view/views.rs | 3 +- .../select_type_option.rs | 2 + .../field/type_options/type_option_cell.rs | 12 +- .../src/services/filter/controller.rs | 14 +- .../src/services/group/action.rs | 10 +- .../src/services/group/configuration.rs | 92 +++++----- .../src/services/group/controller.rs | 75 ++++---- .../controller_impls/checkbox_controller.rs | 31 ++-- .../controller_impls/default_controller.rs | 23 ++- .../multi_select_controller.rs | 31 ++-- .../single_select_controller.rs | 29 ++-- .../group/controller_impls/url_controller.rs | 49 +++--- .../src/services/group/entities.rs | 14 +- .../src/services/group/group_util.rs | 2 +- .../src/services/sort/controller.rs | 6 +- .../tests/database/filter_test/script.rs | 24 +-- .../database/filter_test/text_filter_test.rs | 4 +- .../tests/database/sort_test/script.rs | 4 +- frontend/rust-lib/lib-log/src/layer.rs | 54 +++--- frontend/rust-lib/lib-log/src/lib.rs | 38 ++--- 39 files changed, 602 insertions(+), 504 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_service.dart diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/filter/filter_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/filter/filter_service.dart index f37ff21026..083604b0a1 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/filter/filter_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/filter/filter_service.dart @@ -178,7 +178,7 @@ class FilterBackendService { required FieldType fieldType, required List data, }) { - var insertFilterPayload = AlterFilterPayloadPB.create() + var insertFilterPayload = UpdateFilterPayloadPB.create() ..fieldId = fieldId ..fieldType = fieldType ..viewId = viewId @@ -190,7 +190,7 @@ class FilterBackendService { final payload = DatabaseSettingChangesetPB.create() ..viewId = viewId - ..alterFilter = insertFilterPayload; + ..updateFilter = insertFilterPayload; return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( (l) => left(l), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_listener.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_listener.dart index 04c40da908..3745170937 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_listener.dart @@ -8,7 +8,7 @@ import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group_changeset.pb.dart'; -typedef GroupUpdateValue = Either; +typedef GroupUpdateValue = Either; typedef GroupByNewFieldValue = Either, FlowyError>; class DatabaseGroupListener { @@ -36,17 +36,17 @@ class DatabaseGroupListener { Either result, ) { switch (ty) { - case DatabaseNotification.DidUpdateGroups: + case DatabaseNotification.DidUpdateNumOfGroups: result.fold( (payload) => _numOfGroupsNotifier?.value = - left(GroupChangesetPB.fromBuffer(payload)), + left(GroupChangesPB.fromBuffer(payload)), (error) => _numOfGroupsNotifier?.value = right(error), ); break; case DatabaseNotification.DidGroupByField: result.fold( (payload) => _groupByFieldNotifier?.value = - left(GroupChangesetPB.fromBuffer(payload).initialGroups), + left(GroupChangesPB.fromBuffer(payload).initialGroups), (error) => _groupByFieldNotifier?.value = right(error), ); break; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_service.dart new file mode 100644 index 0000000000..b4b302fafb --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/group/group_service.dart @@ -0,0 +1,37 @@ +import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:dartz/dartz.dart'; + +class GroupBackendService { + final String viewId; + GroupBackendService(this.viewId); + + Future> groupByField({ + required String fieldId, + required FieldType fieldType, + }) { + final payload = GroupByFieldPayloadPB.create() + ..viewId = viewId + ..fieldId = fieldId + ..fieldType = fieldType; + + return DatabaseEventSetGroupByField(payload).send(); + } + + Future> updateGroup({ + required String groupId, + String? name, + bool? visible, + }) { + final payload = UpdateGroupPB.create()..groupId = groupId; + if (name != null) { + payload.name = name; + } + if (visible != null) { + payload.visible = visible; + } + return DatabaseEventUpdateGroup(payload).send(); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/group_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/group_bloc.dart index 2e4a9aa584..defde38af2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/group_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/group_bloc.dart @@ -1,23 +1,24 @@ import 'package:appflowy/plugins/database_view/application/field/field_controller.dart'; -import 'package:appflowy/plugins/database_view/application/setting/setting_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; +import '../group/group_service.dart'; + part 'group_bloc.freezed.dart'; class DatabaseGroupBloc extends Bloc { final FieldController _fieldController; - final SettingBackendService _settingBackendSvc; + final GroupBackendService _groupBackendSvc; Function(List)? _onFieldsFn; DatabaseGroupBloc({ required String viewId, required FieldController fieldController, }) : _fieldController = fieldController, - _settingBackendSvc = SettingBackendService(viewId: viewId), + _groupBackendSvc = GroupBackendService(viewId), super(DatabaseGroupState.initial(viewId, fieldController.fieldInfos)) { on( (event, emit) async { @@ -29,7 +30,7 @@ class DatabaseGroupBloc extends Bloc { emit(state.copyWith(fieldContexts: fieldContexts)); }, setGroupByField: (String fieldId, FieldType fieldType) async { - final result = await _settingBackendSvc.groupByField( + final result = await _groupBackendSvc.groupByField( fieldId: fieldId, fieldType: fieldType, ); diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_service.dart index b8505acc3c..436acad0b2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_service.dart @@ -2,8 +2,6 @@ import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.d import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; class SettingBackendService { @@ -15,19 +13,4 @@ class SettingBackendService { final payload = DatabaseViewIdPB.create()..value = viewId; return DatabaseEventGetDatabaseSetting(payload).send(); } - - Future> groupByField({ - required String fieldId, - required FieldType fieldType, - }) { - final insertGroupPayload = InsertGroupPayloadPB.create() - ..viewId = viewId - ..fieldId = fieldId - ..fieldType = fieldType; - final payload = DatabaseSettingChangesetPB.create() - ..viewId = viewId - ..insertGroup = insertGroupPayload; - - return DatabaseEventUpdateDatabaseSetting(payload).send(); - } } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/sort/sort_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/sort/sort_service.dart index cea008eccb..0bbb15fe6f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/sort/sort_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/sort/sort_service.dart @@ -29,7 +29,7 @@ class SortBackendService { required FieldType fieldType, required SortConditionPB condition, }) { - var insertSortPayload = AlterSortPayloadPB.create() + var insertSortPayload = UpdateSortPayloadPB.create() ..fieldId = fieldId ..fieldType = fieldType ..viewId = viewId @@ -38,7 +38,7 @@ class SortBackendService { final payload = DatabaseSettingChangesetPB.create() ..viewId = viewId - ..alterSort = insertSortPayload; + ..updateSort = insertSortPayload; return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( (l) => left(l), @@ -55,7 +55,7 @@ class SortBackendService { required FieldType fieldType, required SortConditionPB condition, }) { - var insertSortPayload = AlterSortPayloadPB.create() + var insertSortPayload = UpdateSortPayloadPB.create() ..fieldId = fieldId ..fieldType = fieldType ..viewId = viewId @@ -63,7 +63,7 @@ class SortBackendService { final payload = DatabaseSettingChangesetPB.create() ..viewId = viewId - ..alterSort = insertSortPayload; + ..updateSort = insertSortPayload; return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( (l) => left(l), diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts index 930a182d62..46cfb10961 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts @@ -1,18 +1,17 @@ -import { ChangeNotifier } from "$app/utils/change_notifier"; -import { Ok, Result } from "ts-results"; -import { DatabaseNotification, FlowyError, GroupChangesetPB, GroupPB } from "@/services/backend"; -import { DatabaseNotificationObserver } from "../notifications/observer"; +import { ChangeNotifier } from '$app/utils/change_notifier'; +import { Ok, Result } from 'ts-results'; +import { DatabaseNotification, FlowyError, GroupChangesPB, GroupPB } from '@/services/backend'; +import { DatabaseNotificationObserver } from '../notifications/observer'; export type GroupByFieldCallback = (value: Result) => void; -export type GroupChangesetSubscribeCallback = (value: Result) => void; +export type GroupChangesetSubscribeCallback = (value: Result) => void; export class DatabaseGroupObserver { private groupByNotifier?: ChangeNotifier>; - private groupChangesetNotifier?: ChangeNotifier>; + private groupChangesetNotifier?: ChangeNotifier>; private listener?: DatabaseNotificationObserver; - constructor(public readonly viewId: string) { - } + constructor(public readonly viewId: string) {} subscribe = async (callbacks: { onGroupBy: GroupByFieldCallback; @@ -30,14 +29,14 @@ export class DatabaseGroupObserver { switch (notification) { case DatabaseNotification.DidGroupByField: if (result.ok) { - this.groupByNotifier?.notify(Ok(GroupChangesetPB.deserializeBinary(result.val).initial_groups)); + this.groupByNotifier?.notify(Ok(GroupChangesPB.deserializeBinary(result.val).initial_groups)); } else { this.groupByNotifier?.notify(result); } break; - case DatabaseNotification.DidUpdateGroups: + case DatabaseNotification.DidUpdateNumOfGroups: if (result.ok) { - this.groupChangesetNotifier?.notify(Ok(GroupChangesetPB.deserializeBinary(result.val))); + this.groupChangesetNotifier?.notify(Ok(GroupChangesPB.deserializeBinary(result.val))); } else { this.groupChangesetNotifier?.notify(result); } @@ -45,7 +44,7 @@ export class DatabaseGroupObserver { default: break; } - } + }, }); await this.listener.start(); diff --git a/frontend/rust-lib/flowy-database2/src/entities/filter_entities/util.rs b/frontend/rust-lib/flowy-database2/src/entities/filter_entities/util.rs index 853955a0e9..aae8ba4c7f 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/filter_entities/util.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/filter_entities/util.rs @@ -125,7 +125,7 @@ pub struct DeleteFilterParams { } #[derive(ProtoBuf, Debug, Default, Clone)] -pub struct AlterFilterPayloadPB { +pub struct UpdateFilterPayloadPB { #[pb(index = 1)] pub field_id: String, @@ -143,7 +143,7 @@ pub struct AlterFilterPayloadPB { pub view_id: String, } -impl AlterFilterPayloadPB { +impl UpdateFilterPayloadPB { #[allow(dead_code)] pub fn new>( view_id: &str, @@ -162,10 +162,10 @@ impl AlterFilterPayloadPB { } } -impl TryInto for AlterFilterPayloadPB { +impl TryInto for UpdateFilterPayloadPB { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let view_id = NotEmptyStr::parse(self.view_id) .map_err(|_| ErrorCode::DatabaseViewIdIsEmpty)? .0; @@ -217,7 +217,7 @@ impl TryInto for AlterFilterPayloadPB { }, } - Ok(AlterFilterParams { + Ok(UpdateFilterParams { view_id, field_id, filter_id, @@ -229,7 +229,7 @@ impl TryInto for AlterFilterPayloadPB { } #[derive(Debug)] -pub struct AlterFilterParams { +pub struct UpdateFilterParams { pub view_id: String, pub field_id: String, /// Create a new filter if the filter_id is None diff --git a/frontend/rust-lib/flowy-database2/src/entities/group_entities/group.rs b/frontend/rust-lib/flowy-database2/src/entities/group_entities/group.rs index 3cd9216254..99a8e49bb9 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/group_entities/group.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/group_entities/group.rs @@ -5,7 +5,7 @@ use flowy_error::ErrorCode; use crate::entities::parser::NotEmptyStr; use crate::entities::{FieldType, RowPB}; -use crate::services::group::{GroupData, GroupSetting}; +use crate::services::group::{GroupChangeset, GroupData, GroupSetting}; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] pub struct GroupSettingPB { @@ -25,6 +25,29 @@ impl std::convert::From<&GroupSetting> for GroupSettingPB { } } +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct RepeatedGroupSettingPB { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::convert::From> for RepeatedGroupSettingPB { + fn from(items: Vec) -> Self { + Self { items } + } +} + +impl std::convert::From> for RepeatedGroupSettingPB { + fn from(group_settings: Vec) -> Self { + RepeatedGroupSettingPB { + items: group_settings + .iter() + .map(|setting| setting.into()) + .collect(), + } + } +} + #[derive(ProtoBuf, Debug, Default, Clone)] pub struct RepeatedGroupPB { #[pb(index = 1)] @@ -79,107 +102,97 @@ impl std::convert::From for GroupPB { } #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct RepeatedGroupSettingPB { - #[pb(index = 1)] - pub items: Vec, -} - -impl std::convert::From> for RepeatedGroupSettingPB { - fn from(items: Vec) -> Self { - Self { items } - } -} - -impl std::convert::From> for RepeatedGroupSettingPB { - fn from(group_settings: Vec) -> Self { - RepeatedGroupSettingPB { - items: group_settings - .iter() - .map(|setting| setting.into()) - .collect(), - } - } -} - -#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct InsertGroupPayloadPB { +pub struct GroupByFieldPayloadPB { #[pb(index = 1)] pub field_id: String, #[pb(index = 2)] - pub field_type: FieldType, - - #[pb(index = 3)] pub view_id: String, -} - -impl TryInto for InsertGroupPayloadPB { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let field_id = NotEmptyStr::parse(self.field_id) - .map_err(|_| ErrorCode::FieldIdIsEmpty)? - .0; - - let view_id = NotEmptyStr::parse(self.view_id) - .map_err(|_| ErrorCode::ViewIdIsInvalid)? - .0; - - Ok(InsertGroupParams { - field_id, - field_type: self.field_type, - view_id, - }) - } -} - -pub struct InsertGroupParams { - pub view_id: String, - pub field_id: String, - pub field_type: FieldType, -} - -#[derive(ProtoBuf, Debug, Default, Clone)] -pub struct DeleteGroupPayloadPB { - #[pb(index = 1)] - pub field_id: String, - - #[pb(index = 2)] - pub group_id: String, #[pb(index = 3)] pub field_type: FieldType, - - #[pb(index = 4)] - pub view_id: String, } -impl TryInto for DeleteGroupPayloadPB { +impl TryInto for GroupByFieldPayloadPB { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let field_id = NotEmptyStr::parse(self.field_id) .map_err(|_| ErrorCode::FieldIdIsEmpty)? .0; - let group_id = NotEmptyStr::parse(self.group_id) - .map_err(|_| ErrorCode::FieldIdIsEmpty)? - .0; let view_id = NotEmptyStr::parse(self.view_id) .map_err(|_| ErrorCode::ViewIdIsInvalid)? .0; - Ok(DeleteGroupParams { + Ok(GroupByFieldParams { field_id, - field_type: self.field_type, - group_id, view_id, + field_type: self.field_type, }) } } +pub struct GroupByFieldParams { + pub field_id: String, + pub view_id: String, + pub field_type: FieldType, +} + pub struct DeleteGroupParams { pub view_id: String, pub field_id: String, pub group_id: String, pub field_type: FieldType, } + +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct UpdateGroupPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2)] + pub group_id: String, + + #[pb(index = 3, one_of)] + pub name: Option, + + #[pb(index = 4, one_of)] + pub visible: Option, +} + +impl TryInto for UpdateGroupPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let view_id = NotEmptyStr::parse(self.view_id) + .map_err(|_| ErrorCode::ViewIdIsInvalid)? + .0; + let group_id = NotEmptyStr::parse(self.group_id) + .map_err(|_| ErrorCode::GroupIdIsEmpty)? + .0; + + Ok(UpdateGroupParams { + view_id, + group_id, + name: self.name, + visible: self.visible, + }) + } +} + +pub struct UpdateGroupParams { + pub view_id: String, + pub group_id: String, + pub name: Option, + pub visible: Option, +} + +impl From for GroupChangeset { + fn from(params: UpdateGroupParams) -> Self { + Self { + group_id: params.group_id, + name: params.name, + visible: params.visible, + } + } +} diff --git a/frontend/rust-lib/flowy-database2/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-database2/src/entities/group_entities/group_changeset.rs index 59f2ba69ab..5b7b99ae6b 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/group_entities/group_changeset.rs @@ -129,7 +129,7 @@ impl TryInto for MoveGroupPayloadPB { } #[derive(Debug, Default, ProtoBuf)] -pub struct GroupChangesetPB { +pub struct GroupChangesPB { #[pb(index = 1)] pub view_id: String, @@ -146,7 +146,7 @@ pub struct GroupChangesetPB { pub update_groups: Vec, } -impl GroupChangesetPB { +impl GroupChangesPB { pub fn is_empty(&self) -> bool { self.initial_groups.is_empty() && self.inserted_groups.is_empty() diff --git a/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs index b5430fa18b..d8689ff19c 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs @@ -8,10 +8,9 @@ use flowy_error::ErrorCode; use crate::entities::parser::NotEmptyStr; use crate::entities::{ - AlterFilterParams, AlterFilterPayloadPB, AlterSortParams, AlterSortPayloadPB, - CalendarLayoutSettingPB, DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, - DeleteGroupPayloadPB, DeleteSortParams, DeleteSortPayloadPB, InsertGroupParams, - InsertGroupPayloadPB, RepeatedFilterPB, RepeatedGroupSettingPB, RepeatedSortPB, + CalendarLayoutSettingPB, DeleteFilterParams, DeleteFilterPayloadPB, DeleteSortParams, + DeleteSortPayloadPB, RepeatedFilterPB, RepeatedGroupSettingPB, RepeatedSortPB, + UpdateFilterParams, UpdateFilterPayloadPB, UpdateGroupPB, UpdateSortParams, UpdateSortPayloadPB, }; use crate::services::setting::CalendarLayoutSetting; @@ -77,21 +76,18 @@ pub struct DatabaseSettingChangesetPB { pub layout_type: DatabaseLayoutPB, #[pb(index = 3, one_of)] - pub alter_filter: Option, + pub update_filter: Option, #[pb(index = 4, one_of)] pub delete_filter: Option, #[pb(index = 5, one_of)] - pub insert_group: Option, + pub update_group: Option, #[pb(index = 6, one_of)] - pub delete_group: Option, + pub update_sort: Option, #[pb(index = 7, one_of)] - pub alter_sort: Option, - - #[pb(index = 8, one_of)] pub delete_sort: Option, } @@ -103,7 +99,7 @@ impl TryInto for DatabaseSettingChangesetPB { .map_err(|_| ErrorCode::ViewIdIsInvalid)? .0; - let insert_filter = match self.alter_filter { + let insert_filter = match self.update_filter { None => None, Some(payload) => Some(payload.try_into()?), }; @@ -113,17 +109,7 @@ impl TryInto for DatabaseSettingChangesetPB { Some(payload) => Some(payload.try_into()?), }; - let insert_group = match self.insert_group { - Some(payload) => Some(payload.try_into()?), - None => None, - }; - - let delete_group = match self.delete_group { - Some(payload) => Some(payload.try_into()?), - None => None, - }; - - let alert_sort = match self.alter_sort { + let alert_sort = match self.update_sort { None => None, Some(payload) => Some(payload.try_into()?), }; @@ -138,8 +124,6 @@ impl TryInto for DatabaseSettingChangesetPB { layout_type: self.layout_type.into(), insert_filter, delete_filter, - insert_group, - delete_group, alert_sort, delete_sort, }) @@ -149,11 +133,9 @@ impl TryInto for DatabaseSettingChangesetPB { pub struct DatabaseSettingChangesetParams { pub view_id: String, pub layout_type: DatabaseLayout, - pub insert_filter: Option, + pub insert_filter: Option, pub delete_filter: Option, - pub insert_group: Option, - pub delete_group: Option, - pub alert_sort: Option, + pub alert_sort: Option, pub delete_sort: Option, } diff --git a/frontend/rust-lib/flowy-database2/src/entities/sort_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/sort_entities.rs index ceea1fa61b..c306273895 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/sort_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/sort_entities.rs @@ -92,7 +92,7 @@ impl std::convert::From for SortCondition { } #[derive(ProtoBuf, Debug, Default, Clone)] -pub struct AlterSortPayloadPB { +pub struct UpdateSortPayloadPB { #[pb(index = 1)] pub view_id: String, @@ -110,10 +110,10 @@ pub struct AlterSortPayloadPB { pub condition: SortConditionPB, } -impl TryInto for AlterSortPayloadPB { +impl TryInto for UpdateSortPayloadPB { type Error = ErrorCode; - fn try_into(self) -> Result { + fn try_into(self) -> Result { let view_id = NotEmptyStr::parse(self.view_id) .map_err(|_| ErrorCode::DatabaseViewIdIsEmpty)? .0; @@ -131,7 +131,7 @@ impl TryInto for AlterSortPayloadPB { ), }; - Ok(AlterSortParams { + Ok(UpdateSortParams { view_id, field_id, sort_id, @@ -142,7 +142,7 @@ impl TryInto for AlterSortPayloadPB { } #[derive(Debug)] -pub struct AlterSortParams { +pub struct UpdateSortParams { pub view_id: String, pub field_id: String, /// Create a new sort if the sort is None diff --git a/frontend/rust-lib/flowy-database2/src/event_handler.rs b/frontend/rust-lib/flowy-database2/src/event_handler.rs index c68c77b720..f25083acaa 100644 --- a/frontend/rust-lib/flowy-database2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-database2/src/event_handler.rs @@ -15,9 +15,10 @@ use crate::services::cell::CellBuilder; use crate::services::field::{ type_option_data_from_pb_or_default, DateCellChangeset, SelectOptionCellChangeset, }; +use crate::services::group::{GroupChangeset, GroupSettingChangeset}; use crate::services::share::csv::CSVFormat; -#[tracing::instrument(level = "trace", skip(data, manager), err)] +#[tracing::instrument(level = "trace", skip_all, err)] pub(crate) async fn get_database_data_handler( data: AFPluginData, manager: AFPluginState>, @@ -49,24 +50,16 @@ pub(crate) async fn update_database_setting_handler( let params: DatabaseSettingChangesetParams = data.into_inner().try_into()?; let editor = manager.get_database_with_view_id(¶ms.view_id).await?; - if let Some(insert_params) = params.insert_group { - editor.insert_group(insert_params).await?; - } - - if let Some(delete_params) = params.delete_group { - editor.delete_group(delete_params).await?; - } - - if let Some(alter_filter) = params.insert_filter { - editor.create_or_update_filter(alter_filter).await?; + if let Some(update_filter) = params.insert_filter { + editor.create_or_update_filter(update_filter).await?; } if let Some(delete_filter) = params.delete_filter { editor.delete_filter(delete_filter).await?; } - if let Some(alter_sort) = params.alert_sort { - let _ = editor.create_or_update_sort(alter_sort).await?; + if let Some(update_sort) = params.alert_sort { + let _ = editor.create_or_update_sort(update_sort).await?; } if let Some(delete_sort) = params.delete_sort { editor.delete_sort(delete_sort).await?; @@ -525,6 +518,36 @@ pub(crate) async fn get_group_handler( data_result_ok(group) } +#[tracing::instrument(level = "trace", skip_all, err)] +pub(crate) async fn set_group_by_field_handler( + data: AFPluginData, + manager: AFPluginState>, +) -> FlowyResult<()> { + let params: GroupByFieldParams = data.into_inner().try_into()?; + let database_editor = manager.get_database_with_view_id(¶ms.view_id).await?; + database_editor + .set_group_by_field(¶ms.view_id, ¶ms.field_id) + .await?; + Ok(()) +} + +#[tracing::instrument(level = "trace", skip_all, err)] +pub(crate) async fn update_group_handler( + data: AFPluginData, + manager: AFPluginState>, +) -> FlowyResult<()> { + let params: UpdateGroupParams = data.into_inner().try_into()?; + let view_id = params.view_id.clone(); + let database_editor = manager.get_database_with_view_id(&view_id).await?; + let group_setting_changeset = GroupSettingChangeset { + update_groups: vec![GroupChangeset::from(params)], + }; + database_editor + .update_group_setting(&view_id, group_setting_changeset) + .await?; + Ok(()) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn move_group_handler( data: AFPluginData, diff --git a/frontend/rust-lib/flowy-database2/src/event_map.rs b/frontend/rust-lib/flowy-database2/src/event_map.rs index ab73c79b53..065d0aaded 100644 --- a/frontend/rust-lib/flowy-database2/src/event_map.rs +++ b/frontend/rust-lib/flowy-database2/src/event_map.rs @@ -51,6 +51,8 @@ pub fn init(database_manager: Arc) -> AFPlugin { .event(DatabaseEvent::MoveGroupRow, move_group_row_handler) .event(DatabaseEvent::GetGroups, get_groups_handler) .event(DatabaseEvent::GetGroup, get_group_handler) + .event(DatabaseEvent::SetGroupByField, set_group_by_field_handler) + .event(DatabaseEvent::UpdateGroup, update_group_handler) // Database .event(DatabaseEvent::GetDatabases, get_databases_handler) // Calendar @@ -243,25 +245,31 @@ pub enum DatabaseEvent { #[event(input = "MoveGroupRowPayloadPB")] MoveGroupRow = 112, + #[event(input = "GroupByFieldPayloadPB")] + SetGroupByField = 113, + + #[event(input = "UpdateGroupPB")] + UpdateGroup = 114, + /// Returns all the databases #[event(output = "RepeatedDatabaseDescriptionPB")] - GetDatabases = 114, + GetDatabases = 120, #[event(input = "LayoutSettingChangesetPB")] - SetLayoutSetting = 115, + SetLayoutSetting = 121, #[event(input = "DatabaseLayoutIdPB", output = "LayoutSettingPB")] - GetLayoutSetting = 116, + GetLayoutSetting = 122, #[event(input = "CalendarEventRequestPB", output = "RepeatedCalendarEventPB")] - GetAllCalendarEvents = 117, + GetAllCalendarEvents = 123, #[event(input = "RowIdPB", output = "CalendarEventPB")] - GetCalendarEvent = 118, + GetCalendarEvent = 124, #[event(input = "MoveCalendarEventPB")] - MoveCalendarEvent = 119, + MoveCalendarEvent = 125, #[event(input = "DatabaseImportPB")] - ImportCSV = 120, + ImportCSV = 130, } diff --git a/frontend/rust-lib/flowy-database2/src/notification.rs b/frontend/rust-lib/flowy-database2/src/notification.rs index 0a693d4ebe..831877315f 100644 --- a/frontend/rust-lib/flowy-database2/src/notification.rs +++ b/frontend/rust-lib/flowy-database2/src/notification.rs @@ -16,7 +16,7 @@ pub enum DatabaseNotification { /// Trigger after editing a field properties including rename,update type option, etc DidUpdateField = 50, /// Trigger after the number of groups is changed - DidUpdateGroups = 60, + DidUpdateNumOfGroups = 60, /// Trigger after inserting/deleting/updating/moving a row DidUpdateGroupRow = 61, /// Trigger when setting a new grouping field diff --git a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs index 3829ccb021..3178433a4e 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs @@ -15,11 +15,11 @@ use flowy_task::TaskDispatcher; use lib_infra::future::{to_fut, Fut}; use crate::entities::{ - AlterFilterParams, AlterSortParams, CalendarEventPB, CellChangesetNotifyPB, CellPB, - DatabaseFieldChangesetPB, DatabasePB, DatabaseViewSettingPB, DeleteFilterParams, - DeleteGroupParams, DeleteSortParams, FieldChangesetParams, FieldIdPB, FieldPB, FieldType, - GroupPB, IndexFieldPB, InsertGroupParams, InsertedRowPB, LayoutSettingParams, RepeatedFilterPB, - RepeatedGroupPB, RepeatedSortPB, RowPB, RowsChangePB, SelectOptionCellDataPB, SelectOptionPB, + CalendarEventPB, CellChangesetNotifyPB, CellPB, DatabaseFieldChangesetPB, DatabasePB, + DatabaseViewSettingPB, DeleteFilterParams, DeleteGroupParams, DeleteSortParams, + FieldChangesetParams, FieldIdPB, FieldPB, FieldType, GroupPB, IndexFieldPB, InsertedRowPB, + LayoutSettingParams, RepeatedFilterPB, RepeatedGroupPB, RepeatedSortPB, RowPB, RowsChangePB, + SelectOptionCellDataPB, SelectOptionPB, UpdateFilterParams, UpdateSortParams, }; use crate::notification::{send_notification, DatabaseNotification}; use crate::services::cell::{ @@ -34,7 +34,9 @@ use crate::services::field::{ SelectOptionIds, TypeOptionCellDataHandler, TypeOptionCellExt, }; use crate::services::filter::Filter; -use crate::services::group::{default_group_setting, GroupSetting, RowChangeset}; +use crate::services::group::{ + default_group_setting, GroupSetting, GroupSettingChangeset, RowChangeset, +}; use crate::services::share::csv::{CSVExport, CSVFormat}; use crate::services::sort::Sort; @@ -85,18 +87,18 @@ impl DatabaseEditor { self.database.lock().fields.get_field(field_id) } - pub async fn insert_group(&self, params: InsertGroupParams) -> FlowyResult<()> { + pub async fn set_group_by_field(&self, view_id: &str, field_id: &str) -> FlowyResult<()> { { let database = self.database.lock(); - let field = database.fields.get_field(¶ms.field_id); + let field = database.fields.get_field(field_id); if let Some(field) = field { let group_setting = default_group_setting(&field); - database.insert_group_setting(¶ms.view_id, group_setting); + database.insert_group_setting(view_id, group_setting); } } - let view_editor = self.database_views.get_view_editor(¶ms.view_id).await?; - view_editor.v_initialize_new_group(params).await?; + let view_editor = self.database_views.get_view_editor(view_id).await?; + view_editor.v_initialize_new_group(field_id).await?; Ok(()) } @@ -111,8 +113,20 @@ impl DatabaseEditor { Ok(()) } + pub async fn update_group_setting( + &self, + view_id: &str, + group_setting_changeset: GroupSettingChangeset, + ) -> FlowyResult<()> { + let view_editor = self.database_views.get_view_editor(view_id).await?; + view_editor + .update_group_setting(group_setting_changeset) + .await?; + Ok(()) + } + #[tracing::instrument(level = "trace", skip_all, err)] - pub async fn create_or_update_filter(&self, params: AlterFilterParams) -> FlowyResult<()> { + pub async fn create_or_update_filter(&self, params: UpdateFilterParams) -> FlowyResult<()> { let view_editor = self.database_views.get_view_editor(¶ms.view_id).await?; view_editor.v_insert_filter(params).await?; Ok(()) @@ -124,7 +138,7 @@ impl DatabaseEditor { Ok(()) } - pub async fn create_or_update_sort(&self, params: AlterSortParams) -> FlowyResult { + pub async fn create_or_update_sort(&self, params: UpdateSortParams) -> FlowyResult { let view_editor = self.database_views.get_view_editor(¶ms.view_id).await?; let sort = view_editor.v_insert_sort(params).await?; Ok(sort) @@ -549,6 +563,8 @@ impl DatabaseEditor { Some(SelectOptionPB::from(select_option)) } + /// Insert the options into the field's type option and update the cell content with the new options. + /// Only used for single select and multiple select. pub async fn insert_select_options( &self, view_id: &str, @@ -556,30 +572,25 @@ impl DatabaseEditor { row_id: RowId, options: Vec, ) -> FlowyResult<()> { - let field = match self.database.lock().fields.get_field(field_id) { - Some(field) => Ok(field), - None => { - let msg = format!("Field with id:{} not found", &field_id); - Err(FlowyError::internal().context(msg)) - }, - }?; + let field = self.database.lock().fields.get_field(field_id).ok_or( + FlowyError::record_not_found().context(format!("Field with id:{} not found", &field_id)), + )?; + debug_assert!(FieldType::from(field.field_type).is_select_option()); + let mut type_option = select_type_option_from_field(&field)?; let cell_changeset = SelectOptionCellChangeset { insert_option_ids: options.iter().map(|option| option.id.clone()).collect(), ..Default::default() }; + options + .into_iter() + .for_each(|option| type_option.insert_option(option.into())); - for option in options { - type_option.insert_option(option.into()); - } + // Update the field's type option self - .database - .lock() - .fields - .update_field(field_id, |update| { - update.set_type_option(field.field_type, Some(type_option.to_type_option_data())); - }); - + .update_field_type_option(view_id, field_id, type_option.to_type_option_data(), field) + .await?; + // Insert the options into the cell self .update_cell_with_changeset(view_id, row_id, field_id, cell_changeset) .await?; @@ -709,7 +720,7 @@ impl DatabaseEditor { pub async fn group_by_field(&self, view_id: &str, field_id: &str) -> FlowyResult<()> { let view = self.database_views.get_view_editor(view_id).await?; - view.v_update_group_setting(field_id).await?; + view.v_update_grouping_field(field_id).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs index 2a9929a3a0..173be64d96 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs @@ -1,6 +1,6 @@ #![allow(clippy::while_let_loop)] use crate::entities::{ - DatabaseViewSettingPB, FilterChangesetNotificationPB, GroupChangesetPB, GroupRowsNotificationPB, + DatabaseViewSettingPB, FilterChangesetNotificationPB, GroupChangesPB, GroupRowsNotificationPB, ReorderAllRowsPB, ReorderSingleRowPB, RowsVisibilityChangePB, SortChangesetNotificationPB, }; use crate::notification::{send_notification, DatabaseNotification}; @@ -102,8 +102,8 @@ pub async fn notify_did_update_sort(notification: SortChangesetNotificationPB) { } } -pub(crate) async fn notify_did_update_groups(view_id: &str, changeset: GroupChangesetPB) { - send_notification(view_id, DatabaseNotification::DidUpdateGroups) +pub(crate) async fn notify_did_update_num_of_groups(view_id: &str, changeset: GroupChangesPB) { + send_notification(view_id, DatabaseNotification::DidUpdateNumOfGroups) .payload(changeset) .send(); } diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs index e65cefe07d..01e89fb4fb 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs @@ -13,10 +13,10 @@ use flowy_task::TaskDispatcher; use lib_infra::future::Fut; use crate::entities::{ - AlterFilterParams, AlterSortParams, CalendarEventPB, DeleteFilterParams, DeleteGroupParams, - DeleteSortParams, FieldType, GroupChangesetPB, GroupPB, GroupRowsNotificationPB, - InsertGroupParams, InsertedGroupPB, InsertedRowPB, LayoutSettingPB, LayoutSettingParams, RowPB, - RowsChangePB, SortChangesetNotificationPB, SortPB, + CalendarEventPB, DeleteFilterParams, DeleteGroupParams, DeleteSortParams, FieldType, + GroupChangesPB, GroupPB, GroupRowsNotificationPB, InsertedRowPB, LayoutSettingPB, + LayoutSettingParams, RowPB, RowsChangePB, SortChangesetNotificationPB, SortPB, + UpdateFilterParams, UpdateSortParams, }; use crate::notification::{send_notification, DatabaseNotification}; use crate::services::cell::CellCache; @@ -27,7 +27,7 @@ use crate::services::database_view::view_group::{ }; use crate::services::database_view::view_sort::make_sort_controller; use crate::services::database_view::{ - notify_did_update_filter, notify_did_update_group_rows, notify_did_update_groups, + notify_did_update_filter, notify_did_update_group_rows, notify_did_update_num_of_groups, notify_did_update_setting, notify_did_update_sort, DatabaseViewChangedNotifier, DatabaseViewChangedReceiverRunner, }; @@ -35,7 +35,9 @@ use crate::services::field::TypeOptionCellDataHandler; use crate::services::filter::{ Filter, FilterChangeset, FilterController, FilterType, UpdatedFilterType, }; -use crate::services::group::{GroupController, GroupSetting, MoveGroupRowContext, RowChangeset}; +use crate::services::group::{ + GroupController, GroupSetting, GroupSettingChangeset, MoveGroupRowContext, RowChangeset, +}; use crate::services::setting::CalendarLayoutSetting; use crate::services::sort::{DeletedSortType, Sort, SortChangeset, SortController, SortType}; @@ -237,26 +239,28 @@ impl DatabaseViewEditor { .await; if let Some(Ok(result)) = result { - let mut changeset = GroupChangesetPB { + let mut group_changes = GroupChangesPB { view_id: self.view_id.clone(), ..Default::default() }; if let Some(inserted_group) = result.inserted_group { tracing::trace!("Create group after editing the row: {:?}", inserted_group); - changeset.inserted_groups.push(inserted_group); + group_changes.inserted_groups.push(inserted_group); } if let Some(delete_group) = result.deleted_group { tracing::trace!("Delete group after editing the row: {:?}", delete_group); - changeset.deleted_groups.push(delete_group.group_id); + group_changes.deleted_groups.push(delete_group.group_id); + } + + if !group_changes.is_empty() { + notify_did_update_num_of_groups(&self.view_id, group_changes).await; } - notify_did_update_groups(&self.view_id, changeset).await; - tracing::trace!( - "Group changesets after editing the row: {:?}", - result.row_changesets - ); for changeset in result.row_changesets { - notify_did_update_group_rows(changeset).await; + if !changeset.is_empty() { + tracing::trace!("Group change after editing the row: {:?}", changeset); + notify_did_update_group_rows(changeset).await; + } } } else { let update_row = UpdatedRow { @@ -326,15 +330,15 @@ impl DatabaseViewEditor { .await; if let Some(result) = result { - let mut changeset = GroupChangesetPB { - view_id: self.view_id.clone(), - ..Default::default() - }; if let Some(delete_group) = result.deleted_group { - tracing::info!("Delete group after moving the row: {:?}", delete_group); - changeset.deleted_groups.push(delete_group.group_id); + tracing::trace!("Delete group after moving the row: {:?}", delete_group); + let mut changes = GroupChangesPB { + view_id: self.view_id.clone(), + ..Default::default() + }; + changes.deleted_groups.push(delete_group.group_id); + notify_did_update_num_of_groups(&self.view_id, changes).await; } - notify_did_update_groups(&self.view_id, changeset).await; for changeset in result.row_changesets { notify_did_update_group_rows(changeset).await; @@ -371,25 +375,6 @@ impl DatabaseViewEditor { .write() .await .move_group(from_group, to_group)?; - match self.group_controller.read().await.get_group(from_group) { - None => tracing::warn!("Can not find the group with id: {}", from_group), - Some((index, group)) => { - let inserted_group = InsertedGroupPB { - group: GroupPB::from(group), - index: index as i32, - }; - - let changeset = GroupChangesetPB { - view_id: self.view_id.clone(), - inserted_groups: vec![inserted_group], - deleted_groups: vec![from_group.to_string()], - update_groups: vec![], - initial_groups: vec![], - }; - - notify_did_update_groups(&self.view_id, changeset).await; - }, - } Ok(()) } @@ -397,9 +382,9 @@ impl DatabaseViewEditor { self.group_controller.read().await.field_id().to_string() } - pub async fn v_initialize_new_group(&self, params: InsertGroupParams) -> FlowyResult<()> { - if self.group_controller.read().await.field_id() != params.field_id { - self.v_update_group_setting(¶ms.field_id).await?; + pub async fn v_initialize_new_group(&self, field_id: &str) -> FlowyResult<()> { + if self.group_controller.read().await.field_id() != field_id { + self.v_update_grouping_field(field_id).await?; if let Some(view) = self.delegate.get_view_setting(&self.view_id).await { let setting = database_view_setting_pb_from_view(view); @@ -413,12 +398,20 @@ impl DatabaseViewEditor { Ok(()) } + pub async fn update_group_setting(&self, changeset: GroupSettingChangeset) -> FlowyResult<()> { + self + .group_controller + .write() + .await + .apply_group_setting_changeset(changeset) + } + pub async fn v_get_all_sorts(&self) -> Vec { self.delegate.get_all_sorts(&self.view_id) } #[tracing::instrument(level = "trace", skip(self), err)] - pub async fn v_insert_sort(&self, params: AlterSortParams) -> FlowyResult { + pub async fn v_insert_sort(&self, params: UpdateSortParams) -> FlowyResult { let is_exist = params.sort_id.is_some(); let sort_id = match params.sort_id { None => gen_database_sort_id(), @@ -479,7 +472,7 @@ impl DatabaseViewEditor { } #[tracing::instrument(level = "trace", skip(self), err)] - pub async fn v_insert_filter(&self, params: AlterFilterParams) -> FlowyResult<()> { + pub async fn v_insert_filter(&self, params: UpdateFilterParams) -> FlowyResult<()> { let is_exist = params.filter_id.is_some(); let filter_id = match params.filter_id { None => gen_database_filter_id(), @@ -634,9 +627,15 @@ impl DatabaseViewEditor { .sort_controller .read() .await - .did_update_view_field_type_option(&field) + .did_update_field_type_option(&field) .await; + self + .group_controller + .write() + .await + .did_update_field_type_option(&field); + if let Some(filter) = self .delegate .get_filter_by_field_id(&self.view_id, field_id) @@ -660,14 +659,9 @@ impl DatabaseViewEditor { Ok(()) } - /// - /// - /// # Arguments - /// - /// * `field_id`: - /// + /// Called when a grouping field is updated. #[tracing::instrument(level = "debug", skip_all, err)] - pub async fn v_update_group_setting(&self, field_id: &str) -> FlowyResult<()> { + pub async fn v_update_grouping_field(&self, field_id: &str) -> FlowyResult<()> { if let Some(field) = self.delegate.get_field(field_id).await { let new_group_controller = new_group_controller_with_field(self.view_id.clone(), self.delegate.clone(), field).await?; @@ -679,7 +673,7 @@ impl DatabaseViewEditor { .collect(); *self.group_controller.write().await = new_group_controller; - let changeset = GroupChangesetPB { + let changeset = GroupChangesPB { view_id: self.view_id.clone(), initial_groups: new_groups, ..Default::default() diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs index d52f79657e..57988515f7 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs @@ -5,7 +5,6 @@ use collab_database::rows::RowId; use flowy_error::{FlowyError, FlowyResult}; use lib_infra::future::{to_fut, Fut}; -use tracing::trace; use crate::entities::FieldType; use crate::services::database_view::DatabaseViewData; @@ -43,7 +42,6 @@ pub async fn new_group_controller( let fields = delegate.get_fields(&view_id, None).await; let rows = delegate.get_rows(&view_id).await; let layout = delegate.get_layout_for_view(&view_id); - trace!(?fields, ?rows, ?layout, "new_group_controller"); // Read the grouping field or find a new grouping field let mut grouping_field = setting_reader diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/views.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/views.rs index be35466326..1d53b78bfa 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/views.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/views.rs @@ -94,7 +94,7 @@ impl DatabaseViews { // If the id of the grouping field is equal to the updated field's id, then we need to // update the group setting if view_editor.group_id().await == field_id { - view_editor.v_update_group_setting(field_id).await?; + view_editor.v_update_grouping_field(field_id).await?; } view_editor .v_did_update_field_type_option(field_id, old_field) @@ -108,7 +108,6 @@ impl DatabaseViews { return Ok(editor.clone()); } - tracing::trace!("{:p} create view:{} editor", self, view_id); let mut editor_map = self.editor_map.write().await; let editor = Arc::new( DatabaseViewEditor::new( diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs index a5b6ef84ab..6e69f1e4e3 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/selection_type_option/select_type_option.rs @@ -22,6 +22,8 @@ pub trait SelectTypeOptionSharedAction: Send + Sync { fn number_of_max_options(&self) -> Option; /// Insert the `SelectOption` into corresponding type option. + /// If the option already exists, it will be updated. + /// If the option does not exist, it will be inserted at the beginning. fn insert_option(&mut self, new_option: SelectOption) { let options = self.mut_options(); if let Some(index) = options diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option_cell.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option_cell.rs index 45f19321b1..368667fe95 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option_cell.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/type_option_cell.rs @@ -131,12 +131,12 @@ where if let Some(cell_data_cache) = self.cell_data_cache.as_ref() { let read_guard = cell_data_cache.read(); if let Some(cell_data) = read_guard.get(key.as_ref()).cloned() { - tracing::trace!( - "Cell cache hit: field_type:{}, cell: {:?}, cell_data: {:?}", - decoded_field_type, - cell, - cell_data - ); + // tracing::trace!( + // "Cell cache hit: field_type:{}, cell: {:?}, cell_data: {:?}", + // decoded_field_type, + // cell, + // cell_data + // ); return Ok(cell_data); } } diff --git a/frontend/rust-lib/flowy-database2/src/services/filter/controller.rs b/frontend/rust-lib/flowy-database2/src/services/filter/controller.rs index d289424459..2a92c6987d 100644 --- a/frontend/rust-lib/flowy-database2/src/services/filter/controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/filter/controller.rs @@ -219,12 +219,14 @@ impl FilterController { } pub async fn did_receive_row_changed(&self, row_id: RowId) { - self - .gen_task( - FilterEvent::RowDidChanged(row_id), - QualityOfService::UserInteractive, - ) - .await + if !self.cell_filter_cache.read().is_empty() { + self + .gen_task( + FilterEvent::RowDidChanged(row_id), + QualityOfService::UserInteractive, + ) + .await + } } #[tracing::instrument(level = "trace", skip(self))] diff --git a/frontend/rust-lib/flowy-database2/src/services/group/action.rs b/frontend/rust-lib/flowy-database2/src/services/group/action.rs index f7800ff606..8759301d60 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/action.rs @@ -1,7 +1,7 @@ -use crate::entities::{GroupChangesetPB, GroupPB, GroupRowsNotificationPB, InsertedGroupPB}; +use crate::entities::{GroupChangesPB, GroupPB, GroupRowsNotificationPB, InsertedGroupPB}; use crate::services::cell::DecodedCellData; use crate::services::group::controller::MoveGroupRowContext; -use crate::services::group::GroupData; +use crate::services::group::{GroupData, GroupSettingChangeset}; use collab_database::fields::Field; use collab_database::rows::{Cell, Row}; @@ -65,7 +65,7 @@ pub trait GroupCustomize: Send + Sync { } /// Defines the shared actions any group controller can perform. -pub trait GroupControllerActions: Send + Sync { +pub trait GroupControllerOperation: Send + Sync { /// The field that is used for grouping the rows fn field_id(&self) -> &str; @@ -100,7 +100,9 @@ pub trait GroupControllerActions: Send + Sync { fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult; /// Update the group if the corresponding field is changed - fn did_update_group_field(&mut self, field: &Field) -> FlowyResult>; + fn did_update_group_field(&mut self, field: &Field) -> FlowyResult>; + + fn apply_group_setting_changeset(&mut self, changeset: GroupSettingChangeset) -> FlowyResult<()>; } #[derive(Debug)] diff --git a/frontend/rust-lib/flowy-database2/src/services/group/configuration.rs b/frontend/rust-lib/flowy-database2/src/services/group/configuration.rs index 32a85da78e..49fdf01cb4 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/configuration.rs @@ -1,7 +1,7 @@ -use crate::entities::{GroupChangesetPB, GroupPB, InsertedGroupPB}; +use crate::entities::{GroupChangesPB, GroupPB, InsertedGroupPB}; use crate::services::field::RowSingleCellData; use crate::services::group::{ - default_group_setting, GeneratedGroupContext, Group, GroupData, GroupSetting, + default_group_setting, GeneratedGroups, Group, GroupChangeset, GroupData, GroupSetting, }; use collab_database::fields::Field; use flowy_error::{FlowyError, FlowyResult}; @@ -25,7 +25,7 @@ pub trait GroupSettingWriter: Send + Sync + 'static { impl std::fmt::Display for GroupContext { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.groups_map.iter().for_each(|(_, group)| { + self.group_by_id.iter().for_each(|(_, group)| { let _ = f.write_fmt(format_args!( "Group:{} has {} rows \n", group.id, @@ -54,8 +54,9 @@ pub struct GroupContext { /// The grouping field field: Arc, - /// Cache all the groups - groups_map: IndexMap, + /// Cache all the groups. Cache the group by its id. + /// We use the id of the [Field] as the [No Status] group id. + group_by_id: IndexMap, /// A reader that implement the [GroupSettingReader] trait /// @@ -93,7 +94,7 @@ where Ok(Self { view_id, field, - groups_map: IndexMap::new(), + group_by_id: IndexMap::new(), reader, writer, setting, @@ -105,26 +106,26 @@ where /// /// We take the `id` of the `field` as the no status group id pub(crate) fn get_no_status_group(&self) -> Option<&GroupData> { - self.groups_map.get(&self.field.id) + self.group_by_id.get(&self.field.id) } pub(crate) fn get_mut_no_status_group(&mut self) -> Option<&mut GroupData> { - self.groups_map.get_mut(&self.field.id) + self.group_by_id.get_mut(&self.field.id) } pub(crate) fn groups(&self) -> Vec<&GroupData> { - self.groups_map.values().collect() + self.group_by_id.values().collect() } pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut GroupData> { - self.groups_map.get_mut(group_id) + self.group_by_id.get_mut(group_id) } // Returns the index and group specified by the group_id pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &GroupData)> { match ( - self.groups_map.get_index_of(group_id), - self.groups_map.get(group_id), + self.group_by_id.get_index_of(group_id), + self.group_by_id.get(group_id), ) { (Some(index), Some(group)) => Some((index, group)), _ => None, @@ -133,7 +134,7 @@ where /// Iterate mut the groups without `No status` group pub(crate) fn iter_mut_status_groups(&mut self, mut each: impl FnMut(&mut GroupData)) { - self.groups_map.iter_mut().for_each(|(_, group)| { + self.group_by_id.iter_mut().for_each(|(_, group)| { if group.id != self.field.id { each(group); } @@ -141,7 +142,7 @@ where } pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut GroupData)) { - self.groups_map.iter_mut().for_each(|(_, group)| { + self.group_by_id.iter_mut().for_each(|(_, group)| { each(group); }); } @@ -153,7 +154,7 @@ where group.name.clone(), group.id.clone(), ); - self.groups_map.insert(group.id.clone(), group_data); + self.group_by_id.insert(group.id.clone(), group_data); let (index, group_data) = self.get_group(&group.id).unwrap(); let insert_group = InsertedGroupPB { group: GroupPB::from(group_data.clone()), @@ -170,7 +171,7 @@ where #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn delete_group(&mut self, deleted_group_id: &str) -> FlowyResult<()> { - self.groups_map.remove(deleted_group_id); + self.group_by_id.remove(deleted_group_id); self.mut_configuration(|configuration| { configuration .groups @@ -181,11 +182,11 @@ where } pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> { - let from_index = self.groups_map.get_index_of(from_id); - let to_index = self.groups_map.get_index_of(to_id); + let from_index = self.group_by_id.get_index_of(from_id); + let to_index = self.group_by_id.get_index_of(to_id); match (from_index, to_index) { (Some(from_index), Some(to_index)) => { - self.groups_map.move_index(from_index, to_index); + self.group_by_id.move_index(from_index, to_index); self.mut_configuration(|configuration| { let from_index = configuration @@ -205,7 +206,7 @@ where let group = configuration.groups.remove(*from); configuration.groups.insert(*to, group); } - tracing::debug!( + tracing::trace!( "Group order: {:?} ", configuration .groups @@ -237,15 +238,15 @@ where /// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged /// while keeping the order of the old groups. /// - #[tracing::instrument(level = "trace", skip(self, generated_group_context), err)] + #[tracing::instrument(level = "trace", skip_all, err)] pub(crate) fn init_groups( &mut self, - generated_group_context: GeneratedGroupContext, - ) -> FlowyResult> { - let GeneratedGroupContext { + generated_groups: GeneratedGroups, + ) -> FlowyResult> { + let GeneratedGroups { no_status_group, group_configs, - } = generated_group_context; + } = generated_groups; let mut new_groups = vec![]; let mut filter_content_map = HashMap::new(); @@ -310,18 +311,13 @@ where })?; // Update the memory cache of the groups - all_groups.into_iter().for_each(|group_rev| { + all_groups.into_iter().for_each(|group| { let filter_content = filter_content_map - .get(&group_rev.id) + .get(&group.id) .cloned() .unwrap_or_else(|| "".to_owned()); - let group = GroupData::new( - group_rev.id, - self.field.id.clone(), - group_rev.name, - filter_content, - ); - self.groups_map.insert(group.id.clone(), group); + let group = GroupData::new(group.id, self.field.id.clone(), group.name, filter_content); + self.group_by_id.insert(group.id.clone(), group); }); let initial_groups = new_groups @@ -338,13 +334,14 @@ where }) .collect(); - let changeset = GroupChangesetPB { + let changeset = GroupChangesPB { view_id: self.view_id.clone(), initial_groups, deleted_groups: deleted_group_ids, update_groups: vec![], inserted_groups: vec![], }; + tracing::trace!("Group changeset: {:?}", changeset); if changeset.is_empty() { Ok(None) @@ -353,18 +350,15 @@ where } } - #[allow(dead_code)] - pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> { - self.mut_group_rev(group_id, |group_rev| { - group_rev.visible = false; - })?; - Ok(()) - } + pub(crate) fn update_group(&mut self, group_changeset: GroupChangeset) -> FlowyResult<()> { + self.mut_group(&group_changeset.group_id, |group| { + if let Some(visible) = group_changeset.visible { + group.visible = visible; + } - #[allow(dead_code)] - pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> { - self.mut_group_rev(group_id, |group_rev| { - group_rev.visible = true; + if let Some(name) = &group_changeset.name { + group.name = name.clone(); + } })?; Ok(()) } @@ -398,11 +392,7 @@ where Ok(()) } - fn mut_group_rev( - &mut self, - group_id: &str, - mut_groups_fn: impl Fn(&mut Group), - ) -> FlowyResult<()> { + fn mut_group(&mut self, group_id: &str, mut_groups_fn: impl Fn(&mut Group)) -> FlowyResult<()> { self.mut_configuration(|configuration| { match configuration .groups diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller.rs index 7b986cde20..a23b240eda 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller.rs @@ -9,14 +9,14 @@ use serde::Serialize; use flowy_error::FlowyResult; -use crate::entities::{FieldType, GroupChangesetPB, GroupRowsNotificationPB, InsertedRowPB}; +use crate::entities::{FieldType, GroupChangesPB, GroupRowsNotificationPB, InsertedRowPB}; use crate::services::cell::{get_cell_protobuf, CellProtobufBlobParser, DecodedCellData}; use crate::services::group::action::{ - DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerActions, GroupCustomize, + DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, GroupCustomize, }; use crate::services::group::configuration::GroupContext; use crate::services::group::entities::GroupData; -use crate::services::group::Group; +use crate::services::group::{Group, GroupSettingChangeset}; // use collab_database::views::Group; @@ -28,24 +28,30 @@ use crate::services::group::Group; /// If the [FieldType] doesn't implement its group controller, then the [DefaultGroupController] will /// be used. /// -pub trait GroupController: GroupControllerActions + Send + Sync { +pub trait GroupController: GroupControllerOperation + Send + Sync { + /// Called when the type option of the [Field] was updated. + fn did_update_field_type_option(&mut self, field: &Arc); + + /// Called before the row was created. fn will_create_row(&mut self, cells: &mut Cells, field: &Field, group_id: &str); + + /// Called after the row was created. fn did_create_row(&mut self, row: &Row, group_id: &str); } -/// The [GroupGenerator] trait is used to generate the groups for different [FieldType] -pub trait GroupGenerator { +/// The [GroupsBuilder] trait is used to generate the groups for different [FieldType] +pub trait GroupsBuilder { type Context; type TypeOptionType; - fn generate_groups( + fn build( field: &Field, - group_ctx: &Self::Context, + context: &Self::Context, type_option: &Option, - ) -> GeneratedGroupContext; + ) -> GeneratedGroups; } -pub struct GeneratedGroupContext { +pub struct GeneratedGroups { pub no_status_group: Option, pub group_configs: Vec, } @@ -90,21 +96,21 @@ impl RowChangeset { /// C: represents the group configuration that impl [GroupConfigurationSerde] /// T: the type-option data deserializer that impl [TypeOptionDataDeserializer] -/// G: the group generator, [GroupGenerator] +/// G: the group generator, [GroupsBuilder] /// P: the parser that impl [CellProtobufBlobParser] for the CellBytes -pub struct GenericGroupController { +pub struct BaseGroupController { pub grouping_field_id: String, pub type_option: Option, - pub group_ctx: GroupContext, + pub context: GroupContext, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData

, } -impl GenericGroupController +impl BaseGroupController where C: Serialize + DeserializeOwned, T: From, - G: GroupGenerator, TypeOptionType = T>, + G: GroupsBuilder, TypeOptionType = T>, { pub async fn new( grouping_field: &Arc, @@ -112,13 +118,13 @@ where ) -> FlowyResult { let field_type = FieldType::from(grouping_field.field_type); let type_option = grouping_field.get_type_option::(field_type); - let generated_group_context = G::generate_groups(grouping_field, &configuration, &type_option); - let _ = configuration.init_groups(generated_group_context)?; + let generated_groups = G::build(grouping_field, &configuration, &type_option); + let _ = configuration.init_groups(generated_groups)?; Ok(Self { grouping_field_id: grouping_field.id.clone(), type_option, - group_ctx: configuration, + context: configuration, group_action_phantom: PhantomData, cell_parser_phantom: PhantomData, }) @@ -131,7 +137,7 @@ where row: &Row, other_group_changesets: &[GroupRowsNotificationPB], ) -> Option { - let no_status_group = self.group_ctx.get_mut_no_status_group()?; + let no_status_group = self.context.get_mut_no_status_group()?; // [other_group_inserted_row] contains all the inserted rows except the default group. let other_group_inserted_row = other_group_changesets @@ -196,12 +202,12 @@ where } } -impl GroupControllerActions for GenericGroupController +impl GroupControllerOperation for BaseGroupController where P: CellProtobufBlobParser, C: Serialize + DeserializeOwned, T: From, - G: GroupGenerator, TypeOptionType = T>, + G: GroupsBuilder, TypeOptionType = T>, Self: GroupCustomize, { @@ -210,11 +216,11 @@ where } fn groups(&self) -> Vec<&GroupData> { - self.group_ctx.groups() + self.context.groups() } fn get_group(&self, group_id: &str) -> Option<(usize, GroupData)> { - let group = self.group_ctx.get_group(group_id)?; + let group = self.context.get_group(group_id)?; Some((group.0, group.1.clone())) } @@ -230,7 +236,7 @@ where let mut grouped_rows: Vec = vec![]; let cell_bytes = get_cell_protobuf(&cell, field, None); let cell_data = cell_bytes.parser::

()?; - for group in self.group_ctx.groups() { + for group in self.context.groups() { if self.can_group(&group.filter_content, &cell_data) { grouped_rows.push(GroupedRow { row: (*row).clone(), @@ -241,25 +247,25 @@ where if !grouped_rows.is_empty() { for group_row in grouped_rows { - if let Some(group) = self.group_ctx.get_mut_group(&group_row.group_id) { + if let Some(group) = self.context.get_mut_group(&group_row.group_id) { group.add_row(group_row.row); } } continue; } } - match self.group_ctx.get_mut_no_status_group() { + match self.context.get_mut_no_status_group() { None => {}, Some(no_status_group) => no_status_group.add_row((*row).clone()), } } - tracing::Span::current().record("group_result", format!("{},", self.group_ctx,).as_str()); + tracing::Span::current().record("group_result", format!("{},", self.context,).as_str()); Ok(()) } fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()> { - self.group_ctx.move_group(from_group_id, to_group_id) + self.context.move_group(from_group_id, to_group_id) } fn did_update_group_row( @@ -320,7 +326,7 @@ where } } - match self.group_ctx.get_no_status_group() { + match self.context.get_no_status_group() { None => { tracing::error!("Unexpected None value. It should have the no status group"); }, @@ -359,9 +365,18 @@ where Ok(result) } - fn did_update_group_field(&mut self, _field: &Field) -> FlowyResult> { + fn did_update_group_field(&mut self, _field: &Field) -> FlowyResult> { Ok(None) } + + fn apply_group_setting_changeset(&mut self, changeset: GroupSettingChangeset) -> FlowyResult<()> { + for group_changeset in changeset.update_groups { + if let Err(e) = self.context.update_group(group_changeset) { + tracing::error!("Failed to update group: {:?}", e); + } + } + Ok(()) + } } struct GroupedRow { diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/checkbox_controller.rs index f9f32e18ca..7c8ba00c3d 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/checkbox_controller.rs @@ -1,6 +1,7 @@ use collab_database::fields::Field; use collab_database::rows::{new_cell_builder, Cell, Cells, Row}; use serde::{Deserialize, Serialize}; +use std::sync::Arc; use crate::entities::{FieldType, GroupRowsNotificationPB, InsertedRowPB, RowPB}; use crate::services::cell::insert_checkbox_cell; @@ -10,16 +11,16 @@ use crate::services::field::{ use crate::services::group::action::GroupCustomize; use crate::services::group::configuration::GroupContext; use crate::services::group::controller::{ - GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, + BaseGroupController, GroupController, GroupsBuilder, MoveGroupRowContext, }; -use crate::services::group::{move_group_row, GeneratedGroupConfig, GeneratedGroupContext, Group}; +use crate::services::group::{move_group_row, GeneratedGroupConfig, GeneratedGroups, Group}; #[derive(Default, Serialize, Deserialize)] pub struct CheckboxGroupConfiguration { pub hide_empty: bool, } -pub type CheckboxGroupController = GenericGroupController< +pub type CheckboxGroupController = BaseGroupController< CheckboxGroupConfiguration, CheckboxTypeOption, CheckboxGroupGenerator, @@ -52,7 +53,7 @@ impl GroupCustomize for CheckboxGroupController { cell_data: &Self::CellData, ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_status_groups(|group| { + self.context.iter_mut_status_groups(|group| { let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); let is_not_contained = !group.contains_row(&row.id); if group.id == CHECK { @@ -96,7 +97,7 @@ impl GroupCustomize for CheckboxGroupController { fn delete_row(&mut self, row: &Row, _cell_data: &Self::CellData) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_groups(|group| { + self.context.iter_mut_groups(|group| { let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); if group.contains_row(&row.id) { changeset.deleted_rows.push(row.id.clone().into_inner()); @@ -116,7 +117,7 @@ impl GroupCustomize for CheckboxGroupController { mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_groups(|group| { + self.context.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -126,8 +127,12 @@ impl GroupCustomize for CheckboxGroupController { } impl GroupController for CheckboxGroupController { + fn did_update_field_type_option(&mut self, _field: &Arc) { + // Do nothing + } + fn will_create_row(&mut self, cells: &mut Cells, field: &Field, group_id: &str) { - match self.group_ctx.get_group(group_id) { + match self.context.get_group(group_id) { None => tracing::warn!("Can not find the group: {}", group_id), Some((_, group)) => { let is_check = group.id == CHECK; @@ -138,22 +143,22 @@ impl GroupController for CheckboxGroupController { } fn did_create_row(&mut self, row: &Row, group_id: &str) { - if let Some(group) = self.group_ctx.get_mut_group(group_id) { + if let Some(group) = self.context.get_mut_group(group_id) { group.add_row(row.clone()) } } } pub struct CheckboxGroupGenerator(); -impl GroupGenerator for CheckboxGroupGenerator { +impl GroupsBuilder for CheckboxGroupGenerator { type Context = CheckboxGroupContext; type TypeOptionType = CheckboxTypeOption; - fn generate_groups( + fn build( _field: &Field, - _group_ctx: &Self::Context, + _context: &Self::Context, _type_option: &Option, - ) -> GeneratedGroupContext { + ) -> GeneratedGroups { let check_group = GeneratedGroupConfig { group: Group::new(CHECK.to_string(), "".to_string()), filter_content: CHECK.to_string(), @@ -164,7 +169,7 @@ impl GroupGenerator for CheckboxGroupGenerator { filter_content: UNCHECK.to_string(), }; - GeneratedGroupContext { + GeneratedGroups { no_status_group: None, group_configs: vec![check_group, uncheck_group], } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs index 7324ad0063..61e505b824 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs @@ -5,11 +5,13 @@ use collab_database::rows::{Cells, Row}; use flowy_error::FlowyResult; -use crate::entities::GroupChangesetPB; +use crate::entities::GroupChangesPB; use crate::services::group::action::{ - DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerActions, + DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, +}; +use crate::services::group::{ + GroupController, GroupData, GroupSettingChangeset, MoveGroupRowContext, }; -use crate::services::group::{GroupController, GroupData, MoveGroupRowContext}; /// A [DefaultGroupController] is used to handle the group actions for the [FieldType] that doesn't /// implement its own group controller. The default group controller only contains one group, which @@ -37,7 +39,7 @@ impl DefaultGroupController { } } -impl GroupControllerActions for DefaultGroupController { +impl GroupControllerOperation for DefaultGroupController { fn field_id(&self) -> &str { &self.field_id } @@ -95,12 +97,23 @@ impl GroupControllerActions for DefaultGroupController { }) } - fn did_update_group_field(&mut self, _field: &Field) -> FlowyResult> { + fn did_update_group_field(&mut self, _field: &Field) -> FlowyResult> { Ok(None) } + + fn apply_group_setting_changeset( + &mut self, + _changeset: GroupSettingChangeset, + ) -> FlowyResult<()> { + Ok(()) + } } impl GroupController for DefaultGroupController { + fn did_update_field_type_option(&mut self, _field: &Arc) { + // Do nothing + } + fn will_create_row(&mut self, _cells: &mut Cells, _field: &Field, _group_id: &str) {} fn did_create_row(&mut self, _row: &Row, _group_id: &str) {} diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index 595df4ad89..091e51a21c 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -3,14 +3,15 @@ use crate::services::cell::insert_select_option_cell; use crate::services::field::{MultiSelectTypeOption, SelectOptionCellDataParser}; use crate::services::group::action::GroupCustomize; use crate::services::group::controller::{ - GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, + BaseGroupController, GroupController, GroupsBuilder, MoveGroupRowContext, }; use crate::services::group::{ add_or_remove_select_option_row, generate_select_option_groups, make_no_status_group, - move_group_row, remove_select_option_row, GeneratedGroupContext, GroupContext, + move_group_row, remove_select_option_row, GeneratedGroups, GroupContext, }; use collab_database::fields::Field; use collab_database::rows::{Cells, Row}; +use std::sync::Arc; use serde::{Deserialize, Serialize}; @@ -21,7 +22,7 @@ pub struct MultiSelectGroupConfiguration { pub type MultiSelectOptionGroupContext = GroupContext; // MultiSelect -pub type MultiSelectGroupController = GenericGroupController< +pub type MultiSelectGroupController = BaseGroupController< MultiSelectGroupConfiguration, MultiSelectTypeOption, MultiSelectGroupGenerator, @@ -44,7 +45,7 @@ impl GroupCustomize for MultiSelectGroupController { cell_data: &Self::CellData, ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_status_groups(|group| { + self.context.iter_mut_status_groups(|group| { if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row) { changesets.push(changeset); } @@ -54,7 +55,7 @@ impl GroupCustomize for MultiSelectGroupController { fn delete_row(&mut self, row: &Row, cell_data: &Self::CellData) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_status_groups(|group| { + self.context.iter_mut_status_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row) { changesets.push(changeset); } @@ -68,7 +69,7 @@ impl GroupCustomize for MultiSelectGroupController { mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_groups(|group| { + self.context.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -78,8 +79,10 @@ impl GroupCustomize for MultiSelectGroupController { } impl GroupController for MultiSelectGroupController { + fn did_update_field_type_option(&mut self, _field: &Arc) {} + fn will_create_row(&mut self, cells: &mut Cells, field: &Field, group_id: &str) { - match self.group_ctx.get_group(group_id) { + match self.context.get_group(group_id) { None => tracing::warn!("Can not find the group: {}", group_id), Some((_, group)) => { let cell = insert_select_option_cell(vec![group.id.clone()], field); @@ -89,28 +92,28 @@ impl GroupController for MultiSelectGroupController { } fn did_create_row(&mut self, row: &Row, group_id: &str) { - if let Some(group) = self.group_ctx.get_mut_group(group_id) { + if let Some(group) = self.context.get_mut_group(group_id) { group.add_row(row.clone()) } } } -pub struct MultiSelectGroupGenerator(); -impl GroupGenerator for MultiSelectGroupGenerator { +pub struct MultiSelectGroupGenerator; +impl GroupsBuilder for MultiSelectGroupGenerator { type Context = MultiSelectOptionGroupContext; type TypeOptionType = MultiSelectTypeOption; - fn generate_groups( + fn build( field: &Field, - _group_ctx: &Self::Context, + _context: &Self::Context, type_option: &Option, - ) -> GeneratedGroupContext { + ) -> GeneratedGroups { let group_configs = match type_option { None => vec![], Some(type_option) => generate_select_option_groups(&field.id, &type_option.options), }; - GeneratedGroupContext { + GeneratedGroups { no_status_group: Some(make_no_status_group(field)), group_configs, } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index 2fbac01f03..f8bef6d857 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -4,13 +4,14 @@ use crate::services::field::{SelectOptionCellDataParser, SingleSelectTypeOption} use crate::services::group::action::GroupCustomize; use collab_database::fields::Field; use collab_database::rows::{Cells, Row}; +use std::sync::Arc; use crate::services::group::controller::{ - GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, + BaseGroupController, GroupController, GroupsBuilder, MoveGroupRowContext, }; use crate::services::group::controller_impls::select_option_controller::util::*; use crate::services::group::entities::GroupData; -use crate::services::group::{make_no_status_group, GeneratedGroupContext, GroupContext}; +use crate::services::group::{make_no_status_group, GeneratedGroups, GroupContext}; use serde::{Deserialize, Serialize}; @@ -22,7 +23,7 @@ pub struct SingleSelectGroupConfiguration { pub type SingleSelectOptionGroupContext = GroupContext; // SingleSelect -pub type SingleSelectGroupController = GenericGroupController< +pub type SingleSelectGroupController = BaseGroupController< SingleSelectGroupConfiguration, SingleSelectTypeOption, SingleSelectGroupGenerator, @@ -44,7 +45,7 @@ impl GroupCustomize for SingleSelectGroupController { cell_data: &Self::CellData, ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_status_groups(|group| { + self.context.iter_mut_status_groups(|group| { if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row) { changesets.push(changeset); } @@ -54,7 +55,7 @@ impl GroupCustomize for SingleSelectGroupController { fn delete_row(&mut self, row: &Row, cell_data: &Self::CellData) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_status_groups(|group| { + self.context.iter_mut_status_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row) { changesets.push(changeset); } @@ -68,7 +69,7 @@ impl GroupCustomize for SingleSelectGroupController { mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_groups(|group| { + self.context.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -78,8 +79,10 @@ impl GroupCustomize for SingleSelectGroupController { } impl GroupController for SingleSelectGroupController { + fn did_update_field_type_option(&mut self, _field: &Arc) {} + fn will_create_row(&mut self, cells: &mut Cells, field: &Field, group_id: &str) { - let group: Option<&mut GroupData> = self.group_ctx.get_mut_group(group_id); + let group: Option<&mut GroupData> = self.context.get_mut_group(group_id); match group { None => {}, Some(group) => { @@ -89,27 +92,27 @@ impl GroupController for SingleSelectGroupController { } } fn did_create_row(&mut self, row: &Row, group_id: &str) { - if let Some(group) = self.group_ctx.get_mut_group(group_id) { + if let Some(group) = self.context.get_mut_group(group_id) { group.add_row(row.clone()) } } } pub struct SingleSelectGroupGenerator(); -impl GroupGenerator for SingleSelectGroupGenerator { +impl GroupsBuilder for SingleSelectGroupGenerator { type Context = SingleSelectOptionGroupContext; type TypeOptionType = SingleSelectTypeOption; - fn generate_groups( + fn build( field: &Field, - _group_ctx: &Self::Context, + _context: &Self::Context, type_option: &Option, - ) -> GeneratedGroupContext { + ) -> GeneratedGroups { let group_configs = match type_option { None => vec![], Some(type_option) => generate_select_option_groups(&field.id, &type_option.options), }; - GeneratedGroupContext { + GeneratedGroups { no_status_group: Some(make_no_status_group(field)), group_configs, } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/url_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/url_controller.rs index 7580b9d5da..513ceade0c 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/url_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/url_controller.rs @@ -1,6 +1,7 @@ use collab_database::fields::Field; use collab_database::rows::{new_cell_builder, Cell, Cells, Row}; use serde::{Deserialize, Serialize}; +use std::sync::Arc; use flowy_error::FlowyResult; @@ -12,10 +13,10 @@ use crate::services::field::{URLCellData, URLCellDataParser, URLTypeOption}; use crate::services::group::action::GroupCustomize; use crate::services::group::configuration::GroupContext; use crate::services::group::controller::{ - GenericGroupController, GroupController, GroupGenerator, MoveGroupRowContext, + BaseGroupController, GroupController, GroupsBuilder, MoveGroupRowContext, }; use crate::services::group::{ - make_no_status_group, move_group_row, GeneratedGroupConfig, GeneratedGroupContext, Group, + make_no_status_group, move_group_row, GeneratedGroupConfig, GeneratedGroups, Group, }; #[derive(Default, Serialize, Deserialize)] @@ -23,12 +24,8 @@ pub struct URLGroupConfiguration { pub hide_empty: bool, } -pub type URLGroupController = GenericGroupController< - URLGroupConfiguration, - URLTypeOption, - URLGroupGenerator, - URLCellDataParser, ->; +pub type URLGroupController = + BaseGroupController; pub type URLGroupContext = GroupContext; @@ -55,17 +52,17 @@ impl GroupCustomize for URLGroupController { ) -> FlowyResult<(Option, Option)> { // Just return if the group with this url already exists let mut inserted_group = None; - if self.group_ctx.get_group(&_cell_data.url).is_none() { + if self.context.get_group(&_cell_data.url).is_none() { let cell_data: URLCellData = _cell_data.clone().into(); let group = make_group_from_url_cell(&cell_data); - let mut new_group = self.group_ctx.add_new_group(group)?; + let mut new_group = self.context.add_new_group(group)?; new_group.group.rows.push(RowPB::from(row)); inserted_group = Some(new_group); } // Delete the old url group if there are no rows in that group let deleted_group = match _old_cell_data - .and_then(|old_cell_data| self.group_ctx.get_group(&old_cell_data.content)) + .and_then(|old_cell_data| self.context.get_group(&old_cell_data.content)) { None => None, Some((_, group)) => { @@ -80,7 +77,7 @@ impl GroupCustomize for URLGroupController { let deleted_group = match deleted_group { None => None, Some(group) => { - self.group_ctx.delete_group(&group.id)?; + self.context.delete_group(&group.id)?; Some(GroupPB::from(group.clone())) }, }; @@ -94,7 +91,7 @@ impl GroupCustomize for URLGroupController { cell_data: &Self::CellData, ) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_status_groups(|group| { + self.context.iter_mut_status_groups(|group| { let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); if group.id == cell_data.content { if !group.contains_row(&row.id) { @@ -117,7 +114,7 @@ impl GroupCustomize for URLGroupController { fn delete_row(&mut self, row: &Row, _cell_data: &Self::CellData) -> Vec { let mut changesets = vec![]; - self.group_ctx.iter_mut_groups(|group| { + self.context.iter_mut_groups(|group| { let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); if group.contains_row(&row.id) { group.remove_row(&row.id); @@ -137,7 +134,7 @@ impl GroupCustomize for URLGroupController { mut context: MoveGroupRowContext, ) -> Vec { let mut group_changeset = vec![]; - self.group_ctx.iter_mut_groups(|group| { + self.context.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { group_changeset.push(changeset); } @@ -151,14 +148,14 @@ impl GroupCustomize for URLGroupController { _cell_data: &Self::CellData, ) -> Option { let mut deleted_group = None; - if let Some((_, group)) = self.group_ctx.get_group(&_cell_data.content) { + if let Some((_, group)) = self.context.get_group(&_cell_data.content) { if group.rows.len() == 1 { deleted_group = Some(GroupPB::from(group.clone())); } } if deleted_group.is_some() { let _ = self - .group_ctx + .context .delete_group(&deleted_group.as_ref().unwrap().group_id); } deleted_group @@ -166,8 +163,10 @@ impl GroupCustomize for URLGroupController { } impl GroupController for URLGroupController { + fn did_update_field_type_option(&mut self, _field: &Arc) {} + fn will_create_row(&mut self, cells: &mut Cells, field: &Field, group_id: &str) { - match self.group_ctx.get_group(group_id) { + match self.context.get_group(group_id) { None => tracing::warn!("Can not find the group: {}", group_id), Some((_, group)) => { let cell = insert_url_cell(group.id.clone(), field); @@ -177,24 +176,24 @@ impl GroupController for URLGroupController { } fn did_create_row(&mut self, row: &Row, group_id: &str) { - if let Some(group) = self.group_ctx.get_mut_group(group_id) { + if let Some(group) = self.context.get_mut_group(group_id) { group.add_row(row.clone()) } } } pub struct URLGroupGenerator(); -impl GroupGenerator for URLGroupGenerator { +impl GroupsBuilder for URLGroupGenerator { type Context = URLGroupContext; type TypeOptionType = URLTypeOption; - fn generate_groups( + fn build( field: &Field, - group_ctx: &Self::Context, + context: &Self::Context, _type_option: &Option, - ) -> GeneratedGroupContext { + ) -> GeneratedGroups { // Read all the cells for the grouping field - let cells = futures::executor::block_on(group_ctx.get_all_cells()); + let cells = futures::executor::block_on(context.get_all_cells()); // Generate the groups let group_configs = cells @@ -208,7 +207,7 @@ impl GroupGenerator for URLGroupGenerator { .collect(); let no_status_group = Some(make_no_status_group(field)); - GeneratedGroupContext { + GeneratedGroups { no_status_group, group_configs, } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/entities.rs b/frontend/rust-lib/flowy-database2/src/services/group/entities.rs index 27d24b5510..31f99e3b88 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/entities.rs @@ -14,6 +14,16 @@ pub struct GroupSetting { pub content: String, } +pub struct GroupSettingChangeset { + pub update_groups: Vec, +} + +pub struct GroupChangeset { + pub group_id: String, + pub name: Option, + pub visible: Option, +} + impl GroupSetting { pub fn new(field_id: String, field_type: i64, content: String) -> Self { Self { @@ -75,7 +85,7 @@ impl From for GroupSettingMap { pub struct Group { pub id: String, pub name: String, - #[serde(default = "GROUP_REV_VISIBILITY")] + #[serde(default = "GROUP_VISIBILITY")] pub visible: bool, } @@ -104,7 +114,7 @@ impl From for GroupMap { } } -const GROUP_REV_VISIBILITY: fn() -> bool = || true; +const GROUP_VISIBILITY: fn() -> bool = || true; impl Group { pub fn new(id: String, name: String) -> Self { diff --git a/frontend/rust-lib/flowy-database2/src/services/group/group_util.rs b/frontend/rust-lib/flowy-database2/src/services/group/group_util.rs index b330eecfc1..428a72fa11 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/group_util.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/group_util.rs @@ -42,7 +42,7 @@ where W: GroupSettingWriter, { let grouping_field_type = FieldType::from(grouping_field.field_type); - tracing::Span::current().record("grouping_field_type", &grouping_field_type.default_name()); + tracing::Span::current().record("grouping_field", &grouping_field_type.default_name()); let mut group_controller: Box; let configuration_reader = Arc::new(setting_reader); diff --git a/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs b/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs index a8d0c28d61..15229eb81f 100644 --- a/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs @@ -82,7 +82,9 @@ impl SortController { pub async fn did_receive_row_changed(&self, row_id: RowId) { let task_type = SortEvent::RowDidChanged(row_id); - self.gen_task(task_type, QualityOfService::Background).await; + if !self.sorts.is_empty() { + self.gen_task(task_type, QualityOfService::Background).await; + } } // #[tracing::instrument(name = "process_sort_task", level = "trace", skip_all, err)] @@ -169,7 +171,7 @@ impl SortController { .await; } - pub async fn did_update_view_field_type_option(&self, _field_rev: &Field) { + pub async fn did_update_field_type_option(&self, _field: &Field) { // } diff --git a/frontend/rust-lib/flowy-database2/tests/database/filter_test/script.rs b/frontend/rust-lib/flowy-database2/tests/database/filter_test/script.rs index 93c3598dd4..98e9d74051 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/filter_test/script.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/filter_test/script.rs @@ -10,7 +10,7 @@ use collab_database::rows::{Row, RowId}; use futures::TryFutureExt; use tokio::sync::broadcast::Receiver; -use flowy_database2::entities::{AlterFilterParams, AlterFilterPayloadPB, CheckboxFilterConditionPB, CheckboxFilterPB, ChecklistFilterConditionPB, ChecklistFilterPB, DatabaseViewSettingPB, DateFilterConditionPB, DateFilterPB, DeleteFilterParams, FieldType, FilterPB, NumberFilterConditionPB, NumberFilterPB, SelectOptionConditionPB, SelectOptionFilterPB, TextFilterConditionPB, TextFilterPB}; +use flowy_database2::entities::{UpdateFilterParams, UpdateFilterPayloadPB, CheckboxFilterConditionPB, CheckboxFilterPB, ChecklistFilterConditionPB, ChecklistFilterPB, DatabaseViewSettingPB, DateFilterConditionPB, DateFilterPB, DeleteFilterParams, FieldType, FilterPB, NumberFilterConditionPB, NumberFilterPB, SelectOptionConditionPB, SelectOptionFilterPB, TextFilterConditionPB, TextFilterPB}; use flowy_database2::services::database_view::DatabaseViewChanged; use flowy_database2::services::filter::FilterType; @@ -33,7 +33,7 @@ pub enum FilterScript { changed: Option, }, InsertFilter { - payload: AlterFilterPayloadPB, + payload: UpdateFilterPayloadPB, }, CreateTextFilter { condition: TextFilterConditionPB, @@ -151,7 +151,7 @@ impl DatabaseFilterTest { content }; let payload = - AlterFilterPayloadPB::new( + UpdateFilterPayloadPB::new( & self.view_id(), &field, text_filter); self.insert_filter(payload).await; @@ -159,7 +159,7 @@ impl DatabaseFilterTest { FilterScript::UpdateTextFilter { filter, condition, content, changed} => { self.recv = Some(self.editor.subscribe_view_changed(&self.view_id()).await.unwrap()); self.assert_future_changed(changed).await; - let params = AlterFilterParams { + let params = UpdateFilterParams { view_id: self.view_id(), field_id: filter.field_id, filter_id: Some(filter.id), @@ -178,7 +178,7 @@ impl DatabaseFilterTest { content }; let payload = - AlterFilterPayloadPB::new( + UpdateFilterPayloadPB::new( &self.view_id(), &field, number_filter); self.insert_filter(payload).await; @@ -191,7 +191,7 @@ impl DatabaseFilterTest { condition }; let payload = - AlterFilterPayloadPB::new(& self.view_id(), &field, checkbox_filter); + UpdateFilterPayloadPB::new(& self.view_id(), &field, checkbox_filter); self.insert_filter(payload).await; } FilterScript::CreateDateFilter { condition, start, end, timestamp, changed} => { @@ -206,7 +206,7 @@ impl DatabaseFilterTest { }; let payload = - AlterFilterPayloadPB::new(&self.view_id(), &field, date_filter); + UpdateFilterPayloadPB::new(&self.view_id(), &field, date_filter); self.insert_filter(payload).await; } FilterScript::CreateMultiSelectFilter { condition, option_ids} => { @@ -214,7 +214,7 @@ impl DatabaseFilterTest { let field = self.get_first_field(FieldType::MultiSelect); let filter = SelectOptionFilterPB { condition, option_ids }; let payload = - AlterFilterPayloadPB::new(&self.view_id(), &field, filter); + UpdateFilterPayloadPB::new(&self.view_id(), &field, filter); self.insert_filter(payload).await; } FilterScript::CreateSingleSelectFilter { condition, option_ids, changed} => { @@ -223,7 +223,7 @@ impl DatabaseFilterTest { let field = self.get_first_field(FieldType::SingleSelect); let filter = SelectOptionFilterPB { condition, option_ids }; let payload = - AlterFilterPayloadPB::new(& self.view_id(), &field, filter); + UpdateFilterPayloadPB::new(& self.view_id(), &field, filter); self.insert_filter(payload).await; } FilterScript::CreateChecklistFilter { condition,changed} => { @@ -233,7 +233,7 @@ impl DatabaseFilterTest { // let type_option = self.get_checklist_type_option(&field_rev.id); let filter = ChecklistFilterPB { condition }; let payload = - AlterFilterPayloadPB::new(& self.view_id(), &field, filter); + UpdateFilterPayloadPB::new(& self.view_id(), &field, filter); self.insert_filter(payload).await; } FilterScript::AssertFilterCount { count } => { @@ -289,8 +289,8 @@ impl DatabaseFilterTest { } - async fn insert_filter(&self, payload: AlterFilterPayloadPB) { - let params: AlterFilterParams = payload.try_into().unwrap(); + async fn insert_filter(&self, payload: UpdateFilterPayloadPB) { + let params: UpdateFilterParams = payload.try_into().unwrap(); let _ = self.editor.create_or_update_filter(params).await.unwrap(); } diff --git a/frontend/rust-lib/flowy-database2/tests/database/filter_test/text_filter_test.rs b/frontend/rust-lib/flowy-database2/tests/database/filter_test/text_filter_test.rs index 1593e2e2e3..f04478adc0 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/filter_test/text_filter_test.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/filter_test/text_filter_test.rs @@ -1,7 +1,7 @@ use crate::database::filter_test::script::FilterScript::*; use crate::database::filter_test::script::*; use flowy_database2::entities::{ - AlterFilterPayloadPB, FieldType, TextFilterConditionPB, TextFilterPB, + FieldType, TextFilterConditionPB, TextFilterPB, UpdateFilterPayloadPB, }; use flowy_database2::services::filter::FilterType; @@ -195,7 +195,7 @@ async fn grid_filter_delete_test() { condition: TextFilterConditionPB::TextIsEmpty, content: "".to_string(), }; - let payload = AlterFilterPayloadPB::new(&test.view_id(), &field, text_filter); + let payload = UpdateFilterPayloadPB::new(&test.view_id(), &field, text_filter); let scripts = vec![ InsertFilter { payload }, AssertFilterCount { count: 1 }, diff --git a/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs b/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs index 7eedada1b4..544c416960 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs @@ -8,7 +8,7 @@ use collab_database::rows::RowId; use futures::stream::StreamExt; use tokio::sync::broadcast::Receiver; -use flowy_database2::entities::{AlterSortParams, DeleteSortParams, FieldType}; +use flowy_database2::entities::{DeleteSortParams, FieldType, UpdateSortParams}; use flowy_database2::services::cell::stringify_cell_data; use flowy_database2::services::database_view::DatabaseViewChanged; use flowy_database2::services::sort::{Sort, SortCondition, SortType}; @@ -72,7 +72,7 @@ impl DatabaseSortTest { .await .unwrap(), ); - let params = AlterSortParams { + let params = UpdateSortParams { view_id: self.view_id.clone(), field_id: field.id.clone(), sort_id: None, diff --git a/frontend/rust-lib/lib-log/src/layer.rs b/frontend/rust-lib/lib-log/src/layer.rs index 370893f375..9a0af79f9e 100644 --- a/frontend/rust-lib/lib-log/src/layer.rs +++ b/frontend/rust-lib/lib-log/src/layer.rs @@ -13,7 +13,7 @@ const MESSAGE: &str = "msg"; const LOG_MODULE_PATH: &str = "log.module_path"; const LOG_TARGET_PATH: &str = "log.target"; -const FLOWY_RESERVED_FIELDS: [&str; 3] = [LEVEL, TIME, MESSAGE]; +const RESERVED_FIELDS: [&str; 3] = [LEVEL, TIME, MESSAGE]; const IGNORE_FIELDS: [&str; 2] = [LOG_MODULE_PATH, LOG_TARGET_PATH]; pub struct FlowyFormattingLayer { @@ -29,7 +29,7 @@ impl FlowyFormattingLayer { } } - fn serialize_flowy_folder_fields( + fn serialize_fields( &self, map_serializer: &mut impl SerializeMap, message: &str, @@ -45,12 +45,13 @@ impl FlowyFormattingLayer { &self, span: &SpanRef, ty: Type, + ctx: &Context<'_, S>, ) -> Result, std::io::Error> { let mut buffer = Vec::new(); let mut serializer = serde_json::Serializer::new(&mut buffer); let mut map_serializer = serializer.serialize_map(None)?; - let message = format_span_context(span, ty); - self.serialize_flowy_folder_fields(&mut map_serializer, &message, span.metadata().level())?; + let message = format_span_context(span, ty, ctx); + self.serialize_fields(&mut map_serializer, &message, span.metadata().level())?; if self.with_target { map_serializer.serialize_entry("target", &span.metadata().target())?; } @@ -61,7 +62,7 @@ impl FlowyFormattingLayer { let extensions = span.extensions(); if let Some(visitor) = extensions.get::() { for (key, value) in visitor.values() { - if !FLOWY_RESERVED_FIELDS.contains(key) && !IGNORE_FIELDS.contains(key) { + if !RESERVED_FIELDS.contains(key) && !IGNORE_FIELDS.contains(key) { map_serializer.serialize_entry(key, value)?; } else { tracing::debug!( @@ -93,9 +94,9 @@ pub enum Type { impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let repr = match self { - Type::EnterSpan => "START", - Type::ExitSpan => "END", - Type::Event => "EVENT", + Type::EnterSpan => "Start", + Type::ExitSpan => "End", + Type::Event => "Event", }; write!(f, "{}", repr) } @@ -104,14 +105,27 @@ impl fmt::Display for Type { fn format_span_context tracing_subscriber::registry::LookupSpan<'a>>( span: &SpanRef, ty: Type, + context: &Context<'_, S>, ) -> String { - format!("[⛳ {} - {}]", span.metadata().name().to_uppercase(), ty) + match context.lookup_current() { + None => { + if matches!(ty, Type::EnterSpan) { + format!("[🟢 {} - {}]", span.metadata().name().to_uppercase(), ty) + } else { + format!("[🔵 {} - {}]", span.metadata().name().to_uppercase(), ty) + } + }, + Some(_) => { + format!("[{} - {}]", span.metadata().name().to_uppercase(), ty) + }, + } } fn format_event_message tracing_subscriber::registry::LookupSpan<'a>>( current_span: &Option>, event: &Event, event_visitor: &JsonStorage<'_>, + context: &Context<'_, S>, ) -> String { // Extract the "message" field, if provided. Fallback to the target, if missing. let mut message = event_visitor @@ -127,7 +141,11 @@ fn format_event_message tracing_subscriber::registry::Lo // If the event is in the context of a span, prepend the span name to the // message. if let Some(span) = ¤t_span { - message = format!("{} {}", format_span_context(span, Type::Event), message); + message = format!( + "{} {}", + format_span_context(span, Type::Event, context), + message + ); } message @@ -154,12 +172,8 @@ where let mut serializer = serde_json::Serializer::new(&mut buffer); let mut map_serializer = serializer.serialize_map(None)?; - let message = format_event_message(¤t_span, event, &event_visitor); - self.serialize_flowy_folder_fields( - &mut map_serializer, - &message, - event.metadata().level(), - )?; + let message = format_event_message(¤t_span, event, &event_visitor, &ctx); + self.serialize_fields(&mut map_serializer, &message, event.metadata().level())?; // Additional metadata useful for debugging // They should be nested under `src` (see https://github.com/trentm/node-bunyan#src ) // but `tracing` does not support nested values yet @@ -174,7 +188,7 @@ where // Add all the other fields associated with the event, expect the message we // already used. for (key, value) in event_visitor.values().iter().filter(|(&key, _)| { - key != "message" && !FLOWY_RESERVED_FIELDS.contains(&key) && !IGNORE_FIELDS.contains(&key) + key != "message" && !RESERVED_FIELDS.contains(&key) && !IGNORE_FIELDS.contains(&key) }) { map_serializer.serialize_entry(key, value)?; } @@ -184,7 +198,7 @@ where let extensions = span.extensions(); if let Some(visitor) = extensions.get::() { for (key, value) in visitor.values() { - if !FLOWY_RESERVED_FIELDS.contains(key) && !IGNORE_FIELDS.contains(key) { + if !RESERVED_FIELDS.contains(key) && !IGNORE_FIELDS.contains(key) { map_serializer.serialize_entry(key, value)?; } else { tracing::debug!( @@ -207,14 +221,14 @@ where fn new_span(&self, _attrs: &Attributes, id: &Id, ctx: Context<'_, S>) { let span = ctx.span(id).expect("Span not found, this is a bug"); - if let Ok(serialized) = self.serialize_span(&span, Type::EnterSpan) { + if let Ok(serialized) = self.serialize_span(&span, Type::EnterSpan, &ctx) { let _ = self.emit(serialized); } } fn on_close(&self, id: Id, ctx: Context<'_, S>) { let span = ctx.span(&id).expect("Span not found, this is a bug"); - if let Ok(serialized) = self.serialize_span(&span, Type::ExitSpan) { + if let Ok(serialized) = self.serialize_span(&span, Type::ExitSpan, &ctx) { let _ = self.emit(serialized); } } diff --git a/frontend/rust-lib/lib-log/src/lib.rs b/frontend/rust-lib/lib-log/src/lib.rs index d445812746..39d28fd8af 100644 --- a/frontend/rust-lib/lib-log/src/lib.rs +++ b/frontend/rust-lib/lib-log/src/lib.rs @@ -42,30 +42,20 @@ impl Builder { let (non_blocking, guard) = tracing_appender::non_blocking(self.file_appender); let subscriber = tracing_subscriber::fmt() - // .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) - .with_ansi(false) - .with_target(false) - .with_max_level(tracing::Level::TRACE) - .with_writer(std::io::stderr) - .with_thread_ids(true) - // .with_writer(non_blocking) - .json() - .with_current_span(true) - .with_span_list(true) - .compact() - .finish() - .with(env_filter) - .with(JsonStorageLayer) - .with(FlowyFormattingLayer::new(std::io::stdout)) - .with(FlowyFormattingLayer::new(non_blocking)); - - // if cfg!(feature = "use_bunyan") { - // let formatting_layer = BunyanFormattingLayer::new(self.name.clone(), - // std::io::stdout); let _ = - // set_global_default(subscriber.with(JsonStorageLayer).with(formatting_layer)). - // map_err(|e| format!("{:?}", e))?; } else { - // let _ = set_global_default(subscriber).map_err(|e| format!("{:?}", e))?; - // } + .with_ansi(true) + .with_target(false) + .with_max_level(tracing::Level::TRACE) + .with_writer(std::io::stderr) + .with_thread_ids(true) + .json() + // .with_current_span(true) + // .with_span_list(true) + .compact() + .finish() + .with(env_filter) + .with(JsonStorageLayer) + .with(FlowyFormattingLayer::new(std::io::stdout)) + .with(FlowyFormattingLayer::new(non_blocking)); set_global_default(subscriber).map_err(|e| format!("{:?}", e))?; LogTracer::builder()