diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart index 6616dd80d1..0640c1fc6f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart @@ -1,7 +1,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controller.dart'; import 'package:appflowy/plugins/database_view/application/view/view_cache.dart'; -import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/board_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/calendar_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart'; @@ -47,12 +47,10 @@ class GroupCallbacks { } class DatabaseLayoutSettingCallbacks { - final void Function(DatabaseLayoutSettingPB) onLayoutChanged; - final void Function(DatabaseLayoutSettingPB) onLoadLayout; + final void Function(DatabaseLayoutSettingPB) onLayoutSettingsChanged; DatabaseLayoutSettingCallbacks({ - required this.onLayoutChanged, - required this.onLoadLayout, + required this.onLayoutSettingsChanged, }); } @@ -125,11 +123,11 @@ class DatabaseController { void addListener({ DatabaseCallbacks? onDatabaseChanged, - DatabaseLayoutSettingCallbacks? onLayoutChanged, + DatabaseLayoutSettingCallbacks? onLayoutSettingsChanged, GroupCallbacks? onGroupChanged, }) { - if (onLayoutChanged != null) { - _layoutCallbacks.add(onLayoutChanged); + if (onLayoutSettingsChanged != null) { + _layoutCallbacks.add(onLayoutSettingsChanged); } if (onDatabaseChanged != null) { @@ -228,12 +226,14 @@ class DatabaseController { ); } - Future updateLayoutSetting( - CalendarLayoutSettingPB calendarlLayoutSetting, - ) async { + Future updateLayoutSetting({ + BoardLayoutSettingPB? boardLayoutSetting, + CalendarLayoutSettingPB? calendarLayoutSetting, + }) async { await _databaseViewBackendSvc .updateLayoutSetting( - calendarLayoutSetting: calendarlLayoutSetting, + boardLayoutSetting: boardLayoutSetting, + calendarLayoutSetting: calendarLayoutSetting, layoutType: databaseLayout, ) .then((result) { @@ -241,15 +241,6 @@ class DatabaseController { }); } - void updateGroupConfiguration(bool hideUngrouped) async { - final payload = GroupSettingChangesetPB( - viewId: viewId, - groupConfigurationId: "", - hideUngrouped: hideUngrouped, - ); - DatabaseEventUpdateGroupConfiguration(payload).send(); - } - Future dispose() async { await _databaseViewBackendSvc.closeView(); await fieldController.dispose(); @@ -261,9 +252,6 @@ class DatabaseController { } Future _loadGroups() async { - final configResult = await loadGroupConfigurations(viewId: viewId); - _handleGroupConfigurationChanged(configResult); - final groupsResult = await _databaseViewBackendSvc.loadGroups(); groupsResult.fold( (groups) { @@ -280,10 +268,9 @@ class DatabaseController { result.fold( (newDatabaseLayoutSetting) { databaseLayoutSetting = newDatabaseLayoutSetting; - databaseLayoutSetting?.freeze(); for (final callback in _layoutCallbacks) { - callback.onLoadLayout(newDatabaseLayoutSetting); + callback.onLayoutSettingsChanged(newDatabaseLayoutSetting); } }, (r) => Log.error(r), @@ -339,7 +326,6 @@ class DatabaseController { void _listenOnGroupChanged() { _groupListener.start( - onGroupConfigurationChanged: _handleGroupConfigurationChanged, onNumOfGroupsChanged: (result) { result.fold( (changeset) { @@ -386,7 +372,7 @@ class DatabaseController { databaseLayoutSetting?.freeze(); for (final callback in _layoutCallbacks) { - callback.onLayoutChanged(newLayout); + callback.onLayoutSettingsChanged(newLayout); } }, (r) => Log.error(r), @@ -394,29 +380,6 @@ class DatabaseController { }, ); } - - Future, FlowyError>> loadGroupConfigurations({ - required String viewId, - }) { - final payload = DatabaseViewIdPB(value: viewId); - - return DatabaseEventGetGroupConfigurations(payload).send().then((result) { - return result.fold((l) => left(l.items), (r) => right(r)); - }); - } - - void _handleGroupConfigurationChanged( - Either, FlowyError> result, - ) { - result.fold( - (configurations) { - for (final callback in _groupCallbacks) { - callback.onGroupConfigurationChanged?.call(configurations); - } - }, - (r) => Log.error(r), - ); - } } class RowDataBuilder { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart index 623f99b94d..4cfeff8075 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart @@ -1,4 +1,5 @@ import 'package:appflowy/plugins/database_view/application/row/row_service.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/board_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/calendar_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group_changeset.pb.dart'; @@ -114,11 +115,17 @@ class DatabaseViewBackendService { Future> updateLayoutSetting({ required DatabaseLayoutPB layoutType, + BoardLayoutSettingPB? boardLayoutSetting, CalendarLayoutSettingPB? calendarLayoutSetting, }) { final payload = LayoutSettingChangesetPB.create() ..viewId = viewId ..layoutType = layoutType; + + if (boardLayoutSetting != null) { + payload.board = boardLayoutSetting; + } + if (calendarLayoutSetting != null) { payload.calendar = calendarLayoutSetting; } 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 bd419da29b..a07b287f43 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 @@ -15,8 +15,6 @@ typedef GroupByNewFieldValue = Either, FlowyError>; class DatabaseGroupListener { final String viewId; - PublishNotifier? _groupConfigurationNotifier = - PublishNotifier(); PublishNotifier? _numOfGroupsNotifier = PublishNotifier(); PublishNotifier? _groupByFieldNotifier = PublishNotifier(); @@ -24,13 +22,9 @@ class DatabaseGroupListener { DatabaseGroupListener(this.viewId); void start({ - required void Function(GroupConfigurationUpdateValue) - onGroupConfigurationChanged, required void Function(GroupUpdateValue) onNumOfGroupsChanged, required void Function(GroupByNewFieldValue) onGroupByNewField, }) { - _groupConfigurationNotifier - ?.addPublishListener(onGroupConfigurationChanged); _numOfGroupsNotifier?.addPublishListener(onNumOfGroupsChanged); _groupByFieldNotifier?.addPublishListener(onGroupByNewField); _listener = DatabaseNotificationListener( @@ -44,13 +38,6 @@ class DatabaseGroupListener { Either result, ) { switch (ty) { - case DatabaseNotification.DidUpdateGroupConfiguration: - result.fold( - (payload) => _groupConfigurationNotifier?.value = - left(RepeatedGroupSettingPB.fromBuffer(payload).items), - (error) => _groupConfigurationNotifier?.value = right(error), - ); - break; case DatabaseNotification.DidUpdateNumOfGroups: result.fold( (payload) => _numOfGroupsNotifier?.value = @@ -72,9 +59,6 @@ class DatabaseGroupListener { Future stop() async { await _listener?.stop(); - _groupConfigurationNotifier?.dispose(); - _groupConfigurationNotifier = null; - _numOfGroupsNotifier?.dispose(); _numOfGroupsNotifier = null; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/layout/calendar_setting_listener.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/layout/calendar_setting_listener.dart deleted file mode 100644 index 57e2c112a0..0000000000 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/layout/calendar_setting_listener.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'dart:typed_data'; - -import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; -import 'package:dartz/dartz.dart'; - -typedef NewLayoutFieldValue = Either; - -class DatabaseCalendarLayoutListener { - final String viewId; - PublishNotifier? _newLayoutFieldNotifier = - PublishNotifier(); - DatabaseNotificationListener? _listener; - DatabaseCalendarLayoutListener(this.viewId); - - void start({ - required void Function(NewLayoutFieldValue) onCalendarLayoutChanged, - }) { - _newLayoutFieldNotifier?.addPublishListener(onCalendarLayoutChanged); - _listener = DatabaseNotificationListener( - objectId: viewId, - handler: _handler, - ); - } - - void _handler( - DatabaseNotification ty, - Either result, - ) { - switch (ty) { - case DatabaseNotification.DidSetNewLayoutField: - result.fold( - (payload) => _newLayoutFieldNotifier?.value = - left(DatabaseLayoutSettingPB.fromBuffer(payload)), - (error) => _newLayoutFieldNotifier?.value = right(error), - ); - break; - default: - break; - } - } - - Future stop() async { - await _listener?.stop(); - _newLayoutFieldNotifier?.dispose(); - _newLayoutFieldNotifier = null; - } -} 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 22504f6562..3e6bacba59 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,6 +1,7 @@ import 'package:appflowy/plugins/database_view/application/database_controller.dart'; import 'package:appflowy/plugins/database_view/application/field/field_info.dart'; import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/board_entities.pb.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'; @@ -14,7 +15,7 @@ class DatabaseGroupBloc extends Bloc { final DatabaseController _databaseController; final GroupBackendService _groupBackendSvc; Function(List)? _onFieldsFn; - GroupCallbacks? _groupCallbacks; + DatabaseLayoutSettingCallbacks? _layoutSettingCallbacks; DatabaseGroupBloc({ required String viewId, @@ -25,13 +26,13 @@ class DatabaseGroupBloc extends Bloc { DatabaseGroupState.initial( viewId, databaseController.fieldController.fieldInfos, + databaseController.databaseLayoutSetting!.board, ), ) { on( (event, emit) async { event.when( initial: () { - _loadGroupConfigurations(); _startListening(); }, didReceiveFieldUpdate: (fieldInfos) { @@ -43,8 +44,8 @@ class DatabaseGroupBloc extends Bloc { ); result.fold((l) => null, (err) => Log.error(err)); }, - didUpdateHideUngrouped: (bool hideUngrouped) { - emit(state.copyWith(hideUngrouped: hideUngrouped)); + didUpdateLayoutSettings: (layoutSettings) { + emit(state.copyWith(layoutSettings: layoutSettings)); }, ); }, @@ -58,7 +59,7 @@ class DatabaseGroupBloc extends Bloc { .removeListener(onFieldsListener: _onFieldsFn!); _onFieldsFn = null; } - _groupCallbacks = null; + _layoutSettingCallbacks = null; return super.close(); } @@ -70,32 +71,18 @@ class DatabaseGroupBloc extends Bloc { listenWhen: () => !isClosed, ); - _groupCallbacks = GroupCallbacks( - onGroupConfigurationChanged: (configurations) { - if (isClosed) { + _layoutSettingCallbacks = DatabaseLayoutSettingCallbacks( + onLayoutSettingsChanged: (layoutSettings) { + if (isClosed || !layoutSettings.hasBoard()) { return; } - final configuration = configurations.first; add( - DatabaseGroupEvent.didUpdateHideUngrouped( - configuration.hideUngrouped, - ), + DatabaseGroupEvent.didUpdateLayoutSettings(layoutSettings.board), ); }, ); - _databaseController.addListener(onGroupChanged: _groupCallbacks); - } - - void _loadGroupConfigurations() async { - final configResult = await _databaseController.loadGroupConfigurations( - viewId: _databaseController.viewId, - ); - configResult.fold( - (configurations) { - final hideUngrouped = configurations.first.hideUngrouped; - add(DatabaseGroupEvent.didUpdateHideUngrouped(hideUngrouped)); - }, - (err) => Log.error(err), + _databaseController.addListener( + onLayoutSettingsChanged: _layoutSettingCallbacks, ); } } @@ -110,8 +97,9 @@ class DatabaseGroupEvent with _$DatabaseGroupEvent { const factory DatabaseGroupEvent.didReceiveFieldUpdate( List fields, ) = _DidReceiveFieldUpdate; - const factory DatabaseGroupEvent.didUpdateHideUngrouped(bool hideUngrouped) = - _DidUpdateHideUngrouped; + const factory DatabaseGroupEvent.didUpdateLayoutSettings( + BoardLayoutSettingPB layoutSettings, + ) = _DidUpdateLayoutSettings; } @freezed @@ -119,16 +107,17 @@ class DatabaseGroupState with _$DatabaseGroupState { const factory DatabaseGroupState({ required String viewId, required List fieldInfos, - required bool hideUngrouped, + required BoardLayoutSettingPB layoutSettings, }) = _DatabaseGroupState; factory DatabaseGroupState.initial( String viewId, List fieldInfos, + BoardLayoutSettingPB layoutSettings, ) => DatabaseGroupState( viewId: viewId, fieldInfos: fieldInfos, - hideUngrouped: true, + layoutSettings: layoutSettings, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart index d64c154857..bd5decdd8d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart @@ -147,8 +147,8 @@ class BoardBloc extends Bloc { ), ); }, - didUpdateHideUngrouped: (bool hideUngrouped) { - emit(state.copyWith(hideUngrouped: hideUngrouped)); + didUpdateLayoutSettings: (layoutSettings) { + emit(state.copyWith(layoutSettings: layoutSettings)); }, startEditingHeader: (String groupId) { emit( @@ -200,7 +200,7 @@ class BoardBloc extends Bloc { if (ungroupedGroupIndex != -1) { ungroupedGroup = groups[ungroupedGroupIndex]; final group = groups.removeAt(ungroupedGroupIndex); - if (!state.hideUngrouped) { + if (!(state.layoutSettings?.hideUngroupedColumn ?? false)) { groups.add(group); } } @@ -230,20 +230,21 @@ class BoardBloc extends Bloc { } }, ); - final onGroupChanged = GroupCallbacks( - onGroupConfigurationChanged: (configurations) { - if (isClosed) return; - final config = configurations.first; - if (config.hideUngrouped) { - boardController.removeGroup(config.fieldId); + final onLayoutSettingsChanged = DatabaseLayoutSettingCallbacks( + onLayoutSettingsChanged: (layoutSettings) { + if (isClosed || !layoutSettings.hasBoard()) { + return; + } + if (layoutSettings.board.hideUngroupedColumn) { + boardController.removeGroup(ungroupedGroup!.fieldId); } else if (ungroupedGroup != null) { final newGroup = initializeGroupData(ungroupedGroup!); - final controller = initializeGroupController(ungroupedGroup!); - groupControllers[controller.group.groupId] = (controller); boardController.addGroup(newGroup); } - add(BoardEvent.didUpdateHideUngrouped(config.hideUngrouped)); + add(BoardEvent.didUpdateLayoutSettings(layoutSettings.board)); }, + ); + final onGroupChanged = GroupCallbacks( onGroupByField: (groups) { if (isClosed) return; ungroupedGroup = null; @@ -274,6 +275,7 @@ class BoardBloc extends Bloc { databaseController.addListener( onDatabaseChanged: onDatabaseChanged, + onLayoutSettingsChanged: onLayoutSettingsChanged, onGroupChanged: onGroupChanged, ); } @@ -360,8 +362,9 @@ class BoardEvent with _$BoardEvent { ) = _DidReceiveGridUpdate; const factory BoardEvent.didReceiveGroups(List groups) = _DidReceiveGroups; - const factory BoardEvent.didUpdateHideUngrouped(bool hideUngrouped) = - _DidUpdateHideUngrouped; + const factory BoardEvent.didUpdateLayoutSettings( + BoardLayoutSettingPB layoutSettings, + ) = _DidUpdateLayoutSettings; } @freezed @@ -376,7 +379,7 @@ class BoardState with _$BoardState { BoardEditingRow? editingRow, required LoadingState loadingState, required Option noneOrError, - required bool hideUngrouped, + required BoardLayoutSettingPB? layoutSettings, }) = _BoardState; factory BoardState.initial(String viewId) => BoardState( @@ -387,7 +390,7 @@ class BoardState with _$BoardState { isEditingRow: false, noneOrError: none(), loadingState: const LoadingState.loading(), - hideUngrouped: false, + layoutSettings: null, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart index 4a3673a0e8..f2d584d9be 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart @@ -167,7 +167,8 @@ class _BoardContentState extends State { mainAxisSize: MainAxisSize.min, children: [ const VSpace(8.0), - if (state.hideUngrouped) _buildBoardHeader(context), + if (state.layoutSettings?.hideUngroupedColumn ?? false) + _buildBoardHeader(context), Expanded( child: AppFlowyBoard( boardScrollController: scrollManager, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/ungrouped_items_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/ungrouped_items_button.dart index b77809b11f..dc13708321 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/ungrouped_items_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/ungrouped_items_button.dart @@ -17,6 +17,7 @@ import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -61,31 +62,36 @@ class _UnscheduledEventsButtonState extends State { offset: const Offset(0, 8), constraints: const BoxConstraints(maxWidth: 282, maxHeight: 600), - child: OutlinedButton( - style: OutlinedButton.styleFrom( - shape: RoundedRectangleBorder( + child: FlowyTooltip( + message: LocaleKeys.board_ungroupedButtonTooltip.tr(), + child: OutlinedButton( + style: OutlinedButton.styleFrom( + shape: RoundedRectangleBorder( + side: BorderSide( + color: Theme.of(context).dividerColor, + width: 1, + ), + borderRadius: Corners.s6Border, + ), side: BorderSide( color: Theme.of(context).dividerColor, width: 1, ), - borderRadius: Corners.s6Border, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + visualDensity: VisualDensity.compact, ), - side: BorderSide( - color: Theme.of(context).dividerColor, - width: 1, + onPressed: () { + if (state.ungroupedItems.isNotEmpty) { + _popoverController.show(); + } + }, + child: FlowyText.regular( + "${LocaleKeys.board_ungroupedButtonText.tr()} (${state.ungroupedItems.length})", + fontSize: 10, ), - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - visualDensity: VisualDensity.compact, - ), - onPressed: () { - if (state.ungroupedItems.isNotEmpty) { - _popoverController.show(); - } - }, - child: FlowyText.regular( - "${LocaleKeys.board_ungroupedButtonText.tr()} (${state.ungroupedItems.length})", - fontSize: 10, ), ), popupBuilder: (context) { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart index 6a518e3975..f4a2cbdf7a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart @@ -198,7 +198,9 @@ class CalendarBloc extends Bloc { Future _updateCalendarLayoutSetting( CalendarLayoutSettingPB layoutSetting, ) async { - return databaseController.updateLayoutSetting(layoutSetting); + return databaseController.updateLayoutSetting( + calendarLayoutSetting: layoutSetting, + ); } Future?> _loadEvent(RowId rowId) async { @@ -319,14 +321,13 @@ class CalendarBloc extends Bloc { }, ); - final onLayoutChanged = DatabaseLayoutSettingCallbacks( - onLayoutChanged: _didReceiveLayoutSetting, - onLoadLayout: _didReceiveLayoutSetting, + final onLayoutSettingsChanged = DatabaseLayoutSettingCallbacks( + onLayoutSettingsChanged: _didReceiveLayoutSetting, ); databaseController.addListener( onDatabaseChanged: onDatabaseChanged, - onLayoutChanged: onLayoutChanged, + onLayoutSettingsChanged: onLayoutSettingsChanged, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/group/database_group.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/group/database_group.dart index 066cf9f1b6..20699de28f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/group/database_group.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/group/database_group.dart @@ -8,6 +8,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/common/ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart'; import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/board_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -18,6 +19,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:protobuf/protobuf.dart' hide FieldInfo; class DatabaseGroupList extends StatelessWidget { final String viewId; @@ -60,9 +62,9 @@ class DatabaseGroupList extends StatelessWidget { ), ), Toggle( - value: !state.hideUngrouped, + value: !state.layoutSettings.hideUngroupedColumn, onChanged: (value) => - databaseController.updateGroupConfiguration(value), + _updateLayoutSettings(state.layoutSettings, value), style: ToggleStyle.big, padding: EdgeInsets.zero, ), @@ -105,6 +107,19 @@ class DatabaseGroupList extends StatelessWidget { ), ); } + + Future _updateLayoutSettings( + BoardLayoutSettingPB layoutSettings, + bool hideUngrouped, + ) { + layoutSettings.freeze(); + final newLayoutSetting = layoutSettings.rebuild((message) { + message.hideUngroupedColumn = hideUngrouped; + }); + return databaseController.updateLayoutSetting( + boardLayoutSetting: newLayoutSetting, + ); + } } class _GridGroupCell extends StatelessWidget { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/setting/setting_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/setting/setting_button.dart index 5b809371eb..160ff16db5 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/setting/setting_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/setting/setting_button.dart @@ -115,7 +115,9 @@ class ICalendarSettingImpl extends ICalendarSetting { @override void updateLayoutSettings(CalendarLayoutSettingPB layoutSettings) { - _databaseController.updateLayoutSetting(layoutSettings); + _databaseController.updateLayoutSetting( + calendarLayoutSetting: layoutSettings, + ); } @override diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 1915afd372..4adb7acc98 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -751,6 +751,7 @@ "menuName": "Board", "showUngrouped": "Show ungrouped items", "ungroupedButtonText": "Ungrouped", + "ungroupedButtonTooltip": "Contains cards that don't belong in any group", "ungroupedItemsTitle": "Click to add to the board", "groupBy": "Group by", "referencedBoardPrefix": "View of" diff --git a/frontend/rust-lib/flowy-database2/src/entities/board_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/board_entities.rs new file mode 100644 index 0000000000..addab49033 --- /dev/null +++ b/frontend/rust-lib/flowy-database2/src/entities/board_entities.rs @@ -0,0 +1,25 @@ +use flowy_derive::ProtoBuf; + +use crate::services::setting::BoardLayoutSetting; + +#[derive(Debug, Clone, Default, Eq, PartialEq, ProtoBuf)] +pub struct BoardLayoutSettingPB { + #[pb(index = 1)] + pub hide_ungrouped_column: bool, +} + +impl From for BoardLayoutSettingPB { + fn from(setting: BoardLayoutSetting) -> Self { + Self { + hide_ungrouped_column: setting.hide_ungrouped_column, + } + } +} + +impl From for BoardLayoutSetting { + fn from(setting: BoardLayoutSettingPB) -> Self { + Self { + hide_ungrouped_column: setting.hide_ungrouped_column, + } + } +} 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 6e7c2a598f..7200c2987e 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, RowMetaPB}; -use crate::services::group::{GroupChangeset, GroupData, GroupSetting, GroupSettingChangeset}; +use crate::services::group::{GroupChangeset, GroupData, GroupSetting}; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] pub struct GroupSettingPB { @@ -14,9 +14,6 @@ pub struct GroupSettingPB { #[pb(index = 2)] pub field_id: String, - - #[pb(index = 3)] - pub hide_ungrouped: bool, } impl std::convert::From<&GroupSetting> for GroupSettingPB { @@ -24,7 +21,6 @@ impl std::convert::From<&GroupSetting> for GroupSettingPB { GroupSettingPB { id: rev.id.clone(), field_id: rev.field_id.clone(), - hide_ungrouped: rev.hide_ungrouped, } } } @@ -52,26 +48,6 @@ impl std::convert::From> for RepeatedGroupSettingPB { } } -#[derive(Debug, Default, ProtoBuf)] -pub struct GroupSettingChangesetPB { - #[pb(index = 1)] - pub view_id: String, - - #[pb(index = 2)] - pub group_configuration_id: String, - - #[pb(index = 3, one_of)] - pub hide_ungrouped: Option, -} - -impl From for GroupSettingChangeset { - fn from(value: GroupSettingChangesetPB) -> Self { - Self { - hide_ungrouped: value.hide_ungrouped, - } - } -} - #[derive(ProtoBuf, Debug, Default, Clone)] pub struct RepeatedGroupPB { #[pb(index = 1)] diff --git a/frontend/rust-lib/flowy-database2/src/entities/mod.rs b/frontend/rust-lib/flowy-database2/src/entities/mod.rs index 0afd825952..7721615a97 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/mod.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/mod.rs @@ -1,3 +1,4 @@ +mod board_entities; mod calendar_entities; mod cell_entities; mod database_entities; @@ -16,6 +17,7 @@ mod macros; mod share_entities; mod type_option_entities; +pub use board_entities::*; pub use calendar_entities::*; pub use cell_entities::*; pub use database_entities::*; 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 4a6f3de1a2..7bd4284ecb 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/setting_entities.rs @@ -13,7 +13,9 @@ use crate::entities::{ RepeatedSortPB, UpdateFilterParams, UpdateFilterPayloadPB, UpdateGroupPB, UpdateSortParams, UpdateSortPayloadPB, }; -use crate::services::setting::CalendarLayoutSetting; +use crate::services::setting::{BoardLayoutSetting, CalendarLayoutSetting}; + +use super::BoardLayoutSettingPB; /// [DatabaseViewSettingPB] defines the setting options for the grid. Such as the filter, group, and sort. #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] @@ -151,19 +153,51 @@ pub struct DatabaseLayoutSettingPB { pub layout_type: DatabaseLayoutPB, #[pb(index = 2, one_of)] + pub board: Option, + + #[pb(index = 3, one_of)] pub calendar: Option, } +impl DatabaseLayoutSettingPB { + pub fn from_board(layout_setting: BoardLayoutSetting) -> Self { + Self { + layout_type: DatabaseLayoutPB::Board, + board: Some(layout_setting.into()), + calendar: None, + } + } + + pub fn from_calendar(layout_setting: CalendarLayoutSetting) -> Self { + Self { + layout_type: DatabaseLayoutPB::Calendar, + calendar: Some(layout_setting.into()), + board: None, + } + } +} + #[derive(Debug, Clone, Default)] pub struct LayoutSettingParams { pub layout_type: DatabaseLayout, + pub board: Option, pub calendar: Option, } +impl LayoutSettingParams { + pub fn new(layout_type: DatabaseLayout) -> Self { + Self { + layout_type, + ..Default::default() + } + } +} + impl From for DatabaseLayoutSettingPB { fn from(data: LayoutSettingParams) -> Self { Self { layout_type: data.layout_type.into(), + board: data.board.map(|board| board.into()), calendar: data.calendar.map(|calendar| calendar.into()), } } @@ -178,6 +212,9 @@ pub struct LayoutSettingChangesetPB { pub layout_type: DatabaseLayoutPB, #[pb(index = 3, one_of)] + pub board: Option, + + #[pb(index = 4, one_of)] pub calendar: Option, } @@ -185,9 +222,17 @@ pub struct LayoutSettingChangesetPB { pub struct LayoutSettingChangeset { pub view_id: String, pub layout_type: DatabaseLayout, + pub board: Option, pub calendar: Option, } +impl LayoutSettingChangeset { + pub fn is_valid(&self) -> bool { + self.board.is_some() && self.layout_type == DatabaseLayout::Board + || self.calendar.is_some() && self.layout_type == DatabaseLayout::Calendar + } +} + impl TryInto for LayoutSettingChangesetPB { type Error = ErrorCode; @@ -199,7 +244,8 @@ impl TryInto for LayoutSettingChangesetPB { Ok(LayoutSettingChangeset { view_id, layout_type: self.layout_type.into(), - calendar: self.calendar.map(|calendar| calendar.into()), + board: self.board.map(Into::into), + calendar: self.calendar.map(Into::into), }) } } diff --git a/frontend/rust-lib/flowy-database2/src/event_handler.rs b/frontend/rust-lib/flowy-database2/src/event_handler.rs index 3103111812..06547c720f 100644 --- a/frontend/rust-lib/flowy-database2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-database2/src/event_handler.rs @@ -646,36 +646,6 @@ pub(crate) async fn update_date_cell_handler( Ok(()) } -#[tracing::instrument(level = "trace", skip_all, err)] -pub(crate) async fn get_group_configurations_handler( - data: AFPluginData, - manager: AFPluginState>, -) -> DataResult { - let manager = upgrade_manager(manager)?; - let params = data.into_inner(); - let database_editor = manager.get_database_with_view_id(params.as_ref()).await?; - let group_configs = database_editor - .get_group_configuration_settings(params.as_ref()) - .await?; - data_result_ok(group_configs.into()) -} - -#[tracing::instrument(level = "trace", skip_all, err)] -pub(crate) async fn update_group_configuration_handler( - data: AFPluginData, - manager: AFPluginState>, -) -> Result<(), FlowyError> { - let manager = upgrade_manager(manager)?; - let params = data.into_inner(); - let view_id = params.view_id.clone(); - let database_editor = manager.get_database_with_view_id(&view_id).await?; - database_editor - .update_group_configuration_setting(&view_id, params.into()) - .await?; - - Ok(()) -} - #[tracing::instrument(level = "trace", skip_all, err)] pub(crate) async fn get_groups_handler( data: AFPluginData, @@ -786,15 +756,11 @@ pub(crate) async fn set_layout_setting_handler( manager: AFPluginState>, ) -> FlowyResult<()> { let manager = upgrade_manager(manager)?; - let params: LayoutSettingChangeset = data.into_inner().try_into()?; - let database_editor = manager.get_database_with_view_id(¶ms.view_id).await?; - let layout_params = LayoutSettingParams { - layout_type: params.layout_type, - calendar: params.calendar, - }; - database_editor - .set_layout_setting(¶ms.view_id, layout_params) - .await; + let changeset = data.into_inner(); + let view_id = changeset.view_id.clone(); + let params: LayoutSettingChangeset = changeset.try_into()?; + let database_editor = manager.get_database_with_view_id(&view_id).await?; + database_editor.set_layout_setting(&view_id, params).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-database2/src/event_map.rs b/frontend/rust-lib/flowy-database2/src/event_map.rs index 594feac09c..4bb000afae 100644 --- a/frontend/rust-lib/flowy-database2/src/event_map.rs +++ b/frontend/rust-lib/flowy-database2/src/event_map.rs @@ -54,8 +54,6 @@ pub fn init(database_manager: Weak) -> AFPlugin { // Date .event(DatabaseEvent::UpdateDateCell, update_date_cell_handler) // Group - .event(DatabaseEvent::GetGroupConfigurations, get_group_configurations_handler) - .event(DatabaseEvent::UpdateGroupConfiguration, update_group_configuration_handler) .event(DatabaseEvent::SetGroupByField, set_group_by_field_handler) .event(DatabaseEvent::MoveGroup, move_group_handler) .event(DatabaseEvent::MoveGroupRow, move_group_row_handler) @@ -266,14 +264,10 @@ pub enum DatabaseEvent { #[event(input = "DateChangesetPB")] UpdateDateCell = 80, - #[event(input = "DatabaseViewIdPB", output = "RepeatedGroupSettingPB")] - GetGroupConfigurations = 90, - - #[event(input = "GroupSettingChangesetPB")] - UpdateGroupConfiguration = 91, - + /// [SetGroupByField] event is used to create a new grouping in a database + /// view based on the `field_id` #[event(input = "GroupByFieldPayloadPB")] - SetGroupByField = 92, + SetGroupByField = 90, #[event(input = "DatabaseViewIdPB", output = "RepeatedGroupPB")] GetGroups = 100, diff --git a/frontend/rust-lib/flowy-database2/src/notification.rs b/frontend/rust-lib/flowy-database2/src/notification.rs index acf90e4717..5d7e7e1df4 100644 --- a/frontend/rust-lib/flowy-database2/src/notification.rs +++ b/frontend/rust-lib/flowy-database2/src/notification.rs @@ -20,8 +20,6 @@ pub enum DatabaseNotification { DidUpdateCell = 40, /// Trigger after editing a field properties including rename,update type option, etc DidUpdateField = 50, - /// Trigger after the group configuration is changed - DidUpdateGroupConfiguration = 59, /// Trigger after the number of groups is changed DidUpdateNumOfGroups = 60, /// Trigger after inserting/deleting/updating/moving a row @@ -42,18 +40,16 @@ pub enum DatabaseNotification { DidUpdateSettings = 70, // Trigger when the layout setting of the database is updated DidUpdateLayoutSettings = 80, - // Trigger when the layout field of the database is changed - DidSetNewLayoutField = 81, // Trigger when the layout of the database is changed - DidUpdateDatabaseLayout = 82, + DidUpdateDatabaseLayout = 81, // Trigger when the database view is deleted - DidDeleteDatabaseView = 83, + DidDeleteDatabaseView = 82, // Trigger when the database view is moved to trash - DidMoveDatabaseViewToTrash = 84, - DidUpdateDatabaseSyncUpdate = 85, - DidUpdateDatabaseSnapshotState = 86, + DidMoveDatabaseViewToTrash = 83, + DidUpdateDatabaseSyncUpdate = 84, + DidUpdateDatabaseSnapshotState = 85, // Trigger when the field setting is changed - DidUpdateFieldSettings = 87, + DidUpdateFieldSettings = 86, } impl std::convert::From for i32 { @@ -71,7 +67,6 @@ impl std::convert::From for DatabaseNotification { 22 => DatabaseNotification::DidUpdateFields, 40 => DatabaseNotification::DidUpdateCell, 50 => DatabaseNotification::DidUpdateField, - 59 => DatabaseNotification::DidUpdateGroupConfiguration, 60 => DatabaseNotification::DidUpdateNumOfGroups, 61 => DatabaseNotification::DidUpdateGroupRow, 62 => DatabaseNotification::DidGroupByField, @@ -82,7 +77,6 @@ impl std::convert::From for DatabaseNotification { 67 => DatabaseNotification::DidUpdateRowMeta, 70 => DatabaseNotification::DidUpdateSettings, 80 => DatabaseNotification::DidUpdateLayoutSettings, - 81 => DatabaseNotification::DidSetNewLayoutField, 82 => DatabaseNotification::DidUpdateDatabaseLayout, 83 => DatabaseNotification::DidDeleteDatabaseView, 84 => DatabaseNotification::DidMoveDatabaseViewToTrash, 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 b51252a54d..e5343693de 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 @@ -34,9 +34,7 @@ use crate::services::field_settings::{ default_field_settings_by_layout_map, FieldSettings, FieldSettingsChangesetParams, }; use crate::services::filter::Filter; -use crate::services::group::{ - default_group_setting, GroupChangesets, GroupSetting, GroupSettingChangeset, RowChangeset, -}; +use crate::services::group::{default_group_setting, GroupChangesets, GroupSetting, RowChangeset}; use crate::services::share::csv::{CSVExport, CSVFormat}; use crate::services::sort::Sort; @@ -870,40 +868,6 @@ impl DatabaseEditor { Ok(()) } - pub async fn get_group_configuration_settings( - &self, - view_id: &str, - ) -> FlowyResult> { - let view = self.database_views.get_view_editor(view_id).await?; - - let group_settings = view - .v_get_group_configuration_settings() - .await - .into_iter() - .map(|value| GroupSettingPB::from(&value)) - .collect::>(); - - Ok(group_settings) - } - - pub async fn update_group_configuration_setting( - &self, - view_id: &str, - changeset: GroupSettingChangeset, - ) -> FlowyResult<()> { - let view = self.database_views.get_view_editor(view_id).await?; - let group_configuration = view.v_update_group_configuration_setting(changeset).await?; - - if let Some(configuration) = group_configuration { - let payload: RepeatedGroupSettingPB = vec![configuration].into(); - send_notification(view_id, DatabaseNotification::DidUpdateGroupConfiguration) - .payload(payload) - .send(); - } - - Ok(()) - } - #[tracing::instrument(level = "trace", skip_all, err)] pub async fn load_groups(&self, view_id: &str) -> FlowyResult { let view = self.database_views.get_view_editor(view_id).await?; @@ -994,11 +958,15 @@ impl DatabaseEditor { Ok(()) } - pub async fn set_layout_setting(&self, view_id: &str, layout_setting: LayoutSettingParams) { - tracing::trace!("set_layout_setting: {:?}", layout_setting); - if let Ok(view) = self.database_views.get_view_editor(view_id).await { - let _ = view.v_set_layout_settings(layout_setting).await; - }; + #[tracing::instrument(level = "trace", skip_all)] + pub async fn set_layout_setting( + &self, + view_id: &str, + layout_setting: LayoutSettingChangeset, + ) -> FlowyResult<()> { + let view_editor = self.database_views.get_view_editor(view_id).await?; + view_editor.v_set_layout_settings(layout_setting).await?; + Ok(()) } pub async fn get_layout_setting( diff --git a/frontend/rust-lib/flowy-database2/src/services/database/util.rs b/frontend/rust-lib/flowy-database2/src/services/database/util.rs index 393a8f0c1a..69bac217c8 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/util.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/util.rs @@ -1,23 +1,27 @@ -use collab_database::views::DatabaseView; +use collab_database::views::{DatabaseLayout, DatabaseView}; use crate::entities::{ - CalendarLayoutSettingPB, DatabaseLayoutPB, DatabaseLayoutSettingPB, DatabaseViewSettingPB, - FieldSettingsPB, FilterPB, GroupSettingPB, SortPB, + DatabaseLayoutPB, DatabaseLayoutSettingPB, DatabaseViewSettingPB, FieldSettingsPB, FilterPB, + GroupSettingPB, SortPB, }; use crate::services::field_settings::FieldSettings; use crate::services::filter::Filter; use crate::services::group::GroupSetting; -use crate::services::setting::CalendarLayoutSetting; use crate::services::sort::Sort; pub(crate) fn database_view_setting_pb_from_view(view: DatabaseView) -> DatabaseViewSettingPB { let layout_type: DatabaseLayoutPB = view.layout.into(); let layout_setting = if let Some(layout_setting) = view.layout_settings.get(&view.layout) { - let calendar_setting = - CalendarLayoutSettingPB::from(CalendarLayoutSetting::from(layout_setting.clone())); - DatabaseLayoutSettingPB { - layout_type: layout_type.clone(), - calendar: Some(calendar_setting), + match view.layout { + DatabaseLayout::Board => { + let board_setting = layout_setting.clone().into(); + DatabaseLayoutSettingPB::from_board(board_setting) + }, + DatabaseLayout::Calendar => { + let calendar_setting = layout_setting.clone().into(); + DatabaseLayoutSettingPB::from_calendar(calendar_setting) + }, + _ => DatabaseLayoutSettingPB::default(), } } else { DatabaseLayoutSettingPB::default() diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/layout_deps.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/layout_deps.rs index 4171be4146..711ca4d33f 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/layout_deps.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/layout_deps.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use crate::entities::FieldType; use crate::services::field::{DateTypeOption, SingleSelectTypeOption}; use crate::services::field_settings::default_field_settings_by_layout_map; -use crate::services::setting::CalendarLayoutSetting; +use crate::services::setting::{BoardLayoutSetting, CalendarLayoutSetting}; /// When creating a database, we need to resolve the dependencies of the views. /// Different database views have different dependencies. For example, a board @@ -32,6 +32,7 @@ impl DatabaseLayoutDepsResolver { match self.database_layout { DatabaseLayout::Grid => (None, None), DatabaseLayout::Board => { + let layout_settings = BoardLayoutSetting::new().into(); if !self .database .lock() @@ -40,9 +41,9 @@ impl DatabaseLayoutDepsResolver { .any(|field| FieldType::from(field.field_type).can_be_group()) { let select_field = self.create_select_field(); - (Some(select_field), None) + (Some(select_field), Some(layout_settings)) } else { - (None, None) + (None, Some(layout_settings)) } }, DatabaseLayout::Calendar => { @@ -74,7 +75,9 @@ impl DatabaseLayoutDepsResolver { // Insert the layout setting if it's not exist match &self.database_layout { DatabaseLayout::Grid => {}, - DatabaseLayout::Board => {}, + DatabaseLayout::Board => { + self.create_board_layout_setting_if_need(view_id); + }, DatabaseLayout::Calendar => { let date_field_id = match fields .into_iter() @@ -97,6 +100,21 @@ impl DatabaseLayoutDepsResolver { } } + fn create_board_layout_setting_if_need(&self, view_id: &str) { + if self + .database + .lock() + .get_layout_setting::(view_id, &self.database_layout) + .is_none() + { + let layout_setting = BoardLayoutSetting::new(); + self + .database + .lock() + .insert_layout_setting(view_id, &self.database_layout, layout_setting); + } + } + fn create_calendar_layout_setting_if_need(&self, view_id: &str, field_id: &str) { if self .database 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 66d9760476..8dfc39416b 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,8 +13,8 @@ use flowy_error::{FlowyError, FlowyResult}; use crate::entities::{ CalendarEventPB, DatabaseLayoutMetaPB, DatabaseLayoutSettingPB, DeleteFilterParams, DeleteGroupParams, DeleteSortParams, FieldType, FieldVisibility, GroupChangesPB, GroupPB, - GroupRowsNotificationPB, InsertedRowPB, LayoutSettingParams, RowMetaPB, RowsChangePB, - SortChangesetNotificationPB, SortPB, UpdateFilterParams, UpdateSortParams, + GroupRowsNotificationPB, InsertedRowPB, LayoutSettingChangeset, LayoutSettingParams, RowMetaPB, + RowsChangePB, SortChangesetNotificationPB, SortPB, UpdateFilterParams, UpdateSortParams, }; use crate::notification::{send_notification, DatabaseNotification}; use crate::services::cell::CellCache; @@ -34,10 +34,7 @@ use crate::services::field_settings::FieldSettings; use crate::services::filter::{ Filter, FilterChangeset, FilterController, FilterType, UpdatedFilterType, }; -use crate::services::group::{ - GroupChangesets, GroupController, GroupSetting, GroupSettingChangeset, MoveGroupRowContext, - RowChangeset, -}; +use crate::services::group::{GroupChangesets, GroupController, MoveGroupRowContext, RowChangeset}; use crate::services::setting::CalendarLayoutSetting; use crate::services::sort::{DeletedSortType, Sort, SortChangeset, SortController, SortType}; @@ -377,19 +374,6 @@ impl DatabaseViewEditor { Ok(()) } - pub async fn v_update_group_configuration_setting( - &self, - changeset: GroupSettingChangeset, - ) -> FlowyResult> { - let result = self - .mut_group_controller(|group_controller, _| { - group_controller.apply_group_configuration_setting_changeset(changeset) - }) - .await; - - Ok(result.flatten()) - } - pub async fn v_update_group(&self, changeset: GroupChangesets) -> FlowyResult<()> { let mut type_option_data = TypeOptionData::new(); let old_field = if let Some(controller) = self.group_controller.write().await.as_mut() { @@ -412,9 +396,6 @@ impl DatabaseViewEditor { Ok(()) } - pub async fn v_get_group_configuration_settings(&self) -> Vec { - self.delegate.get_group_setting(&self.view_id) - } pub async fn v_get_all_sorts(&self) -> Vec { self.delegate.get_all_sorts(&self.view_id) } @@ -550,7 +531,11 @@ impl DatabaseViewEditor { let mut layout_setting = LayoutSettingParams::default(); match layout_ty { DatabaseLayout::Grid => {}, - DatabaseLayout::Board => {}, + DatabaseLayout::Board => { + if let Some(value) = self.delegate.get_layout_setting(&self.view_id, layout_ty) { + layout_setting.board = Some(value.into()); + } + }, DatabaseLayout::Calendar => { if let Some(value) = self.delegate.get_layout_setting(&self.view_id, layout_ty) { let calendar_setting = CalendarLayoutSetting::from(value); @@ -574,48 +559,50 @@ impl DatabaseViewEditor { layout_setting } - /// Update the calendar settings and send the notification to refresh the UI - pub async fn v_set_layout_settings(&self, params: LayoutSettingParams) -> FlowyResult<()> { - // Maybe it needs no send notification to refresh the UI - if let Some(new_calendar_setting) = params.calendar { - if let Some(field) = self.delegate.get_field(&new_calendar_setting.field_id) { - let field_type = FieldType::from(field.field_type); - if field_type != FieldType::DateTime { - return Err(FlowyError::unexpect_calendar_field_type()); - } + /// Update the layout settings and send the notification to refresh the UI + pub async fn v_set_layout_settings(&self, params: LayoutSettingChangeset) -> FlowyResult<()> { + if self.v_get_layout_type().await != params.layout_type || !params.is_valid() { + return Err(FlowyError::invalid_data()); + } - let old_calender_setting = self - .v_get_layout_settings(¶ms.layout_type) - .await - .calendar; + let layout_setting_pb = match params.layout_type { + DatabaseLayout::Board => { + let layout_setting = params.board.unwrap(); self.delegate.insert_layout_setting( &self.view_id, ¶ms.layout_type, - new_calendar_setting.clone().into(), + layout_setting.clone().into(), ); - let new_field_id = new_calendar_setting.field_id.clone(); - let layout_setting_pb: DatabaseLayoutSettingPB = LayoutSettingParams { - layout_type: params.layout_type, - calendar: Some(new_calendar_setting), - } - .into(); - if let Some(old_calendar_setting) = old_calender_setting { - // compare the new layout field id is equal to old layout field id - // if not equal, send the DidSetNewLayoutField notification - // if equal, send the DidUpdateLayoutSettings notification - if old_calendar_setting.field_id != new_field_id { - send_notification(&self.view_id, DatabaseNotification::DidSetNewLayoutField) - .payload(layout_setting_pb.clone()) - .send(); + Some(DatabaseLayoutSettingPB::from_board(layout_setting)) + }, + DatabaseLayout::Calendar => { + let layout_setting = params.calendar.unwrap(); + + if let Some(field) = self.delegate.get_field(&layout_setting.field_id) { + if FieldType::from(field.field_type) != FieldType::DateTime { + return Err(FlowyError::unexpect_calendar_field_type()); } - } - send_notification(&self.view_id, DatabaseNotification::DidUpdateLayoutSettings) - .payload(layout_setting_pb) - .send(); - } + self.delegate.insert_layout_setting( + &self.view_id, + ¶ms.layout_type, + layout_setting.clone().into(), + ); + + Some(DatabaseLayoutSettingPB::from_calendar(layout_setting)) + } else { + None + } + }, + _ => None, + }; + + if let Some(payload) = layout_setting_pb { + send_notification(&self.view_id, DatabaseNotification::DidUpdateLayoutSettings) + .payload(payload) + .send(); } Ok(()) 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 376391dbd1..1c28fce8ad 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/action.rs @@ -6,10 +6,7 @@ use flowy_error::FlowyResult; use crate::entities::{GroupChangesPB, GroupPB, GroupRowsNotificationPB, InsertedGroupPB}; use crate::services::field::TypeOption; -use crate::services::group::entities::GroupSetting; -use crate::services::group::{ - GroupChangesets, GroupData, GroupSettingChangeset, MoveGroupRowContext, -}; +use crate::services::group::{GroupChangesets, GroupData, MoveGroupRowContext}; /// Using polymorphism to provides the customs action for different group controller. /// @@ -119,11 +116,6 @@ pub trait GroupControllerOperation: Send + Sync { &mut self, changeset: &GroupChangesets, ) -> FlowyResult; - - fn apply_group_configuration_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 aca56b5495..f8f1aa8c21 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/configuration.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/configuration.rs @@ -18,7 +18,6 @@ use crate::entities::{GroupChangesPB, GroupPB, InsertedGroupPB}; use crate::services::field::RowSingleCellData; use crate::services::group::{ default_group_setting, GeneratedGroups, Group, GroupChangeset, GroupData, GroupSetting, - GroupSettingChangeset, }; pub trait GroupSettingReader: Send + Sync + 'static { @@ -390,20 +389,6 @@ where Ok(()) } - pub(crate) fn update_configuration( - &mut self, - changeset: GroupSettingChangeset, - ) -> FlowyResult> { - self.mut_configuration(|configuration| match changeset.hide_ungrouped { - Some(value) if value != configuration.hide_ungrouped => { - configuration.hide_ungrouped = value; - true - }, - _ => false, - })?; - Ok(Some(GroupSetting::clone(&self.setting))) - } - pub(crate) async fn get_all_cells(&self) -> Vec { self .reader @@ -432,9 +417,7 @@ where let view_id = self.view_id.clone(); tokio::spawn(async move { match writer.save_configuration(&view_id, configuration).await { - Ok(_) => { - tracing::trace!("SUCCESSFULLY SAVED CONFIGURATION"); // TODO(richard): remove this - }, + Ok(_) => {}, Err(e) => { tracing::error!("Save group configuration failed: {}", e); }, 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 77845f7338..ab847755b2 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller.rs @@ -19,10 +19,8 @@ use crate::services::group::action::{ DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, GroupCustomize, }; use crate::services::group::configuration::GroupContext; -use crate::services::group::entities::{GroupData, GroupSetting}; -use crate::services::group::{ - GroupChangeset, GroupChangesets, GroupSettingChangeset, GroupsBuilder, MoveGroupRowContext, -}; +use crate::services::group::entities::GroupData; +use crate::services::group::{GroupChangeset, GroupChangesets, GroupsBuilder, MoveGroupRowContext}; // use collab_database::views::Group; @@ -361,13 +359,6 @@ where } Ok(type_option_data) } - - fn apply_group_configuration_setting_changeset( - &mut self, - changeset: GroupSettingChangeset, - ) -> FlowyResult> { - self.context.update_configuration(changeset) - } } struct GroupedRow { 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 49c3c10147..19d02c0285 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 @@ -10,10 +10,7 @@ use crate::entities::GroupChangesPB; use crate::services::group::action::{ DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, }; -use crate::services::group::{ - GroupChangesets, GroupController, GroupData, GroupSetting, GroupSettingChangeset, - MoveGroupRowContext, -}; +use crate::services::group::{GroupChangesets, 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 @@ -110,13 +107,6 @@ impl GroupControllerOperation for DefaultGroupController { ) -> FlowyResult { Ok(TypeOptionData::default()) } - - fn apply_group_configuration_setting_changeset( - &mut self, - _changeset: GroupSettingChangeset, - ) -> FlowyResult> { - Ok(None) - } } impl GroupController for DefaultGroupController { 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 f7427f9510..0badcc1e49 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/entities.rs @@ -12,11 +12,6 @@ pub struct GroupSetting { pub field_type: i64, pub groups: Vec, pub content: String, - pub hide_ungrouped: bool, -} - -pub struct GroupSettingChangeset { - pub hide_ungrouped: Option, } pub struct GroupChangesets { @@ -38,14 +33,13 @@ pub struct GroupChangeset { } impl GroupSetting { - pub fn new(field_id: String, field_type: i64, content: String, hide_ungrouped: bool) -> Self { + pub fn new(field_id: String, field_type: i64, content: String) -> Self { Self { id: gen_database_group_id(), field_id, field_type, groups: vec![], content, - hide_ungrouped, } } } @@ -55,7 +49,6 @@ const FIELD_ID: &str = "field_id"; const FIELD_TYPE: &str = "ty"; const GROUPS: &str = "groups"; const CONTENT: &str = "content"; -const HIDE_UNGROUPED: &str = "hide_ungrouped"; impl TryFrom for GroupSetting { type Error = anyhow::Error; @@ -65,9 +58,8 @@ impl TryFrom for GroupSetting { value.get_str_value(GROUP_ID), value.get_str_value(FIELD_ID), value.get_i64_value(FIELD_TYPE), - value.get_bool_value(HIDE_UNGROUPED), ) { - (Some(id), Some(field_id), Some(field_type), Some(hide_ungrouped)) => { + (Some(id), Some(field_id), Some(field_type)) => { let content = value.get_str_value(CONTENT).unwrap_or_default(); let groups = value.try_get_array(GROUPS); Ok(Self { @@ -76,7 +68,6 @@ impl TryFrom for GroupSetting { field_type, groups, content, - hide_ungrouped, }) }, _ => { @@ -94,7 +85,6 @@ impl From for GroupSettingMap { .insert_i64_value(FIELD_TYPE, setting.field_type) .insert_maps(GROUPS, setting.groups) .insert_str_value(CONTENT, setting.content) - .insert_bool_value(HIDE_UNGROUPED, setting.hide_ungrouped) .build() } } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs b/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs index 36f0c5b568..c221c7fdaf 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs @@ -234,7 +234,7 @@ pub fn find_new_grouping_field( /// pub fn default_group_setting(field: &Field) -> GroupSetting { let field_id = field.id.clone(); - GroupSetting::new(field_id, field.field_type, "".to_owned(), false) + GroupSetting::new(field_id, field.field_type, "".to_owned()) } pub fn make_no_status_group(field: &Field) -> Group { diff --git a/frontend/rust-lib/flowy-database2/src/services/group/mod.rs b/frontend/rust-lib/flowy-database2/src/services/group/mod.rs index fd11447bb8..c9f9e91b65 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/mod.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/mod.rs @@ -8,5 +8,5 @@ mod group_builder; pub(crate) use configuration::*; pub(crate) use controller::*; pub(crate) use controller_impls::*; -pub use entities::*; +pub(crate) use entities::*; pub(crate) use group_builder::*; diff --git a/frontend/rust-lib/flowy-database2/src/services/setting/entities.rs b/frontend/rust-lib/flowy-database2/src/services/setting/entities.rs index 808d2f7a75..2e0ee02935 100644 --- a/frontend/rust-lib/flowy-database2/src/services/setting/entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/setting/entities.rs @@ -89,3 +89,32 @@ impl CalendarLayout { pub const DEFAULT_FIRST_DAY_OF_WEEK: i32 = 0; pub const DEFAULT_SHOW_WEEKENDS: bool = true; pub const DEFAULT_SHOW_WEEK_NUMBERS: bool = true; + +#[derive(Debug, Clone, Default)] +pub struct BoardLayoutSetting { + pub hide_ungrouped_column: bool, +} + +impl BoardLayoutSetting { + pub fn new() -> Self { + Self::default() + } +} + +impl From for BoardLayoutSetting { + fn from(setting: LayoutSetting) -> Self { + Self { + hide_ungrouped_column: setting + .get_bool_value("hide_ungrouped_column") + .unwrap_or_default(), + } + } +} + +impl From for LayoutSetting { + fn from(setting: BoardLayoutSetting) -> Self { + LayoutSettingBuilder::new() + .insert_bool_value("hide_ungrouped_column", setting.hide_ungrouped_column) + .build() + } +} diff --git a/frontend/rust-lib/flowy-database2/src/template.rs b/frontend/rust-lib/flowy-database2/src/template.rs index 4f819ac43a..23a217638c 100644 --- a/frontend/rust-lib/flowy-database2/src/template.rs +++ b/frontend/rust-lib/flowy-database2/src/template.rs @@ -8,7 +8,7 @@ use crate::services::field::{ FieldBuilder, SelectOption, SelectOptionColor, SingleSelectTypeOption, }; use crate::services::field_settings::DatabaseFieldSettingsMapBuilder; -use crate::services::setting::CalendarLayoutSetting; +use crate::services::setting::{BoardLayoutSetting, CalendarLayoutSetting}; pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams { let text_field = FieldBuilder::from_field_type(FieldType::RichText) @@ -93,12 +93,15 @@ pub fn make_default_board(view_id: &str, name: &str) -> CreateDatabaseParams { let field_settings = DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build(); + let mut layout_settings = LayoutSettings::default(); + layout_settings.insert(DatabaseLayout::Board, BoardLayoutSetting::new().into()); + CreateDatabaseParams { database_id: gen_database_id(), view_id: view_id.to_string(), name: name.to_string(), layout: DatabaseLayout::Board, - layout_settings: Default::default(), + layout_settings, filters: vec![], groups: vec![], sorts: vec![], diff --git a/frontend/rust-lib/flowy-database2/tests/database/group_test/test.rs b/frontend/rust-lib/flowy-database2/tests/database/group_test/test.rs index fb37bbea6a..d9fb97a865 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/group_test/test.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/group_test/test.rs @@ -28,23 +28,6 @@ async fn group_init_test() { test.run_scripts(scripts).await; } -// #[tokio::test] -// async fn group_configuration_setting_test() { -// let mut test = DatabaseGroupTest::new().await; -// let scripts = vec![ -// AssertGroupConfiguration { -// hide_ungrouped: false, -// }, -// UpdateGroupConfiguration { -// hide_ungrouped: Some(true), -// }, -// AssertGroupConfiguration { -// hide_ungrouped: true, -// }, -// ]; -// test.run_scripts(scripts).await; -// } - #[tokio::test] async fn group_move_row_test() { let mut test = DatabaseGroupTest::new().await; diff --git a/frontend/rust-lib/flowy-database2/tests/database/layout_test/script.rs b/frontend/rust-lib/flowy-database2/tests/database/layout_test/script.rs index 02103f81b7..6800a7e4db 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/layout_test/script.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/layout_test/script.rs @@ -1,13 +1,15 @@ use collab_database::fields::Field; use collab_database::views::DatabaseLayout; -use flowy_database2::entities::FieldType; -use flowy_database2::services::setting::CalendarLayoutSetting; +use flowy_database2::entities::{FieldType, LayoutSettingChangeset, LayoutSettingParams}; +use flowy_database2::services::setting::{BoardLayoutSetting, CalendarLayoutSetting}; use crate::database::database_editor::DatabaseEditorTest; pub enum LayoutScript { + AssertBoardLayoutSetting { expected: BoardLayoutSetting }, AssertCalendarLayoutSetting { expected: CalendarLayoutSetting }, + UpdateBoardLayoutSetting { new_setting: BoardLayoutSetting }, AssertDefaultAllCalendarEvents, AssertAllCalendarEventsCount { expected: usize }, UpdateDatabaseLayout { layout: DatabaseLayout }, @@ -23,21 +25,39 @@ impl DatabaseLayoutTest { Self { database_test } } + pub async fn new_board() -> Self { + let database_test = DatabaseEditorTest::new_board().await; + Self { database_test } + } + pub async fn new_calendar() -> Self { let database_test = DatabaseEditorTest::new_calendar().await; Self { database_test } } + pub async fn get_first_date_field(&self) -> Field { + self.database_test.get_first_field(FieldType::DateTime) + } + + async fn get_layout_setting( + &self, + view_id: &str, + layout_ty: DatabaseLayout, + ) -> LayoutSettingParams { + self + .database_test + .editor + .get_layout_setting(view_id, layout_ty) + .await + .unwrap() + } + pub async fn run_scripts(&mut self, scripts: Vec) { for script in scripts { self.run_script(script).await; } } - pub async fn get_first_date_field(&self) -> Field { - self.database_test.get_first_field(FieldType::DateTime) - } - pub async fn run_script(&mut self, script: LayoutScript) { match script { LayoutScript::UpdateDatabaseLayout { layout } => { @@ -56,19 +76,27 @@ impl DatabaseLayoutTest { .await; assert_eq!(events.len(), expected); }, + LayoutScript::AssertBoardLayoutSetting { expected } => { + let view_id = self.database_test.view_id.clone(); + let layout_ty = DatabaseLayout::Board; + + let layout_settings = self.get_layout_setting(&view_id, layout_ty).await; + + assert!(layout_settings.calendar.is_none()); + assert_eq!( + layout_settings.board.unwrap().hide_ungrouped_column, + expected.hide_ungrouped_column + ); + }, LayoutScript::AssertCalendarLayoutSetting { expected } => { let view_id = self.database_test.view_id.clone(); let layout_ty = DatabaseLayout::Calendar; - let calendar_setting = self - .database_test - .editor - .get_layout_setting(&view_id, layout_ty) - .await - .unwrap() - .calendar - .unwrap(); + let layout_settings = self.get_layout_setting(&view_id, layout_ty).await; + assert!(layout_settings.board.is_none()); + + let calendar_setting = layout_settings.calendar.unwrap(); assert_eq!(calendar_setting.layout_ty, expected.layout_ty); assert_eq!( calendar_setting.first_day_of_week, @@ -76,6 +104,20 @@ impl DatabaseLayoutTest { ); assert_eq!(calendar_setting.show_weekends, expected.show_weekends); }, + LayoutScript::UpdateBoardLayoutSetting { new_setting } => { + let changeset = LayoutSettingChangeset { + view_id: self.database_test.view_id.clone(), + layout_type: DatabaseLayout::Board, + board: Some(new_setting), + calendar: None, + }; + self + .database_test + .editor + .set_layout_setting(&self.database_test.view_id, changeset) + .await + .unwrap() + }, LayoutScript::AssertDefaultAllCalendarEvents => { let events = self .database_test diff --git a/frontend/rust-lib/flowy-database2/tests/database/layout_test/test.rs b/frontend/rust-lib/flowy-database2/tests/database/layout_test/test.rs index a380e4b511..7a8d5749eb 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/layout_test/test.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/layout_test/test.rs @@ -1,9 +1,31 @@ use collab_database::views::DatabaseLayout; +use flowy_database2::services::setting::BoardLayoutSetting; use flowy_database2::services::setting::CalendarLayoutSetting; use crate::database::layout_test::script::DatabaseLayoutTest; use crate::database::layout_test::script::LayoutScript::*; +#[tokio::test] +async fn board_layout_setting_test() { + let mut test = DatabaseLayoutTest::new_board().await; + let default_board_setting = BoardLayoutSetting::new(); + let new_board_setting = BoardLayoutSetting { + hide_ungrouped_column: true, + }; + let scripts = vec![ + AssertBoardLayoutSetting { + expected: default_board_setting, + }, + UpdateBoardLayoutSetting { + new_setting: new_board_setting.clone(), + }, + AssertBoardLayoutSetting { + expected: new_board_setting, + }, + ]; + test.run_scripts(scripts).await; +} + #[tokio::test] async fn calendar_initial_layout_setting_test() { let mut test = DatabaseLayoutTest::new_calendar().await; diff --git a/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs b/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs index a6fd10cce7..d26f3bd59f 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/mock_data/board_mock_data.rs @@ -1,6 +1,7 @@ use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData}; -use collab_database::views::{DatabaseLayout, DatabaseView}; +use collab_database::views::{DatabaseLayout, DatabaseView, LayoutSetting, LayoutSettings}; use flowy_database2::services::field_settings::DatabaseFieldSettingsMapBuilder; +use flowy_database2::services::setting::BoardLayoutSetting; use strum::IntoEnumIterator; use flowy_database2::entities::FieldType; @@ -128,6 +129,8 @@ pub fn make_test_board() -> DatabaseData { } } + let board_setting: LayoutSetting = BoardLayoutSetting::new().into(); + let field_settings = DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build(); @@ -238,12 +241,15 @@ pub fn make_test_board() -> DatabaseData { rows.push(row); } + let mut layout_settings = LayoutSettings::new(); + layout_settings.insert(DatabaseLayout::Board, board_setting); + let view = DatabaseView { id: gen_database_view_id(), database_id: gen_database_id(), name: "".to_string(), layout: DatabaseLayout::Board, - layout_settings: Default::default(), + layout_settings, filters: vec![], group_settings: vec![], sorts: vec![],