mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: read group data from backend
This commit is contained in:
parent
e29aaf8388
commit
5de6a7447a
@ -1,7 +0,0 @@
|
||||
use flowy_derive::ProtoBuf;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct CheckboxGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
pub(crate) hide_empty: bool,
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct UrlGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct TextGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct SelectOptionGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct NumberGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct DateGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
pub condition: DateCondition,
|
||||
|
||||
#[pb(index = 2)]
|
||||
hide_empty: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
|
||||
#[repr(u8)]
|
||||
pub enum DateCondition {
|
||||
Relative = 0,
|
||||
Day = 1,
|
||||
Week = 2,
|
||||
Month = 3,
|
||||
Year = 4,
|
||||
}
|
||||
|
||||
impl std::default::Default for DateCondition {
|
||||
fn default() -> Self {
|
||||
DateCondition::Relative
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct CheckboxGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
pub(crate) hide_empty: bool,
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct DateGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
pub condition: DateCondition,
|
||||
|
||||
#[pb(index = 2)]
|
||||
hide_empty: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum)]
|
||||
#[repr(u8)]
|
||||
pub enum DateCondition {
|
||||
Relative = 0,
|
||||
Day = 1,
|
||||
Week = 2,
|
||||
Month = 3,
|
||||
Year = 4,
|
||||
}
|
||||
|
||||
impl std::default::Default for DateCondition {
|
||||
fn default() -> Self {
|
||||
DateCondition::Relative
|
||||
}
|
||||
}
|
@ -1,15 +1,5 @@
|
||||
mod checkbox_group;
|
||||
mod date_group;
|
||||
mod configuration;
|
||||
mod group;
|
||||
mod number_group;
|
||||
mod select_option_group;
|
||||
mod text_group;
|
||||
mod url_group;
|
||||
|
||||
pub use checkbox_group::*;
|
||||
pub use date_group::*;
|
||||
pub use configuration::*;
|
||||
pub use group::*;
|
||||
pub use number_group::*;
|
||||
pub use select_option_group::*;
|
||||
pub use text_group::*;
|
||||
pub use url_group::*;
|
||||
|
@ -1,7 +0,0 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct NumberGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct SelectOptionGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct TextGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct UrlGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
hide_empty: bool,
|
||||
}
|
@ -114,6 +114,11 @@ impl AnyCellData {
|
||||
pub struct CellBytes(pub Bytes);
|
||||
|
||||
pub trait CellBytesParser {
|
||||
type Object;
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object>;
|
||||
}
|
||||
|
||||
pub trait CellBytesCustomParser {
|
||||
type Object;
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object>;
|
||||
}
|
||||
@ -132,11 +137,18 @@ impl CellBytes {
|
||||
Ok(Self(bytes))
|
||||
}
|
||||
|
||||
pub fn with_parser<P>(&self) -> FlowyResult<P::Object>
|
||||
pub fn parser<P>(&self) -> FlowyResult<P::Object>
|
||||
where
|
||||
P: CellBytesParser,
|
||||
{
|
||||
P::parse(&self.0)
|
||||
P::parser(&self.0)
|
||||
}
|
||||
|
||||
pub fn custom_parser<P>(&self, parser: P) -> FlowyResult<P::Object>
|
||||
where
|
||||
P: CellBytesCustomParser,
|
||||
{
|
||||
parser.parse(&self.0)
|
||||
}
|
||||
|
||||
// pub fn parse<'a, T: TryFrom<&'a [u8]>>(&'a self) -> FlowyResult<T>
|
||||
|
@ -60,7 +60,7 @@ impl ToString for CheckboxCellData {
|
||||
pub struct CheckboxCellDataParser();
|
||||
impl CellBytesParser for CheckboxCellDataParser {
|
||||
type Object = CheckboxCellData;
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
match String::from_utf8(bytes.to_vec()) {
|
||||
Ok(s) => CheckboxCellData::from_str(&s),
|
||||
Err(_) => Ok(CheckboxCellData("".to_string())),
|
||||
|
@ -3,7 +3,7 @@ mod tests {
|
||||
use crate::entities::FieldType;
|
||||
use crate::services::cell::CellDataOperation;
|
||||
use crate::services::field::*;
|
||||
// use crate::services::field::{DateCellChangeset, DateCellData, DateFormat, DateTypeOption, TimeFormat};
|
||||
// use crate::services::field::{DateCellChangeset, DateCellData, DateFormat, DateTypeOptionPB, TimeFormat};
|
||||
use flowy_grid_data_model::revision::FieldRevision;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@ -137,7 +137,7 @@ mod tests {
|
||||
let decoded_data = type_option
|
||||
.decode_cell_data(encoded_data.into(), &FieldType::DateTime, field_rev)
|
||||
.unwrap()
|
||||
.with_parser(DateCellDataParser())
|
||||
.parser::<DateCellDataParser>()
|
||||
.unwrap();
|
||||
|
||||
if type_option.include_time {
|
||||
|
@ -204,7 +204,7 @@ pub struct DateCellDataParser();
|
||||
impl CellBytesParser for DateCellDataParser {
|
||||
type Object = DateCellDataPB;
|
||||
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
DateCellDataPB::try_from(bytes.as_ref()).map_err(internal_error)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::services::cell::CellBytesParser;
|
||||
use crate::services::cell::{CellBytesCustomParser, CellBytesParser};
|
||||
use crate::services::field::number_currency::Currency;
|
||||
use crate::services::field::{strip_currency_symbol, NumberFormat, STRIP_SYMBOL};
|
||||
use bytes::Bytes;
|
||||
@ -93,8 +93,19 @@ impl ToString for NumberCellData {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct NumberCellDataParser(pub NumberFormat);
|
||||
pub struct NumberCellDataParser();
|
||||
impl CellBytesParser for NumberCellDataParser {
|
||||
type Object = NumberCellData;
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
match String::from_utf8(bytes.to_vec()) {
|
||||
Ok(s) => NumberCellData::from_format_str(&s, true, &NumberFormat::Num),
|
||||
Err(_) => Ok(NumberCellData::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NumberCellCustomDataParser(pub NumberFormat);
|
||||
impl CellBytesCustomParser for NumberCellCustomDataParser {
|
||||
type Object = NumberCellData;
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
match String::from_utf8(bytes.to_vec()) {
|
||||
|
@ -180,7 +180,7 @@ mod tests {
|
||||
type_option
|
||||
.decode_cell_data(cell_data.into(), &field_type, field_rev)
|
||||
.unwrap()
|
||||
.with_parser(SelectOptionCellDataParser())
|
||||
.parser::<SelectOptionCellDataParser>()
|
||||
.unwrap()
|
||||
.select_options,
|
||||
);
|
||||
|
@ -206,7 +206,7 @@ impl std::ops::DerefMut for SelectOptionIds {
|
||||
pub struct SelectOptionIdsParser();
|
||||
impl CellBytesParser for SelectOptionIdsParser {
|
||||
type Object = SelectOptionIds;
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
match String::from_utf8(bytes.to_vec()) {
|
||||
Ok(s) => Ok(SelectOptionIds::from(s)),
|
||||
Err(_) => Ok(SelectOptionIds::from("".to_owned())),
|
||||
@ -218,7 +218,7 @@ pub struct SelectOptionCellDataParser();
|
||||
impl CellBytesParser for SelectOptionCellDataParser {
|
||||
type Object = SelectOptionCellDataPB;
|
||||
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
SelectOptionCellDataPB::try_from(bytes.as_ref()).map_err(internal_error)
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ mod tests {
|
||||
type_option
|
||||
.decode_cell_data(cell_data.into(), &field_type, field_rev)
|
||||
.unwrap()
|
||||
.with_parser(SelectOptionCellDataParser())
|
||||
.parser::<SelectOptionCellDataParser>()
|
||||
.unwrap()
|
||||
.select_options,
|
||||
);
|
||||
|
@ -96,7 +96,7 @@ impl FromCellString for TextCellData {
|
||||
pub struct TextCellDataParser();
|
||||
impl CellBytesParser for TextCellDataParser {
|
||||
type Object = TextCellData;
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
match String::from_utf8(bytes.to_vec()) {
|
||||
Ok(s) => Ok(TextCellData(s)),
|
||||
Err(_) => Ok(TextCellData("".to_owned())),
|
||||
@ -124,7 +124,7 @@ mod tests {
|
||||
type_option
|
||||
.decode_cell_data(1647251762.to_string().into(), &field_type, &date_time_field_rev)
|
||||
.unwrap()
|
||||
.with_parser(DateCellDataParser())
|
||||
.parser::<DateCellDataParser>()
|
||||
.unwrap()
|
||||
.date,
|
||||
"Mar 14,2022".to_owned()
|
||||
@ -144,7 +144,7 @@ mod tests {
|
||||
&single_select_field_rev
|
||||
)
|
||||
.unwrap()
|
||||
.with_parser(SelectOptionCellDataParser())
|
||||
.parser::<SelectOptionCellDataParser>()
|
||||
.unwrap()
|
||||
.select_options,
|
||||
vec![done_option],
|
||||
@ -167,7 +167,7 @@ mod tests {
|
||||
type_option
|
||||
.decode_cell_data(cell_data.into(), &FieldType::MultiSelect, &multi_select_field_rev)
|
||||
.unwrap()
|
||||
.with_parser(SelectOptionCellDataParser())
|
||||
.parser::<SelectOptionCellDataParser>()
|
||||
.unwrap()
|
||||
.select_options,
|
||||
vec![google_option, facebook_option]
|
||||
|
@ -184,7 +184,7 @@ mod tests {
|
||||
type_option
|
||||
.decode_cell_data(encoded_data.into(), field_type, field_rev)
|
||||
.unwrap()
|
||||
.with_parser(URLCellDataParser())
|
||||
.parser::<URLCellDataParser>()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub struct URLCellDataParser();
|
||||
impl CellBytesParser for URLCellDataParser {
|
||||
type Object = URLCellDataPB;
|
||||
|
||||
fn parse(&self, bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
fn parser(bytes: &Bytes) -> FlowyResult<Self::Object> {
|
||||
URLCellDataPB::try_from(bytes.as_ref()).map_err(internal_error)
|
||||
}
|
||||
}
|
||||
|
@ -564,8 +564,9 @@ impl GridRevisionEditor {
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub async fn load_groups(&self) -> FlowyResult<RepeatedGridGroupPB> {
|
||||
let groups = self.group_service.load_groups().await.unwrap_or(vec![]);
|
||||
let groups = self.group_service.load_groups().await.unwrap_or_default();
|
||||
Ok(RepeatedGridGroupPB { items: groups })
|
||||
}
|
||||
|
||||
|
@ -1,70 +0,0 @@
|
||||
use crate::entities::{
|
||||
CheckboxGroupConfigurationPB, DateGroupConfigurationPB, NumberGroupConfigurationPB,
|
||||
SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB,
|
||||
};
|
||||
use crate::services::cell::CellBytes;
|
||||
use crate::services::field::{
|
||||
CheckboxCellDataParser, DateCellDataParser, NumberCellDataParser, NumberFormat, SelectOptionCellDataParser,
|
||||
TextCellDataParser, URLCellDataParser,
|
||||
};
|
||||
use crate::services::group::GroupAction;
|
||||
|
||||
// impl GroupAction for TextGroupConfigurationPB {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// if let Ok(cell_data) = cell_bytes.with_parser(TextCellDataParser()) {
|
||||
// cell_data.as_ref() == content
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl GroupAction for NumberGroupConfigurationPB {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// if let Ok(cell_data) = cell_bytes.with_parser(NumberCellDataParser(NumberFormat::Num)) {
|
||||
// false
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl GroupAction for DateGroupConfigurationPB {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// if let Ok(cell_data) = cell_bytes.with_parser(DateCellDataParser()) {
|
||||
// false
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl GroupAction for SelectOptionGroupConfigurationPB {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// if let Ok(cell_data) = cell_bytes.with_parser(SelectOptionCellDataParser()) {
|
||||
// false
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl GroupAction for UrlGroupConfigurationPB {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// if let Ok(cell_data) = cell_bytes.with_parser(URLCellDataParser()) {
|
||||
// false
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl GroupAction for CheckboxGroupConfigurationPB {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// if let Ok(cell_data) = cell_bytes.with_parser(CheckboxCellDataParser()) {
|
||||
// false
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
@ -1,7 +1,43 @@
|
||||
use crate::entities::CheckboxGroupConfigurationPB;
|
||||
use crate::services::cell::{AnyCellData, CellData, CellGroupOperation};
|
||||
use crate::services::field::{CheckboxCellData, CheckboxTypeOptionPB};
|
||||
use crate::services::group::GroupController;
|
||||
use flowy_error::FlowyResult;
|
||||
|
||||
// pub type CheckboxGroupGenerator = GroupGenerator<CheckboxGroupConfigurationPB, CheckboxTypeOptionPB>;
|
||||
use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK};
|
||||
use crate::services::group::{Group, GroupAction, GroupCellContentProvider, GroupController, GroupGenerator};
|
||||
|
||||
pub type CheckboxGroupController =
|
||||
GroupController<CheckboxGroupConfigurationPB, CheckboxTypeOptionPB, CheckboxGroupGenerator, CheckboxCellDataParser>;
|
||||
|
||||
pub struct CheckboxGroupGenerator();
|
||||
impl GroupGenerator for CheckboxGroupGenerator {
|
||||
type ConfigurationType = CheckboxGroupConfigurationPB;
|
||||
type TypeOptionType = CheckboxTypeOptionPB;
|
||||
|
||||
fn gen_groups(
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
_type_option: &Option<Self::TypeOptionType>,
|
||||
_cell_content_provider: &dyn GroupCellContentProvider,
|
||||
) -> Vec<Group> {
|
||||
let check_group = Group {
|
||||
id: "true".to_string(),
|
||||
desc: "".to_string(),
|
||||
rows: vec![],
|
||||
content: CHECK.to_string(),
|
||||
};
|
||||
|
||||
let uncheck_group = Group {
|
||||
id: "false".to_string(),
|
||||
desc: "".to_string(),
|
||||
rows: vec![],
|
||||
content: UNCHECK.to_string(),
|
||||
};
|
||||
|
||||
vec![check_group, uncheck_group]
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupAction for CheckboxGroupController {
|
||||
type CellDataType = CheckboxCellData;
|
||||
|
||||
fn should_group(&self, _content: &str, _cell_data: &Self::CellDataType) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
use crate::entities::CheckboxGroupConfigurationPB;
|
||||
use crate::services::field::DateTypeOptionPB;
|
||||
use crate::services::group::GroupController;
|
||||
|
||||
// pub type CheckboxGroupGenerator = GroupGenerator<CheckboxGroupConfigurationPB, DateTypeOptionPB>;
|
@ -1,52 +1,70 @@
|
||||
use crate::services::cell::{decode_any_cell_data, CellBytes, CellBytesParser};
|
||||
use crate::entities::{GroupPB, RowPB};
|
||||
use crate::services::cell::{decode_any_cell_data, CellBytesParser};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{
|
||||
CellRevision, FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer,
|
||||
FieldRevision, GroupConfigurationRevision, RowRevision, TypeOptionDataDeserializer,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use indexmap::IndexMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait GroupAction<CD> {
|
||||
fn should_group(&self, content: &str, cell_data: CD) -> bool;
|
||||
pub trait GroupAction {
|
||||
type CellDataType;
|
||||
|
||||
fn should_group(&self, content: &str, cell_data: &Self::CellDataType) -> bool;
|
||||
}
|
||||
|
||||
pub trait GroupCellContentProvider {
|
||||
/// We need to group the rows base on the deduplication cell content when the field type is
|
||||
/// RichText.
|
||||
fn deduplication_cell_content(&self, field_id: &str) -> Vec<String> {
|
||||
fn deduplication_cell_content(&self, _field_id: &str) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GroupGenerator<C, T> {
|
||||
pub trait GroupGenerator {
|
||||
type ConfigurationType;
|
||||
type TypeOptionType;
|
||||
|
||||
fn gen_groups(
|
||||
configuration: &Option<C>,
|
||||
type_option: &Option<T>,
|
||||
configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
cell_content_provider: &dyn GroupCellContentProvider,
|
||||
) -> HashMap<String, Group>;
|
||||
) -> Vec<Group>;
|
||||
}
|
||||
|
||||
pub struct GroupController<C, T, G, CP> {
|
||||
field_rev: Arc<FieldRevision>,
|
||||
groups: HashMap<String, Group>,
|
||||
type_option: Option<T>,
|
||||
configuration: Option<C>,
|
||||
pub field_rev: Arc<FieldRevision>,
|
||||
pub groups: IndexMap<String, Group>,
|
||||
pub type_option: Option<T>,
|
||||
pub configuration: Option<C>,
|
||||
group_action_phantom: PhantomData<G>,
|
||||
cell_parser_phantom: PhantomData<CP>,
|
||||
}
|
||||
|
||||
pub struct Group {
|
||||
row_ids: Vec<String>,
|
||||
content: String,
|
||||
pub id: String,
|
||||
pub desc: String,
|
||||
pub rows: Vec<RowPB>,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl std::convert::From<Group> for GroupPB {
|
||||
fn from(group: Group) -> Self {
|
||||
Self {
|
||||
group_id: group.id,
|
||||
desc: group.desc,
|
||||
rows: group.rows,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, T, G, CP> GroupController<C, T, G, CP>
|
||||
where
|
||||
C: TryFrom<Bytes, Error = protobuf::ProtobufError>,
|
||||
T: TypeOptionDataDeserializer,
|
||||
G: GroupGenerator<C, T>,
|
||||
G: GroupGenerator<ConfigurationType = C, TypeOptionType = T>,
|
||||
{
|
||||
pub fn new(
|
||||
field_rev: Arc<FieldRevision>,
|
||||
@ -57,46 +75,63 @@ where
|
||||
None => None,
|
||||
Some(content) => Some(C::try_from(Bytes::from(content))?),
|
||||
};
|
||||
let field_type_rev = field_rev.field_type_rev.clone();
|
||||
let field_type_rev = field_rev.field_type_rev;
|
||||
let type_option = field_rev.get_type_option_entry::<T>(field_type_rev);
|
||||
let groups = G::gen_groups(&configuration, &type_option, cell_content_provider);
|
||||
Ok(Self {
|
||||
field_rev,
|
||||
groups: G::gen_groups(&configuration, &type_option, cell_content_provider),
|
||||
groups: groups.into_iter().map(|group| (group.id.clone(), group)).collect(),
|
||||
type_option,
|
||||
configuration,
|
||||
group_action_phantom: PhantomData,
|
||||
cell_parser_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn take_groups(self) -> Vec<Group> {
|
||||
self.groups.into_values().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, T, G, CP> GroupController<C, T, G, CP>
|
||||
where
|
||||
CP: CellBytesParser,
|
||||
Self: GroupAction<CP::Object>,
|
||||
Self: GroupAction<CellDataType = CP::Object>,
|
||||
{
|
||||
pub fn group_row(&mut self, row: &RowRevision) {
|
||||
pub fn group_rows(&mut self, rows: &[Arc<RowRevision>]) -> FlowyResult<()> {
|
||||
if self.configuration.is_none() {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(cell_rev) = row.cells.get(&self.field_rev.id) {
|
||||
let mut group_row_id = None;
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &self.field_rev);
|
||||
// let cell_data = cell_bytes.with_parser(CP);
|
||||
for group in self.groups.values() {
|
||||
let cell_rev: CellRevision = cell_rev.clone();
|
||||
|
||||
// if self.should_group(&group.content, cell_bytes) {
|
||||
// group_row_id = Some(row.id.clone());
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
for row in rows {
|
||||
if let Some(cell_rev) = row.cells.get(&self.field_rev.id) {
|
||||
let mut records: Vec<GroupRecord> = vec![];
|
||||
|
||||
if let Some(group_row_id) = group_row_id {
|
||||
self.groups.get_mut(&group_row_id).map(|group| {
|
||||
group.row_ids.push(group_row_id);
|
||||
});
|
||||
let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), &self.field_rev);
|
||||
let cell_data = cell_bytes.parser::<CP>()?;
|
||||
for group in self.groups.values() {
|
||||
if self.should_group(&group.content, &cell_data) {
|
||||
records.push(GroupRecord {
|
||||
row: row.into(),
|
||||
group_id: group.id.clone(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for record in records {
|
||||
if let Some(group) = self.groups.get_mut(&record.group_id) {
|
||||
group.rows.push(record.row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct GroupRecord {
|
||||
row: RowPB,
|
||||
group_id: String,
|
||||
}
|
||||
|
@ -1,15 +1,7 @@
|
||||
mod checkbox_group;
|
||||
mod date_group;
|
||||
mod generator;
|
||||
mod number_group;
|
||||
mod select_option_group;
|
||||
mod text_group;
|
||||
mod url_group;
|
||||
|
||||
pub use checkbox_group::*;
|
||||
pub use date_group::*;
|
||||
pub use generator::*;
|
||||
pub use number_group::*;
|
||||
pub use select_option_group::*;
|
||||
pub use text_group::*;
|
||||
pub use url_group::*;
|
||||
|
@ -1,5 +0,0 @@
|
||||
use crate::entities::NumberGroupConfigurationPB;
|
||||
use crate::services::field::NumberTypeOptionPB;
|
||||
use crate::services::group::GroupController;
|
||||
|
||||
// pub type NumberGroupGenerator = GroupGenerator<NumberGroupConfigurationPB, NumberTypeOptionPB>;
|
@ -1,12 +1,11 @@
|
||||
use crate::entities::SelectOptionGroupConfigurationPB;
|
||||
use crate::services::cell::CellBytes;
|
||||
|
||||
use crate::services::field::{
|
||||
MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SelectedSelectOptions,
|
||||
SingleSelectTypeOptionPB,
|
||||
MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB,
|
||||
};
|
||||
use crate::services::group::{Group, GroupAction, GroupCellContentProvider, GroupController, GroupGenerator};
|
||||
use std::collections::HashMap;
|
||||
|
||||
// SingleSelect
|
||||
pub type SingleSelectGroupController = GroupController<
|
||||
SelectOptionGroupConfigurationPB,
|
||||
SingleSelectTypeOptionPB,
|
||||
@ -15,38 +14,74 @@ pub type SingleSelectGroupController = GroupController<
|
||||
>;
|
||||
|
||||
pub struct SingleSelectGroupGenerator();
|
||||
impl GroupGenerator<SelectOptionGroupConfigurationPB, SingleSelectTypeOptionPB> for SingleSelectGroupGenerator {
|
||||
impl GroupGenerator for SingleSelectGroupGenerator {
|
||||
type ConfigurationType = SelectOptionGroupConfigurationPB;
|
||||
type TypeOptionType = SingleSelectTypeOptionPB;
|
||||
fn gen_groups(
|
||||
configuration: &Option<SelectOptionGroupConfigurationPB>,
|
||||
type_option: &Option<SingleSelectTypeOptionPB>,
|
||||
cell_content_provider: &dyn GroupCellContentProvider,
|
||||
) -> HashMap<String, Group> {
|
||||
todo!()
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
_cell_content_provider: &dyn GroupCellContentProvider,
|
||||
) -> Vec<Group> {
|
||||
match type_option {
|
||||
None => vec![],
|
||||
Some(type_option) => type_option
|
||||
.options
|
||||
.iter()
|
||||
.map(|option| Group {
|
||||
id: option.id.clone(),
|
||||
desc: option.name.clone(),
|
||||
rows: vec![],
|
||||
content: option.id.clone(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupAction<SelectOptionCellDataPB> for SingleSelectGroupController {
|
||||
fn should_group(&self, content: &str, cell_data: SelectOptionCellDataPB) -> bool {
|
||||
todo!()
|
||||
impl GroupAction for SingleSelectGroupController {
|
||||
type CellDataType = SelectOptionCellDataPB;
|
||||
fn should_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||
cell_data.select_options.iter().any(|option| option.id == content)
|
||||
}
|
||||
}
|
||||
|
||||
// pub type MultiSelectGroupController =
|
||||
// GroupController<SelectOptionGroupConfigurationPB, MultiSelectTypeOptionPB, MultiSelectGroupGenerator>;
|
||||
//
|
||||
// pub struct MultiSelectGroupGenerator();
|
||||
// impl GroupGenerator<SelectOptionGroupConfigurationPB, MultiSelectTypeOptionPB> for MultiSelectGroupGenerator {
|
||||
// fn gen_groups(
|
||||
// configuration: &Option<SelectOptionGroupConfigurationPB>,
|
||||
// type_option: &Option<MultiSelectTypeOptionPB>,
|
||||
// cell_content_provider: &dyn GroupCellContentProvider,
|
||||
// ) -> HashMap<String, Group> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl GroupAction for MultiSelectGroupController {
|
||||
// fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
// MultiSelect
|
||||
pub type MultiSelectGroupController = GroupController<
|
||||
SelectOptionGroupConfigurationPB,
|
||||
MultiSelectTypeOptionPB,
|
||||
MultiSelectGroupGenerator,
|
||||
SelectOptionCellDataParser,
|
||||
>;
|
||||
|
||||
pub struct MultiSelectGroupGenerator();
|
||||
impl GroupGenerator for MultiSelectGroupGenerator {
|
||||
type ConfigurationType = SelectOptionGroupConfigurationPB;
|
||||
type TypeOptionType = MultiSelectTypeOptionPB;
|
||||
|
||||
fn gen_groups(
|
||||
_configuration: &Option<Self::ConfigurationType>,
|
||||
type_option: &Option<Self::TypeOptionType>,
|
||||
_cell_content_provider: &dyn GroupCellContentProvider,
|
||||
) -> Vec<Group> {
|
||||
match type_option {
|
||||
None => vec![],
|
||||
Some(type_option) => type_option
|
||||
.options
|
||||
.iter()
|
||||
.map(|option| Group {
|
||||
id: option.id.clone(),
|
||||
desc: option.name.clone(),
|
||||
rows: vec![],
|
||||
content: option.id.clone(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupAction for MultiSelectGroupController {
|
||||
type CellDataType = SelectOptionCellDataPB;
|
||||
fn should_group(&self, content: &str, cell_data: &SelectOptionCellDataPB) -> bool {
|
||||
cell_data.select_options.iter().any(|option| option.id == content)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
use crate::entities::TextGroupConfigurationPB;
|
||||
use crate::services::field::RichTextTypeOptionPB;
|
||||
use crate::services::group::GroupController;
|
||||
|
||||
// pub type TextGroupGenerator = GroupGenerator<TextGroupConfigurationPB, RichTextTypeOptionPB>;
|
@ -1,5 +0,0 @@
|
||||
use crate::entities::UrlGroupConfigurationPB;
|
||||
use crate::services::field::URLTypeOptionPB;
|
||||
use crate::services::group::GroupController;
|
||||
|
||||
// pub type UrlGroupGenerator = GroupGenerator<UrlGroupConfigurationPB, URLTypeOptionPB>;
|
@ -1,15 +1,16 @@
|
||||
use crate::services::block_manager::GridBlockManager;
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use crate::services::group::{
|
||||
CheckboxGroupController, Group, GroupCellContentProvider, MultiSelectGroupController, SingleSelectGroupController,
|
||||
};
|
||||
|
||||
use crate::entities::{
|
||||
CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupPB, NumberGroupConfigurationPB,
|
||||
SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB,
|
||||
};
|
||||
use crate::services::block_manager::GridBlockManager;
|
||||
use crate::services::cell::{decode_any_cell_data, CellBytes};
|
||||
use crate::services::field::TextCellDataParser;
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use crate::services::group::{GroupAction, GroupCellContentProvider, SingleSelectGroupController};
|
||||
use bytes::Bytes;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, GroupConfigurationRevision, RowRevision};
|
||||
use flowy_grid_data_model::revision::{gen_grid_group_id, FieldRevision, GroupConfigurationRevision, RowRevision};
|
||||
use flowy_sync::client_grid::GridRevisionPad;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
@ -39,53 +40,102 @@ impl GridGroupService {
|
||||
|
||||
pub(crate) async fn load_groups(&self) -> Option<Vec<GroupPB>> {
|
||||
let grid_pad = self.grid_pad.read().await;
|
||||
let field_rev = find_group_field(grid_pad.fields())?;
|
||||
let field_type: FieldType = field_rev.field_type_rev.clone().into();
|
||||
let setting = grid_pad.get_setting_rev();
|
||||
let mut configurations = setting.get_groups(&setting.layout, &field_rev.id, &field_rev.field_type_rev)?;
|
||||
|
||||
if configurations.is_empty() {
|
||||
return None;
|
||||
}
|
||||
assert_eq!(configurations.len(), 1);
|
||||
let configuration = (&*configurations.pop().unwrap()).clone();
|
||||
let field_rev = find_group_field(grid_pad.fields()).unwrap();
|
||||
let field_type: FieldType = field_rev.field_type_rev.into();
|
||||
let configuration = self.get_group_configuration(field_rev).await;
|
||||
|
||||
let blocks = self.block_manager.get_block_snapshots(None).await.unwrap();
|
||||
|
||||
let row_revs = blocks
|
||||
.into_iter()
|
||||
.map(|block| block.row_revs)
|
||||
.flatten()
|
||||
.collect::<Vec<Arc<RowRevision>>>();
|
||||
|
||||
// let a = SingleSelectGroupController::new;
|
||||
// let b = a(field_rev.clone(), configuration, &self.grid_pad);
|
||||
match self.build_groups(&field_type, field_rev, row_revs, configuration) {
|
||||
Ok(groups) => Some(groups),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
let groups = match field_type {
|
||||
async fn get_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
let grid_pad = self.grid_pad.read().await;
|
||||
let setting = grid_pad.get_setting_rev();
|
||||
let layout = &setting.layout;
|
||||
let configurations = setting.get_groups(layout, &field_rev.id, &field_rev.field_type_rev);
|
||||
match configurations {
|
||||
None => self.default_group_configuration(field_rev),
|
||||
Some(mut configurations) => {
|
||||
assert_eq!(configurations.len(), 1);
|
||||
(&*configurations.pop().unwrap()).clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_group_configuration(&self, field_rev: &FieldRevision) -> GroupConfigurationRevision {
|
||||
let field_type: FieldType = field_rev.field_type_rev.clone().into();
|
||||
let bytes: Bytes = match field_type {
|
||||
FieldType::RichText => TextGroupConfigurationPB::default().try_into().unwrap(),
|
||||
FieldType::Number => NumberGroupConfigurationPB::default().try_into().unwrap(),
|
||||
FieldType::DateTime => DateGroupConfigurationPB::default().try_into().unwrap(),
|
||||
FieldType::SingleSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(),
|
||||
FieldType::MultiSelect => SelectOptionGroupConfigurationPB::default().try_into().unwrap(),
|
||||
FieldType::Checkbox => CheckboxGroupConfigurationPB::default().try_into().unwrap(),
|
||||
FieldType::URL => UrlGroupConfigurationPB::default().try_into().unwrap(),
|
||||
};
|
||||
GroupConfigurationRevision {
|
||||
id: gen_grid_group_id(),
|
||||
field_id: field_rev.id.clone(),
|
||||
field_type_rev: field_rev.field_type_rev.clone(),
|
||||
content: Some(bytes.to_vec()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
fn build_groups(
|
||||
&self,
|
||||
field_type: &FieldType,
|
||||
field_rev: &Arc<FieldRevision>,
|
||||
row_revs: Vec<Arc<RowRevision>>,
|
||||
configuration: GroupConfigurationRevision,
|
||||
) -> FlowyResult<Vec<GroupPB>> {
|
||||
let groups: Vec<Group> = match field_type {
|
||||
FieldType::RichText => {
|
||||
// let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
FieldType::Number => {
|
||||
// let generator = GroupGenerator::<NumberGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
FieldType::DateTime => {
|
||||
// let generator = GroupGenerator::<DateGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
FieldType::SingleSelect => {
|
||||
let group_controller =
|
||||
SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad);
|
||||
let mut group_controller =
|
||||
SingleSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
let _ = group_controller.group_rows(&row_revs)?;
|
||||
group_controller.take_groups()
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
// let group_generator = MultiSelectGroupControllern(configuration);
|
||||
let mut group_controller =
|
||||
MultiSelectGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
let _ = group_controller.group_rows(&row_revs)?;
|
||||
group_controller.take_groups()
|
||||
}
|
||||
FieldType::Checkbox => {
|
||||
// let generator = GroupGenerator::<CheckboxGroupConfigurationPB>::from_configuration(configuration);
|
||||
let mut group_controller =
|
||||
CheckboxGroupController::new(field_rev.clone(), configuration, &self.grid_pad)?;
|
||||
let _ = group_controller.group_rows(&row_revs)?;
|
||||
group_controller.take_groups()
|
||||
}
|
||||
FieldType::URL => {
|
||||
// let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
None
|
||||
|
||||
Ok(groups.into_iter().map(GroupPB::from).collect())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
mod group_configuration;
|
||||
mod group_generator;
|
||||
mod group_service;
|
||||
|
||||
pub(crate) use group_configuration::*;
|
||||
pub(crate) use group_generator::*;
|
||||
pub(crate) use group_service::*;
|
||||
|
@ -162,7 +162,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(TextCellDataParser())
|
||||
.parser::<TextCellDataParser>()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(cell_data.as_ref(), &expected);
|
||||
@ -177,7 +177,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(NumberCellDataParser(number_type_option.format))
|
||||
.custom_parser(NumberCellCustomDataParser(number_type_option.format))
|
||||
.unwrap();
|
||||
assert_eq!(cell_data.to_string(), expected);
|
||||
}
|
||||
@ -187,7 +187,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(DateCellDataParser())
|
||||
.parser::<DateCellDataParser>()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(cell_data.date, expected);
|
||||
@ -198,7 +198,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(SelectOptionCellDataParser())
|
||||
.parser::<SelectOptionCellDataParser>()
|
||||
.unwrap();
|
||||
let select_option = cell_data.select_options.first().unwrap();
|
||||
assert_eq!(select_option.name, expected);
|
||||
@ -209,7 +209,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(SelectOptionCellDataParser())
|
||||
.parser::<SelectOptionCellDataParser>()
|
||||
.unwrap();
|
||||
|
||||
let s = cell_data
|
||||
@ -228,7 +228,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(CheckboxCellDataParser())
|
||||
.parser::<CheckboxCellDataParser>()
|
||||
.unwrap();
|
||||
assert_eq!(cell_data.to_string(), expected);
|
||||
}
|
||||
@ -238,7 +238,7 @@ impl GridRowTest {
|
||||
.get_cell_bytes(&cell_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_parser(URLCellDataParser())
|
||||
.parser::<URLCellDataParser>()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(cell_data.content, expected);
|
||||
|
@ -259,7 +259,7 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldMeta) {
|
||||
let cloned_field_meta = field_meta.clone();
|
||||
|
||||
let type_option_data = field_meta
|
||||
.get_type_option_entry::<RichTextTypeOption>(&field_meta.field_type)
|
||||
.get_type_option_entry::<RichTextTypeOptionPB>(&field_meta.field_type)
|
||||
.unwrap()
|
||||
.protobuf_bytes()
|
||||
.to_vec();
|
||||
|
@ -572,7 +572,7 @@ fn make_group_revision(params: &CreateGridGroupParams) -> GroupConfigurationRevi
|
||||
GroupConfigurationRevision {
|
||||
id: gen_grid_group_id(),
|
||||
field_id: params.field_id.clone(),
|
||||
field_type_rev: params.field_type_rev.clone(),
|
||||
field_type_rev: params.field_type_rev,
|
||||
content: params.content.clone(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user