2022-08-24 16:57:53 +08:00
|
|
|
use crate::entities::{GroupPB, GroupViewChangesetPB, InsertedGroupPB};
|
2022-08-21 22:47:24 +08:00
|
|
|
use crate::services::group::{default_group_configuration, Group};
|
|
|
|
use flowy_error::{FlowyError, FlowyResult};
|
2022-08-20 15:40:13 +08:00
|
|
|
use flowy_grid_data_model::revision::{
|
2022-08-25 13:44:58 +08:00
|
|
|
FieldRevision, FieldTypeRevision, GroupConfigurationContentSerde, GroupConfigurationRevision, GroupRevision,
|
2022-08-20 15:40:13 +08:00
|
|
|
};
|
2022-08-21 13:56:06 +08:00
|
|
|
use indexmap::IndexMap;
|
2022-08-20 15:40:13 +08:00
|
|
|
use lib_infra::future::AFFuture;
|
2022-08-25 13:44:58 +08:00
|
|
|
use std::fmt::Formatter;
|
2022-08-24 16:57:53 +08:00
|
|
|
use std::marker::PhantomData;
|
2022-08-20 15:40:13 +08:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
pub trait GroupConfigurationReader: Send + Sync + 'static {
|
2022-08-21 22:47:24 +08:00
|
|
|
fn get_group_configuration(
|
|
|
|
&self,
|
|
|
|
field_rev: Arc<FieldRevision>,
|
|
|
|
) -> AFFuture<Option<Arc<GroupConfigurationRevision>>>;
|
2022-08-20 15:40:13 +08:00
|
|
|
}
|
|
|
|
|
2022-08-20 23:54:51 +08:00
|
|
|
pub trait GroupConfigurationWriter: Send + Sync + 'static {
|
2022-08-20 15:40:13 +08:00
|
|
|
fn save_group_configuration(
|
|
|
|
&self,
|
|
|
|
field_id: &str,
|
|
|
|
field_type: FieldTypeRevision,
|
2022-08-22 08:53:02 +08:00
|
|
|
group_configuration: GroupConfigurationRevision,
|
2022-08-20 15:40:13 +08:00
|
|
|
) -> AFFuture<FlowyResult<()>>;
|
|
|
|
}
|
|
|
|
|
2022-08-25 13:44:58 +08:00
|
|
|
impl<T> std::fmt::Display for GenericGroupConfiguration<T> {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
self.groups_map.iter().for_each(|(_, group)| {
|
|
|
|
let _ = f.write_fmt(format_args!("Group:{} has {} rows \n", group.id, group.rows.len()));
|
|
|
|
});
|
2022-08-30 15:21:53 +08:00
|
|
|
let _ = f.write_fmt(format_args!(
|
|
|
|
"Default group has {} rows \n",
|
|
|
|
self.default_group.rows.len()
|
|
|
|
));
|
2022-08-25 13:44:58 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-20 15:40:13 +08:00
|
|
|
pub struct GenericGroupConfiguration<C> {
|
2022-08-24 16:57:53 +08:00
|
|
|
view_id: String,
|
2022-08-22 08:53:02 +08:00
|
|
|
pub configuration: Arc<GroupConfigurationRevision>,
|
|
|
|
configuration_content: PhantomData<C>,
|
2022-08-20 15:40:13 +08:00
|
|
|
field_rev: Arc<FieldRevision>,
|
2022-08-21 13:56:06 +08:00
|
|
|
groups_map: IndexMap<String, Group>,
|
2022-08-30 15:21:53 +08:00
|
|
|
/// default_group is used to store the rows that don't belong to any groups.
|
|
|
|
default_group: Group,
|
2022-08-20 15:40:13 +08:00
|
|
|
writer: Arc<dyn GroupConfigurationWriter>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C> GenericGroupConfiguration<C>
|
|
|
|
where
|
2022-08-22 08:53:02 +08:00
|
|
|
C: GroupConfigurationContentSerde,
|
2022-08-20 15:40:13 +08:00
|
|
|
{
|
2022-08-22 08:53:02 +08:00
|
|
|
#[tracing::instrument(level = "trace", skip_all, err)]
|
2022-08-20 15:40:13 +08:00
|
|
|
pub async fn new(
|
2022-08-24 16:57:53 +08:00
|
|
|
view_id: String,
|
2022-08-20 15:40:13 +08:00
|
|
|
field_rev: Arc<FieldRevision>,
|
|
|
|
reader: Arc<dyn GroupConfigurationReader>,
|
|
|
|
writer: Arc<dyn GroupConfigurationWriter>,
|
|
|
|
) -> FlowyResult<Self> {
|
2022-08-30 15:21:53 +08:00
|
|
|
let default_group_id = format!("{}_default_group", view_id);
|
|
|
|
let default_group = Group {
|
|
|
|
id: default_group_id,
|
|
|
|
field_id: field_rev.id.clone(),
|
|
|
|
name: format!("No {}", field_rev.name),
|
|
|
|
is_default: true,
|
|
|
|
rows: vec![],
|
|
|
|
content: "".to_string(),
|
|
|
|
};
|
2022-08-22 08:53:02 +08:00
|
|
|
let configuration = match reader.get_group_configuration(field_rev.clone()).await {
|
2022-08-21 22:47:24 +08:00
|
|
|
None => {
|
|
|
|
let default_group_configuration = default_group_configuration(&field_rev);
|
|
|
|
writer
|
2022-08-22 08:53:02 +08:00
|
|
|
.save_group_configuration(&field_rev.id, field_rev.ty, default_group_configuration.clone())
|
2022-08-21 22:47:24 +08:00
|
|
|
.await?;
|
|
|
|
Arc::new(default_group_configuration)
|
|
|
|
}
|
|
|
|
Some(configuration) => configuration,
|
|
|
|
};
|
|
|
|
|
2022-08-22 08:53:02 +08:00
|
|
|
// let configuration = C::from_configuration_content(&configuration_rev.content)?;
|
2022-08-20 15:40:13 +08:00
|
|
|
Ok(Self {
|
2022-08-24 16:57:53 +08:00
|
|
|
view_id,
|
2022-08-20 15:40:13 +08:00
|
|
|
field_rev,
|
2022-08-21 13:56:06 +08:00
|
|
|
groups_map: IndexMap::new(),
|
2022-08-30 15:21:53 +08:00
|
|
|
default_group,
|
2022-08-20 15:40:13 +08:00
|
|
|
writer,
|
|
|
|
configuration,
|
2022-08-22 08:53:02 +08:00
|
|
|
configuration_content: PhantomData,
|
2022-08-20 15:40:13 +08:00
|
|
|
})
|
|
|
|
}
|
2022-08-20 16:44:44 +08:00
|
|
|
|
2022-08-21 13:56:06 +08:00
|
|
|
pub(crate) fn groups(&self) -> Vec<&Group> {
|
|
|
|
self.groups_map.values().collect()
|
2022-08-20 23:54:51 +08:00
|
|
|
}
|
2022-08-21 13:56:06 +08:00
|
|
|
|
|
|
|
pub(crate) fn clone_groups(&self) -> Vec<Group> {
|
2022-08-30 15:21:53 +08:00
|
|
|
let mut groups: Vec<Group> = self.groups_map.values().cloned().collect();
|
|
|
|
groups.push(self.default_group.clone());
|
|
|
|
groups
|
2022-08-21 13:56:06 +08:00
|
|
|
}
|
|
|
|
|
2022-08-24 16:57:53 +08:00
|
|
|
pub(crate) fn merge_groups(&mut self, groups: Vec<Group>) -> FlowyResult<Option<GroupViewChangesetPB>> {
|
|
|
|
let MergeGroupResult {
|
|
|
|
groups,
|
|
|
|
inserted_groups,
|
|
|
|
updated_groups,
|
|
|
|
} = merge_groups(&self.configuration.groups, groups);
|
|
|
|
|
|
|
|
let group_revs = groups
|
|
|
|
.iter()
|
2022-08-25 13:44:58 +08:00
|
|
|
.map(|group| GroupRevision::new(group.id.clone(), group.name.clone()))
|
|
|
|
.collect::<Vec<GroupRevision>>();
|
2022-08-24 16:57:53 +08:00
|
|
|
|
2022-08-22 08:53:02 +08:00
|
|
|
self.mut_configuration(move |configuration| {
|
2022-08-25 13:44:58 +08:00
|
|
|
let mut is_changed = false;
|
|
|
|
for new_group_rev in group_revs {
|
|
|
|
match configuration
|
|
|
|
.groups
|
|
|
|
.iter()
|
|
|
|
.position(|group_rev| group_rev.id == new_group_rev.id)
|
|
|
|
{
|
|
|
|
None => {
|
|
|
|
configuration.groups.push(new_group_rev);
|
|
|
|
is_changed = true;
|
|
|
|
}
|
|
|
|
Some(pos) => {
|
|
|
|
let removed_group = configuration.groups.remove(pos);
|
|
|
|
if removed_group != new_group_rev {
|
|
|
|
is_changed = true;
|
|
|
|
}
|
|
|
|
configuration.groups.insert(pos, new_group_rev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is_changed
|
2022-08-22 08:53:02 +08:00
|
|
|
})?;
|
2022-08-21 22:47:24 +08:00
|
|
|
|
2022-08-21 13:56:06 +08:00
|
|
|
groups.into_iter().for_each(|group| {
|
|
|
|
self.groups_map.insert(group.id.clone(), group);
|
|
|
|
});
|
2022-08-24 16:57:53 +08:00
|
|
|
|
|
|
|
let changeset = make_group_view_changeset(self.view_id.clone(), inserted_groups, updated_groups);
|
|
|
|
tracing::trace!("Group changeset: {:?}", changeset);
|
|
|
|
if changeset.is_empty() {
|
|
|
|
Ok(None)
|
|
|
|
} else {
|
|
|
|
Ok(Some(changeset))
|
|
|
|
}
|
2022-08-20 23:54:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub(crate) async fn hide_group(&mut self, group_id: &str) -> FlowyResult<()> {
|
2022-08-22 08:53:02 +08:00
|
|
|
self.mut_configuration_group(group_id, |group_rev| {
|
2022-08-20 23:54:51 +08:00
|
|
|
group_rev.visible = false;
|
2022-08-22 08:53:02 +08:00
|
|
|
})?;
|
2022-08-20 23:54:51 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub(crate) async fn show_group(&mut self, group_id: &str) -> FlowyResult<()> {
|
2022-08-22 08:53:02 +08:00
|
|
|
self.mut_configuration_group(group_id, |group_rev| {
|
2022-08-20 23:54:51 +08:00
|
|
|
group_rev.visible = true;
|
2022-08-22 08:53:02 +08:00
|
|
|
})?;
|
2022-08-20 23:54:51 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-08-24 16:57:53 +08:00
|
|
|
pub(crate) fn iter_mut_groups(&mut self, mut each: impl FnMut(&mut Group)) {
|
2022-08-21 13:56:06 +08:00
|
|
|
self.groups_map.iter_mut().for_each(|(_, group)| {
|
2022-08-22 16:16:15 +08:00
|
|
|
each(group);
|
2022-08-21 13:56:06 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn get_mut_group(&mut self, group_id: &str) -> Option<&mut Group> {
|
|
|
|
self.groups_map.get_mut(group_id)
|
|
|
|
}
|
|
|
|
|
2022-08-30 15:21:53 +08:00
|
|
|
pub(crate) fn get_mut_default_group(&mut self) -> &mut Group {
|
|
|
|
&mut self.default_group
|
|
|
|
}
|
|
|
|
|
2022-08-22 16:16:15 +08:00
|
|
|
pub(crate) fn move_group(&mut self, from_id: &str, to_id: &str) -> FlowyResult<()> {
|
|
|
|
let from_index = self.groups_map.get_index_of(from_id);
|
|
|
|
let to_index = self.groups_map.get_index_of(to_id);
|
|
|
|
match (from_index, to_index) {
|
2022-08-21 22:47:24 +08:00
|
|
|
(Some(from_index), Some(to_index)) => {
|
|
|
|
self.groups_map.swap_indices(from_index, to_index);
|
2022-08-22 08:53:02 +08:00
|
|
|
|
|
|
|
self.mut_configuration(|configuration| {
|
2022-08-25 13:44:58 +08:00
|
|
|
let from_index = configuration.groups.iter().position(|group| group.id == from_id);
|
|
|
|
let to_index = configuration.groups.iter().position(|group| group.id == to_id);
|
2022-08-22 08:53:02 +08:00
|
|
|
if let (Some(from), Some(to)) = (from_index, to_index) {
|
|
|
|
configuration.groups.swap(from, to);
|
|
|
|
}
|
|
|
|
true
|
|
|
|
})?;
|
2022-08-21 22:47:24 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
_ => Err(FlowyError::out_of_bounds()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the index and group specified by the group_id
|
|
|
|
pub(crate) fn get_group(&self, group_id: &str) -> Option<(usize, &Group)> {
|
|
|
|
match (self.groups_map.get_index_of(group_id), self.groups_map.get(group_id)) {
|
|
|
|
(Some(index), Some(group)) => Some((index, group)),
|
|
|
|
_ => None,
|
|
|
|
}
|
2022-08-21 13:56:06 +08:00
|
|
|
}
|
|
|
|
|
2022-08-22 08:53:02 +08:00
|
|
|
pub fn save_configuration(&self) -> FlowyResult<()> {
|
|
|
|
let configuration = (&*self.configuration).clone();
|
|
|
|
let writer = self.writer.clone();
|
|
|
|
let field_id = self.field_rev.id.clone();
|
2022-08-22 16:16:15 +08:00
|
|
|
let field_type = self.field_rev.ty;
|
2022-08-22 08:53:02 +08:00
|
|
|
tokio::spawn(async move {
|
|
|
|
match writer
|
|
|
|
.save_group_configuration(&field_id, field_type, configuration)
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
|
|
|
tracing::error!("Save group configuration failed: {}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-08-20 23:54:51 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
2022-08-20 15:40:13 +08:00
|
|
|
|
2022-08-22 08:53:02 +08:00
|
|
|
fn mut_configuration_group(
|
|
|
|
&mut self,
|
|
|
|
group_id: &str,
|
2022-08-25 13:44:58 +08:00
|
|
|
mut_groups_fn: impl Fn(&mut GroupRevision),
|
2022-08-22 08:53:02 +08:00
|
|
|
) -> FlowyResult<()> {
|
|
|
|
self.mut_configuration(|configuration| {
|
2022-08-25 13:44:58 +08:00
|
|
|
match configuration.groups.iter_mut().find(|group| group.id == group_id) {
|
2022-08-22 08:53:02 +08:00
|
|
|
None => false,
|
|
|
|
Some(group_rev) => {
|
|
|
|
mut_groups_fn(group_rev);
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn mut_configuration(
|
|
|
|
&mut self,
|
|
|
|
mut_configuration_fn: impl FnOnce(&mut GroupConfigurationRevision) -> bool,
|
|
|
|
) -> FlowyResult<()> {
|
|
|
|
let configuration = Arc::make_mut(&mut self.configuration);
|
|
|
|
let is_changed = mut_configuration_fn(configuration);
|
|
|
|
if is_changed {
|
|
|
|
let _ = self.save_configuration()?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2022-08-20 15:40:13 +08:00
|
|
|
|
2022-08-25 13:44:58 +08:00
|
|
|
fn merge_groups(old_groups: &[GroupRevision], groups: Vec<Group>) -> MergeGroupResult {
|
2022-08-24 16:57:53 +08:00
|
|
|
let mut merge_result = MergeGroupResult::new();
|
|
|
|
if old_groups.is_empty() {
|
|
|
|
merge_result.groups = groups;
|
|
|
|
return merge_result;
|
2022-08-20 15:40:13 +08:00
|
|
|
}
|
2022-08-20 23:54:51 +08:00
|
|
|
|
2022-08-24 16:57:53 +08:00
|
|
|
// group_map is a helper map is used to filter out the new groups.
|
2022-08-21 13:56:06 +08:00
|
|
|
let mut group_map: IndexMap<String, Group> = IndexMap::new();
|
|
|
|
groups.into_iter().for_each(|group| {
|
|
|
|
group_map.insert(group.id.clone(), group);
|
|
|
|
});
|
2022-08-20 23:54:51 +08:00
|
|
|
|
2022-08-24 16:57:53 +08:00
|
|
|
// The group is ordered in old groups. Add them before adding the new groups
|
|
|
|
for group_rev in old_groups {
|
2022-08-25 13:44:58 +08:00
|
|
|
if let Some(group) = group_map.remove(&group_rev.id) {
|
2022-08-24 16:57:53 +08:00
|
|
|
if group.name == group_rev.name {
|
|
|
|
merge_result.add_group(group);
|
|
|
|
} else {
|
|
|
|
merge_result.add_updated_group(group);
|
|
|
|
}
|
2022-08-21 13:56:06 +08:00
|
|
|
}
|
2022-08-20 23:54:51 +08:00
|
|
|
}
|
2022-08-21 13:56:06 +08:00
|
|
|
|
2022-08-24 16:57:53 +08:00
|
|
|
// Find out the new groups
|
2022-08-30 16:45:48 +08:00
|
|
|
let new_groups = group_map.into_values();
|
2022-08-24 16:57:53 +08:00
|
|
|
for (index, group) in new_groups.into_iter().enumerate() {
|
|
|
|
merge_result.add_insert_group(index, group);
|
|
|
|
}
|
|
|
|
merge_result
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MergeGroupResult {
|
|
|
|
groups: Vec<Group>,
|
|
|
|
inserted_groups: Vec<InsertedGroupPB>,
|
|
|
|
updated_groups: Vec<Group>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MergeGroupResult {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
groups: vec![],
|
|
|
|
inserted_groups: vec![],
|
|
|
|
updated_groups: vec![],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_updated_group(&mut self, group: Group) {
|
|
|
|
self.groups.push(group.clone());
|
|
|
|
self.updated_groups.push(group);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_group(&mut self, group: Group) {
|
2022-08-30 16:45:48 +08:00
|
|
|
self.groups.push(group);
|
2022-08-24 16:57:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn add_insert_group(&mut self, index: usize, group: Group) {
|
|
|
|
self.groups.push(group.clone());
|
|
|
|
let inserted_group = InsertedGroupPB {
|
|
|
|
group: GroupPB::from(group),
|
|
|
|
index: index as i32,
|
|
|
|
};
|
|
|
|
self.inserted_groups.push(inserted_group);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn make_group_view_changeset(
|
|
|
|
view_id: String,
|
|
|
|
inserted_groups: Vec<InsertedGroupPB>,
|
|
|
|
updated_group: Vec<Group>,
|
|
|
|
) -> GroupViewChangesetPB {
|
2022-08-30 16:45:48 +08:00
|
|
|
GroupViewChangesetPB {
|
2022-08-24 16:57:53 +08:00
|
|
|
view_id,
|
|
|
|
inserted_groups,
|
|
|
|
deleted_groups: vec![],
|
|
|
|
update_groups: updated_group.into_iter().map(GroupPB::from).collect(),
|
2022-08-30 16:45:48 +08:00
|
|
|
}
|
2022-08-20 15:40:13 +08:00
|
|
|
}
|