mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add group documentation (#1258)
This commit is contained in:
parent
4549ed20e7
commit
4e122a9452
@ -250,13 +250,6 @@ impl TryInto<FieldTypeOptionIdParams> for FieldTypeOptionIdPB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Certain field types have user-defined options such as color, date format, number format,
|
|
||||||
/// or a list of values for a multi-select list. These options are defined within a specialization
|
|
||||||
/// of the FieldTypeOption class.
|
|
||||||
///
|
|
||||||
/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
|
|
||||||
/// for more information.
|
|
||||||
///
|
|
||||||
#[derive(Debug, Default, ProtoBuf)]
|
#[derive(Debug, Default, ProtoBuf)]
|
||||||
pub struct FieldTypeOptionDataPB {
|
pub struct FieldTypeOptionDataPB {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
@ -510,7 +503,15 @@ pub struct FieldChangesetParams {
|
|||||||
|
|
||||||
pub type_option_data: Option<Vec<u8>>,
|
pub type_option_data: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
/// Certain field types have user-defined options such as color, date format, number format,
|
||||||
|
/// or a list of values for a multi-select list. These options are defined within a specialization
|
||||||
|
/// of the FieldTypeOption class.
|
||||||
|
///
|
||||||
|
/// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
|
||||||
|
/// for more information.
|
||||||
|
///
|
||||||
|
/// The order of the enum can't be changed. If you want to add a new type,
|
||||||
|
/// it would be better to append it to the end of the list.
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
@ -525,8 +526,6 @@ pub struct FieldChangesetParams {
|
|||||||
Serialize_repr,
|
Serialize_repr,
|
||||||
Deserialize_repr,
|
Deserialize_repr,
|
||||||
)]
|
)]
|
||||||
/// The order of the enum can't be changed. If you want to add a new type,
|
|
||||||
/// it would be better to append it to the end of the list.
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum FieldType {
|
pub enum FieldType {
|
||||||
RichText = 0,
|
RichText = 0,
|
||||||
|
@ -193,7 +193,7 @@ impl GridRevisionEditor {
|
|||||||
.modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev.clone())?))
|
.modify(|grid_pad| Ok(grid_pad.replace_field_rev(field_rev.clone())?))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match self.view_manager.did_update_field(&field_rev.id, false).await {
|
match self.view_manager.did_update_view_field(&field_rev.id).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => tracing::error!("View manager update field failed: {:?}", e),
|
Err(e) => tracing::error!("View manager update field failed: {:?}", e),
|
||||||
}
|
}
|
||||||
@ -214,27 +214,28 @@ impl GridRevisionEditor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Switch the field with id to a new field type.
|
||||||
|
///
|
||||||
|
/// If the field type is not exist before, the default type option data will be created.
|
||||||
|
/// Each field type has its corresponding data, aka, the type option data. Check out [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid#fieldtype)
|
||||||
|
/// for more information
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `field_id`: the id of the field
|
||||||
|
/// * `field_type`: the new field type of the field
|
||||||
|
///
|
||||||
pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> {
|
pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> {
|
||||||
// let block_ids = self
|
let type_option_builder = |field_type: &FieldTypeRevision| -> String {
|
||||||
// .get_block_metas()
|
|
||||||
// .await?
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|block_meta| block_meta.block_id)
|
|
||||||
// .collect();
|
|
||||||
// let cell_revs = self
|
|
||||||
// .block_meta_manager
|
|
||||||
// .get_cell_revs(block_ids, field_id, None)
|
|
||||||
// .await?;
|
|
||||||
|
|
||||||
let type_option_json_builder = |field_type: &FieldTypeRevision| -> String {
|
|
||||||
let field_type: FieldType = field_type.into();
|
let field_type: FieldType = field_type.into();
|
||||||
|
|
||||||
return default_type_option_builder_from_type(&field_type)
|
return default_type_option_builder_from_type(&field_type)
|
||||||
.data_format()
|
.data_format()
|
||||||
.json_str();
|
.json_str();
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = self
|
let _ = self
|
||||||
.modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?))
|
.modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_builder)?))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let _ = self.notify_did_update_grid_field(field_id).await?;
|
let _ = self.notify_did_update_grid_field(field_id).await?;
|
||||||
@ -276,6 +277,7 @@ impl GridRevisionEditor {
|
|||||||
Ok(field_revs)
|
Ok(field_revs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||||
async fn update_field_rev(&self, params: FieldChangesetParams, field_type: FieldType) -> FlowyResult<()> {
|
async fn update_field_rev(&self, params: FieldChangesetParams, field_type: FieldType) -> FlowyResult<()> {
|
||||||
let mut is_type_option_changed = false;
|
let mut is_type_option_changed = false;
|
||||||
let _ = self
|
let _ = self
|
||||||
@ -333,14 +335,15 @@ impl GridRevisionEditor {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match self
|
if is_type_option_changed {
|
||||||
.view_manager
|
let _ = self
|
||||||
.did_update_field(¶ms.field_id, is_type_option_changed)
|
.view_manager
|
||||||
.await
|
.did_update_view_field_type_option(¶ms.field_id)
|
||||||
{
|
.await?;
|
||||||
Ok(_) => {}
|
} else {
|
||||||
Err(e) => tracing::error!("View manager update field failed: {:?}", e),
|
let _ = self.view_manager.did_update_view_field(¶ms.field_id).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,9 @@ impl GridViewRevisionEditor {
|
|||||||
pub(crate) async fn did_delete_view_row(&self, row_rev: &RowRevision) {
|
pub(crate) async fn did_delete_view_row(&self, row_rev: &RowRevision) {
|
||||||
// Send the group notification if the current view has groups;
|
// Send the group notification if the current view has groups;
|
||||||
let changesets = self
|
let changesets = self
|
||||||
.mut_group_controller(|group_controller, field_rev| group_controller.did_delete_row(row_rev, &field_rev))
|
.mut_group_controller(|group_controller, field_rev| {
|
||||||
|
group_controller.did_delete_delete_row(row_rev, &field_rev)
|
||||||
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if let Some(changesets) = changesets {
|
if let Some(changesets) = changesets {
|
||||||
@ -131,7 +133,9 @@ impl GridViewRevisionEditor {
|
|||||||
|
|
||||||
pub(crate) async fn did_update_view_row(&self, row_rev: &RowRevision) {
|
pub(crate) async fn did_update_view_row(&self, row_rev: &RowRevision) {
|
||||||
let changesets = self
|
let changesets = self
|
||||||
.mut_group_controller(|group_controller, field_rev| group_controller.did_update_row(row_rev, &field_rev))
|
.mut_group_controller(|group_controller, field_rev| {
|
||||||
|
group_controller.did_update_group_row(row_rev, &field_rev)
|
||||||
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if let Some(changesets) = changesets {
|
if let Some(changesets) = changesets {
|
||||||
@ -239,7 +243,7 @@ impl GridViewRevisionEditor {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if self.group_controller.read().await.field_id() != params.field_id {
|
if self.group_controller.read().await.field_id() != params.field_id {
|
||||||
let _ = self.group_by_field(¶ms.field_id).await?;
|
let _ = self.group_by_view_field(¶ms.field_id).await?;
|
||||||
self.notify_did_update_setting().await;
|
self.notify_did_update_setting().await;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -279,9 +283,9 @@ impl GridViewRevisionEditor {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||||
pub(crate) async fn did_update_field(&self, field_id: &str) -> FlowyResult<()> {
|
pub(crate) async fn did_update_view_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
|
if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
|
||||||
match self.group_controller.write().await.did_update_field(&field_rev)? {
|
match self.group_controller.write().await.did_update_group_field(&field_rev)? {
|
||||||
None => {}
|
None => {}
|
||||||
Some(changeset) => {
|
Some(changeset) => {
|
||||||
self.notify_did_update_view(changeset).await;
|
self.notify_did_update_view(changeset).await;
|
||||||
@ -291,8 +295,14 @@ impl GridViewRevisionEditor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `field_id`:
|
||||||
|
///
|
||||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||||
pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
|
pub(crate) async fn group_by_view_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
|
if let Some(field_rev) = self.field_delegate.get_field_rev(field_id).await {
|
||||||
let new_group_controller = new_group_controller_with_field_rev(
|
let new_group_controller = new_group_controller_with_field_rev(
|
||||||
self.user_id.clone(),
|
self.user_id.clone(),
|
||||||
@ -386,6 +396,7 @@ impl GridViewRevisionEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn new_group_controller(
|
async fn new_group_controller(
|
||||||
user_id: String,
|
user_id: String,
|
||||||
view_id: String,
|
view_id: String,
|
||||||
@ -412,6 +423,17 @@ async fn new_group_controller(
|
|||||||
new_group_controller_with_field_rev(user_id, view_id, view_rev_pad, rev_manager, field_rev, row_delegate).await
|
new_group_controller_with_field_rev(user_id, view_id, view_rev_pad, rev_manager, field_rev, row_delegate).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a [GroupController]
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `user_id`:
|
||||||
|
/// * `view_id`:
|
||||||
|
/// * `view_rev_pad`:
|
||||||
|
/// * `rev_manager`:
|
||||||
|
/// * `field_rev`:
|
||||||
|
/// * `row_delegate`:
|
||||||
|
///
|
||||||
async fn new_group_controller_with_field_rev(
|
async fn new_group_controller_with_field_rev(
|
||||||
user_id: String,
|
user_id: String,
|
||||||
view_id: String,
|
view_id: String,
|
||||||
|
@ -93,7 +93,7 @@ impl GridViewManager {
|
|||||||
|
|
||||||
pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
|
pub(crate) async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
let view_editor = self.get_default_view_editor().await?;
|
let view_editor = self.get_default_view_editor().await?;
|
||||||
let _ = view_editor.group_by_field(field_id).await?;
|
let _ = view_editor.group_by_view_field(field_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,18 +177,28 @@ impl GridViewManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||||
pub(crate) async fn did_update_field(&self, field_id: &str, is_type_option_changed: bool) -> FlowyResult<()> {
|
pub(crate) async fn did_update_view_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
let view_editor = self.get_default_view_editor().await?;
|
let view_editor = self.get_default_view_editor().await?;
|
||||||
// Only the field_id of the updated field is equal to the field_id of the group.
|
// Only the field_id of the updated field is equal to the field_id of the group.
|
||||||
// Update the group
|
// Update the group
|
||||||
if view_editor.group_id().await != field_id {
|
if view_editor.group_id().await != field_id {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if is_type_option_changed {
|
let _ = view_editor.did_update_view_field(field_id).await?;
|
||||||
let _ = view_editor.group_by_field(field_id).await?;
|
Ok(())
|
||||||
} else {
|
}
|
||||||
let _ = view_editor.did_update_field(field_id).await?;
|
|
||||||
}
|
/// Notifies the view's field type option data is changed
|
||||||
|
/// For the moment, only the groups will be generated after the type option data changed. A
|
||||||
|
/// [FieldRevision] has a property named type_options contains a list of type option data.
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `field_id`: the id of the field in current view
|
||||||
|
///
|
||||||
|
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||||
|
pub(crate) async fn did_update_view_field_type_option(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
|
let view_editor = self.get_default_view_editor().await?;
|
||||||
|
let _ = view_editor.group_by_view_field(field_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::entities::{GroupPB, GroupViewChangesetPB};
|
use crate::entities::{GroupPB, GroupViewChangesetPB};
|
||||||
use crate::services::group::{default_group_configuration, make_default_group, GeneratedGroup, Group};
|
use crate::services::group::{default_group_configuration, make_no_status_group, GeneratedGroupConfig, Group};
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision,
|
FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision,
|
||||||
@ -34,14 +34,28 @@ impl<T> std::fmt::Display for GroupContext<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [GroupContext] represents as the groups memory cache
|
||||||
|
/// Each [GenericGroupController] has its own [GroupContext], the `context` has its own configuration
|
||||||
|
/// that is restored from the disk.
|
||||||
|
///
|
||||||
|
/// The `context` contains a list of [Group]s and the grouping [FieldRevision]
|
||||||
pub struct GroupContext<C> {
|
pub struct GroupContext<C> {
|
||||||
pub view_id: String,
|
pub view_id: String,
|
||||||
|
/// The group configuration restored from the disk.
|
||||||
|
///
|
||||||
|
/// Uses the [GroupConfigurationReader] to read the configuration data from disk
|
||||||
configuration: Arc<GroupConfigurationRevision>,
|
configuration: Arc<GroupConfigurationRevision>,
|
||||||
configuration_content: PhantomData<C>,
|
configuration_phantom: PhantomData<C>,
|
||||||
|
|
||||||
|
/// The grouping field
|
||||||
field_rev: Arc<FieldRevision>,
|
field_rev: Arc<FieldRevision>,
|
||||||
|
|
||||||
|
/// Cache all the groups
|
||||||
groups_map: IndexMap<String, Group>,
|
groups_map: IndexMap<String, Group>,
|
||||||
/// default_group is used to store the rows that don't belong to any groups.
|
|
||||||
// default_group: Group,
|
/// A writer that implement the [GroupConfigurationWriter] trait is used to save the
|
||||||
|
/// configuration to disk
|
||||||
|
///
|
||||||
writer: Arc<dyn GroupConfigurationWriter>,
|
writer: Arc<dyn GroupConfigurationWriter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,19 +87,21 @@ where
|
|||||||
groups_map: IndexMap::new(),
|
groups_map: IndexMap::new(),
|
||||||
writer,
|
writer,
|
||||||
configuration,
|
configuration,
|
||||||
configuration_content: PhantomData,
|
configuration_phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_default_group(&self) -> Option<&Group> {
|
/// Returns the no `status` group
|
||||||
|
///
|
||||||
|
/// We take the `id` of the `field` as the default group id
|
||||||
|
pub(crate) fn get_no_status_group(&self) -> Option<&Group> {
|
||||||
self.groups_map.get(&self.field_rev.id)
|
self.groups_map.get(&self.field_rev.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_mut_default_group(&mut self) -> Option<&mut Group> {
|
pub(crate) fn get_mut_no_status_group(&mut self) -> Option<&mut Group> {
|
||||||
self.groups_map.get_mut(&self.field_rev.id)
|
self.groups_map.get_mut(&self.field_rev.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the groups without the default group
|
|
||||||
pub(crate) fn groups(&self) -> Vec<&Group> {
|
pub(crate) fn groups(&self) -> Vec<&Group> {
|
||||||
self.groups_map.values().collect()
|
self.groups_map.values().collect()
|
||||||
}
|
}
|
||||||
@ -142,23 +158,38 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, generated_groups), err)]
|
/// Reset the memory cache of the groups and update the group configuration
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `generated_group_configs`: the generated groups contains a list of [GeneratedGroupConfig].
|
||||||
|
///
|
||||||
|
/// Each [FieldType] can implement the [GroupGenerator] trait in order to generate different
|
||||||
|
/// groups. For example, the FieldType::Checkbox has the [CheckboxGroupGenerator] that implements
|
||||||
|
/// the [GroupGenerator] trait.
|
||||||
|
///
|
||||||
|
/// Consider the passed-in generated_group_configs as new groups, the groups in the current
|
||||||
|
/// [GroupConfigurationRevision] as old groups. The old groups and the new groups will be merged
|
||||||
|
/// while keeping the order of the old groups.
|
||||||
|
///
|
||||||
|
#[tracing::instrument(level = "debug", skip(self, generated_group_configs), err)]
|
||||||
pub(crate) fn init_groups(
|
pub(crate) fn init_groups(
|
||||||
&mut self,
|
&mut self,
|
||||||
generated_groups: Vec<GeneratedGroup>,
|
generated_group_configs: Vec<GeneratedGroupConfig>,
|
||||||
) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||||
let mut new_groups = vec![];
|
let mut new_groups = vec![];
|
||||||
let mut filter_content_map = HashMap::new();
|
let mut filter_content_map = HashMap::new();
|
||||||
generated_groups.into_iter().for_each(|generate_group| {
|
generated_group_configs.into_iter().for_each(|generate_group| {
|
||||||
filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content);
|
filter_content_map.insert(generate_group.group_rev.id.clone(), generate_group.filter_content);
|
||||||
new_groups.push(generate_group.group_rev);
|
new_groups.push(generate_group.group_rev);
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut old_groups = self.configuration.groups.clone();
|
let mut old_groups = self.configuration.groups.clone();
|
||||||
if !old_groups.iter().any(|group| group.id == self.field_rev.id) {
|
if !old_groups.iter().any(|group| group.id == self.field_rev.id) {
|
||||||
old_groups.push(make_default_group(&self.field_rev));
|
old_groups.push(make_no_status_group(&self.field_rev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The `all_group_revs` represents as the combination of the new groups and old groups
|
||||||
let MergeGroupResult {
|
let MergeGroupResult {
|
||||||
mut all_group_revs,
|
mut all_group_revs,
|
||||||
new_group_revs,
|
new_group_revs,
|
||||||
@ -171,6 +202,7 @@ where
|
|||||||
.map(|group_rev| group_rev.id)
|
.map(|group_rev| group_rev.id)
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
// Delete/Insert the group in the current configuration
|
||||||
self.mut_configuration(|configuration| {
|
self.mut_configuration(|configuration| {
|
||||||
let mut is_changed = false;
|
let mut is_changed = false;
|
||||||
if !deleted_group_ids.is_empty() {
|
if !deleted_group_ids.is_empty() {
|
||||||
@ -179,7 +211,6 @@ where
|
|||||||
.retain(|group| !deleted_group_ids.contains(&group.id));
|
.retain(|group| !deleted_group_ids.contains(&group.id));
|
||||||
is_changed = true;
|
is_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for group_rev in &mut all_group_revs {
|
for group_rev in &mut all_group_revs {
|
||||||
match configuration
|
match configuration
|
||||||
.groups
|
.groups
|
||||||
@ -187,14 +218,20 @@ where
|
|||||||
.position(|old_group_rev| old_group_rev.id == group_rev.id)
|
.position(|old_group_rev| old_group_rev.id == group_rev.id)
|
||||||
{
|
{
|
||||||
None => {
|
None => {
|
||||||
|
// Push the group to the end of the list if it doesn't exist in the group
|
||||||
configuration.groups.push(group_rev.clone());
|
configuration.groups.push(group_rev.clone());
|
||||||
is_changed = true;
|
is_changed = true;
|
||||||
}
|
}
|
||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
let mut old_group = configuration.groups.remove(pos);
|
let mut old_group = configuration.groups.remove(pos);
|
||||||
group_rev.update_with_other(&old_group);
|
|
||||||
is_changed = is_group_changed(group_rev, &old_group);
|
|
||||||
|
|
||||||
|
// Take the old group setting
|
||||||
|
group_rev.update_with_other(&old_group);
|
||||||
|
if !is_changed {
|
||||||
|
is_changed = is_group_changed(group_rev, &old_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consider the the name of the `group_rev` as the newest.
|
||||||
old_group.name = group_rev.name.clone();
|
old_group.name = group_rev.name.clone();
|
||||||
configuration.groups.insert(pos, old_group);
|
configuration.groups.insert(pos, old_group);
|
||||||
}
|
}
|
||||||
@ -203,6 +240,7 @@ where
|
|||||||
is_changed
|
is_changed
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Update the memory cache of the groups
|
||||||
all_group_revs.into_iter().for_each(|group_rev| {
|
all_group_revs.into_iter().for_each(|group_rev| {
|
||||||
let filter_content = filter_content_map
|
let filter_content = filter_content_map
|
||||||
.get(&group_rev.id)
|
.get(&group_rev.id)
|
||||||
@ -257,24 +295,6 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
|
||||||
pub fn save_configuration(&self) -> FlowyResult<()> {
|
|
||||||
let configuration = (&*self.configuration).clone();
|
|
||||||
let writer = self.writer.clone();
|
|
||||||
let field_id = self.field_rev.id.clone();
|
|
||||||
let field_type = self.field_rev.ty;
|
|
||||||
tokio::spawn(async move {
|
|
||||||
match writer.save_configuration(&field_id, field_type, configuration).await {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!("Save group configuration failed: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mut_configuration(
|
fn mut_configuration(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut_configuration_fn: impl FnOnce(&mut GroupConfigurationRevision) -> bool,
|
mut_configuration_fn: impl FnOnce(&mut GroupConfigurationRevision) -> bool,
|
||||||
@ -282,7 +302,18 @@ where
|
|||||||
let configuration = Arc::make_mut(&mut self.configuration);
|
let configuration = Arc::make_mut(&mut self.configuration);
|
||||||
let is_changed = mut_configuration_fn(configuration);
|
let is_changed = mut_configuration_fn(configuration);
|
||||||
if is_changed {
|
if is_changed {
|
||||||
let _ = self.save_configuration()?;
|
let configuration = (&*self.configuration).clone();
|
||||||
|
let writer = self.writer.clone();
|
||||||
|
let field_id = self.field_rev.id.clone();
|
||||||
|
let field_type = self.field_rev.ty;
|
||||||
|
tokio::spawn(async move {
|
||||||
|
match writer.save_configuration(&field_id, field_type, configuration).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Save group configuration failed: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -302,13 +333,6 @@ where
|
|||||||
|
|
||||||
fn merge_groups(old_groups: Vec<GroupRevision>, new_groups: Vec<GroupRevision>) -> MergeGroupResult {
|
fn merge_groups(old_groups: Vec<GroupRevision>, new_groups: Vec<GroupRevision>) -> MergeGroupResult {
|
||||||
let mut merge_result = MergeGroupResult::new();
|
let mut merge_result = MergeGroupResult::new();
|
||||||
// if old_groups.is_empty() {
|
|
||||||
// merge_result.all_group_revs.extend(new_groups.clone());
|
|
||||||
// merge_result.all_group_revs.push(default_group);
|
|
||||||
// merge_result.new_group_revs = new_groups;
|
|
||||||
// return merge_result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// group_map is a helper map is used to filter out the new groups.
|
// group_map is a helper map is used to filter out the new groups.
|
||||||
let mut new_group_map: IndexMap<String, GroupRevision> = IndexMap::new();
|
let mut new_group_map: IndexMap<String, GroupRevision> = IndexMap::new();
|
||||||
new_groups.into_iter().for_each(|group_rev| {
|
new_groups.into_iter().for_each(|group_rev| {
|
||||||
|
@ -10,14 +10,20 @@ use flowy_grid_data_model::revision::{
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
// Each kind of group must implement this trait to provide custom group
|
/// The [GroupController] trait defines the group actions, including create/delete/move items
|
||||||
// operations. For example, insert cell data to the row_rev when creating
|
/// For example, the group will insert a item if the one of the new [RowRevision]'s [CellRevision]s
|
||||||
// a new row.
|
/// content match the group filter.
|
||||||
pub trait GroupController: GroupControllerSharedOperation + Send + Sync {
|
///
|
||||||
|
/// Different [FieldType] has a different controller that implements the [GroupController] trait.
|
||||||
|
/// If the [FieldType] doesn't implement its group controller, then the [DefaultGroupController] will
|
||||||
|
/// be used.
|
||||||
|
///
|
||||||
|
pub trait GroupController: GroupControllerActions + Send + Sync {
|
||||||
fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
|
fn will_create_row(&mut self, row_rev: &mut RowRevision, field_rev: &FieldRevision, group_id: &str);
|
||||||
fn did_create_row(&mut self, row_pb: &RowPB, group_id: &str);
|
fn did_create_row(&mut self, row_pb: &RowPB, group_id: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [GroupGenerator] trait is used to generate the groups for different [FieldType]
|
||||||
pub trait GroupGenerator {
|
pub trait GroupGenerator {
|
||||||
type Context;
|
type Context;
|
||||||
type TypeOptionType;
|
type TypeOptionType;
|
||||||
@ -26,10 +32,10 @@ pub trait GroupGenerator {
|
|||||||
field_id: &str,
|
field_id: &str,
|
||||||
group_ctx: &Self::Context,
|
group_ctx: &Self::Context,
|
||||||
type_option: &Option<Self::TypeOptionType>,
|
type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroup>;
|
) -> Vec<GeneratedGroupConfig>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GeneratedGroup {
|
pub struct GeneratedGroupConfig {
|
||||||
pub group_rev: GroupRevision,
|
pub group_rev: GroupRevision,
|
||||||
pub filter_content: String,
|
pub filter_content: String,
|
||||||
}
|
}
|
||||||
@ -42,29 +48,42 @@ pub struct MoveGroupRowContext<'a> {
|
|||||||
pub to_row_id: Option<String>,
|
pub to_row_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines the shared actions each group controller can perform.
|
/// Defines the shared actions each group controller can perform.
|
||||||
pub trait GroupControllerSharedOperation: Send + Sync {
|
pub trait GroupControllerActions: Send + Sync {
|
||||||
// The field that is used for grouping the rows
|
/// The field that is used for grouping the rows
|
||||||
fn field_id(&self) -> &str;
|
fn field_id(&self) -> &str;
|
||||||
|
|
||||||
|
/// Returns number of groups the current field has
|
||||||
fn groups(&self) -> Vec<Group>;
|
fn groups(&self) -> Vec<Group>;
|
||||||
|
|
||||||
|
/// Returns the index and the group data with group_id
|
||||||
fn get_group(&self, group_id: &str) -> Option<(usize, Group)>;
|
fn get_group(&self, group_id: &str) -> Option<(usize, Group)>;
|
||||||
|
|
||||||
|
/// Separates the rows into different groups
|
||||||
fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>;
|
fn fill_groups(&mut self, row_revs: &[Arc<RowRevision>], field_rev: &FieldRevision) -> FlowyResult<()>;
|
||||||
|
|
||||||
|
/// Remove the group with from_group_id and insert it to the index with to_group_id
|
||||||
fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()>;
|
fn move_group(&mut self, from_group_id: &str, to_group_id: &str) -> FlowyResult<()>;
|
||||||
fn did_update_row(
|
|
||||||
|
/// Insert the row to the group if the corresponding cell data is changed
|
||||||
|
fn did_update_group_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<Vec<GroupChangesetPB>>;
|
) -> FlowyResult<Vec<GroupChangesetPB>>;
|
||||||
|
|
||||||
fn did_delete_row(
|
/// Remove the row from the group if the corresponding cell data is changed
|
||||||
|
fn did_delete_delete_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
) -> FlowyResult<Vec<GroupChangesetPB>>;
|
) -> FlowyResult<Vec<GroupChangesetPB>>;
|
||||||
|
|
||||||
|
/// Move the row from one group to another group
|
||||||
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupChangesetPB>>;
|
fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult<Vec<GroupChangesetPB>>;
|
||||||
|
|
||||||
fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>>;
|
/// Update the group if the corresponding field is changed
|
||||||
|
fn did_update_group_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// C: represents the group configuration that impl [GroupConfigurationSerde]
|
/// C: represents the group configuration that impl [GroupConfigurationSerde]
|
||||||
@ -106,7 +125,7 @@ where
|
|||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
other_group_changesets: &[GroupChangesetPB],
|
other_group_changesets: &[GroupChangesetPB],
|
||||||
) -> Option<GroupChangesetPB> {
|
) -> Option<GroupChangesetPB> {
|
||||||
let default_group = self.group_ctx.get_mut_default_group()?;
|
let default_group = self.group_ctx.get_mut_no_status_group()?;
|
||||||
|
|
||||||
// [other_group_inserted_row] contains all the inserted rows except the default group.
|
// [other_group_inserted_row] contains all the inserted rows except the default group.
|
||||||
let other_group_inserted_row = other_group_changesets
|
let other_group_inserted_row = other_group_changesets
|
||||||
@ -167,7 +186,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, T, G, P> GroupControllerSharedOperation for GenericGroupController<C, T, G, P>
|
impl<C, T, G, P> GroupControllerActions for GenericGroupController<C, T, G, P>
|
||||||
where
|
where
|
||||||
P: CellBytesParser,
|
P: CellBytesParser,
|
||||||
C: GroupConfigurationContentSerde,
|
C: GroupConfigurationContentSerde,
|
||||||
@ -228,7 +247,7 @@ where
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.group_ctx.get_mut_default_group() {
|
match self.group_ctx.get_mut_no_status_group() {
|
||||||
None => {}
|
None => {}
|
||||||
Some(default_group) => default_group.add_row(row_rev.into()),
|
Some(default_group) => default_group.add_row(row_rev.into()),
|
||||||
}
|
}
|
||||||
@ -242,7 +261,7 @@ where
|
|||||||
self.group_ctx.move_group(from_group_id, to_group_id)
|
self.group_ctx.move_group(from_group_id, to_group_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_update_row(
|
fn did_update_group_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
@ -263,7 +282,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_delete_row(
|
fn did_delete_delete_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
row_rev: &RowRevision,
|
row_rev: &RowRevision,
|
||||||
field_rev: &FieldRevision,
|
field_rev: &FieldRevision,
|
||||||
@ -273,7 +292,7 @@ where
|
|||||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
|
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1;
|
||||||
let cell_data = cell_bytes.parser::<P>()?;
|
let cell_data = cell_bytes.parser::<P>()?;
|
||||||
Ok(self.remove_row_if_match(row_rev, &cell_data))
|
Ok(self.remove_row_if_match(row_rev, &cell_data))
|
||||||
} else if let Some(group) = self.group_ctx.get_default_group() {
|
} else if let Some(group) = self.group_ctx.get_no_status_group() {
|
||||||
Ok(vec![GroupChangesetPB::delete(
|
Ok(vec![GroupChangesetPB::delete(
|
||||||
group.id.clone(),
|
group.id.clone(),
|
||||||
vec![row_rev.id.clone()],
|
vec![row_rev.id.clone()],
|
||||||
@ -300,7 +319,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_update_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
fn did_update_group_field(&mut self, field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||||
let type_option = field_rev.get_type_option::<T>(field_rev.ty);
|
let type_option = field_rev.get_type_option::<T>(field_rev.ty);
|
||||||
let groups = G::generate_groups(&field_rev.id, &self.group_ctx, &type_option);
|
let groups = G::generate_groups(&field_rev.id, &self.group_ctx, &type_option);
|
||||||
let changeset = self.group_ctx.init_groups(groups)?;
|
let changeset = self.group_ctx.init_groups(groups)?;
|
||||||
|
@ -7,7 +7,7 @@ use crate::services::group::controller::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::services::cell::insert_checkbox_cell;
|
use crate::services::cell::insert_checkbox_cell;
|
||||||
use crate::services::group::{move_group_row, GeneratedGroup};
|
use crate::services::group::{move_group_row, GeneratedGroupConfig};
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision,
|
CellRevision, CheckboxGroupConfigurationRevision, FieldRevision, GroupRevision, RowRevision,
|
||||||
};
|
};
|
||||||
@ -116,13 +116,13 @@ impl GroupGenerator for CheckboxGroupGenerator {
|
|||||||
_field_id: &str,
|
_field_id: &str,
|
||||||
_group_ctx: &Self::Context,
|
_group_ctx: &Self::Context,
|
||||||
_type_option: &Option<Self::TypeOptionType>,
|
_type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroup> {
|
) -> Vec<GeneratedGroupConfig> {
|
||||||
let check_group = GeneratedGroup {
|
let check_group = GeneratedGroupConfig {
|
||||||
group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()),
|
group_rev: GroupRevision::new(CHECK.to_string(), "".to_string()),
|
||||||
filter_content: CHECK.to_string(),
|
filter_content: CHECK.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let uncheck_group = GeneratedGroup {
|
let uncheck_group = GeneratedGroupConfig {
|
||||||
group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()),
|
group_rev: GroupRevision::new(UNCHECK.to_string(), "".to_string()),
|
||||||
filter_content: UNCHECK.to_string(),
|
filter_content: UNCHECK.to_string(),
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
|
use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB};
|
||||||
use crate::services::group::{Group, GroupController, GroupControllerSharedOperation, MoveGroupRowContext};
|
use crate::services::group::{Group, GroupController, GroupControllerActions, MoveGroupRowContext};
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::FlowyResult;
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// means all rows will be grouped in the same group.
|
||||||
|
///
|
||||||
pub struct DefaultGroupController {
|
pub struct DefaultGroupController {
|
||||||
pub field_id: String,
|
pub field_id: String,
|
||||||
pub group: Group,
|
pub group: Group,
|
||||||
@ -26,7 +30,7 @@ impl DefaultGroupController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GroupControllerSharedOperation for DefaultGroupController {
|
impl GroupControllerActions for DefaultGroupController {
|
||||||
fn field_id(&self) -> &str {
|
fn field_id(&self) -> &str {
|
||||||
&self.field_id
|
&self.field_id
|
||||||
}
|
}
|
||||||
@ -50,7 +54,7 @@ impl GroupControllerSharedOperation for DefaultGroupController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_update_row(
|
fn did_update_group_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
_row_rev: &RowRevision,
|
_row_rev: &RowRevision,
|
||||||
_field_rev: &FieldRevision,
|
_field_rev: &FieldRevision,
|
||||||
@ -58,7 +62,7 @@ impl GroupControllerSharedOperation for DefaultGroupController {
|
|||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_delete_row(
|
fn did_delete_delete_row(
|
||||||
&mut self,
|
&mut self,
|
||||||
_row_rev: &RowRevision,
|
_row_rev: &RowRevision,
|
||||||
_field_rev: &FieldRevision,
|
_field_rev: &FieldRevision,
|
||||||
@ -70,7 +74,7 @@ impl GroupControllerSharedOperation for DefaultGroupController {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_update_field(&mut self, _field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
fn did_update_group_field(&mut self, _field_rev: &FieldRevision) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use crate::services::group::controller::{
|
|||||||
};
|
};
|
||||||
use crate::services::group::controller_impls::select_option_controller::util::*;
|
use crate::services::group::controller_impls::select_option_controller::util::*;
|
||||||
|
|
||||||
use crate::services::group::GeneratedGroup;
|
use crate::services::group::GeneratedGroupConfig;
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
|
|
||||||
// MultiSelect
|
// MultiSelect
|
||||||
@ -83,7 +83,7 @@ impl GroupGenerator for MultiSelectGroupGenerator {
|
|||||||
field_id: &str,
|
field_id: &str,
|
||||||
group_ctx: &Self::Context,
|
group_ctx: &Self::Context,
|
||||||
type_option: &Option<Self::TypeOptionType>,
|
type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroup> {
|
) -> Vec<GeneratedGroupConfig> {
|
||||||
match type_option {
|
match type_option {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),
|
Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),
|
||||||
|
@ -9,7 +9,7 @@ use crate::services::group::controller::{
|
|||||||
use crate::services::group::controller_impls::select_option_controller::util::*;
|
use crate::services::group::controller_impls::select_option_controller::util::*;
|
||||||
use crate::services::group::entities::Group;
|
use crate::services::group::entities::Group;
|
||||||
|
|
||||||
use crate::services::group::GeneratedGroup;
|
use crate::services::group::GeneratedGroupConfig;
|
||||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
use flowy_grid_data_model::revision::{FieldRevision, RowRevision, SelectOptionGroupConfigurationRevision};
|
||||||
|
|
||||||
// SingleSelect
|
// SingleSelect
|
||||||
@ -83,7 +83,7 @@ impl GroupGenerator for SingleSelectGroupGenerator {
|
|||||||
field_id: &str,
|
field_id: &str,
|
||||||
group_ctx: &Self::Context,
|
group_ctx: &Self::Context,
|
||||||
type_option: &Option<Self::TypeOptionType>,
|
type_option: &Option<Self::TypeOptionType>,
|
||||||
) -> Vec<GeneratedGroup> {
|
) -> Vec<GeneratedGroupConfig> {
|
||||||
match type_option {
|
match type_option {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),
|
Some(type_option) => generate_select_option_groups(field_id, group_ctx, &type_option.options),
|
||||||
|
@ -3,7 +3,7 @@ use crate::services::cell::{insert_checkbox_cell, insert_select_option_cell};
|
|||||||
use crate::services::field::{SelectOptionCellDataPB, SelectOptionPB, CHECK};
|
use crate::services::field::{SelectOptionCellDataPB, SelectOptionPB, CHECK};
|
||||||
use crate::services::group::configuration::GroupContext;
|
use crate::services::group::configuration::GroupContext;
|
||||||
use crate::services::group::controller::MoveGroupRowContext;
|
use crate::services::group::controller::MoveGroupRowContext;
|
||||||
use crate::services::group::{GeneratedGroup, Group};
|
use crate::services::group::{GeneratedGroupConfig, Group};
|
||||||
use flowy_grid_data_model::revision::{
|
use flowy_grid_data_model::revision::{
|
||||||
CellRevision, FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision,
|
CellRevision, FieldRevision, GroupRevision, RowRevision, SelectOptionGroupConfigurationRevision,
|
||||||
};
|
};
|
||||||
@ -155,10 +155,10 @@ pub fn generate_select_option_groups(
|
|||||||
_field_id: &str,
|
_field_id: &str,
|
||||||
_group_ctx: &SelectOptionGroupContext,
|
_group_ctx: &SelectOptionGroupContext,
|
||||||
options: &[SelectOptionPB],
|
options: &[SelectOptionPB],
|
||||||
) -> Vec<GeneratedGroup> {
|
) -> Vec<GeneratedGroupConfig> {
|
||||||
let groups = options
|
let groups = options
|
||||||
.iter()
|
.iter()
|
||||||
.map(|option| GeneratedGroup {
|
.map(|option| GeneratedGroupConfig {
|
||||||
group_rev: GroupRevision::new(option.id.clone(), option.name.clone()),
|
group_rev: GroupRevision::new(option.id.clone(), option.name.clone()),
|
||||||
filter_content: option.id.clone(),
|
filter_content: option.id.clone(),
|
||||||
})
|
})
|
||||||
|
@ -13,6 +13,17 @@ use flowy_grid_data_model::revision::{
|
|||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Returns a group controller.
|
||||||
|
///
|
||||||
|
/// Each view can be grouped by one field, each field has its own group controller.
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `view_id`: the id of the view
|
||||||
|
/// * `field_rev`: the grouping field
|
||||||
|
/// * `row_revs`: the rows will be separated into different groups
|
||||||
|
/// * `configuration_reader`: a reader used to read the group configuration from disk
|
||||||
|
/// * `configuration_writer`: as writer used to write the group configuration to disk
|
||||||
|
///
|
||||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||||
pub async fn make_group_controller<R, W>(
|
pub async fn make_group_controller<R, W>(
|
||||||
view_id: String,
|
view_id: String,
|
||||||
@ -58,6 +69,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Separates the rows into different groups
|
||||||
let _ = group_controller.fill_groups(&row_revs, &field_rev)?;
|
let _ = group_controller.fill_groups(&row_revs, &field_rev)?;
|
||||||
Ok(group_controller)
|
Ok(group_controller)
|
||||||
}
|
}
|
||||||
@ -75,6 +87,12 @@ pub fn find_group_field(field_revs: &[Arc<FieldRevision>], layout: &LayoutRevisi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a `default` group configuration for the [FieldRevision]
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `field_rev`: making the group configuration for the field
|
||||||
|
///
|
||||||
pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||||
let field_id = field_rev.id.clone();
|
let field_id = field_rev.id.clone();
|
||||||
let field_type_rev = field_rev.ty;
|
let field_type_rev = field_rev.ty;
|
||||||
@ -115,17 +133,17 @@ pub fn default_group_configuration(field_rev: &FieldRevision) -> GroupConfigurat
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Append the no `status` group
|
// Append the no `status` group
|
||||||
let default_group_rev = GroupRevision {
|
let no_status_group_rev = GroupRevision {
|
||||||
id: field_rev.id.clone(),
|
id: field_rev.id.clone(),
|
||||||
name: format!("No {}", field_rev.name),
|
name: format!("No {}", field_rev.name),
|
||||||
visible: true,
|
visible: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
group_configuration_rev.groups.push(default_group_rev);
|
group_configuration_rev.groups.push(no_status_group_rev);
|
||||||
group_configuration_rev
|
group_configuration_rev
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_default_group(field_rev: &FieldRevision) -> GroupRevision {
|
pub fn make_no_status_group(field_rev: &FieldRevision) -> GroupRevision {
|
||||||
GroupRevision {
|
GroupRevision {
|
||||||
id: field_rev.id.clone(),
|
id: field_rev.id.clone(),
|
||||||
name: format!("No {}", field_rev.name),
|
name: format!("No {}", field_rev.name),
|
||||||
|
@ -133,11 +133,20 @@ impl GridRevisionPad {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Modifies the current field type of the [FieldTypeRevision]
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `field_id`: the id of the field
|
||||||
|
/// * `field_type`: the new field type of the field
|
||||||
|
/// * `type_option_builder`: builder for creating the field type's type option data
|
||||||
|
///
|
||||||
|
///
|
||||||
pub fn switch_to_field<B, T>(
|
pub fn switch_to_field<B, T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
field_id: &str,
|
field_id: &str,
|
||||||
field_type: T,
|
field_type: T,
|
||||||
type_option_json_builder: B,
|
type_option_builder: B,
|
||||||
) -> CollaborateResult<Option<GridRevisionChangeset>>
|
) -> CollaborateResult<Option<GridRevisionChangeset>>
|
||||||
where
|
where
|
||||||
B: FnOnce(&FieldTypeRevision) -> String,
|
B: FnOnce(&FieldTypeRevision) -> String,
|
||||||
@ -153,8 +162,9 @@ impl GridRevisionPad {
|
|||||||
}
|
}
|
||||||
Some(field_rev) => {
|
Some(field_rev) => {
|
||||||
let mut_field_rev = Arc::make_mut(field_rev);
|
let mut_field_rev = Arc::make_mut(field_rev);
|
||||||
|
// If the type option data isn't exist before, creating the default type option data.
|
||||||
if mut_field_rev.get_type_option_str(field_type).is_none() {
|
if mut_field_rev.get_type_option_str(field_type).is_none() {
|
||||||
let type_option_json = type_option_json_builder(&field_type);
|
let type_option_json = type_option_builder(&field_type);
|
||||||
mut_field_rev.insert_type_option_str(&field_type, type_option_json);
|
mut_field_rev.insert_type_option_str(&field_type, type_option_json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user