mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: calendar plugin backend database data (#1884)
* chore: implement CalendarBloc * chore: enable save and read the calendar setting * style: more precise variable name * chore: backend calendar settings * chore: protobuf for layout settings * chore: update test * chore: Enumerate the LayoutTypePB enum type to get the supported layout types * fix: deserialize object type is not the same as serialize object type * chore: add set/get calendar settings event * ci: fix wanrings --------- Co-authored-by: nathan <nathan@appflowy.io> Co-authored-by: vedon <vedon.fu@gmail.com>
This commit is contained in:
parent
01a388c1c4
commit
6877607c5e
@ -0,0 +1,159 @@
|
||||
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
|
||||
import 'package:calendar_view/calendar_view.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'calendar_data_controller.dart';
|
||||
|
||||
part 'calendar_bloc.freezed.dart';
|
||||
|
||||
class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
|
||||
final CalendarDataController _databaseDataController;
|
||||
final EventController calendarEventsController = EventController();
|
||||
|
||||
GridFieldController get fieldController =>
|
||||
_databaseDataController.fieldController;
|
||||
String get databaseId => _databaseDataController.databaseId;
|
||||
|
||||
CalendarBloc({required ViewPB view})
|
||||
: _databaseDataController = CalendarDataController(view: view),
|
||||
super(CalendarState.initial(view.id)) {
|
||||
on<CalendarEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
initial: () async {
|
||||
_startListening();
|
||||
await _openDatabase(emit);
|
||||
},
|
||||
didReceiveCalendarSettings: (CalendarSettingsPB settings) {
|
||||
emit(state.copyWith(settings: Some(settings)));
|
||||
},
|
||||
didReceiveDatabaseUpdate: (DatabasePB database) {
|
||||
emit(state.copyWith(database: Some(database)));
|
||||
},
|
||||
didReceiveError: (FlowyError error) {
|
||||
emit(state.copyWith(noneOrError: Some(error)));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openDatabase(Emitter<CalendarState> emit) async {
|
||||
final result = await _databaseDataController.openDatabase();
|
||||
result.fold(
|
||||
(database) => emit(
|
||||
state.copyWith(loadingState: DatabaseLoadingState.finish(left(unit))),
|
||||
),
|
||||
(err) => emit(
|
||||
state.copyWith(loadingState: DatabaseLoadingState.finish(right(err))),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
GridRowCache? getRowCache(String blockId) {
|
||||
return _databaseDataController.rowCache;
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
_databaseDataController.addListener(
|
||||
onDatabaseChanged: (database) {
|
||||
if (!isClosed) return;
|
||||
|
||||
add(CalendarEvent.didReceiveDatabaseUpdate(database));
|
||||
},
|
||||
onSettingsChanged: (CalendarSettingsPB settings) {
|
||||
if (isClosed) return;
|
||||
add(CalendarEvent.didReceiveCalendarSettings(settings));
|
||||
},
|
||||
onArrangeWithNewField: (field) {
|
||||
if (isClosed) return;
|
||||
_initializeEvents(field);
|
||||
// add(CalendarEvent.)
|
||||
},
|
||||
onError: (err) {
|
||||
Log.error(err);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _initializeEvents(FieldPB dateField) {
|
||||
calendarEventsController.removeWhere((element) => true);
|
||||
|
||||
const events = <CalendarEventData<CalendarData>>[];
|
||||
|
||||
// final List<CalendarEventData<CalendarData>> events = rows.map((row) {
|
||||
// final event = CalendarEventData(
|
||||
// title: "",
|
||||
// date: row -> dateField -> value,
|
||||
// event: row,
|
||||
// );
|
||||
|
||||
// return event;
|
||||
// }).toList();
|
||||
|
||||
calendarEventsController.addAll(events);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class CalendarEvent with _$CalendarEvent {
|
||||
const factory CalendarEvent.initial() = _InitialCalendar;
|
||||
const factory CalendarEvent.didReceiveCalendarSettings(
|
||||
CalendarSettingsPB settings) = _DidReceiveCalendarSettings;
|
||||
const factory CalendarEvent.didReceiveError(FlowyError error) =
|
||||
_DidReceiveError;
|
||||
const factory CalendarEvent.didReceiveDatabaseUpdate(DatabasePB database) =
|
||||
_DidReceiveDatabaseUpdate;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class CalendarState with _$CalendarState {
|
||||
const factory CalendarState({
|
||||
required String databaseId,
|
||||
required Option<DatabasePB> database,
|
||||
required Option<FieldPB> dateField,
|
||||
required Option<List<RowInfo>> unscheduledRows,
|
||||
required Option<CalendarSettingsPB> settings,
|
||||
required DatabaseLoadingState loadingState,
|
||||
required Option<FlowyError> noneOrError,
|
||||
}) = _CalendarState;
|
||||
|
||||
factory CalendarState.initial(String databaseId) => CalendarState(
|
||||
database: none(),
|
||||
databaseId: databaseId,
|
||||
dateField: none(),
|
||||
unscheduledRows: none(),
|
||||
settings: none(),
|
||||
noneOrError: none(),
|
||||
loadingState: const _Loading(),
|
||||
);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DatabaseLoadingState with _$DatabaseLoadingState {
|
||||
const factory DatabaseLoadingState.loading() = _Loading;
|
||||
const factory DatabaseLoadingState.finish(
|
||||
Either<Unit, FlowyError> successOrFail) = _Finish;
|
||||
}
|
||||
|
||||
class CalendarEditingRow {
|
||||
RowPB row;
|
||||
int? index;
|
||||
|
||||
CalendarEditingRow({
|
||||
required this.row,
|
||||
required this.index,
|
||||
});
|
||||
}
|
||||
|
||||
class CalendarData {
|
||||
final RowInfo rowInfo;
|
||||
CalendarData(this.rowInfo);
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:app_flowy/plugins/grid/application/view/grid_view_cache.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import 'calendar_listener.dart';
|
||||
|
||||
typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldInfo>);
|
||||
typedef OnDatabaseChanged = void Function(DatabasePB);
|
||||
typedef OnSettingsChanged = void Function(CalendarSettingsPB);
|
||||
typedef OnArrangeWithNewField = void Function(FieldPB);
|
||||
|
||||
typedef OnRowsChanged = void Function(List<RowInfo>, RowsChangedReason);
|
||||
typedef OnError = void Function(FlowyError);
|
||||
|
||||
class CalendarDataController {
|
||||
final String databaseId;
|
||||
final DatabaseFFIService _databaseFFIService;
|
||||
final GridFieldController fieldController;
|
||||
final CalendarListener _listener;
|
||||
late DatabaseViewCache _viewCache;
|
||||
|
||||
OnFieldsChanged? _onFieldsChanged;
|
||||
OnDatabaseChanged? _onDatabaseChanged;
|
||||
OnRowsChanged? _onRowsChanged;
|
||||
OnSettingsChanged? _onSettingsChanged;
|
||||
OnArrangeWithNewField? _onArrangeWithNewField;
|
||||
OnError? _onError;
|
||||
|
||||
List<RowInfo> get rowInfos => _viewCache.rowInfos;
|
||||
GridRowCache get rowCache => _viewCache.rowCache;
|
||||
|
||||
CalendarDataController({required ViewPB view})
|
||||
: databaseId = view.id,
|
||||
_listener = CalendarListener(view.id),
|
||||
_databaseFFIService = DatabaseFFIService(viewId: view.id),
|
||||
fieldController = GridFieldController(databaseId: view.id) {
|
||||
_viewCache = DatabaseViewCache(
|
||||
databaseId: view.id,
|
||||
fieldController: fieldController,
|
||||
);
|
||||
_viewCache.addListener(onRowsChanged: (reason) {
|
||||
_onRowsChanged?.call(rowInfos, reason);
|
||||
});
|
||||
}
|
||||
|
||||
void addListener({
|
||||
required OnDatabaseChanged onDatabaseChanged,
|
||||
OnFieldsChanged? onFieldsChanged,
|
||||
OnRowsChanged? onRowsChanged,
|
||||
required OnSettingsChanged? onSettingsChanged,
|
||||
required OnArrangeWithNewField? onArrangeWithNewField,
|
||||
required OnError? onError,
|
||||
}) {
|
||||
_onDatabaseChanged = onDatabaseChanged;
|
||||
_onFieldsChanged = onFieldsChanged;
|
||||
_onRowsChanged = onRowsChanged;
|
||||
_onSettingsChanged = onSettingsChanged;
|
||||
_onArrangeWithNewField = onArrangeWithNewField;
|
||||
_onError = onError;
|
||||
|
||||
fieldController.addListener(onFields: (fields) {
|
||||
_onFieldsChanged?.call(UnmodifiableListView(fields));
|
||||
});
|
||||
|
||||
_listener.start(
|
||||
onCalendarSettingsChanged: (result) {
|
||||
result.fold(
|
||||
(settings) => _onSettingsChanged?.call(settings),
|
||||
(e) => _onError?.call(e),
|
||||
);
|
||||
},
|
||||
onArrangeWithNewField: (result) {
|
||||
result.fold(
|
||||
(settings) => _onArrangeWithNewField?.call(settings),
|
||||
(e) => _onError?.call(e),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<Either<Unit, FlowyError>> openDatabase() async {
|
||||
final result = await _databaseFFIService.openGrid();
|
||||
return result.fold(
|
||||
(database) async {
|
||||
_onDatabaseChanged?.call(database);
|
||||
return fieldController
|
||||
.loadFields(fieldIds: database.fields)
|
||||
.then((result) {
|
||||
return result.fold(
|
||||
(l) => Future(() async {
|
||||
_viewCache.rowCache.initializeRows(database.rows);
|
||||
return left(l);
|
||||
}),
|
||||
(err) => right(err),
|
||||
);
|
||||
});
|
||||
},
|
||||
(err) => right(err),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
await _viewCache.dispose();
|
||||
await _databaseFFIService.closeGrid();
|
||||
await fieldController.dispose();
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:app_flowy/core/grid_notification.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
typedef CalendarSettingsValue = Either<CalendarSettingsPB, FlowyError>;
|
||||
typedef ArrangeWithNewField = Either<FieldPB, FlowyError>;
|
||||
|
||||
class CalendarListener {
|
||||
final String viewId;
|
||||
PublishNotifier<CalendarSettingsValue>? _calendarSettingsNotifier =
|
||||
PublishNotifier();
|
||||
PublishNotifier<ArrangeWithNewField>? _arrangeWithNewFieldNotifier =
|
||||
PublishNotifier();
|
||||
DatabaseNotificationListener? _listener;
|
||||
CalendarListener(this.viewId);
|
||||
|
||||
void start({
|
||||
required void Function(CalendarSettingsValue) onCalendarSettingsChanged,
|
||||
required void Function(ArrangeWithNewField) onArrangeWithNewField,
|
||||
}) {
|
||||
_calendarSettingsNotifier?.addPublishListener(onCalendarSettingsChanged);
|
||||
_arrangeWithNewFieldNotifier?.addPublishListener(onArrangeWithNewField);
|
||||
_listener = DatabaseNotificationListener(
|
||||
objectId: viewId,
|
||||
handler: _handler,
|
||||
);
|
||||
}
|
||||
|
||||
void _handler(
|
||||
DatabaseNotification ty,
|
||||
Either<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DatabaseNotification.DidUpdateCalendarSettings:
|
||||
result.fold(
|
||||
(payload) => _calendarSettingsNotifier?.value =
|
||||
left(CalendarSettingsPB.fromBuffer(payload)),
|
||||
(error) => _calendarSettingsNotifier?.value = right(error),
|
||||
);
|
||||
break;
|
||||
case DatabaseNotification.DidArrangeCalendarWithNewField:
|
||||
result.fold(
|
||||
(payload) => _arrangeWithNewFieldNotifier?.value =
|
||||
left(FieldPB.fromBuffer(payload)),
|
||||
(error) => _arrangeWithNewFieldNotifier?.value = right(error),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _listener?.stop();
|
||||
_calendarSettingsNotifier?.dispose();
|
||||
_calendarSettingsNotifier = null;
|
||||
|
||||
_arrangeWithNewFieldNotifier?.dispose();
|
||||
_arrangeWithNewFieldNotifier = null;
|
||||
}
|
||||
}
|
@ -294,6 +294,33 @@ impl DatabaseViewRevisionPad {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the settings for the given layout. If it's not exists then will return the
|
||||
/// default settings for the given layout.
|
||||
/// Each [database view](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/database-view) has its own settings.
|
||||
pub fn get_layout_setting<T>(&self, layout: &LayoutRevision) -> Option<T>
|
||||
where
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
let settings_str = self.view.layout_settings.get(layout)?;
|
||||
serde_json::from_str::<T>(settings_str).ok()
|
||||
}
|
||||
|
||||
/// updates the settings for the given layout type
|
||||
pub fn update_layout_setting<T>(
|
||||
&mut self,
|
||||
layout: &LayoutRevision,
|
||||
settings: &T,
|
||||
) -> SyncResult<Option<GridViewRevisionChangeset>>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
let settings_str = serde_json::to_string(settings).map_err(internal_sync_error)?;
|
||||
self.modify(|view| {
|
||||
view.layout_settings.insert(layout.clone(), settings_str);
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn json_str(&self) -> SyncResult<String> {
|
||||
make_grid_view_rev_json_str(&self.view)
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
use crate::entities::parser::NotEmptyStr;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::ErrorCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Default, ProtoBuf)]
|
||||
pub struct CalendarSettingsPB {
|
||||
#[pb(index = 1)]
|
||||
pub view_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub layout_ty: CalendarLayout,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub first_day_of_week: i32,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub show_weekends: bool,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub show_week_numbers: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CalendarSettingsParams {
|
||||
pub(crate) view_id: String,
|
||||
layout_ty: CalendarLayout,
|
||||
first_day_of_week: i32,
|
||||
show_weekends: bool,
|
||||
show_week_numbers: bool,
|
||||
}
|
||||
|
||||
const DEFAULT_FIRST_DAY_OF_WEEK: i32 = 0;
|
||||
const DEFAULT_SHOW_WEEKENDS: bool = true;
|
||||
const DEFAULT_SHOW_WEEK_NUMBERS: bool = true;
|
||||
|
||||
impl CalendarSettingsParams {
|
||||
pub fn default_with(view_id: String) -> Self {
|
||||
CalendarSettingsParams {
|
||||
view_id: view_id.to_string(),
|
||||
layout_ty: CalendarLayout::default(),
|
||||
first_day_of_week: DEFAULT_FIRST_DAY_OF_WEEK,
|
||||
show_weekends: DEFAULT_SHOW_WEEKENDS,
|
||||
show_week_numbers: DEFAULT_SHOW_WEEK_NUMBERS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<CalendarSettingsParams> for CalendarSettingsPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<CalendarSettingsParams, Self::Error> {
|
||||
let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::ViewIdInvalid)?;
|
||||
Ok(CalendarSettingsParams {
|
||||
view_id: view_id.0,
|
||||
layout_ty: self.layout_ty,
|
||||
first_day_of_week: self.first_day_of_week,
|
||||
show_weekends: self.show_weekends,
|
||||
show_week_numbers: self.show_week_numbers,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<CalendarSettingsParams> for CalendarSettingsPB {
|
||||
fn from(params: CalendarSettingsParams) -> Self {
|
||||
CalendarSettingsPB {
|
||||
view_id: params.view_id,
|
||||
layout_ty: params.layout_ty,
|
||||
first_day_of_week: params.first_day_of_week,
|
||||
show_weekends: params.show_weekends,
|
||||
show_week_numbers: params.show_week_numbers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Default, ProtoBuf_Enum, Serialize_repr, Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum CalendarLayout {
|
||||
#[default]
|
||||
MonthLayout = 0,
|
||||
WeekLayout = 1,
|
||||
DayLayout = 2,
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
mod calendar_entities;
|
||||
mod cell_entities;
|
||||
mod field_entities;
|
||||
pub mod filter_entities;
|
||||
@ -9,6 +10,7 @@ pub mod setting_entities;
|
||||
mod sort_entities;
|
||||
mod view_entities;
|
||||
|
||||
pub use calendar_entities::*;
|
||||
pub use cell_entities::*;
|
||||
pub use field_entities::*;
|
||||
pub use filter_entities::*;
|
||||
|
@ -1,25 +1,24 @@
|
||||
use crate::entities::parser::NotEmptyStr;
|
||||
use crate::entities::{
|
||||
AlterFilterParams, AlterFilterPayloadPB, AlterSortParams, AlterSortPayloadPB, DeleteFilterParams,
|
||||
DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, DeleteSortParams,
|
||||
DeleteSortPayloadPB, InsertGroupParams, InsertGroupPayloadPB, RepeatedFilterPB,
|
||||
AlterFilterParams, AlterFilterPayloadPB, AlterSortParams, AlterSortPayloadPB, CalendarSettingsPB,
|
||||
DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB,
|
||||
DeleteSortParams, DeleteSortPayloadPB, InsertGroupParams, InsertGroupPayloadPB, RepeatedFilterPB,
|
||||
RepeatedGroupConfigurationPB, RepeatedSortPB,
|
||||
};
|
||||
use database_model::LayoutRevision;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::ErrorCode;
|
||||
use std::convert::TryInto;
|
||||
use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
/// [DatabaseViewSettingPB] defines the setting options for the grid. Such as the filter, group, and sort.
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct DatabaseViewSettingPB {
|
||||
#[pb(index = 1)]
|
||||
pub support_layouts: Vec<ViewLayoutPB>,
|
||||
pub current_layout: LayoutTypePB,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub current_layout: LayoutTypePB,
|
||||
pub layout_setting: LayoutSettingPB,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub filters: RepeatedFilterPB,
|
||||
@ -31,23 +30,6 @@ pub struct DatabaseViewSettingPB {
|
||||
pub sorts: RepeatedSortPB,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct ViewLayoutPB {
|
||||
#[pb(index = 1)]
|
||||
ty: LayoutTypePB,
|
||||
}
|
||||
|
||||
impl ViewLayoutPB {
|
||||
pub fn all() -> Vec<ViewLayoutPB> {
|
||||
let mut layouts = vec![];
|
||||
for layout_ty in LayoutTypePB::iter() {
|
||||
layouts.push(ViewLayoutPB { ty: layout_ty })
|
||||
}
|
||||
|
||||
layouts
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, EnumIter)]
|
||||
#[repr(u8)]
|
||||
pub enum LayoutTypePB {
|
||||
@ -176,3 +158,15 @@ impl DatabaseSettingChangesetParams {
|
||||
self.insert_filter.is_some() || self.delete_filter.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Default, ProtoBuf, Clone)]
|
||||
pub struct LayoutSettingPB {
|
||||
#[pb(index = 1, one_of)]
|
||||
pub calendar: Option<CalendarSettingsPB>,
|
||||
}
|
||||
|
||||
impl LayoutSettingPB {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
@ -560,3 +560,23 @@ pub(crate) async fn move_group_row_handler(
|
||||
editor.move_group_row(params).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, manager), err)]
|
||||
pub(crate) async fn set_calendar_setting_handler(
|
||||
data: AFPluginData<CalendarSettingsPB>,
|
||||
manager: AFPluginState<Arc<DatabaseManager>>,
|
||||
) -> FlowyResult<()> {
|
||||
let params: CalendarSettingsParams = data.into_inner().try_into()?;
|
||||
let _ = manager.get_database_editor(params.view_id.as_ref()).await?;
|
||||
todo!("nathan: depends on the main branch refactoring")
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, manager), err)]
|
||||
pub(crate) async fn get_calendar_setting_handler(
|
||||
data: AFPluginData<DatabaseViewIdPB>,
|
||||
manager: AFPluginState<Arc<DatabaseManager>>,
|
||||
) -> FlowyResult<()> {
|
||||
let view_id = data.into_inner().value;
|
||||
let _ = manager.get_database_editor(view_id.as_ref()).await?;
|
||||
todo!("nathan: depends on the main branch refactoring")
|
||||
}
|
||||
|
@ -47,7 +47,10 @@ pub fn init(database_manager: Arc<DatabaseManager>) -> AFPlugin {
|
||||
.event(DatabaseEvent::CreateBoardCard, create_board_card_handler)
|
||||
.event(DatabaseEvent::MoveGroup, move_group_handler)
|
||||
.event(DatabaseEvent::MoveGroupRow, move_group_row_handler)
|
||||
.event(DatabaseEvent::GetGroup, get_groups_handler);
|
||||
.event(DatabaseEvent::GetGroup, get_groups_handler)
|
||||
// Calendar
|
||||
.event(DatabaseEvent::SetCalenderSetting, set_calendar_setting_handler)
|
||||
.event(DatabaseEvent::GetCalendarSetting, get_calendar_setting_handler);
|
||||
|
||||
plugin
|
||||
}
|
||||
@ -229,4 +232,10 @@ pub enum DatabaseEvent {
|
||||
|
||||
#[event(input = "MoveGroupRowPayloadPB")]
|
||||
GroupByField = 113,
|
||||
|
||||
#[event(input = "CalendarSettingsPB")]
|
||||
SetCalenderSetting = 114,
|
||||
|
||||
#[event()]
|
||||
GetCalendarSetting = 115,
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ pub enum DatabaseNotification {
|
||||
DidReorderSingleRow = 66,
|
||||
/// Trigger when the settings of the database are changed
|
||||
DidUpdateSettings = 70,
|
||||
DidUpdateCalendarSettings = 80,
|
||||
DidArrangeCalendarWithNewField = 81,
|
||||
}
|
||||
|
||||
impl std::default::Default for DatabaseNotification {
|
||||
|
@ -635,6 +635,26 @@ impl DatabaseViewRevisionEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the current calendar settings
|
||||
pub async fn get_calendar_settings(&self) -> FlowyResult<CalendarSettingsParams> {
|
||||
let settings = self
|
||||
.pad
|
||||
.read()
|
||||
.await
|
||||
.get_layout_setting(&LayoutRevision::Calendar)
|
||||
.unwrap_or_else(|| CalendarSettingsParams::default_with(self.view_id.to_string()));
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
/// Update the calendar settings and send the notification to refresh the UI
|
||||
pub async fn update_calendar_settings(&self, params: CalendarSettingsParams) -> FlowyResult<()> {
|
||||
// Maybe it needs no send notification to refresh the UI
|
||||
self
|
||||
.modify(|pad| Ok(pad.update_layout_setting(&LayoutRevision::Calendar, ¶ms)?))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub async fn did_update_view_field_type_option(
|
||||
&self,
|
||||
@ -878,7 +898,7 @@ async fn new_group_controller(
|
||||
.await
|
||||
}
|
||||
|
||||
/// Returns a [GroupController]
|
||||
/// Returns a [GroupController]
|
||||
///
|
||||
async fn new_group_controller_with_field_rev(
|
||||
user_id: String,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::{DatabaseViewSettingPB, LayoutTypePB, ViewLayoutPB};
|
||||
use crate::entities::{CalendarSettingsParams, DatabaseViewSettingPB, LayoutSettingPB};
|
||||
use crate::services::database_view::{get_cells_for_field, DatabaseViewEditorDelegate};
|
||||
use crate::services::field::RowSingleCellData;
|
||||
use crate::services::filter::{FilterController, FilterDelegate, FilterType};
|
||||
@ -7,8 +7,8 @@ use crate::services::row::DatabaseBlockRowRevision;
|
||||
use crate::services::sort::{SortDelegate, SortType};
|
||||
use bytes::Bytes;
|
||||
use database_model::{
|
||||
FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision, RowRevision,
|
||||
SortRevision,
|
||||
FieldRevision, FieldTypeRevision, FilterRevision, GroupConfigurationRevision, LayoutRevision,
|
||||
RowRevision, SortRevision,
|
||||
};
|
||||
use flowy_client_sync::client_database::{DatabaseViewRevisionPad, GridViewRevisionChangeset};
|
||||
use flowy_client_sync::make_operations_from_revisions;
|
||||
@ -146,13 +146,24 @@ pub fn make_grid_setting(
|
||||
view_pad: &DatabaseViewRevisionPad,
|
||||
field_revs: &[Arc<FieldRevision>],
|
||||
) -> DatabaseViewSettingPB {
|
||||
let layout_type: LayoutTypePB = view_pad.layout.clone().into();
|
||||
let layout_type: LayoutRevision = view_pad.layout.clone();
|
||||
let mut layout_settings = LayoutSettingPB::new();
|
||||
match layout_type {
|
||||
LayoutRevision::Grid => {},
|
||||
LayoutRevision::Board => {},
|
||||
LayoutRevision::Calendar => {
|
||||
layout_settings.calendar = view_pad
|
||||
.get_layout_setting::<CalendarSettingsParams>(&layout_type)
|
||||
.map(|params| params.into());
|
||||
},
|
||||
}
|
||||
|
||||
let filters = view_pad.get_all_filters(field_revs);
|
||||
let group_configurations = view_pad.get_groups_by_field_revs(field_revs);
|
||||
let sorts = view_pad.get_all_sorts(field_revs);
|
||||
DatabaseViewSettingPB {
|
||||
support_layouts: ViewLayoutPB::all(),
|
||||
current_layout: layout_type,
|
||||
current_layout: layout_type.into(),
|
||||
layout_setting: layout_settings,
|
||||
filters: filters.into(),
|
||||
sorts: sorts.into(),
|
||||
group_configurations: group_configurations.into(),
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{FilterConfiguration, GroupConfiguration, SortConfiguration};
|
||||
use indexmap::IndexMap;
|
||||
use nanoid::nanoid;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::*;
|
||||
@ -38,6 +39,9 @@ pub struct DatabaseViewRevision {
|
||||
|
||||
pub layout: LayoutRevision,
|
||||
|
||||
#[serde(default)]
|
||||
pub layout_settings: LayoutSettings,
|
||||
|
||||
#[serde(default)]
|
||||
pub filters: FilterConfiguration,
|
||||
|
||||
@ -54,6 +58,7 @@ impl DatabaseViewRevision {
|
||||
view_id,
|
||||
database_id,
|
||||
layout,
|
||||
layout_settings: Default::default(),
|
||||
filters: Default::default(),
|
||||
groups: Default::default(),
|
||||
sorts: Default::default(),
|
||||
@ -65,6 +70,27 @@ impl DatabaseViewRevision {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct LayoutSettings {
|
||||
#[serde(with = "indexmap::serde_seq")]
|
||||
inner: IndexMap<LayoutRevision, String>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for LayoutSettings {
|
||||
type Target = IndexMap<LayoutRevision, String>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for LayoutSettings {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct RowOrderRevision {
|
||||
pub row_id: String,
|
||||
@ -80,6 +106,7 @@ mod tests {
|
||||
view_id: "1".to_string(),
|
||||
database_id: "1".to_string(),
|
||||
layout: Default::default(),
|
||||
layout_settings: Default::default(),
|
||||
filters: Default::default(),
|
||||
groups: Default::default(),
|
||||
sorts: Default::default(),
|
||||
@ -87,7 +114,7 @@ mod tests {
|
||||
let s = serde_json::to_string(&grid_view_revision).unwrap();
|
||||
assert_eq!(
|
||||
s,
|
||||
r#"{"view_id":"1","grid_id":"1","layout":0,"filters":[],"groups":[],"sorts":[]}"#
|
||||
r#"{"view_id":"1","grid_id":"1","layout":0,"layout_settings":[],"filters":[],"groups":[],"sorts":[]}"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user