feat: enable group condition (#5248)

* feat: enable group condition

* style: added i18n for date field group conditions

* fix: flutter analyze

* fix: test use i18n

* fix: more localization

---------

Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com>
Co-authored-by: Mathias Mogensen <mathias@appflowy.io>
This commit is contained in:
Mohammad Zolfaghari
2024-06-13 01:32:16 +03:30
committed by GitHub
parent f1a4deb459
commit 4f4be7eac7
16 changed files with 421 additions and 70 deletions

View File

@ -1,5 +1,10 @@
use crate::services::group::Group;
use crate::{
entities::FieldType,
services::group::{DateCondition, DateGroupConfiguration, Group},
};
use bytes::Bytes;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::FlowyResult;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct URLGroupConfigurationPB {
@ -46,16 +51,33 @@ pub struct NumberGroupConfigurationPB {
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct DateGroupConfigurationPB {
#[pb(index = 1)]
pub condition: DateCondition,
pub condition: DateConditionPB,
#[pb(index = 2)]
hide_empty: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
impl From<DateGroupConfigurationPB> for DateGroupConfiguration {
fn from(data: DateGroupConfigurationPB) -> Self {
Self {
condition: data.condition.into(),
hide_empty: data.hide_empty,
}
}
}
impl From<DateGroupConfiguration> for DateGroupConfigurationPB {
fn from(data: DateGroupConfiguration) -> Self {
Self {
condition: data.condition.into(),
hide_empty: data.hide_empty,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, Default)]
#[repr(u8)]
#[derive(Default)]
pub enum DateCondition {
pub enum DateConditionPB {
#[default]
Relative = 0,
Day = 1,
@ -64,8 +86,56 @@ pub enum DateCondition {
Year = 4,
}
impl From<DateConditionPB> for DateCondition {
fn from(data: DateConditionPB) -> Self {
match data {
DateConditionPB::Relative => DateCondition::Relative,
DateConditionPB::Day => DateCondition::Day,
DateConditionPB::Week => DateCondition::Week,
DateConditionPB::Month => DateCondition::Month,
DateConditionPB::Year => DateCondition::Year,
}
}
}
impl From<DateCondition> for DateConditionPB {
fn from(data: DateCondition) -> Self {
match data {
DateCondition::Relative => DateConditionPB::Relative,
DateCondition::Day => DateConditionPB::Day,
DateCondition::Week => DateConditionPB::Week,
DateCondition::Month => DateConditionPB::Month,
DateCondition::Year => DateConditionPB::Year,
}
}
}
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct CheckboxGroupConfigurationPB {
#[pb(index = 1)]
pub(crate) hide_empty: bool,
}
pub fn group_config_pb_to_json_str<T: Into<Bytes>>(
bytes: T,
field_type: &FieldType,
) -> FlowyResult<String> {
let bytes = bytes.into();
match field_type {
FieldType::DateTime => DateGroupConfigurationPB::try_from(bytes)
.map(|pb| DateGroupConfiguration::from(pb).to_json())?,
_ => Ok("".to_string()),
}
}
pub fn group_config_json_to_pb(setting_content: String, field_type: &FieldType) -> Bytes {
match field_type {
FieldType::DateTime => {
let date_group_config = DateGroupConfiguration::from_json(setting_content.as_ref()).unwrap();
DateGroupConfigurationPB::from(date_group_config)
.try_into()
.unwrap()
},
_ => Bytes::new(),
}
}

View File

@ -5,9 +5,11 @@ use flowy_error::ErrorCode;
use validator::Validate;
use crate::entities::parser::NotEmptyStr;
use crate::entities::RowMetaPB;
use crate::entities::{FieldType, RowMetaPB};
use crate::services::group::{GroupChangeset, GroupData, GroupSetting};
use super::group_config_json_to_pb;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GroupSettingPB {
#[pb(index = 1)]
@ -15,13 +17,18 @@ pub struct GroupSettingPB {
#[pb(index = 2)]
pub field_id: String,
#[pb(index = 3)]
pub content: Vec<u8>,
}
impl std::convert::From<&GroupSetting> for GroupSettingPB {
fn from(rev: &GroupSetting) -> Self {
let field_type = FieldType::from(rev.field_type);
GroupSettingPB {
id: rev.id.clone(),
field_id: rev.field_id.clone(),
content: group_config_json_to_pb(rev.content.clone(), &field_type).to_vec(),
}
}
}
@ -105,6 +112,9 @@ pub struct GroupByFieldPayloadPB {
#[pb(index = 2)]
pub view_id: String,
#[pb(index = 3)]
pub setting_content: Vec<u8>,
}
impl TryInto<GroupByFieldParams> for GroupByFieldPayloadPB {
@ -118,13 +128,18 @@ impl TryInto<GroupByFieldParams> for GroupByFieldPayloadPB {
.map_err(|_| ErrorCode::ViewIdIsInvalid)?
.0;
Ok(GroupByFieldParams { field_id, view_id })
Ok(GroupByFieldParams {
field_id,
view_id,
setting_content: self.setting_content,
})
}
}
pub struct GroupByFieldParams {
pub field_id: String,
pub view_id: String,
pub setting_content: Vec<u8>,
}
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone, Validate)]

View File

@ -656,7 +656,7 @@ pub(crate) async fn set_group_by_field_handler(
let params: GroupByFieldParams = data.into_inner().try_into()?;
let database_editor = manager.get_database_with_view_id(&params.view_id).await?;
database_editor
.set_group_by_field(&params.view_id, &params.field_id)
.set_group_by_field(&params.view_id, &params.field_id, params.setting_content)
.await?;
Ok(())
}

View File

@ -136,20 +136,37 @@ impl DatabaseEditor {
self.database.lock().fields.get_field(field_id)
}
pub async fn set_group_by_field(&self, view_id: &str, field_id: &str) -> FlowyResult<()> {
pub async fn set_group_by_field(
&self,
view_id: &str,
field_id: &str,
data: Vec<u8>,
) -> FlowyResult<()> {
let old_group_settings: Vec<GroupSetting>;
let mut setting_content = "".to_string();
{
let database = self.database.lock();
let field = database.fields.get_field(field_id);
old_group_settings = database.get_all_group_setting(view_id);
if let Some(field) = field {
let group_setting = default_group_setting(&field);
let field_type = FieldType::from(field.field_type);
setting_content = group_config_pb_to_json_str(data, &field_type)?;
let mut group_setting = default_group_setting(&field);
group_setting.content = setting_content.clone();
database.views.update_database_view(view_id, |view| {
view.set_groups(vec![group_setting.into()]);
});
}
}
let old_group_setting = old_group_settings.iter().find(|g| g.field_id == field_id);
let has_same_content =
old_group_setting.is_some() && old_group_setting.unwrap().content == setting_content;
let view_editor = self.database_views.get_view_editor(view_id).await?;
view_editor.v_initialize_new_group(field_id).await?;
if !view_editor.is_grouping_field(field_id).await || !has_same_content {
view_editor.v_initialize_new_group(field_id).await?;
}
Ok(())
}

View File

@ -401,15 +401,12 @@ impl DatabaseViewEditor {
/// Called when the user changes the grouping field
pub async fn v_initialize_new_group(&self, field_id: &str) -> FlowyResult<()> {
let is_grouping_field = self.is_grouping_field(field_id).await;
if !is_grouping_field {
self.v_group_by_field(field_id).await?;
if let Some(view) = self.delegate.get_view(&self.view_id).await {
let setting = database_view_setting_pb_from_view(view);
notify_did_update_setting(&self.view_id, setting).await;
}
if let Some(view) = self.delegate.get_view(&self.view_id).await {
let setting = database_view_setting_pb_from_view(view);
notify_did_update_setting(&self.view_id, setting).await;
}
self.v_group_by_field(field_id).await?;
Ok(())
}

View File

@ -6,7 +6,7 @@ use collab_database::rows::{new_cell_builder, Cell, Cells, Row, RowDetail};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use flowy_error::FlowyResult;
use flowy_error::{internal_error, FlowyResult};
use crate::entities::{
FieldType, GroupPB, GroupRowsNotificationPB, InsertedGroupPB, InsertedRowPB, RowMetaPB,
@ -27,13 +27,13 @@ pub struct DateGroupConfiguration {
}
impl DateGroupConfiguration {
fn from_json(s: &str) -> Result<Self, serde_json::Error> {
pub fn from_json(s: &str) -> Result<Self, serde_json::Error> {
serde_json::from_str(s)
}
#[allow(dead_code)]
fn to_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string(self)
pub fn to_json(&self) -> FlowyResult<String> {
serde_json::to_string(self).map_err(internal_error)
}
}