refactor: hide ungrouped feature (#3817)

* refactor: remove unused notification and listener

* revert: remove hide_ungrouped from group settings

* chore: add board layout setting

* chore: listen to layout settings on ui

* fix: duplicated group controller initialization

* chore: add a tooltip to the ungrouped items button

* chore: trailing comma
This commit is contained in:
Richard Shiue 2023-10-29 11:26:49 +08:00 committed by GitHub
parent 993532a2f0
commit b9a25f449f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 419 additions and 486 deletions

View File

@ -1,7 +1,7 @@
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart'; 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/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/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/calendar_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/database_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'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
@ -47,12 +47,10 @@ class GroupCallbacks {
} }
class DatabaseLayoutSettingCallbacks { class DatabaseLayoutSettingCallbacks {
final void Function(DatabaseLayoutSettingPB) onLayoutChanged; final void Function(DatabaseLayoutSettingPB) onLayoutSettingsChanged;
final void Function(DatabaseLayoutSettingPB) onLoadLayout;
DatabaseLayoutSettingCallbacks({ DatabaseLayoutSettingCallbacks({
required this.onLayoutChanged, required this.onLayoutSettingsChanged,
required this.onLoadLayout,
}); });
} }
@ -125,11 +123,11 @@ class DatabaseController {
void addListener({ void addListener({
DatabaseCallbacks? onDatabaseChanged, DatabaseCallbacks? onDatabaseChanged,
DatabaseLayoutSettingCallbacks? onLayoutChanged, DatabaseLayoutSettingCallbacks? onLayoutSettingsChanged,
GroupCallbacks? onGroupChanged, GroupCallbacks? onGroupChanged,
}) { }) {
if (onLayoutChanged != null) { if (onLayoutSettingsChanged != null) {
_layoutCallbacks.add(onLayoutChanged); _layoutCallbacks.add(onLayoutSettingsChanged);
} }
if (onDatabaseChanged != null) { if (onDatabaseChanged != null) {
@ -228,12 +226,14 @@ class DatabaseController {
); );
} }
Future<void> updateLayoutSetting( Future<void> updateLayoutSetting({
CalendarLayoutSettingPB calendarlLayoutSetting, BoardLayoutSettingPB? boardLayoutSetting,
) async { CalendarLayoutSettingPB? calendarLayoutSetting,
}) async {
await _databaseViewBackendSvc await _databaseViewBackendSvc
.updateLayoutSetting( .updateLayoutSetting(
calendarLayoutSetting: calendarlLayoutSetting, boardLayoutSetting: boardLayoutSetting,
calendarLayoutSetting: calendarLayoutSetting,
layoutType: databaseLayout, layoutType: databaseLayout,
) )
.then((result) { .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<void> dispose() async { Future<void> dispose() async {
await _databaseViewBackendSvc.closeView(); await _databaseViewBackendSvc.closeView();
await fieldController.dispose(); await fieldController.dispose();
@ -261,9 +252,6 @@ class DatabaseController {
} }
Future<void> _loadGroups() async { Future<void> _loadGroups() async {
final configResult = await loadGroupConfigurations(viewId: viewId);
_handleGroupConfigurationChanged(configResult);
final groupsResult = await _databaseViewBackendSvc.loadGroups(); final groupsResult = await _databaseViewBackendSvc.loadGroups();
groupsResult.fold( groupsResult.fold(
(groups) { (groups) {
@ -280,10 +268,9 @@ class DatabaseController {
result.fold( result.fold(
(newDatabaseLayoutSetting) { (newDatabaseLayoutSetting) {
databaseLayoutSetting = newDatabaseLayoutSetting; databaseLayoutSetting = newDatabaseLayoutSetting;
databaseLayoutSetting?.freeze();
for (final callback in _layoutCallbacks) { for (final callback in _layoutCallbacks) {
callback.onLoadLayout(newDatabaseLayoutSetting); callback.onLayoutSettingsChanged(newDatabaseLayoutSetting);
} }
}, },
(r) => Log.error(r), (r) => Log.error(r),
@ -339,7 +326,6 @@ class DatabaseController {
void _listenOnGroupChanged() { void _listenOnGroupChanged() {
_groupListener.start( _groupListener.start(
onGroupConfigurationChanged: _handleGroupConfigurationChanged,
onNumOfGroupsChanged: (result) { onNumOfGroupsChanged: (result) {
result.fold( result.fold(
(changeset) { (changeset) {
@ -386,7 +372,7 @@ class DatabaseController {
databaseLayoutSetting?.freeze(); databaseLayoutSetting?.freeze();
for (final callback in _layoutCallbacks) { for (final callback in _layoutCallbacks) {
callback.onLayoutChanged(newLayout); callback.onLayoutSettingsChanged(newLayout);
} }
}, },
(r) => Log.error(r), (r) => Log.error(r),
@ -394,29 +380,6 @@ class DatabaseController {
}, },
); );
} }
Future<Either<List<GroupSettingPB>, 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<List<GroupSettingPB>, FlowyError> result,
) {
result.fold(
(configurations) {
for (final callback in _groupCallbacks) {
callback.onGroupConfigurationChanged?.call(configurations);
}
},
(r) => Log.error(r),
);
}
} }
class RowDataBuilder { class RowDataBuilder {

View File

@ -1,4 +1,5 @@
import 'package:appflowy/plugins/database_view/application/row/row_service.dart'; 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/calendar_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/database_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'; import 'package:appflowy_backend/protobuf/flowy-database2/group_changeset.pb.dart';
@ -114,11 +115,17 @@ class DatabaseViewBackendService {
Future<Either<Unit, FlowyError>> updateLayoutSetting({ Future<Either<Unit, FlowyError>> updateLayoutSetting({
required DatabaseLayoutPB layoutType, required DatabaseLayoutPB layoutType,
BoardLayoutSettingPB? boardLayoutSetting,
CalendarLayoutSettingPB? calendarLayoutSetting, CalendarLayoutSettingPB? calendarLayoutSetting,
}) { }) {
final payload = LayoutSettingChangesetPB.create() final payload = LayoutSettingChangesetPB.create()
..viewId = viewId ..viewId = viewId
..layoutType = layoutType; ..layoutType = layoutType;
if (boardLayoutSetting != null) {
payload.board = boardLayoutSetting;
}
if (calendarLayoutSetting != null) { if (calendarLayoutSetting != null) {
payload.calendar = calendarLayoutSetting; payload.calendar = calendarLayoutSetting;
} }

View File

@ -15,8 +15,6 @@ typedef GroupByNewFieldValue = Either<List<GroupPB>, FlowyError>;
class DatabaseGroupListener { class DatabaseGroupListener {
final String viewId; final String viewId;
PublishNotifier<GroupConfigurationUpdateValue>? _groupConfigurationNotifier =
PublishNotifier();
PublishNotifier<GroupUpdateValue>? _numOfGroupsNotifier = PublishNotifier(); PublishNotifier<GroupUpdateValue>? _numOfGroupsNotifier = PublishNotifier();
PublishNotifier<GroupByNewFieldValue>? _groupByFieldNotifier = PublishNotifier<GroupByNewFieldValue>? _groupByFieldNotifier =
PublishNotifier(); PublishNotifier();
@ -24,13 +22,9 @@ class DatabaseGroupListener {
DatabaseGroupListener(this.viewId); DatabaseGroupListener(this.viewId);
void start({ void start({
required void Function(GroupConfigurationUpdateValue)
onGroupConfigurationChanged,
required void Function(GroupUpdateValue) onNumOfGroupsChanged, required void Function(GroupUpdateValue) onNumOfGroupsChanged,
required void Function(GroupByNewFieldValue) onGroupByNewField, required void Function(GroupByNewFieldValue) onGroupByNewField,
}) { }) {
_groupConfigurationNotifier
?.addPublishListener(onGroupConfigurationChanged);
_numOfGroupsNotifier?.addPublishListener(onNumOfGroupsChanged); _numOfGroupsNotifier?.addPublishListener(onNumOfGroupsChanged);
_groupByFieldNotifier?.addPublishListener(onGroupByNewField); _groupByFieldNotifier?.addPublishListener(onGroupByNewField);
_listener = DatabaseNotificationListener( _listener = DatabaseNotificationListener(
@ -44,13 +38,6 @@ class DatabaseGroupListener {
Either<Uint8List, FlowyError> result, Either<Uint8List, FlowyError> result,
) { ) {
switch (ty) { switch (ty) {
case DatabaseNotification.DidUpdateGroupConfiguration:
result.fold(
(payload) => _groupConfigurationNotifier?.value =
left(RepeatedGroupSettingPB.fromBuffer(payload).items),
(error) => _groupConfigurationNotifier?.value = right(error),
);
break;
case DatabaseNotification.DidUpdateNumOfGroups: case DatabaseNotification.DidUpdateNumOfGroups:
result.fold( result.fold(
(payload) => _numOfGroupsNotifier?.value = (payload) => _numOfGroupsNotifier?.value =
@ -72,9 +59,6 @@ class DatabaseGroupListener {
Future<void> stop() async { Future<void> stop() async {
await _listener?.stop(); await _listener?.stop();
_groupConfigurationNotifier?.dispose();
_groupConfigurationNotifier = null;
_numOfGroupsNotifier?.dispose(); _numOfGroupsNotifier?.dispose();
_numOfGroupsNotifier = null; _numOfGroupsNotifier = null;

View File

@ -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<DatabaseLayoutSettingPB, FlowyError>;
class DatabaseCalendarLayoutListener {
final String viewId;
PublishNotifier<NewLayoutFieldValue>? _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<Uint8List, FlowyError> result,
) {
switch (ty) {
case DatabaseNotification.DidSetNewLayoutField:
result.fold(
(payload) => _newLayoutFieldNotifier?.value =
left(DatabaseLayoutSettingPB.fromBuffer(payload)),
(error) => _newLayoutFieldNotifier?.value = right(error),
);
break;
default:
break;
}
}
Future<void> stop() async {
await _listener?.stop();
_newLayoutFieldNotifier?.dispose();
_newLayoutFieldNotifier = null;
}
}

View File

@ -1,6 +1,7 @@
import 'package:appflowy/plugins/database_view/application/database_controller.dart'; import 'package:appflowy/plugins/database_view/application/database_controller.dart';
import 'package:appflowy/plugins/database_view/application/field/field_info.dart'; import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
import 'package:appflowy_backend/log.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:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
@ -14,7 +15,7 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
final DatabaseController _databaseController; final DatabaseController _databaseController;
final GroupBackendService _groupBackendSvc; final GroupBackendService _groupBackendSvc;
Function(List<FieldInfo>)? _onFieldsFn; Function(List<FieldInfo>)? _onFieldsFn;
GroupCallbacks? _groupCallbacks; DatabaseLayoutSettingCallbacks? _layoutSettingCallbacks;
DatabaseGroupBloc({ DatabaseGroupBloc({
required String viewId, required String viewId,
@ -25,13 +26,13 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
DatabaseGroupState.initial( DatabaseGroupState.initial(
viewId, viewId,
databaseController.fieldController.fieldInfos, databaseController.fieldController.fieldInfos,
databaseController.databaseLayoutSetting!.board,
), ),
) { ) {
on<DatabaseGroupEvent>( on<DatabaseGroupEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
initial: () { initial: () {
_loadGroupConfigurations();
_startListening(); _startListening();
}, },
didReceiveFieldUpdate: (fieldInfos) { didReceiveFieldUpdate: (fieldInfos) {
@ -43,8 +44,8 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
); );
result.fold((l) => null, (err) => Log.error(err)); result.fold((l) => null, (err) => Log.error(err));
}, },
didUpdateHideUngrouped: (bool hideUngrouped) { didUpdateLayoutSettings: (layoutSettings) {
emit(state.copyWith(hideUngrouped: hideUngrouped)); emit(state.copyWith(layoutSettings: layoutSettings));
}, },
); );
}, },
@ -58,7 +59,7 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
.removeListener(onFieldsListener: _onFieldsFn!); .removeListener(onFieldsListener: _onFieldsFn!);
_onFieldsFn = null; _onFieldsFn = null;
} }
_groupCallbacks = null; _layoutSettingCallbacks = null;
return super.close(); return super.close();
} }
@ -70,32 +71,18 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
listenWhen: () => !isClosed, listenWhen: () => !isClosed,
); );
_groupCallbacks = GroupCallbacks( _layoutSettingCallbacks = DatabaseLayoutSettingCallbacks(
onGroupConfigurationChanged: (configurations) { onLayoutSettingsChanged: (layoutSettings) {
if (isClosed) { if (isClosed || !layoutSettings.hasBoard()) {
return; return;
} }
final configuration = configurations.first;
add( add(
DatabaseGroupEvent.didUpdateHideUngrouped( DatabaseGroupEvent.didUpdateLayoutSettings(layoutSettings.board),
configuration.hideUngrouped,
),
); );
}, },
); );
_databaseController.addListener(onGroupChanged: _groupCallbacks); _databaseController.addListener(
} onLayoutSettingsChanged: _layoutSettingCallbacks,
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),
); );
} }
} }
@ -110,8 +97,9 @@ class DatabaseGroupEvent with _$DatabaseGroupEvent {
const factory DatabaseGroupEvent.didReceiveFieldUpdate( const factory DatabaseGroupEvent.didReceiveFieldUpdate(
List<FieldInfo> fields, List<FieldInfo> fields,
) = _DidReceiveFieldUpdate; ) = _DidReceiveFieldUpdate;
const factory DatabaseGroupEvent.didUpdateHideUngrouped(bool hideUngrouped) = const factory DatabaseGroupEvent.didUpdateLayoutSettings(
_DidUpdateHideUngrouped; BoardLayoutSettingPB layoutSettings,
) = _DidUpdateLayoutSettings;
} }
@freezed @freezed
@ -119,16 +107,17 @@ class DatabaseGroupState with _$DatabaseGroupState {
const factory DatabaseGroupState({ const factory DatabaseGroupState({
required String viewId, required String viewId,
required List<FieldInfo> fieldInfos, required List<FieldInfo> fieldInfos,
required bool hideUngrouped, required BoardLayoutSettingPB layoutSettings,
}) = _DatabaseGroupState; }) = _DatabaseGroupState;
factory DatabaseGroupState.initial( factory DatabaseGroupState.initial(
String viewId, String viewId,
List<FieldInfo> fieldInfos, List<FieldInfo> fieldInfos,
BoardLayoutSettingPB layoutSettings,
) => ) =>
DatabaseGroupState( DatabaseGroupState(
viewId: viewId, viewId: viewId,
fieldInfos: fieldInfos, fieldInfos: fieldInfos,
hideUngrouped: true, layoutSettings: layoutSettings,
); );
} }

View File

@ -147,8 +147,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
), ),
); );
}, },
didUpdateHideUngrouped: (bool hideUngrouped) { didUpdateLayoutSettings: (layoutSettings) {
emit(state.copyWith(hideUngrouped: hideUngrouped)); emit(state.copyWith(layoutSettings: layoutSettings));
}, },
startEditingHeader: (String groupId) { startEditingHeader: (String groupId) {
emit( emit(
@ -200,7 +200,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
if (ungroupedGroupIndex != -1) { if (ungroupedGroupIndex != -1) {
ungroupedGroup = groups[ungroupedGroupIndex]; ungroupedGroup = groups[ungroupedGroupIndex];
final group = groups.removeAt(ungroupedGroupIndex); final group = groups.removeAt(ungroupedGroupIndex);
if (!state.hideUngrouped) { if (!(state.layoutSettings?.hideUngroupedColumn ?? false)) {
groups.add(group); groups.add(group);
} }
} }
@ -230,20 +230,21 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
} }
}, },
); );
final onGroupChanged = GroupCallbacks( final onLayoutSettingsChanged = DatabaseLayoutSettingCallbacks(
onGroupConfigurationChanged: (configurations) { onLayoutSettingsChanged: (layoutSettings) {
if (isClosed) return; if (isClosed || !layoutSettings.hasBoard()) {
final config = configurations.first; return;
if (config.hideUngrouped) { }
boardController.removeGroup(config.fieldId); if (layoutSettings.board.hideUngroupedColumn) {
boardController.removeGroup(ungroupedGroup!.fieldId);
} else if (ungroupedGroup != null) { } else if (ungroupedGroup != null) {
final newGroup = initializeGroupData(ungroupedGroup!); final newGroup = initializeGroupData(ungroupedGroup!);
final controller = initializeGroupController(ungroupedGroup!);
groupControllers[controller.group.groupId] = (controller);
boardController.addGroup(newGroup); boardController.addGroup(newGroup);
} }
add(BoardEvent.didUpdateHideUngrouped(config.hideUngrouped)); add(BoardEvent.didUpdateLayoutSettings(layoutSettings.board));
}, },
);
final onGroupChanged = GroupCallbacks(
onGroupByField: (groups) { onGroupByField: (groups) {
if (isClosed) return; if (isClosed) return;
ungroupedGroup = null; ungroupedGroup = null;
@ -274,6 +275,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
databaseController.addListener( databaseController.addListener(
onDatabaseChanged: onDatabaseChanged, onDatabaseChanged: onDatabaseChanged,
onLayoutSettingsChanged: onLayoutSettingsChanged,
onGroupChanged: onGroupChanged, onGroupChanged: onGroupChanged,
); );
} }
@ -360,8 +362,9 @@ class BoardEvent with _$BoardEvent {
) = _DidReceiveGridUpdate; ) = _DidReceiveGridUpdate;
const factory BoardEvent.didReceiveGroups(List<GroupPB> groups) = const factory BoardEvent.didReceiveGroups(List<GroupPB> groups) =
_DidReceiveGroups; _DidReceiveGroups;
const factory BoardEvent.didUpdateHideUngrouped(bool hideUngrouped) = const factory BoardEvent.didUpdateLayoutSettings(
_DidUpdateHideUngrouped; BoardLayoutSettingPB layoutSettings,
) = _DidUpdateLayoutSettings;
} }
@freezed @freezed
@ -376,7 +379,7 @@ class BoardState with _$BoardState {
BoardEditingRow? editingRow, BoardEditingRow? editingRow,
required LoadingState loadingState, required LoadingState loadingState,
required Option<FlowyError> noneOrError, required Option<FlowyError> noneOrError,
required bool hideUngrouped, required BoardLayoutSettingPB? layoutSettings,
}) = _BoardState; }) = _BoardState;
factory BoardState.initial(String viewId) => BoardState( factory BoardState.initial(String viewId) => BoardState(
@ -387,7 +390,7 @@ class BoardState with _$BoardState {
isEditingRow: false, isEditingRow: false,
noneOrError: none(), noneOrError: none(),
loadingState: const LoadingState.loading(), loadingState: const LoadingState.loading(),
hideUngrouped: false, layoutSettings: null,
); );
} }

View File

@ -167,7 +167,8 @@ class _BoardContentState extends State<BoardContent> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const VSpace(8.0), const VSpace(8.0),
if (state.hideUngrouped) _buildBoardHeader(context), if (state.layoutSettings?.hideUngroupedColumn ?? false)
_buildBoardHeader(context),
Expanded( Expanded(
child: AppFlowyBoard( child: AppFlowyBoard(
boardScrollController: scrollManager, boardScrollController: scrollManager,

View File

@ -17,6 +17,7 @@ import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.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/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -61,31 +62,36 @@ class _UnscheduledEventsButtonState extends State<UngroupedItemsButton> {
offset: const Offset(0, 8), offset: const Offset(0, 8),
constraints: constraints:
const BoxConstraints(maxWidth: 282, maxHeight: 600), const BoxConstraints(maxWidth: 282, maxHeight: 600),
child: OutlinedButton( child: FlowyTooltip(
style: OutlinedButton.styleFrom( message: LocaleKeys.board_ungroupedButtonTooltip.tr(),
shape: RoundedRectangleBorder( child: OutlinedButton(
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Theme.of(context).dividerColor,
width: 1,
),
borderRadius: Corners.s6Border,
),
side: BorderSide( side: BorderSide(
color: Theme.of(context).dividerColor, color: Theme.of(context).dividerColor,
width: 1, width: 1,
), ),
borderRadius: Corners.s6Border, padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
visualDensity: VisualDensity.compact,
), ),
side: BorderSide( onPressed: () {
color: Theme.of(context).dividerColor, if (state.ungroupedItems.isNotEmpty) {
width: 1, _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) { popupBuilder: (context) {

View File

@ -198,7 +198,9 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
Future<void> _updateCalendarLayoutSetting( Future<void> _updateCalendarLayoutSetting(
CalendarLayoutSettingPB layoutSetting, CalendarLayoutSettingPB layoutSetting,
) async { ) async {
return databaseController.updateLayoutSetting(layoutSetting); return databaseController.updateLayoutSetting(
calendarLayoutSetting: layoutSetting,
);
} }
Future<CalendarEventData<CalendarDayEvent>?> _loadEvent(RowId rowId) async { Future<CalendarEventData<CalendarDayEvent>?> _loadEvent(RowId rowId) async {
@ -319,14 +321,13 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
}, },
); );
final onLayoutChanged = DatabaseLayoutSettingCallbacks( final onLayoutSettingsChanged = DatabaseLayoutSettingCallbacks(
onLayoutChanged: _didReceiveLayoutSetting, onLayoutSettingsChanged: _didReceiveLayoutSetting,
onLoadLayout: _didReceiveLayoutSetting,
); );
databaseController.addListener( databaseController.addListener(
onDatabaseChanged: onDatabaseChanged, onDatabaseChanged: onDatabaseChanged,
onLayoutChanged: onLayoutChanged, onLayoutSettingsChanged: onLayoutSettingsChanged,
); );
} }

View File

@ -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/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.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.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:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
import 'package:easy_localization/easy_localization.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/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:protobuf/protobuf.dart' hide FieldInfo;
class DatabaseGroupList extends StatelessWidget { class DatabaseGroupList extends StatelessWidget {
final String viewId; final String viewId;
@ -60,9 +62,9 @@ class DatabaseGroupList extends StatelessWidget {
), ),
), ),
Toggle( Toggle(
value: !state.hideUngrouped, value: !state.layoutSettings.hideUngroupedColumn,
onChanged: (value) => onChanged: (value) =>
databaseController.updateGroupConfiguration(value), _updateLayoutSettings(state.layoutSettings, value),
style: ToggleStyle.big, style: ToggleStyle.big,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
), ),
@ -105,6 +107,19 @@ class DatabaseGroupList extends StatelessWidget {
), ),
); );
} }
Future<void> _updateLayoutSettings(
BoardLayoutSettingPB layoutSettings,
bool hideUngrouped,
) {
layoutSettings.freeze();
final newLayoutSetting = layoutSettings.rebuild((message) {
message.hideUngroupedColumn = hideUngrouped;
});
return databaseController.updateLayoutSetting(
boardLayoutSetting: newLayoutSetting,
);
}
} }
class _GridGroupCell extends StatelessWidget { class _GridGroupCell extends StatelessWidget {

View File

@ -115,7 +115,9 @@ class ICalendarSettingImpl extends ICalendarSetting {
@override @override
void updateLayoutSettings(CalendarLayoutSettingPB layoutSettings) { void updateLayoutSettings(CalendarLayoutSettingPB layoutSettings) {
_databaseController.updateLayoutSetting(layoutSettings); _databaseController.updateLayoutSetting(
calendarLayoutSetting: layoutSettings,
);
} }
@override @override

View File

@ -751,6 +751,7 @@
"menuName": "Board", "menuName": "Board",
"showUngrouped": "Show ungrouped items", "showUngrouped": "Show ungrouped items",
"ungroupedButtonText": "Ungrouped", "ungroupedButtonText": "Ungrouped",
"ungroupedButtonTooltip": "Contains cards that don't belong in any group",
"ungroupedItemsTitle": "Click to add to the board", "ungroupedItemsTitle": "Click to add to the board",
"groupBy": "Group by", "groupBy": "Group by",
"referencedBoardPrefix": "View of" "referencedBoardPrefix": "View of"

View File

@ -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<BoardLayoutSetting> for BoardLayoutSettingPB {
fn from(setting: BoardLayoutSetting) -> Self {
Self {
hide_ungrouped_column: setting.hide_ungrouped_column,
}
}
}
impl From<BoardLayoutSettingPB> for BoardLayoutSetting {
fn from(setting: BoardLayoutSettingPB) -> Self {
Self {
hide_ungrouped_column: setting.hide_ungrouped_column,
}
}
}

View File

@ -5,7 +5,7 @@ use flowy_error::ErrorCode;
use crate::entities::parser::NotEmptyStr; use crate::entities::parser::NotEmptyStr;
use crate::entities::{FieldType, RowMetaPB}; 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)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GroupSettingPB { pub struct GroupSettingPB {
@ -14,9 +14,6 @@ pub struct GroupSettingPB {
#[pb(index = 2)] #[pb(index = 2)]
pub field_id: String, pub field_id: String,
#[pb(index = 3)]
pub hide_ungrouped: bool,
} }
impl std::convert::From<&GroupSetting> for GroupSettingPB { impl std::convert::From<&GroupSetting> for GroupSettingPB {
@ -24,7 +21,6 @@ impl std::convert::From<&GroupSetting> for GroupSettingPB {
GroupSettingPB { GroupSettingPB {
id: rev.id.clone(), id: rev.id.clone(),
field_id: rev.field_id.clone(), field_id: rev.field_id.clone(),
hide_ungrouped: rev.hide_ungrouped,
} }
} }
} }
@ -52,26 +48,6 @@ impl std::convert::From<Vec<GroupSetting>> 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<bool>,
}
impl From<GroupSettingChangesetPB> for GroupSettingChangeset {
fn from(value: GroupSettingChangesetPB) -> Self {
Self {
hide_ungrouped: value.hide_ungrouped,
}
}
}
#[derive(ProtoBuf, Debug, Default, Clone)] #[derive(ProtoBuf, Debug, Default, Clone)]
pub struct RepeatedGroupPB { pub struct RepeatedGroupPB {
#[pb(index = 1)] #[pb(index = 1)]

View File

@ -1,3 +1,4 @@
mod board_entities;
mod calendar_entities; mod calendar_entities;
mod cell_entities; mod cell_entities;
mod database_entities; mod database_entities;
@ -16,6 +17,7 @@ mod macros;
mod share_entities; mod share_entities;
mod type_option_entities; mod type_option_entities;
pub use board_entities::*;
pub use calendar_entities::*; pub use calendar_entities::*;
pub use cell_entities::*; pub use cell_entities::*;
pub use database_entities::*; pub use database_entities::*;

View File

@ -13,7 +13,9 @@ use crate::entities::{
RepeatedSortPB, UpdateFilterParams, UpdateFilterPayloadPB, UpdateGroupPB, UpdateSortParams, RepeatedSortPB, UpdateFilterParams, UpdateFilterPayloadPB, UpdateGroupPB, UpdateSortParams,
UpdateSortPayloadPB, 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. /// [DatabaseViewSettingPB] defines the setting options for the grid. Such as the filter, group, and sort.
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
@ -151,19 +153,51 @@ pub struct DatabaseLayoutSettingPB {
pub layout_type: DatabaseLayoutPB, pub layout_type: DatabaseLayoutPB,
#[pb(index = 2, one_of)] #[pb(index = 2, one_of)]
pub board: Option<BoardLayoutSettingPB>,
#[pb(index = 3, one_of)]
pub calendar: Option<CalendarLayoutSettingPB>, pub calendar: Option<CalendarLayoutSettingPB>,
} }
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)] #[derive(Debug, Clone, Default)]
pub struct LayoutSettingParams { pub struct LayoutSettingParams {
pub layout_type: DatabaseLayout, pub layout_type: DatabaseLayout,
pub board: Option<BoardLayoutSetting>,
pub calendar: Option<CalendarLayoutSetting>, pub calendar: Option<CalendarLayoutSetting>,
} }
impl LayoutSettingParams {
pub fn new(layout_type: DatabaseLayout) -> Self {
Self {
layout_type,
..Default::default()
}
}
}
impl From<LayoutSettingParams> for DatabaseLayoutSettingPB { impl From<LayoutSettingParams> for DatabaseLayoutSettingPB {
fn from(data: LayoutSettingParams) -> Self { fn from(data: LayoutSettingParams) -> Self {
Self { Self {
layout_type: data.layout_type.into(), layout_type: data.layout_type.into(),
board: data.board.map(|board| board.into()),
calendar: data.calendar.map(|calendar| calendar.into()), calendar: data.calendar.map(|calendar| calendar.into()),
} }
} }
@ -178,6 +212,9 @@ pub struct LayoutSettingChangesetPB {
pub layout_type: DatabaseLayoutPB, pub layout_type: DatabaseLayoutPB,
#[pb(index = 3, one_of)] #[pb(index = 3, one_of)]
pub board: Option<BoardLayoutSettingPB>,
#[pb(index = 4, one_of)]
pub calendar: Option<CalendarLayoutSettingPB>, pub calendar: Option<CalendarLayoutSettingPB>,
} }
@ -185,9 +222,17 @@ pub struct LayoutSettingChangesetPB {
pub struct LayoutSettingChangeset { pub struct LayoutSettingChangeset {
pub view_id: String, pub view_id: String,
pub layout_type: DatabaseLayout, pub layout_type: DatabaseLayout,
pub board: Option<BoardLayoutSetting>,
pub calendar: Option<CalendarLayoutSetting>, pub calendar: Option<CalendarLayoutSetting>,
} }
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<LayoutSettingChangeset> for LayoutSettingChangesetPB { impl TryInto<LayoutSettingChangeset> for LayoutSettingChangesetPB {
type Error = ErrorCode; type Error = ErrorCode;
@ -199,7 +244,8 @@ impl TryInto<LayoutSettingChangeset> for LayoutSettingChangesetPB {
Ok(LayoutSettingChangeset { Ok(LayoutSettingChangeset {
view_id, view_id,
layout_type: self.layout_type.into(), 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),
}) })
} }
} }

View File

@ -646,36 +646,6 @@ pub(crate) async fn update_date_cell_handler(
Ok(()) Ok(())
} }
#[tracing::instrument(level = "trace", skip_all, err)]
pub(crate) async fn get_group_configurations_handler(
data: AFPluginData<DatabaseViewIdPB>,
manager: AFPluginState<Weak<DatabaseManager>>,
) -> DataResult<RepeatedGroupSettingPB, FlowyError> {
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<GroupSettingChangesetPB>,
manager: AFPluginState<Weak<DatabaseManager>>,
) -> 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)] #[tracing::instrument(level = "trace", skip_all, err)]
pub(crate) async fn get_groups_handler( pub(crate) async fn get_groups_handler(
data: AFPluginData<DatabaseViewIdPB>, data: AFPluginData<DatabaseViewIdPB>,
@ -786,15 +756,11 @@ pub(crate) async fn set_layout_setting_handler(
manager: AFPluginState<Weak<DatabaseManager>>, manager: AFPluginState<Weak<DatabaseManager>>,
) -> FlowyResult<()> { ) -> FlowyResult<()> {
let manager = upgrade_manager(manager)?; let manager = upgrade_manager(manager)?;
let params: LayoutSettingChangeset = data.into_inner().try_into()?; let changeset = data.into_inner();
let database_editor = manager.get_database_with_view_id(&params.view_id).await?; let view_id = changeset.view_id.clone();
let layout_params = LayoutSettingParams { let params: LayoutSettingChangeset = changeset.try_into()?;
layout_type: params.layout_type, let database_editor = manager.get_database_with_view_id(&view_id).await?;
calendar: params.calendar, database_editor.set_layout_setting(&view_id, params).await?;
};
database_editor
.set_layout_setting(&params.view_id, layout_params)
.await;
Ok(()) Ok(())
} }

View File

@ -54,8 +54,6 @@ pub fn init(database_manager: Weak<DatabaseManager>) -> AFPlugin {
// Date // Date
.event(DatabaseEvent::UpdateDateCell, update_date_cell_handler) .event(DatabaseEvent::UpdateDateCell, update_date_cell_handler)
// Group // 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::SetGroupByField, set_group_by_field_handler)
.event(DatabaseEvent::MoveGroup, move_group_handler) .event(DatabaseEvent::MoveGroup, move_group_handler)
.event(DatabaseEvent::MoveGroupRow, move_group_row_handler) .event(DatabaseEvent::MoveGroupRow, move_group_row_handler)
@ -266,14 +264,10 @@ pub enum DatabaseEvent {
#[event(input = "DateChangesetPB")] #[event(input = "DateChangesetPB")]
UpdateDateCell = 80, UpdateDateCell = 80,
#[event(input = "DatabaseViewIdPB", output = "RepeatedGroupSettingPB")] /// [SetGroupByField] event is used to create a new grouping in a database
GetGroupConfigurations = 90, /// view based on the `field_id`
#[event(input = "GroupSettingChangesetPB")]
UpdateGroupConfiguration = 91,
#[event(input = "GroupByFieldPayloadPB")] #[event(input = "GroupByFieldPayloadPB")]
SetGroupByField = 92, SetGroupByField = 90,
#[event(input = "DatabaseViewIdPB", output = "RepeatedGroupPB")] #[event(input = "DatabaseViewIdPB", output = "RepeatedGroupPB")]
GetGroups = 100, GetGroups = 100,

View File

@ -20,8 +20,6 @@ pub enum DatabaseNotification {
DidUpdateCell = 40, DidUpdateCell = 40,
/// Trigger after editing a field properties including rename,update type option, etc /// Trigger after editing a field properties including rename,update type option, etc
DidUpdateField = 50, DidUpdateField = 50,
/// Trigger after the group configuration is changed
DidUpdateGroupConfiguration = 59,
/// Trigger after the number of groups is changed /// Trigger after the number of groups is changed
DidUpdateNumOfGroups = 60, DidUpdateNumOfGroups = 60,
/// Trigger after inserting/deleting/updating/moving a row /// Trigger after inserting/deleting/updating/moving a row
@ -42,18 +40,16 @@ pub enum DatabaseNotification {
DidUpdateSettings = 70, DidUpdateSettings = 70,
// Trigger when the layout setting of the database is updated // Trigger when the layout setting of the database is updated
DidUpdateLayoutSettings = 80, DidUpdateLayoutSettings = 80,
// Trigger when the layout field of the database is changed
DidSetNewLayoutField = 81,
// Trigger when the layout of the database is changed // Trigger when the layout of the database is changed
DidUpdateDatabaseLayout = 82, DidUpdateDatabaseLayout = 81,
// Trigger when the database view is deleted // Trigger when the database view is deleted
DidDeleteDatabaseView = 83, DidDeleteDatabaseView = 82,
// Trigger when the database view is moved to trash // Trigger when the database view is moved to trash
DidMoveDatabaseViewToTrash = 84, DidMoveDatabaseViewToTrash = 83,
DidUpdateDatabaseSyncUpdate = 85, DidUpdateDatabaseSyncUpdate = 84,
DidUpdateDatabaseSnapshotState = 86, DidUpdateDatabaseSnapshotState = 85,
// Trigger when the field setting is changed // Trigger when the field setting is changed
DidUpdateFieldSettings = 87, DidUpdateFieldSettings = 86,
} }
impl std::convert::From<DatabaseNotification> for i32 { impl std::convert::From<DatabaseNotification> for i32 {
@ -71,7 +67,6 @@ impl std::convert::From<i32> for DatabaseNotification {
22 => DatabaseNotification::DidUpdateFields, 22 => DatabaseNotification::DidUpdateFields,
40 => DatabaseNotification::DidUpdateCell, 40 => DatabaseNotification::DidUpdateCell,
50 => DatabaseNotification::DidUpdateField, 50 => DatabaseNotification::DidUpdateField,
59 => DatabaseNotification::DidUpdateGroupConfiguration,
60 => DatabaseNotification::DidUpdateNumOfGroups, 60 => DatabaseNotification::DidUpdateNumOfGroups,
61 => DatabaseNotification::DidUpdateGroupRow, 61 => DatabaseNotification::DidUpdateGroupRow,
62 => DatabaseNotification::DidGroupByField, 62 => DatabaseNotification::DidGroupByField,
@ -82,7 +77,6 @@ impl std::convert::From<i32> for DatabaseNotification {
67 => DatabaseNotification::DidUpdateRowMeta, 67 => DatabaseNotification::DidUpdateRowMeta,
70 => DatabaseNotification::DidUpdateSettings, 70 => DatabaseNotification::DidUpdateSettings,
80 => DatabaseNotification::DidUpdateLayoutSettings, 80 => DatabaseNotification::DidUpdateLayoutSettings,
81 => DatabaseNotification::DidSetNewLayoutField,
82 => DatabaseNotification::DidUpdateDatabaseLayout, 82 => DatabaseNotification::DidUpdateDatabaseLayout,
83 => DatabaseNotification::DidDeleteDatabaseView, 83 => DatabaseNotification::DidDeleteDatabaseView,
84 => DatabaseNotification::DidMoveDatabaseViewToTrash, 84 => DatabaseNotification::DidMoveDatabaseViewToTrash,

View File

@ -34,9 +34,7 @@ use crate::services::field_settings::{
default_field_settings_by_layout_map, FieldSettings, FieldSettingsChangesetParams, default_field_settings_by_layout_map, FieldSettings, FieldSettingsChangesetParams,
}; };
use crate::services::filter::Filter; use crate::services::filter::Filter;
use crate::services::group::{ use crate::services::group::{default_group_setting, GroupChangesets, GroupSetting, RowChangeset};
default_group_setting, GroupChangesets, GroupSetting, GroupSettingChangeset, RowChangeset,
};
use crate::services::share::csv::{CSVExport, CSVFormat}; use crate::services::share::csv::{CSVExport, CSVFormat};
use crate::services::sort::Sort; use crate::services::sort::Sort;
@ -870,40 +868,6 @@ impl DatabaseEditor {
Ok(()) Ok(())
} }
pub async fn get_group_configuration_settings(
&self,
view_id: &str,
) -> FlowyResult<Vec<GroupSettingPB>> {
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::<Vec<GroupSettingPB>>();
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)] #[tracing::instrument(level = "trace", skip_all, err)]
pub async fn load_groups(&self, view_id: &str) -> FlowyResult<RepeatedGroupPB> { pub async fn load_groups(&self, view_id: &str) -> FlowyResult<RepeatedGroupPB> {
let view = self.database_views.get_view_editor(view_id).await?; let view = self.database_views.get_view_editor(view_id).await?;
@ -994,11 +958,15 @@ impl DatabaseEditor {
Ok(()) Ok(())
} }
pub async fn set_layout_setting(&self, view_id: &str, layout_setting: LayoutSettingParams) { #[tracing::instrument(level = "trace", skip_all)]
tracing::trace!("set_layout_setting: {:?}", layout_setting); pub async fn set_layout_setting(
if let Ok(view) = self.database_views.get_view_editor(view_id).await { &self,
let _ = view.v_set_layout_settings(layout_setting).await; 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( pub async fn get_layout_setting(

View File

@ -1,23 +1,27 @@
use collab_database::views::DatabaseView; use collab_database::views::{DatabaseLayout, DatabaseView};
use crate::entities::{ use crate::entities::{
CalendarLayoutSettingPB, DatabaseLayoutPB, DatabaseLayoutSettingPB, DatabaseViewSettingPB, DatabaseLayoutPB, DatabaseLayoutSettingPB, DatabaseViewSettingPB, FieldSettingsPB, FilterPB,
FieldSettingsPB, FilterPB, GroupSettingPB, SortPB, GroupSettingPB, SortPB,
}; };
use crate::services::field_settings::FieldSettings; use crate::services::field_settings::FieldSettings;
use crate::services::filter::Filter; use crate::services::filter::Filter;
use crate::services::group::GroupSetting; use crate::services::group::GroupSetting;
use crate::services::setting::CalendarLayoutSetting;
use crate::services::sort::Sort; use crate::services::sort::Sort;
pub(crate) fn database_view_setting_pb_from_view(view: DatabaseView) -> DatabaseViewSettingPB { pub(crate) fn database_view_setting_pb_from_view(view: DatabaseView) -> DatabaseViewSettingPB {
let layout_type: DatabaseLayoutPB = view.layout.into(); let layout_type: DatabaseLayoutPB = view.layout.into();
let layout_setting = if let Some(layout_setting) = view.layout_settings.get(&view.layout) { let layout_setting = if let Some(layout_setting) = view.layout_settings.get(&view.layout) {
let calendar_setting = match view.layout {
CalendarLayoutSettingPB::from(CalendarLayoutSetting::from(layout_setting.clone())); DatabaseLayout::Board => {
DatabaseLayoutSettingPB { let board_setting = layout_setting.clone().into();
layout_type: layout_type.clone(), DatabaseLayoutSettingPB::from_board(board_setting)
calendar: Some(calendar_setting), },
DatabaseLayout::Calendar => {
let calendar_setting = layout_setting.clone().into();
DatabaseLayoutSettingPB::from_calendar(calendar_setting)
},
_ => DatabaseLayoutSettingPB::default(),
} }
} else { } else {
DatabaseLayoutSettingPB::default() DatabaseLayoutSettingPB::default()

View File

@ -6,7 +6,7 @@ use std::sync::Arc;
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::field::{DateTypeOption, SingleSelectTypeOption}; use crate::services::field::{DateTypeOption, SingleSelectTypeOption};
use crate::services::field_settings::default_field_settings_by_layout_map; 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. /// When creating a database, we need to resolve the dependencies of the views.
/// Different database views have different dependencies. For example, a board /// Different database views have different dependencies. For example, a board
@ -32,6 +32,7 @@ impl DatabaseLayoutDepsResolver {
match self.database_layout { match self.database_layout {
DatabaseLayout::Grid => (None, None), DatabaseLayout::Grid => (None, None),
DatabaseLayout::Board => { DatabaseLayout::Board => {
let layout_settings = BoardLayoutSetting::new().into();
if !self if !self
.database .database
.lock() .lock()
@ -40,9 +41,9 @@ impl DatabaseLayoutDepsResolver {
.any(|field| FieldType::from(field.field_type).can_be_group()) .any(|field| FieldType::from(field.field_type).can_be_group())
{ {
let select_field = self.create_select_field(); let select_field = self.create_select_field();
(Some(select_field), None) (Some(select_field), Some(layout_settings))
} else { } else {
(None, None) (None, Some(layout_settings))
} }
}, },
DatabaseLayout::Calendar => { DatabaseLayout::Calendar => {
@ -74,7 +75,9 @@ impl DatabaseLayoutDepsResolver {
// Insert the layout setting if it's not exist // Insert the layout setting if it's not exist
match &self.database_layout { match &self.database_layout {
DatabaseLayout::Grid => {}, DatabaseLayout::Grid => {},
DatabaseLayout::Board => {}, DatabaseLayout::Board => {
self.create_board_layout_setting_if_need(view_id);
},
DatabaseLayout::Calendar => { DatabaseLayout::Calendar => {
let date_field_id = match fields let date_field_id = match fields
.into_iter() .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::<BoardLayoutSetting>(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) { fn create_calendar_layout_setting_if_need(&self, view_id: &str, field_id: &str) {
if self if self
.database .database

View File

@ -13,8 +13,8 @@ use flowy_error::{FlowyError, FlowyResult};
use crate::entities::{ use crate::entities::{
CalendarEventPB, DatabaseLayoutMetaPB, DatabaseLayoutSettingPB, DeleteFilterParams, CalendarEventPB, DatabaseLayoutMetaPB, DatabaseLayoutSettingPB, DeleteFilterParams,
DeleteGroupParams, DeleteSortParams, FieldType, FieldVisibility, GroupChangesPB, GroupPB, DeleteGroupParams, DeleteSortParams, FieldType, FieldVisibility, GroupChangesPB, GroupPB,
GroupRowsNotificationPB, InsertedRowPB, LayoutSettingParams, RowMetaPB, RowsChangePB, GroupRowsNotificationPB, InsertedRowPB, LayoutSettingChangeset, LayoutSettingParams, RowMetaPB,
SortChangesetNotificationPB, SortPB, UpdateFilterParams, UpdateSortParams, RowsChangePB, SortChangesetNotificationPB, SortPB, UpdateFilterParams, UpdateSortParams,
}; };
use crate::notification::{send_notification, DatabaseNotification}; use crate::notification::{send_notification, DatabaseNotification};
use crate::services::cell::CellCache; use crate::services::cell::CellCache;
@ -34,10 +34,7 @@ use crate::services::field_settings::FieldSettings;
use crate::services::filter::{ use crate::services::filter::{
Filter, FilterChangeset, FilterController, FilterType, UpdatedFilterType, Filter, FilterChangeset, FilterController, FilterType, UpdatedFilterType,
}; };
use crate::services::group::{ use crate::services::group::{GroupChangesets, GroupController, MoveGroupRowContext, RowChangeset};
GroupChangesets, GroupController, GroupSetting, GroupSettingChangeset, MoveGroupRowContext,
RowChangeset,
};
use crate::services::setting::CalendarLayoutSetting; use crate::services::setting::CalendarLayoutSetting;
use crate::services::sort::{DeletedSortType, Sort, SortChangeset, SortController, SortType}; use crate::services::sort::{DeletedSortType, Sort, SortChangeset, SortController, SortType};
@ -377,19 +374,6 @@ impl DatabaseViewEditor {
Ok(()) Ok(())
} }
pub async fn v_update_group_configuration_setting(
&self,
changeset: GroupSettingChangeset,
) -> FlowyResult<Option<GroupSetting>> {
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<()> { pub async fn v_update_group(&self, changeset: GroupChangesets) -> FlowyResult<()> {
let mut type_option_data = TypeOptionData::new(); let mut type_option_data = TypeOptionData::new();
let old_field = if let Some(controller) = self.group_controller.write().await.as_mut() { let old_field = if let Some(controller) = self.group_controller.write().await.as_mut() {
@ -412,9 +396,6 @@ impl DatabaseViewEditor {
Ok(()) Ok(())
} }
pub async fn v_get_group_configuration_settings(&self) -> Vec<GroupSetting> {
self.delegate.get_group_setting(&self.view_id)
}
pub async fn v_get_all_sorts(&self) -> Vec<Sort> { pub async fn v_get_all_sorts(&self) -> Vec<Sort> {
self.delegate.get_all_sorts(&self.view_id) self.delegate.get_all_sorts(&self.view_id)
} }
@ -550,7 +531,11 @@ impl DatabaseViewEditor {
let mut layout_setting = LayoutSettingParams::default(); let mut layout_setting = LayoutSettingParams::default();
match layout_ty { match layout_ty {
DatabaseLayout::Grid => {}, 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 => { DatabaseLayout::Calendar => {
if let Some(value) = self.delegate.get_layout_setting(&self.view_id, layout_ty) { if let Some(value) = self.delegate.get_layout_setting(&self.view_id, layout_ty) {
let calendar_setting = CalendarLayoutSetting::from(value); let calendar_setting = CalendarLayoutSetting::from(value);
@ -574,48 +559,50 @@ impl DatabaseViewEditor {
layout_setting layout_setting
} }
/// Update the calendar settings and send the notification to refresh the UI /// Update the layout settings and send the notification to refresh the UI
pub async fn v_set_layout_settings(&self, params: LayoutSettingParams) -> FlowyResult<()> { pub async fn v_set_layout_settings(&self, params: LayoutSettingChangeset) -> FlowyResult<()> {
// Maybe it needs no send notification to refresh the UI if self.v_get_layout_type().await != params.layout_type || !params.is_valid() {
if let Some(new_calendar_setting) = params.calendar { return Err(FlowyError::invalid_data());
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());
}
let old_calender_setting = self let layout_setting_pb = match params.layout_type {
.v_get_layout_settings(&params.layout_type) DatabaseLayout::Board => {
.await let layout_setting = params.board.unwrap();
.calendar;
self.delegate.insert_layout_setting( self.delegate.insert_layout_setting(
&self.view_id, &self.view_id,
&params.layout_type, &params.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 { Some(DatabaseLayoutSettingPB::from_board(layout_setting))
// compare the new layout field id is equal to old layout field id },
// if not equal, send the DidSetNewLayoutField notification DatabaseLayout::Calendar => {
// if equal, send the DidUpdateLayoutSettings notification let layout_setting = params.calendar.unwrap();
if old_calendar_setting.field_id != new_field_id {
send_notification(&self.view_id, DatabaseNotification::DidSetNewLayoutField) if let Some(field) = self.delegate.get_field(&layout_setting.field_id) {
.payload(layout_setting_pb.clone()) if FieldType::from(field.field_type) != FieldType::DateTime {
.send(); return Err(FlowyError::unexpect_calendar_field_type());
} }
}
send_notification(&self.view_id, DatabaseNotification::DidUpdateLayoutSettings) self.delegate.insert_layout_setting(
.payload(layout_setting_pb) &self.view_id,
.send(); &params.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(()) Ok(())

View File

@ -6,10 +6,7 @@ use flowy_error::FlowyResult;
use crate::entities::{GroupChangesPB, GroupPB, GroupRowsNotificationPB, InsertedGroupPB}; use crate::entities::{GroupChangesPB, GroupPB, GroupRowsNotificationPB, InsertedGroupPB};
use crate::services::field::TypeOption; use crate::services::field::TypeOption;
use crate::services::group::entities::GroupSetting; use crate::services::group::{GroupChangesets, GroupData, MoveGroupRowContext};
use crate::services::group::{
GroupChangesets, GroupData, GroupSettingChangeset, MoveGroupRowContext,
};
/// Using polymorphism to provides the customs action for different group controller. /// Using polymorphism to provides the customs action for different group controller.
/// ///
@ -119,11 +116,6 @@ pub trait GroupControllerOperation: Send + Sync {
&mut self, &mut self,
changeset: &GroupChangesets, changeset: &GroupChangesets,
) -> FlowyResult<TypeOptionData>; ) -> FlowyResult<TypeOptionData>;
fn apply_group_configuration_setting_changeset(
&mut self,
changeset: GroupSettingChangeset,
) -> FlowyResult<Option<GroupSetting>>;
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -18,7 +18,6 @@ use crate::entities::{GroupChangesPB, GroupPB, InsertedGroupPB};
use crate::services::field::RowSingleCellData; use crate::services::field::RowSingleCellData;
use crate::services::group::{ use crate::services::group::{
default_group_setting, GeneratedGroups, Group, GroupChangeset, GroupData, GroupSetting, default_group_setting, GeneratedGroups, Group, GroupChangeset, GroupData, GroupSetting,
GroupSettingChangeset,
}; };
pub trait GroupSettingReader: Send + Sync + 'static { pub trait GroupSettingReader: Send + Sync + 'static {
@ -390,20 +389,6 @@ where
Ok(()) Ok(())
} }
pub(crate) fn update_configuration(
&mut self,
changeset: GroupSettingChangeset,
) -> FlowyResult<Option<GroupSetting>> {
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<RowSingleCellData> { pub(crate) async fn get_all_cells(&self) -> Vec<RowSingleCellData> {
self self
.reader .reader
@ -432,9 +417,7 @@ where
let view_id = self.view_id.clone(); let view_id = self.view_id.clone();
tokio::spawn(async move { tokio::spawn(async move {
match writer.save_configuration(&view_id, configuration).await { match writer.save_configuration(&view_id, configuration).await {
Ok(_) => { Ok(_) => {},
tracing::trace!("SUCCESSFULLY SAVED CONFIGURATION"); // TODO(richard): remove this
},
Err(e) => { Err(e) => {
tracing::error!("Save group configuration failed: {}", e); tracing::error!("Save group configuration failed: {}", e);
}, },

View File

@ -19,10 +19,8 @@ use crate::services::group::action::{
DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, GroupCustomize, DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, GroupCustomize,
}; };
use crate::services::group::configuration::GroupContext; use crate::services::group::configuration::GroupContext;
use crate::services::group::entities::{GroupData, GroupSetting}; use crate::services::group::entities::GroupData;
use crate::services::group::{ use crate::services::group::{GroupChangeset, GroupChangesets, GroupsBuilder, MoveGroupRowContext};
GroupChangeset, GroupChangesets, GroupSettingChangeset, GroupsBuilder, MoveGroupRowContext,
};
// use collab_database::views::Group; // use collab_database::views::Group;
@ -361,13 +359,6 @@ where
} }
Ok(type_option_data) Ok(type_option_data)
} }
fn apply_group_configuration_setting_changeset(
&mut self,
changeset: GroupSettingChangeset,
) -> FlowyResult<Option<GroupSetting>> {
self.context.update_configuration(changeset)
}
} }
struct GroupedRow { struct GroupedRow {

View File

@ -10,10 +10,7 @@ use crate::entities::GroupChangesPB;
use crate::services::group::action::{ use crate::services::group::action::{
DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation, DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupControllerOperation,
}; };
use crate::services::group::{ use crate::services::group::{GroupChangesets, GroupController, GroupData, MoveGroupRowContext};
GroupChangesets, GroupController, GroupData, GroupSetting, GroupSettingChangeset,
MoveGroupRowContext,
};
/// A [DefaultGroupController] is used to handle the group actions for the [FieldType] that doesn't /// 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 /// implement its own group controller. The default group controller only contains one group, which
@ -110,13 +107,6 @@ impl GroupControllerOperation for DefaultGroupController {
) -> FlowyResult<TypeOptionData> { ) -> FlowyResult<TypeOptionData> {
Ok(TypeOptionData::default()) Ok(TypeOptionData::default())
} }
fn apply_group_configuration_setting_changeset(
&mut self,
_changeset: GroupSettingChangeset,
) -> FlowyResult<Option<GroupSetting>> {
Ok(None)
}
} }
impl GroupController for DefaultGroupController { impl GroupController for DefaultGroupController {

View File

@ -12,11 +12,6 @@ pub struct GroupSetting {
pub field_type: i64, pub field_type: i64,
pub groups: Vec<Group>, pub groups: Vec<Group>,
pub content: String, pub content: String,
pub hide_ungrouped: bool,
}
pub struct GroupSettingChangeset {
pub hide_ungrouped: Option<bool>,
} }
pub struct GroupChangesets { pub struct GroupChangesets {
@ -38,14 +33,13 @@ pub struct GroupChangeset {
} }
impl GroupSetting { 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 { Self {
id: gen_database_group_id(), id: gen_database_group_id(),
field_id, field_id,
field_type, field_type,
groups: vec![], groups: vec![],
content, content,
hide_ungrouped,
} }
} }
} }
@ -55,7 +49,6 @@ const FIELD_ID: &str = "field_id";
const FIELD_TYPE: &str = "ty"; const FIELD_TYPE: &str = "ty";
const GROUPS: &str = "groups"; const GROUPS: &str = "groups";
const CONTENT: &str = "content"; const CONTENT: &str = "content";
const HIDE_UNGROUPED: &str = "hide_ungrouped";
impl TryFrom<GroupSettingMap> for GroupSetting { impl TryFrom<GroupSettingMap> for GroupSetting {
type Error = anyhow::Error; type Error = anyhow::Error;
@ -65,9 +58,8 @@ impl TryFrom<GroupSettingMap> for GroupSetting {
value.get_str_value(GROUP_ID), value.get_str_value(GROUP_ID),
value.get_str_value(FIELD_ID), value.get_str_value(FIELD_ID),
value.get_i64_value(FIELD_TYPE), 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 content = value.get_str_value(CONTENT).unwrap_or_default();
let groups = value.try_get_array(GROUPS); let groups = value.try_get_array(GROUPS);
Ok(Self { Ok(Self {
@ -76,7 +68,6 @@ impl TryFrom<GroupSettingMap> for GroupSetting {
field_type, field_type,
groups, groups,
content, content,
hide_ungrouped,
}) })
}, },
_ => { _ => {
@ -94,7 +85,6 @@ impl From<GroupSetting> for GroupSettingMap {
.insert_i64_value(FIELD_TYPE, setting.field_type) .insert_i64_value(FIELD_TYPE, setting.field_type)
.insert_maps(GROUPS, setting.groups) .insert_maps(GROUPS, setting.groups)
.insert_str_value(CONTENT, setting.content) .insert_str_value(CONTENT, setting.content)
.insert_bool_value(HIDE_UNGROUPED, setting.hide_ungrouped)
.build() .build()
} }
} }

View File

@ -234,7 +234,7 @@ pub fn find_new_grouping_field(
/// ///
pub fn default_group_setting(field: &Field) -> GroupSetting { pub fn default_group_setting(field: &Field) -> GroupSetting {
let field_id = field.id.clone(); 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 { pub fn make_no_status_group(field: &Field) -> Group {

View File

@ -8,5 +8,5 @@ mod group_builder;
pub(crate) use configuration::*; pub(crate) use configuration::*;
pub(crate) use controller::*; pub(crate) use controller::*;
pub(crate) use controller_impls::*; pub(crate) use controller_impls::*;
pub use entities::*; pub(crate) use entities::*;
pub(crate) use group_builder::*; pub(crate) use group_builder::*;

View File

@ -89,3 +89,32 @@ impl CalendarLayout {
pub const DEFAULT_FIRST_DAY_OF_WEEK: i32 = 0; pub const DEFAULT_FIRST_DAY_OF_WEEK: i32 = 0;
pub const DEFAULT_SHOW_WEEKENDS: bool = true; pub const DEFAULT_SHOW_WEEKENDS: bool = true;
pub const DEFAULT_SHOW_WEEK_NUMBERS: 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<LayoutSetting> for BoardLayoutSetting {
fn from(setting: LayoutSetting) -> Self {
Self {
hide_ungrouped_column: setting
.get_bool_value("hide_ungrouped_column")
.unwrap_or_default(),
}
}
}
impl From<BoardLayoutSetting> for LayoutSetting {
fn from(setting: BoardLayoutSetting) -> Self {
LayoutSettingBuilder::new()
.insert_bool_value("hide_ungrouped_column", setting.hide_ungrouped_column)
.build()
}
}

View File

@ -8,7 +8,7 @@ use crate::services::field::{
FieldBuilder, SelectOption, SelectOptionColor, SingleSelectTypeOption, FieldBuilder, SelectOption, SelectOptionColor, SingleSelectTypeOption,
}; };
use crate::services::field_settings::DatabaseFieldSettingsMapBuilder; 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 { pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams {
let text_field = FieldBuilder::from_field_type(FieldType::RichText) 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 = let field_settings =
DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build(); DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build();
let mut layout_settings = LayoutSettings::default();
layout_settings.insert(DatabaseLayout::Board, BoardLayoutSetting::new().into());
CreateDatabaseParams { CreateDatabaseParams {
database_id: gen_database_id(), database_id: gen_database_id(),
view_id: view_id.to_string(), view_id: view_id.to_string(),
name: name.to_string(), name: name.to_string(),
layout: DatabaseLayout::Board, layout: DatabaseLayout::Board,
layout_settings: Default::default(), layout_settings,
filters: vec![], filters: vec![],
groups: vec![], groups: vec![],
sorts: vec![], sorts: vec![],

View File

@ -28,23 +28,6 @@ async fn group_init_test() {
test.run_scripts(scripts).await; 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] #[tokio::test]
async fn group_move_row_test() { async fn group_move_row_test() {
let mut test = DatabaseGroupTest::new().await; let mut test = DatabaseGroupTest::new().await;

View File

@ -1,13 +1,15 @@
use collab_database::fields::Field; use collab_database::fields::Field;
use collab_database::views::DatabaseLayout; use collab_database::views::DatabaseLayout;
use flowy_database2::entities::FieldType; use flowy_database2::entities::{FieldType, LayoutSettingChangeset, LayoutSettingParams};
use flowy_database2::services::setting::CalendarLayoutSetting; use flowy_database2::services::setting::{BoardLayoutSetting, CalendarLayoutSetting};
use crate::database::database_editor::DatabaseEditorTest; use crate::database::database_editor::DatabaseEditorTest;
pub enum LayoutScript { pub enum LayoutScript {
AssertBoardLayoutSetting { expected: BoardLayoutSetting },
AssertCalendarLayoutSetting { expected: CalendarLayoutSetting }, AssertCalendarLayoutSetting { expected: CalendarLayoutSetting },
UpdateBoardLayoutSetting { new_setting: BoardLayoutSetting },
AssertDefaultAllCalendarEvents, AssertDefaultAllCalendarEvents,
AssertAllCalendarEventsCount { expected: usize }, AssertAllCalendarEventsCount { expected: usize },
UpdateDatabaseLayout { layout: DatabaseLayout }, UpdateDatabaseLayout { layout: DatabaseLayout },
@ -23,21 +25,39 @@ impl DatabaseLayoutTest {
Self { database_test } 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 { pub async fn new_calendar() -> Self {
let database_test = DatabaseEditorTest::new_calendar().await; let database_test = DatabaseEditorTest::new_calendar().await;
Self { database_test } 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<LayoutScript>) { pub async fn run_scripts(&mut self, scripts: Vec<LayoutScript>) {
for script in scripts { for script in scripts {
self.run_script(script).await; 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) { pub async fn run_script(&mut self, script: LayoutScript) {
match script { match script {
LayoutScript::UpdateDatabaseLayout { layout } => { LayoutScript::UpdateDatabaseLayout { layout } => {
@ -56,19 +76,27 @@ impl DatabaseLayoutTest {
.await; .await;
assert_eq!(events.len(), expected); 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 } => { LayoutScript::AssertCalendarLayoutSetting { expected } => {
let view_id = self.database_test.view_id.clone(); let view_id = self.database_test.view_id.clone();
let layout_ty = DatabaseLayout::Calendar; let layout_ty = DatabaseLayout::Calendar;
let calendar_setting = self let layout_settings = self.get_layout_setting(&view_id, layout_ty).await;
.database_test
.editor
.get_layout_setting(&view_id, layout_ty)
.await
.unwrap()
.calendar
.unwrap();
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.layout_ty, expected.layout_ty);
assert_eq!( assert_eq!(
calendar_setting.first_day_of_week, calendar_setting.first_day_of_week,
@ -76,6 +104,20 @@ impl DatabaseLayoutTest {
); );
assert_eq!(calendar_setting.show_weekends, expected.show_weekends); 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 => { LayoutScript::AssertDefaultAllCalendarEvents => {
let events = self let events = self
.database_test .database_test

View File

@ -1,9 +1,31 @@
use collab_database::views::DatabaseLayout; use collab_database::views::DatabaseLayout;
use flowy_database2::services::setting::BoardLayoutSetting;
use flowy_database2::services::setting::CalendarLayoutSetting; use flowy_database2::services::setting::CalendarLayoutSetting;
use crate::database::layout_test::script::DatabaseLayoutTest; use crate::database::layout_test::script::DatabaseLayoutTest;
use crate::database::layout_test::script::LayoutScript::*; 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] #[tokio::test]
async fn calendar_initial_layout_setting_test() { async fn calendar_initial_layout_setting_test() {
let mut test = DatabaseLayoutTest::new_calendar().await; let mut test = DatabaseLayoutTest::new_calendar().await;

View File

@ -1,6 +1,7 @@
use collab_database::database::{gen_database_id, gen_database_view_id, gen_row_id, DatabaseData}; 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::field_settings::DatabaseFieldSettingsMapBuilder;
use flowy_database2::services::setting::BoardLayoutSetting;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use flowy_database2::entities::FieldType; 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 = let field_settings =
DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build(); DatabaseFieldSettingsMapBuilder::new(fields.clone(), DatabaseLayout::Board).build();
@ -238,12 +241,15 @@ pub fn make_test_board() -> DatabaseData {
rows.push(row); rows.push(row);
} }
let mut layout_settings = LayoutSettings::new();
layout_settings.insert(DatabaseLayout::Board, board_setting);
let view = DatabaseView { let view = DatabaseView {
id: gen_database_view_id(), id: gen_database_view_id(),
database_id: gen_database_id(), database_id: gen_database_id(),
name: "".to_string(), name: "".to_string(),
layout: DatabaseLayout::Board, layout: DatabaseLayout::Board,
layout_settings: Default::default(), layout_settings,
filters: vec![], filters: vec![],
group_settings: vec![], group_settings: vec![],
sorts: vec![], sorts: vec![],