mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: per-view field settings (#3199)
* chore: field-setting entities-events-notifications * chore: update field settings * chore: add tests * chore: add docs * chore: use an enum for field visibility * chore: clippy warnings * fix: deps fields * chore: collab merge main * chore: collab ref * test: fix tests * fix: tauri bump collab rev
This commit is contained in:
@ -311,6 +311,13 @@ impl std::convert::From<String> for RepeatedFieldIdPB {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<String>> for RepeatedFieldIdPB {
|
||||
fn from(value: Vec<String>) -> Self {
|
||||
let field_ids = value.into_iter().map(FieldIdPB::from).collect();
|
||||
RepeatedFieldIdPB { items: field_ids }
|
||||
}
|
||||
}
|
||||
|
||||
/// [TypeOptionChangesetPB] is used to update the type-option data.
|
||||
#[derive(ProtoBuf, Default)]
|
||||
pub struct TypeOptionChangesetPB {
|
||||
|
@ -0,0 +1,118 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::ErrorCode;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::entities::parser::NotEmptyStr;
|
||||
use crate::entities::RepeatedFieldIdPB;
|
||||
use crate::impl_into_field_visibility;
|
||||
use crate::services::field_settings::{FieldSettings, FieldSettingsChangesetParams};
|
||||
|
||||
/// Defines the field settings for a field in a view.
|
||||
#[derive(Debug, Default, Clone, ProtoBuf)]
|
||||
pub struct FieldSettingsPB {
|
||||
#[pb(index = 1)]
|
||||
pub field_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub visibility: FieldVisibility,
|
||||
}
|
||||
|
||||
impl From<FieldSettings> for FieldSettingsPB {
|
||||
fn from(value: FieldSettings) -> Self {
|
||||
Self {
|
||||
field_id: value.field_id,
|
||||
visibility: value.visibility,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Default, Clone, ProtoBuf_Enum, PartialEq)]
|
||||
pub enum FieldVisibility {
|
||||
#[default]
|
||||
AlwaysShown = 0,
|
||||
HideWhenEmpty = 1,
|
||||
AlwaysHidden = 2,
|
||||
}
|
||||
|
||||
impl_into_field_visibility!(i64);
|
||||
impl_into_field_visibility!(u8);
|
||||
|
||||
impl From<FieldVisibility> for i64 {
|
||||
fn from(value: FieldVisibility) -> Self {
|
||||
(value as u8) as i64
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, ProtoBuf)]
|
||||
pub struct FieldIdsPB {
|
||||
#[pb(index = 1)]
|
||||
pub view_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub field_ids: RepeatedFieldIdPB,
|
||||
}
|
||||
|
||||
/// Defines a set of fields in a database view, identified by their `field_ids`
|
||||
pub struct FieldIdsParams {
|
||||
pub view_id: String,
|
||||
pub field_ids: Vec<String>,
|
||||
}
|
||||
|
||||
impl TryInto<(String, Vec<String>)> for FieldIdsPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<(String, Vec<String>), Self::Error> {
|
||||
let view_id = NotEmptyStr::parse(self.view_id)
|
||||
.map_err(|_| ErrorCode::ViewIdIsInvalid)?
|
||||
.0;
|
||||
let field_ids = self
|
||||
.field_ids
|
||||
.deref()
|
||||
.iter()
|
||||
.map(|field_id| field_id.field_id.clone())
|
||||
.collect();
|
||||
|
||||
Ok((view_id, field_ids))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, ProtoBuf)]
|
||||
pub struct RepeatedFieldSettingsPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<FieldSettingsPB>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, ProtoBuf)]
|
||||
pub struct FieldSettingsChangesetPB {
|
||||
#[pb(index = 1)]
|
||||
pub view_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub field_id: String,
|
||||
|
||||
#[pb(index = 3, one_of)]
|
||||
pub visibility: Option<FieldVisibility>,
|
||||
}
|
||||
|
||||
impl From<FieldSettingsChangesetParams> for FieldSettingsChangesetPB {
|
||||
fn from(value: FieldSettingsChangesetParams) -> Self {
|
||||
Self {
|
||||
view_id: value.view_id,
|
||||
field_id: value.field_id,
|
||||
visibility: value.visibility,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<FieldSettingsChangesetPB> for FieldSettingsChangesetParams {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_from(value: FieldSettingsChangesetPB) -> Result<Self, Self::Error> {
|
||||
Ok(FieldSettingsChangesetParams {
|
||||
view_id: value.view_id,
|
||||
field_id: value.field_id,
|
||||
visibility: value.visibility,
|
||||
})
|
||||
}
|
||||
}
|
@ -23,3 +23,22 @@ macro_rules! impl_into_field_type {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_into_field_visibility {
|
||||
($target: ident) => {
|
||||
impl std::convert::From<$target> for FieldVisibility {
|
||||
fn from(ty: $target) -> Self {
|
||||
match ty {
|
||||
0 => FieldVisibility::AlwaysShown,
|
||||
1 => FieldVisibility::HideWhenEmpty,
|
||||
2 => FieldVisibility::AlwaysHidden,
|
||||
_ => {
|
||||
tracing::error!("🔴Can't parser FieldVisibility from value: {}", ty);
|
||||
FieldVisibility::AlwaysShown
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ mod calendar_entities;
|
||||
mod cell_entities;
|
||||
mod database_entities;
|
||||
mod field_entities;
|
||||
mod field_settings_entities;
|
||||
pub mod filter_entities;
|
||||
mod group_entities;
|
||||
pub mod parser;
|
||||
@ -19,6 +20,7 @@ pub use calendar_entities::*;
|
||||
pub use cell_entities::*;
|
||||
pub use database_entities::*;
|
||||
pub use field_entities::*;
|
||||
pub use field_settings_entities::*;
|
||||
pub use filter_entities::*;
|
||||
pub use group_entities::*;
|
||||
pub use row_entities::*;
|
||||
|
@ -14,6 +14,7 @@ use crate::services::field::checklist_type_option::ChecklistCellChangeset;
|
||||
use crate::services::field::{
|
||||
type_option_data_from_pb_or_default, DateCellChangeset, SelectOptionCellChangeset,
|
||||
};
|
||||
use crate::services::field_settings::FieldSettingsChangesetParams;
|
||||
use crate::services::group::{GroupChangeset, GroupSettingChangeset};
|
||||
use crate::services::share::csv::CSVFormat;
|
||||
|
||||
@ -891,3 +892,36 @@ pub(crate) async fn get_snapshots_handler(
|
||||
let snapshots = manager.get_database_snapshots(&view_id, 10).await?;
|
||||
data_result_ok(RepeatedDatabaseSnapshotPB { items: snapshots })
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub(crate) async fn get_field_settings_handler(
|
||||
data: AFPluginData<FieldIdsPB>,
|
||||
manager: AFPluginState<Weak<DatabaseManager>>,
|
||||
) -> DataResult<RepeatedFieldSettingsPB, FlowyError> {
|
||||
let manager = upgrade_manager(manager)?;
|
||||
let (view_id, field_ids) = data.into_inner().try_into()?;
|
||||
let database_editor = manager.get_database_with_view_id(&view_id).await?;
|
||||
let field_settings = database_editor
|
||||
.get_field_settings(&view_id, field_ids)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(FieldSettingsPB::from)
|
||||
.collect::<Vec<FieldSettingsPB>>();
|
||||
data_result_ok(RepeatedFieldSettingsPB {
|
||||
items: field_settings,
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub(crate) async fn update_field_settings_handler(
|
||||
data: AFPluginData<FieldSettingsChangesetPB>,
|
||||
manager: AFPluginState<Weak<DatabaseManager>>,
|
||||
) -> FlowyResult<()> {
|
||||
let manager = upgrade_manager(manager)?;
|
||||
let params: FieldSettingsChangesetParams = data.into_inner().try_into()?;
|
||||
let database_editor = manager.get_database_with_view_id(¶ms.view_id).await?;
|
||||
database_editor
|
||||
.update_field_settings_with_changeset(params)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -72,8 +72,12 @@ pub fn init(database_manager: Weak<DatabaseManager>) -> AFPlugin {
|
||||
.event(DatabaseEvent::SetLayoutSetting, set_layout_setting_handler)
|
||||
.event(DatabaseEvent::GetLayoutSetting, get_layout_setting_handler)
|
||||
.event(DatabaseEvent::CreateDatabaseView, create_database_view)
|
||||
// Export
|
||||
.event(DatabaseEvent::ExportCSV, export_csv_handler)
|
||||
.event(DatabaseEvent::GetDatabaseSnapshots, get_snapshots_handler)
|
||||
// Field settings
|
||||
.event(DatabaseEvent::GetFieldSettings, get_field_settings_handler)
|
||||
.event(DatabaseEvent::UpdateFieldSettings, update_field_settings_handler)
|
||||
}
|
||||
|
||||
/// [DatabaseEvent] defines events that are used to interact with the Grid. You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/protobuf)
|
||||
@ -315,4 +319,12 @@ pub enum DatabaseEvent {
|
||||
/// Returns all the snapshots of the database view.
|
||||
#[event(input = "DatabaseViewIdPB", output = "RepeatedDatabaseSnapshotPB")]
|
||||
GetDatabaseSnapshots = 150,
|
||||
|
||||
/// Returns the field settings for the provided fields in the given view
|
||||
#[event(input = "FieldIdsPB", output = "RepeatedFieldSettingsPB")]
|
||||
GetFieldSettings = 160,
|
||||
|
||||
/// Updates the field settings for a field in the given view
|
||||
#[event(input = "FieldSettingsChangesetPB")]
|
||||
UpdateFieldSettings = 161,
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ use crate::entities::{
|
||||
use crate::notification::{send_notification, DatabaseNotification};
|
||||
use crate::services::database::DatabaseEditor;
|
||||
use crate::services::database_view::DatabaseLayoutDepsResolver;
|
||||
use crate::services::field_settings::{
|
||||
default_field_settings_by_layout, default_field_settings_by_layout_map,
|
||||
};
|
||||
use crate::services::share::csv::{CSVFormat, CSVImporter, ImportResult};
|
||||
|
||||
pub trait DatabaseUser: Send + Sync {
|
||||
@ -249,12 +252,18 @@ impl DatabaseManager {
|
||||
database_view_id: String,
|
||||
) -> FlowyResult<()> {
|
||||
let wdb = self.get_workspace_database().await?;
|
||||
let mut params = CreateViewParams::new(database_id.clone(), database_view_id, name, layout);
|
||||
let mut params = CreateViewParams::new(
|
||||
database_id.clone(),
|
||||
database_view_id,
|
||||
name,
|
||||
layout,
|
||||
default_field_settings_by_layout(layout),
|
||||
);
|
||||
if let Some(database) = wdb.get_database(&database_id).await {
|
||||
let (field, layout_setting) = DatabaseLayoutDepsResolver::new(database, layout)
|
||||
.resolve_deps_when_create_database_linked_view();
|
||||
if let Some(field) = field {
|
||||
params = params.with_deps_fields(vec![field]);
|
||||
params = params.with_deps_fields(vec![field], default_field_settings_by_layout_map())
|
||||
}
|
||||
if let Some(layout_setting) = layout_setting {
|
||||
params = params.with_layout_setting(layout_setting);
|
||||
|
@ -50,6 +50,8 @@ pub enum DatabaseNotification {
|
||||
DidMoveDatabaseViewToTrash = 84,
|
||||
DidUpdateDatabaseSyncUpdate = 85,
|
||||
DidUpdateDatabaseSnapshotState = 86,
|
||||
// Trigger when the field setting is changed
|
||||
DidUpdateFieldSettings = 87,
|
||||
}
|
||||
|
||||
impl std::convert::From<DatabaseNotification> for i32 {
|
||||
@ -81,6 +83,7 @@ impl std::convert::From<i32> for DatabaseNotification {
|
||||
82 => DatabaseNotification::DidUpdateDatabaseLayout,
|
||||
83 => DatabaseNotification::DidDeleteDatabaseView,
|
||||
84 => DatabaseNotification::DidMoveDatabaseViewToTrash,
|
||||
87 => DatabaseNotification::DidUpdateFieldSettings,
|
||||
_ => DatabaseNotification::Unknown,
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,10 @@ use crate::services::field::{
|
||||
type_option_data_from_pb_or_default, type_option_to_pb, DateCellData, SelectOptionCellChangeset,
|
||||
SelectOptionIds, TypeOptionCellDataHandler, TypeOptionCellExt,
|
||||
};
|
||||
use crate::services::field_settings::{
|
||||
default_field_settings_by_layout, default_field_settings_by_layout_map, FieldSettings,
|
||||
FieldSettingsChangesetParams,
|
||||
};
|
||||
use crate::services::filter::Filter;
|
||||
use crate::services::group::{
|
||||
default_group_setting, GroupSetting, GroupSettingChangeset, RowChangeset,
|
||||
@ -474,15 +478,17 @@ impl DatabaseEditor {
|
||||
None => default_type_option_data_from_type(field_type),
|
||||
Some(type_option_data) => type_option_data_from_pb_or_default(type_option_data, field_type),
|
||||
};
|
||||
let (index, field) =
|
||||
self
|
||||
.database
|
||||
.lock()
|
||||
.create_field_with_mut(view_id, name, field_type.into(), |field| {
|
||||
field
|
||||
.type_options
|
||||
.insert(field_type.to_string(), type_option_data.clone());
|
||||
});
|
||||
let (index, field) = self.database.lock().create_field_with_mut(
|
||||
view_id,
|
||||
name,
|
||||
field_type.into(),
|
||||
|field| {
|
||||
field
|
||||
.type_options
|
||||
.insert(field_type.to_string(), type_option_data.clone());
|
||||
},
|
||||
default_field_settings_by_layout_map(),
|
||||
);
|
||||
|
||||
let _ = self
|
||||
.notify_did_insert_database_field(field.clone(), index)
|
||||
@ -1101,6 +1107,35 @@ impl DatabaseEditor {
|
||||
Ok(csv)
|
||||
}
|
||||
|
||||
pub async fn get_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
field_ids: Vec<String>,
|
||||
) -> Result<Vec<FieldSettings>, anyhow::Error> {
|
||||
let view = self.database_views.get_view_editor(view_id).await?;
|
||||
view.v_get_field_settings(field_ids).await
|
||||
}
|
||||
|
||||
pub async fn get_all_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
) -> Result<Vec<FieldSettings>, anyhow::Error> {
|
||||
let view = self.database_views.get_view_editor(view_id).await?;
|
||||
view.v_get_all_field_settings().await
|
||||
}
|
||||
|
||||
pub async fn update_field_settings_with_changeset(
|
||||
&self,
|
||||
params: FieldSettingsChangesetParams,
|
||||
) -> FlowyResult<()> {
|
||||
let view = self.database_views.get_view_editor(¶ms.view_id).await?;
|
||||
view
|
||||
.v_update_field_settings(¶ms.view_id, ¶ms.field_id, params.visibility)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_auto_updated_fields(&self, view_id: &str) -> Vec<Field> {
|
||||
self
|
||||
.database
|
||||
@ -1188,6 +1223,7 @@ impl DatabaseViewData for DatabaseViewDataImpl {
|
||||
.type_options
|
||||
.insert(field_type.to_string(), type_option_data);
|
||||
},
|
||||
default_field_settings_by_layout_map(),
|
||||
);
|
||||
to_fut(async move { field })
|
||||
}
|
||||
@ -1353,4 +1389,68 @@ impl DatabaseViewData for DatabaseViewDataImpl {
|
||||
TypeOptionCellExt::new_with_cell_data_cache(field, Some(self.cell_cache.clone()))
|
||||
.get_type_option_cell_data_handler(field_type)
|
||||
}
|
||||
|
||||
fn get_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
field_ids: Vec<String>,
|
||||
) -> Result<Vec<FieldSettings>, anyhow::Error> {
|
||||
let field_settings_map = self
|
||||
.database
|
||||
.lock()
|
||||
.get_field_settings(view_id, Some(field_ids));
|
||||
|
||||
let field_settings: Result<Vec<FieldSettings>, anyhow::Error> = field_settings_map
|
||||
.into_iter()
|
||||
.map(|(field_id, field_settings)| FieldSettings::try_from_anymap(field_id, field_settings))
|
||||
.collect();
|
||||
|
||||
field_settings
|
||||
}
|
||||
|
||||
fn get_all_field_settings(&self, view_id: &str) -> Result<Vec<FieldSettings>, anyhow::Error> {
|
||||
let field_settings_map = self.database.lock().get_field_settings(view_id, None);
|
||||
|
||||
let field_settings: Result<Vec<FieldSettings>, anyhow::Error> = field_settings_map
|
||||
.into_iter()
|
||||
.map(|(field_id, field_settings)| FieldSettings::try_from_anymap(field_id, field_settings))
|
||||
.collect();
|
||||
|
||||
field_settings
|
||||
}
|
||||
|
||||
fn update_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
field_id: &str,
|
||||
visibility: Option<FieldVisibility>,
|
||||
) {
|
||||
let field_settings = self
|
||||
.get_field_settings(view_id, vec![field_id.to_string()])
|
||||
.ok();
|
||||
|
||||
let new_field_settings = match field_settings {
|
||||
Some(field_settings) => {
|
||||
let mut field_settings = field_settings.first().unwrap().clone();
|
||||
field_settings.visibility = visibility.unwrap_or(field_settings.visibility);
|
||||
field_settings
|
||||
},
|
||||
None => {
|
||||
let layout_ty = self.get_layout_for_view(view_id);
|
||||
let mut field_settings = FieldSettings::try_from_anymap(
|
||||
field_id.to_string(),
|
||||
default_field_settings_by_layout(layout_ty),
|
||||
)
|
||||
.unwrap();
|
||||
field_settings.visibility = visibility.unwrap_or(field_settings.visibility);
|
||||
field_settings
|
||||
},
|
||||
};
|
||||
|
||||
self.database.lock().update_field_settings(
|
||||
view_id,
|
||||
Some(vec![field_id.to_string()]),
|
||||
new_field_settings,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::entities::FieldType;
|
||||
use crate::services::field::{DateTypeOption, SingleSelectTypeOption};
|
||||
use crate::services::field_settings::default_field_settings_by_layout_map;
|
||||
use crate::services::setting::CalendarLayoutSetting;
|
||||
|
||||
/// When creating a database, we need to resolve the dependencies of the views.
|
||||
@ -83,7 +84,10 @@ impl DatabaseLayoutDepsResolver {
|
||||
tracing::trace!("Create a new date field after layout type change");
|
||||
let field = self.create_date_field();
|
||||
let field_id = field.id.clone();
|
||||
self.database.lock().create_field(field);
|
||||
self
|
||||
.database
|
||||
.lock()
|
||||
.create_field(field, default_field_settings_by_layout_map());
|
||||
field_id
|
||||
},
|
||||
Some(date_field) => date_field.id,
|
||||
|
@ -14,9 +14,9 @@ use lib_infra::future::Fut;
|
||||
|
||||
use crate::entities::{
|
||||
CalendarEventPB, DatabaseLayoutMetaPB, DatabaseLayoutSettingPB, DeleteFilterParams,
|
||||
DeleteGroupParams, DeleteSortParams, FieldType, GroupChangesPB, GroupPB, GroupRowsNotificationPB,
|
||||
InsertedRowPB, LayoutSettingParams, RowMetaPB, RowsChangePB, SortChangesetNotificationPB, SortPB,
|
||||
UpdateFilterParams, UpdateSortParams,
|
||||
DeleteGroupParams, DeleteSortParams, FieldType, FieldVisibility, GroupChangesPB, GroupPB,
|
||||
GroupRowsNotificationPB, InsertedRowPB, LayoutSettingParams, RowMetaPB, RowsChangePB,
|
||||
SortChangesetNotificationPB, SortPB, UpdateFilterParams, UpdateSortParams,
|
||||
};
|
||||
use crate::notification::{send_notification, DatabaseNotification};
|
||||
use crate::services::cell::CellCache;
|
||||
@ -32,6 +32,7 @@ use crate::services::database_view::{
|
||||
DatabaseViewChangedNotifier, DatabaseViewChangedReceiverRunner,
|
||||
};
|
||||
use crate::services::field::TypeOptionCellDataHandler;
|
||||
use crate::services::field_settings::FieldSettings;
|
||||
use crate::services::filter::{
|
||||
Filter, FilterChangeset, FilterController, FilterType, UpdatedFilterType,
|
||||
};
|
||||
@ -123,6 +124,21 @@ pub trait DatabaseViewData: Send + Sync + 'static {
|
||||
field: &Field,
|
||||
field_type: &FieldType,
|
||||
) -> Option<Box<dyn TypeOptionCellDataHandler>>;
|
||||
|
||||
fn get_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
field_ids: Vec<String>,
|
||||
) -> Result<Vec<FieldSettings>, anyhow::Error>;
|
||||
|
||||
fn get_all_field_settings(&self, view_id: &str) -> Result<Vec<FieldSettings>, anyhow::Error>;
|
||||
|
||||
fn update_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
field_id: &str,
|
||||
visibility: Option<FieldVisibility>,
|
||||
);
|
||||
}
|
||||
|
||||
pub struct DatabaseViewEditor {
|
||||
@ -892,6 +908,30 @@ impl DatabaseViewEditor {
|
||||
.send();
|
||||
}
|
||||
|
||||
pub async fn v_get_field_settings(
|
||||
&self,
|
||||
field_ids: Vec<String>,
|
||||
) -> Result<Vec<FieldSettings>, anyhow::Error> {
|
||||
self.delegate.get_field_settings(&self.view_id, field_ids)
|
||||
}
|
||||
|
||||
pub async fn v_get_all_field_settings(&self) -> Result<Vec<FieldSettings>, anyhow::Error> {
|
||||
self.delegate.get_all_field_settings(&self.view_id)
|
||||
}
|
||||
|
||||
pub async fn v_update_field_settings(
|
||||
&self,
|
||||
view_id: &str,
|
||||
field_id: &str,
|
||||
visibility: Option<FieldVisibility>,
|
||||
) -> FlowyResult<()> {
|
||||
self
|
||||
.delegate
|
||||
.update_field_settings(view_id, field_id, visibility);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn mut_group_controller<F, T>(&self, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&mut Box<dyn GroupController>, Arc<Field>) -> FlowyResult<T>,
|
||||
|
@ -0,0 +1,47 @@
|
||||
use anyhow::bail;
|
||||
use collab::core::any_map::AnyMapExtension;
|
||||
use collab_database::views::{FieldSettingsMap, FieldSettingsMapBuilder};
|
||||
|
||||
use crate::entities::FieldVisibility;
|
||||
|
||||
/// Stores the field settings for a single field
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FieldSettings {
|
||||
pub field_id: String,
|
||||
pub visibility: FieldVisibility,
|
||||
}
|
||||
|
||||
pub const VISIBILITY: &str = "visibility";
|
||||
|
||||
impl FieldSettings {
|
||||
pub fn try_from_anymap(
|
||||
field_id: String,
|
||||
field_settings: FieldSettingsMap,
|
||||
) -> Result<Self, anyhow::Error> {
|
||||
let visibility = match field_settings.get_i64_value(VISIBILITY) {
|
||||
Some(visbility) => visbility.into(),
|
||||
_ => bail!("Invalid field settings data"),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
field_id,
|
||||
visibility,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FieldSettings> for FieldSettingsMap {
|
||||
fn from(field_settings: FieldSettings) -> Self {
|
||||
FieldSettingsMapBuilder::new()
|
||||
.insert_i64_value(VISIBILITY, field_settings.visibility.into())
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the changeset to a field's settings.
|
||||
/// A `Some` value for constitutes a change in that particular setting
|
||||
pub struct FieldSettingsChangesetParams {
|
||||
pub view_id: String,
|
||||
pub field_id: String,
|
||||
pub visibility: Option<FieldVisibility>,
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use collab_database::views::{DatabaseLayout, FieldSettingsMap, FieldSettingsMapBuilder};
|
||||
|
||||
use crate::{entities::FieldVisibility, services::field_settings::VISIBILITY};
|
||||
|
||||
/// Creates a map of the database layout and the default field settings for fields
|
||||
/// in a view of that database layout
|
||||
pub fn default_field_settings_by_layout_map() -> HashMap<DatabaseLayout, FieldSettingsMap> {
|
||||
let mut template = HashMap::new();
|
||||
for layout_ty in DatabaseLayout::iter() {
|
||||
template.insert(layout_ty, default_field_settings_by_layout(layout_ty));
|
||||
}
|
||||
|
||||
template
|
||||
}
|
||||
|
||||
/// Returns the default FieldSettingsMap for the given database layout
|
||||
pub fn default_field_settings_by_layout(layout_ty: DatabaseLayout) -> FieldSettingsMap {
|
||||
let visibility = default_visibility(layout_ty);
|
||||
FieldSettingsMapBuilder::new()
|
||||
.insert_i64_value(VISIBILITY, visibility.into())
|
||||
.build()
|
||||
}
|
||||
|
||||
/// Returns the default visibility of a field for the given database layout
|
||||
pub fn default_visibility(layout_ty: DatabaseLayout) -> FieldVisibility {
|
||||
match layout_ty {
|
||||
DatabaseLayout::Grid => FieldVisibility::AlwaysShown,
|
||||
DatabaseLayout::Board => FieldVisibility::HideWhenEmpty,
|
||||
DatabaseLayout::Calendar => FieldVisibility::HideWhenEmpty,
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
use collab_database::views::DatabaseLayout;
|
||||
|
||||
use crate::entities::FieldVisibility;
|
||||
|
||||
use crate::services::field_settings::{default_visibility, FieldSettings};
|
||||
|
||||
/// Helper struct to create a new field setting
|
||||
pub struct FieldSettingsBuilder {
|
||||
field_settings: FieldSettings,
|
||||
}
|
||||
|
||||
impl FieldSettingsBuilder {
|
||||
pub fn new(field_id: &str) -> Self {
|
||||
let field_settings = FieldSettings {
|
||||
field_id: field_id.to_string(),
|
||||
visibility: FieldVisibility::AlwaysShown,
|
||||
};
|
||||
Self { field_settings }
|
||||
}
|
||||
|
||||
pub fn from_layout_type(field_id: &str, layout_ty: DatabaseLayout) -> Self {
|
||||
let field_settings = FieldSettings {
|
||||
field_id: field_id.to_string(),
|
||||
visibility: default_visibility(layout_ty),
|
||||
};
|
||||
Self { field_settings }
|
||||
}
|
||||
|
||||
pub fn field_id(mut self, field_id: &str) -> Self {
|
||||
self.field_settings.field_id = field_id.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn visibility(mut self, visibility: FieldVisibility) -> Self {
|
||||
self.field_settings.visibility = visibility;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> FieldSettings {
|
||||
self.field_settings
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
mod entities;
|
||||
mod field_settings;
|
||||
mod field_settings_builder;
|
||||
|
||||
pub use entities::*;
|
||||
pub use field_settings::*;
|
||||
pub use field_settings_builder::*;
|
@ -2,6 +2,7 @@ pub mod cell;
|
||||
pub mod database;
|
||||
pub mod database_view;
|
||||
pub mod field;
|
||||
pub mod field_settings;
|
||||
pub mod filter;
|
||||
pub mod group;
|
||||
pub mod setting;
|
||||
|
@ -9,6 +9,7 @@ use flowy_error::{FlowyError, FlowyResult};
|
||||
|
||||
use crate::entities::FieldType;
|
||||
use crate::services::field::{default_type_option_data_from_type, CELL_DATA};
|
||||
use crate::services::field_settings::default_field_settings_by_layout;
|
||||
use crate::services::share::csv::CSVFormat;
|
||||
|
||||
#[derive(Default)]
|
||||
@ -134,6 +135,7 @@ fn database_from_fields_and_rows(
|
||||
sorts: vec![],
|
||||
created_rows,
|
||||
fields,
|
||||
field_settings: default_field_settings_by_layout(DatabaseLayout::Grid),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use crate::services::cell::{insert_select_option_cell, insert_text_cell};
|
||||
use crate::services::field::{
|
||||
FieldBuilder, SelectOption, SelectOptionColor, SingleSelectTypeOption,
|
||||
};
|
||||
use crate::services::field_settings::default_field_settings_by_layout;
|
||||
use crate::services::setting::CalendarLayoutSetting;
|
||||
|
||||
pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams {
|
||||
@ -41,6 +42,7 @@ pub fn make_default_grid(view_id: &str, name: &str) -> CreateDatabaseParams {
|
||||
CreateRowParams::new(gen_row_id()),
|
||||
],
|
||||
fields: vec![text_field, single_select, checkbox_field],
|
||||
field_settings: default_field_settings_by_layout(DatabaseLayout::Grid),
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,6 +94,7 @@ pub fn make_default_board(view_id: &str, name: &str) -> CreateDatabaseParams {
|
||||
sorts: vec![],
|
||||
created_rows: rows,
|
||||
fields: vec![text_field, single_select],
|
||||
field_settings: default_field_settings_by_layout(DatabaseLayout::Board),
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,5 +136,6 @@ pub fn make_default_calendar(view_id: &str, name: &str) -> CreateDatabaseParams
|
||||
sorts: vec![],
|
||||
created_rows: vec![],
|
||||
fields: vec![text_field, date_field, multi_select_field],
|
||||
field_settings: default_field_settings_by_layout(DatabaseLayout::Calendar),
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user