chore: config group service

This commit is contained in:
appflowy 2022-08-11 21:18:27 +08:00
parent cefd571dd0
commit 461751cf59
57 changed files with 533 additions and 294 deletions

View File

@ -1,7 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/builder.dart';
import 'package:appflowy_board/appflowy_board.dart'; import 'package:appflowy_board/appflowy_board.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
@ -57,8 +56,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
didReceiveGridUpdate: (GridPB grid) { didReceiveGridUpdate: (GridPB grid) {
emit(state.copyWith(grid: Some(grid))); emit(state.copyWith(grid: Some(grid)));
}, },
groupByField: (FieldPB field) { didReceiveGroups: (List<GroupPB> groups) {
emit(state.copyWith(groupField: Some(field))); emit(state.copyWith(groups: groups));
}, },
); );
}, },
@ -83,50 +82,20 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
add(BoardEvent.didReceiveGridUpdate(grid)); add(BoardEvent.didReceiveGridUpdate(grid));
} }
}, },
onFieldsChanged: (fields) { onGroupChanged: (groups) {
if (!isClosed) { List<AFBoardColumnData> columns = groups.map((group) {
_buildColumns(fields);
}
},
onGroupChanged: (groups) {},
onError: (err) {
Log.error(err);
},
);
}
void _buildColumns(UnmodifiableListView<FieldPB> fields) {
FieldPB? groupField;
for (final field in fields) {
if (field.fieldType == FieldType.SingleSelect) {
groupField = field;
_buildColumnsFromSingleSelect(field);
}
}
assert(groupField != null);
add(BoardEvent.groupByField(groupField!));
}
void _buildColumnsFromSingleSelect(FieldPB field) {
final typeOptionContext = makeTypeOptionContext<SingleSelectTypeOptionPB>(
gridId: _dataController.gridId,
field: field,
);
typeOptionContext.loadTypeOptionData(
onCompleted: (singleSelect) {
List<AFBoardColumnData> columns = singleSelect.options.map((option) {
return AFBoardColumnData( return AFBoardColumnData(
id: option.id, id: group.groupId,
desc: option.name, desc: group.desc,
customData: option, customData: group,
); );
}).toList(); }).toList();
boardDataController.addColumns(columns); boardDataController.addColumns(columns);
}, },
onError: (err) => Log.error(err), onError: (err) {
Log.error(err);
},
); );
} }
@ -147,7 +116,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
class BoardEvent with _$BoardEvent { class BoardEvent with _$BoardEvent {
const factory BoardEvent.initial() = InitialGrid; const factory BoardEvent.initial() = InitialGrid;
const factory BoardEvent.createRow() = _CreateRow; const factory BoardEvent.createRow() = _CreateRow;
const factory BoardEvent.groupByField(FieldPB field) = _GroupByField; const factory BoardEvent.didReceiveGroups(List<GroupPB> groups) =
_DidReceiveGroup;
const factory BoardEvent.didReceiveGridUpdate( const factory BoardEvent.didReceiveGridUpdate(
GridPB grid, GridPB grid,
) = _DidReceiveGridUpdate; ) = _DidReceiveGridUpdate;
@ -158,14 +128,14 @@ class BoardState with _$BoardState {
const factory BoardState({ const factory BoardState({
required String gridId, required String gridId,
required Option<GridPB> grid, required Option<GridPB> grid,
required Option<FieldPB> groupField, required List<GroupPB> groups,
required List<RowInfo> rowInfos, required List<RowInfo> rowInfos,
required GridLoadingState loadingState, required GridLoadingState loadingState,
}) = _BoardState; }) = _BoardState;
factory BoardState.initial(String gridId) => BoardState( factory BoardState.initial(String gridId) => BoardState(
rowInfos: [], rowInfos: [],
groupField: none(), groups: [],
grid: none(), grid: none(),
gridId: gridId, gridId: gridId,
loadingState: const _Loading(), loadingState: const _Loading(),

View File

@ -5,6 +5,7 @@ use flowy_folder::entities::{
trash::{RepeatedTrashPB, TrashIdPB, TrashType}, trash::{RepeatedTrashPB, TrashIdPB, TrashType},
view::{CreateViewPayloadPB, UpdateViewPayloadPB}, view::{CreateViewPayloadPB, UpdateViewPayloadPB},
workspace::{CreateWorkspacePayloadPB, RepeatedWorkspacePB}, workspace::{CreateWorkspacePayloadPB, RepeatedWorkspacePB},
SubViewDataTypePB,
}; };
use flowy_folder::entities::{ use flowy_folder::entities::{
app::{AppPB, RepeatedAppPB}, app::{AppPB, RepeatedAppPB},
@ -353,13 +354,18 @@ pub async fn create_view(
desc: &str, desc: &str,
data_type: ViewDataTypePB, data_type: ViewDataTypePB,
) -> ViewPB { ) -> ViewPB {
let sub_data_type = match data_type {
ViewDataTypePB::TextBlock => None,
ViewDataTypePB::Database => Some(SubViewDataTypePB::Grid),
};
let request = CreateViewPayloadPB { let request = CreateViewPayloadPB {
belong_to_id: app_id.to_string(), belong_to_id: app_id.to_string(),
name: name.to_string(), name: name.to_string(),
desc: desc.to_string(), desc: desc.to_string(),
thumbnail: None, thumbnail: None,
data_type, data_type,
sub_data_type: None, sub_data_type,
plugin_type: 0, plugin_type: 0,
data: vec![], data: vec![],
}; };

View File

@ -518,6 +518,14 @@ pub enum FieldType {
URL = 6, URL = 6,
} }
pub const RICH_TEXT_FIELD: FieldType = FieldType::RichText;
pub const NUMBER_FIELD: FieldType = FieldType::Number;
pub const DATE_FIELD: FieldType = FieldType::DateTime;
pub const SINGLE_SELECT_FIELD: FieldType = FieldType::SingleSelect;
pub const MULTI_SELECT_FIELD: FieldType = FieldType::MultiSelect;
pub const CHECKBOX_FIELD: FieldType = FieldType::Checkbox;
pub const URL_FIELD: FieldType = FieldType::URL;
impl std::default::Default for FieldType { impl std::default::Default for FieldType {
fn default() -> Self { fn default() -> Self {
FieldType::RichText FieldType::RichText
@ -549,35 +557,39 @@ impl FieldType {
} }
pub fn is_number(&self) -> bool { pub fn is_number(&self) -> bool {
self == &FieldType::Number self == &NUMBER_FIELD
} }
pub fn is_text(&self) -> bool { pub fn is_text(&self) -> bool {
self == &FieldType::RichText self == &RICH_TEXT_FIELD
} }
pub fn is_checkbox(&self) -> bool { pub fn is_checkbox(&self) -> bool {
self == &FieldType::Checkbox self == &CHECKBOX_FIELD
} }
pub fn is_date(&self) -> bool { pub fn is_date(&self) -> bool {
self == &FieldType::DateTime self == &DATE_FIELD
} }
pub fn is_single_select(&self) -> bool { pub fn is_single_select(&self) -> bool {
self == &FieldType::SingleSelect self == &SINGLE_SELECT_FIELD
} }
pub fn is_multi_select(&self) -> bool { pub fn is_multi_select(&self) -> bool {
self == &FieldType::MultiSelect self == &MULTI_SELECT_FIELD
} }
pub fn is_url(&self) -> bool { pub fn is_url(&self) -> bool {
self == &FieldType::URL self == &URL_FIELD
} }
pub fn is_select_option(&self) -> bool { pub fn is_select_option(&self) -> bool {
self == &FieldType::MultiSelect || self == &FieldType::SingleSelect self == &MULTI_SELECT_FIELD || self == &SINGLE_SELECT_FIELD
}
pub fn can_be_group(&self) -> bool {
self.is_select_option()
} }
} }

View File

@ -1,10 +1,10 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::revision::GridFilterRevision; use flowy_grid_data_model::revision::FilterConfigurationRevision;
use std::sync::Arc; use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridCheckboxFilter { pub struct CheckboxFilterConfigurationPB {
#[pb(index = 1)] #[pb(index = 1)]
pub condition: CheckboxCondition, pub condition: CheckboxCondition,
} }
@ -40,9 +40,9 @@ impl std::convert::TryFrom<u8> for CheckboxCondition {
} }
} }
impl std::convert::From<Arc<GridFilterRevision>> for GridCheckboxFilter { impl std::convert::From<Arc<FilterConfigurationRevision>> for CheckboxFilterConfigurationPB {
fn from(rev: Arc<GridFilterRevision>) -> Self { fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
GridCheckboxFilter { CheckboxFilterConfigurationPB {
condition: CheckboxCondition::try_from(rev.condition).unwrap_or(CheckboxCondition::IsChecked), condition: CheckboxCondition::try_from(rev.condition).unwrap_or(CheckboxCondition::IsChecked),
} }
} }

View File

@ -2,13 +2,13 @@ use crate::entities::FieldType;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::GridFilterRevision; use flowy_grid_data_model::revision::FilterConfigurationRevision;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridDateFilter { pub struct DateFilterConfigurationPB {
#[pb(index = 1)] #[pb(index = 1)]
pub condition: DateFilterCondition, pub condition: DateFilterCondition,
@ -120,10 +120,10 @@ impl std::convert::TryFrom<u8> for DateFilterCondition {
} }
} }
} }
impl std::convert::From<Arc<GridFilterRevision>> for GridDateFilter { impl std::convert::From<Arc<FilterConfigurationRevision>> for DateFilterConfigurationPB {
fn from(rev: Arc<GridFilterRevision>) -> Self { fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
let condition = DateFilterCondition::try_from(rev.condition).unwrap_or(DateFilterCondition::DateIs); let condition = DateFilterCondition::try_from(rev.condition).unwrap_or(DateFilterCondition::DateIs);
let mut filter = GridDateFilter { let mut filter = DateFilterConfigurationPB {
condition, condition,
..Default::default() ..Default::default()
}; };

View File

@ -1,11 +1,11 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::revision::GridFilterRevision; use flowy_grid_data_model::revision::FilterConfigurationRevision;
use std::sync::Arc; use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridNumberFilter { pub struct NumberFilterConfigurationPB {
#[pb(index = 1)] #[pb(index = 1)]
pub condition: NumberFilterCondition, pub condition: NumberFilterCondition,
@ -55,9 +55,9 @@ impl std::convert::TryFrom<u8> for NumberFilterCondition {
} }
} }
impl std::convert::From<Arc<GridFilterRevision>> for GridNumberFilter { impl std::convert::From<Arc<FilterConfigurationRevision>> for NumberFilterConfigurationPB {
fn from(rev: Arc<GridFilterRevision>) -> Self { fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
GridNumberFilter { NumberFilterConfigurationPB {
condition: NumberFilterCondition::try_from(rev.condition).unwrap_or(NumberFilterCondition::Equal), condition: NumberFilterCondition::try_from(rev.condition).unwrap_or(NumberFilterCondition::Equal),
content: rev.content.clone(), content: rev.content.clone(),
} }

View File

@ -1,11 +1,11 @@
use crate::services::field::SelectOptionIds; use crate::services::field::SelectOptionIds;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::revision::GridFilterRevision; use flowy_grid_data_model::revision::FilterConfigurationRevision;
use std::sync::Arc; use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridSelectOptionFilter { pub struct SelectOptionFilterConfigurationPB {
#[pb(index = 1)] #[pb(index = 1)]
pub condition: SelectOptionCondition, pub condition: SelectOptionCondition,
@ -47,10 +47,10 @@ impl std::convert::TryFrom<u8> for SelectOptionCondition {
} }
} }
impl std::convert::From<Arc<GridFilterRevision>> for GridSelectOptionFilter { impl std::convert::From<Arc<FilterConfigurationRevision>> for SelectOptionFilterConfigurationPB {
fn from(rev: Arc<GridFilterRevision>) -> Self { fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
let ids = SelectOptionIds::from(rev.content.clone()); let ids = SelectOptionIds::from(rev.content.clone());
GridSelectOptionFilter { SelectOptionFilterConfigurationPB {
condition: SelectOptionCondition::try_from(rev.condition).unwrap_or(SelectOptionCondition::OptionIs), condition: SelectOptionCondition::try_from(rev.condition).unwrap_or(SelectOptionCondition::OptionIs),
option_ids: ids.into_inner(), option_ids: ids.into_inner(),
} }

View File

@ -1,10 +1,10 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::revision::GridFilterRevision; use flowy_grid_data_model::revision::FilterConfigurationRevision;
use std::sync::Arc; use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridTextFilter { pub struct TextFilterConfigurationPB {
#[pb(index = 1)] #[pb(index = 1)]
pub condition: TextFilterCondition, pub condition: TextFilterCondition,
@ -54,9 +54,9 @@ impl std::convert::TryFrom<u8> for TextFilterCondition {
} }
} }
impl std::convert::From<Arc<GridFilterRevision>> for GridTextFilter { impl std::convert::From<Arc<FilterConfigurationRevision>> for TextFilterConfigurationPB {
fn from(rev: Arc<GridFilterRevision>) -> Self { fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
GridTextFilter { TextFilterConfigurationPB {
condition: TextFilterCondition::try_from(rev.condition).unwrap_or(TextFilterCondition::Is), condition: TextFilterCondition::try_from(rev.condition).unwrap_or(TextFilterCondition::Is),
content: rev.content.clone(), content: rev.content.clone(),
} }

View File

@ -5,7 +5,7 @@ use crate::entities::{
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::{FieldRevision, GridFilterRevision}; use flowy_grid_data_model::revision::{FieldRevision, FilterConfigurationRevision};
use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams}; use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams};
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc; use std::sync::Arc;
@ -22,14 +22,14 @@ pub struct RepeatedGridConfigurationFilterPB {
pub items: Vec<GridFilterConfiguration>, pub items: Vec<GridFilterConfiguration>,
} }
impl std::convert::From<&GridFilterRevision> for GridFilterConfiguration { impl std::convert::From<&FilterConfigurationRevision> for GridFilterConfiguration {
fn from(rev: &GridFilterRevision) -> Self { fn from(rev: &FilterConfigurationRevision) -> Self {
Self { id: rev.id.clone() } Self { id: rev.id.clone() }
} }
} }
impl std::convert::From<Vec<Arc<GridFilterRevision>>> for RepeatedGridConfigurationFilterPB { impl std::convert::From<Vec<Arc<FilterConfigurationRevision>>> for RepeatedGridConfigurationFilterPB {
fn from(revs: Vec<Arc<GridFilterRevision>>) -> Self { fn from(revs: Vec<Arc<FilterConfigurationRevision>>) -> Self {
RepeatedGridConfigurationFilterPB { RepeatedGridConfigurationFilterPB {
items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(), items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(),
} }

View File

@ -0,0 +1,7 @@
use flowy_derive::ProtoBuf;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct CheckboxGroupConfigurationPB {
#[pb(index = 1)]
pub(crate) hide_empty: bool,
}

View File

@ -0,0 +1,26 @@
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
}
}

View File

@ -2,7 +2,7 @@ use crate::entities::{FieldType, RowPB};
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::GridGroupRevision; use flowy_grid_data_model::revision::GroupConfigurationRevision;
use flowy_sync::entities::grid::{CreateGridGroupParams, DeleteGroupParams}; use flowy_sync::entities::grid::{CreateGridGroupParams, DeleteGroupParams};
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc; use std::sync::Arc;
@ -14,17 +14,13 @@ pub struct GridGroupConfigurationPB {
#[pb(index = 2)] #[pb(index = 2)]
pub group_field_id: String, pub group_field_id: String,
#[pb(index = 3, one_of)]
pub sub_group_field_id: Option<String>,
} }
impl std::convert::From<&GridGroupRevision> for GridGroupConfigurationPB { impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationPB {
fn from(rev: &GridGroupRevision) -> Self { fn from(rev: &GroupConfigurationRevision) -> Self {
GridGroupConfigurationPB { GridGroupConfigurationPB {
id: rev.id.clone(), id: rev.id.clone(),
group_field_id: rev.field_id.clone(), group_field_id: rev.field_id.clone(),
sub_group_field_id: rev.sub_field_id.clone(),
} }
} }
} }
@ -32,7 +28,7 @@ impl std::convert::From<&GridGroupRevision> for GridGroupConfigurationPB {
#[derive(ProtoBuf, Debug, Default, Clone)] #[derive(ProtoBuf, Debug, Default, Clone)]
pub struct RepeatedGridGroupPB { pub struct RepeatedGridGroupPB {
#[pb(index = 1)] #[pb(index = 1)]
items: Vec<GroupPB>, pub(crate) items: Vec<GroupPB>,
} }
#[derive(ProtoBuf, Debug, Default, Clone)] #[derive(ProtoBuf, Debug, Default, Clone)]
@ -59,8 +55,8 @@ impl std::convert::From<Vec<GridGroupConfigurationPB>> for RepeatedGridGroupConf
} }
} }
impl std::convert::From<Vec<Arc<GridGroupRevision>>> for RepeatedGridGroupConfigurationPB { impl std::convert::From<Vec<Arc<GroupConfigurationRevision>>> for RepeatedGridGroupConfigurationPB {
fn from(revs: Vec<Arc<GridGroupRevision>>) -> Self { fn from(revs: Vec<Arc<GroupConfigurationRevision>>) -> Self {
RepeatedGridGroupConfigurationPB { RepeatedGridGroupConfigurationPB {
items: revs.iter().map(|rev| rev.as_ref().into()).collect(), items: revs.iter().map(|rev| rev.as_ref().into()).collect(),
} }
@ -72,11 +68,11 @@ pub struct CreateGridGroupPayloadPB {
#[pb(index = 1)] #[pb(index = 1)]
pub field_id: String, pub field_id: String,
#[pb(index = 2, one_of)] #[pb(index = 2)]
pub sub_field_id: Option<String>,
#[pb(index = 3)]
pub field_type: FieldType, pub field_type: FieldType,
#[pb(index = 3, one_of)]
pub content: Option<Vec<u8>>,
} }
impl TryInto<CreateGridGroupParams> for CreateGridGroupPayloadPB { impl TryInto<CreateGridGroupParams> for CreateGridGroupPayloadPB {
@ -87,15 +83,10 @@ impl TryInto<CreateGridGroupParams> for CreateGridGroupPayloadPB {
.map_err(|_| ErrorCode::FieldIdIsEmpty)? .map_err(|_| ErrorCode::FieldIdIsEmpty)?
.0; .0;
let sub_field_id = match self.sub_field_id {
None => None,
Some(field_id) => Some(NotEmptyStr::parse(field_id).map_err(|_| ErrorCode::FieldIdIsEmpty)?.0),
};
Ok(CreateGridGroupParams { Ok(CreateGridGroupParams {
field_id, field_id,
sub_field_id,
field_type_rev: self.field_type.into(), field_type_rev: self.field_type.into(),
content: self.content,
}) })
} }
} }

View File

@ -1,3 +1,15 @@
mod checkbox_group;
mod date_group;
mod group; 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 group::*; pub use group::*;
pub use number_group::*;
pub use select_option_group::*;
pub use text_group::*;
pub use url_group::*;

View File

@ -0,0 +1,7 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct NumberGroupConfigurationPB {
#[pb(index = 1)]
hide_empty: bool,
}

View File

@ -0,0 +1,7 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct SelectOptionGroupConfigurationPB {
#[pb(index = 1)]
hide_empty: bool,
}

View File

@ -0,0 +1,7 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct TextGroupConfigurationPB {
#[pb(index = 1)]
hide_empty: bool,
}

View File

@ -0,0 +1,7 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct UrlGroupConfigurationPB {
#[pb(index = 1)]
hide_empty: bool,
}

View File

@ -1,7 +1,7 @@
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode; use flowy_error::ErrorCode;
use flowy_grid_data_model::parser::NotEmptyStr; use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::GridSortRevision; use flowy_grid_data_model::revision::SortConfigurationRevision;
use flowy_sync::entities::grid::CreateGridSortParams; use flowy_sync::entities::grid::CreateGridSortParams;
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc; use std::sync::Arc;
@ -15,8 +15,8 @@ pub struct GridSort {
pub field_id: Option<String>, pub field_id: Option<String>,
} }
impl std::convert::From<&GridSortRevision> for GridSort { impl std::convert::From<&SortConfigurationRevision> for GridSort {
fn from(rev: &GridSortRevision) -> Self { fn from(rev: &SortConfigurationRevision) -> Self {
GridSort { GridSort {
id: rev.id.clone(), id: rev.id.clone(),
@ -31,8 +31,8 @@ pub struct RepeatedGridSortPB {
pub items: Vec<GridSort>, pub items: Vec<GridSort>,
} }
impl std::convert::From<Vec<Arc<GridSortRevision>>> for RepeatedGridSortPB { impl std::convert::From<Vec<Arc<SortConfigurationRevision>>> for RepeatedGridSortPB {
fn from(revs: Vec<Arc<GridSortRevision>>) -> Self { fn from(revs: Vec<Arc<SortConfigurationRevision>>) -> Self {
RepeatedGridSortPB { RepeatedGridSortPB {
items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(), items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(),
} }

View File

@ -407,12 +407,12 @@ pub(crate) async fn update_date_cell_handler(
} }
#[tracing::instrument(level = "trace", skip_all, err)] #[tracing::instrument(level = "trace", skip_all, err)]
pub(crate) async fn get_group_handler( pub(crate) async fn get_groups_handler(
data: Data<GridIdPB>, data: Data<GridIdPB>,
manager: AppData<Arc<GridManager>>, manager: AppData<Arc<GridManager>>,
) -> DataResult<RepeatedGridGroupPB, FlowyError> { ) -> DataResult<RepeatedGridGroupPB, FlowyError> {
let params: GridIdPB = data.into_inner(); let params: GridIdPB = data.into_inner();
let editor = manager.get_grid_editor(&params.value)?; let editor = manager.get_grid_editor(&params.value)?;
let group = editor.get_group().await?; let group = editor.load_groups().await?;
data_result(group) data_result(group)
} }

View File

@ -39,7 +39,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
// Date // Date
.event(GridEvent::UpdateDateCell, update_date_cell_handler) .event(GridEvent::UpdateDateCell, update_date_cell_handler)
// Group // Group
.event(GridEvent::GetGroup, update_date_cell_handler); .event(GridEvent::GetGroup, get_groups_handler);
module module
} }

View File

@ -11,6 +11,10 @@ pub trait CellFilterOperation<T> {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &T) -> FlowyResult<bool>; fn apply_filter(&self, any_cell_data: AnyCellData, filter: &T) -> FlowyResult<bool>;
} }
pub trait CellGroupOperation {
fn apply_group(&self, any_cell_data: AnyCellData, group_content: &str) -> FlowyResult<bool>;
}
/// Return object that describes the cell. /// Return object that describes the cell.
pub trait CellDisplayable<CD> { pub trait CellDisplayable<CD> {
fn display_data( fn display_data(
@ -55,15 +59,15 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
let changeset = changeset.to_string(); let changeset = changeset.to_string();
let field_type = field_rev.field_type_rev.into(); let field_type = field_rev.field_type_rev.into();
let s = match field_type { let s = match field_type {
FieldType::RichText => RichTextTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::RichText => RichTextTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::Number => NumberTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::Number => NumberTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::DateTime => DateTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::DateTime => DateTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::SingleSelect => { FieldType::SingleSelect => {
SingleSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev) SingleSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev)
} }
FieldType::MultiSelect => MultiSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::MultiSelect => MultiSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::Checkbox => CheckboxTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::Checkbox => CheckboxTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::URL => URLTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev), FieldType::URL => URLTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
}?; }?;
Ok(AnyCellData::new(s, field_type).json()) Ok(AnyCellData::new(s, field_type).json())
@ -97,13 +101,13 @@ pub fn try_decode_cell_data(
let field_type: FieldTypeRevision = t_field_type.into(); let field_type: FieldTypeRevision = t_field_type.into();
let data = match t_field_type { let data = match t_field_type {
FieldType::RichText => field_rev FieldType::RichText => field_rev
.get_type_option_entry::<RichTextTypeOption>(field_type)? .get_type_option_entry::<RichTextTypeOptionPB>(field_type)?
.decode_cell_data(cell_data.into(), s_field_type, field_rev), .decode_cell_data(cell_data.into(), s_field_type, field_rev),
FieldType::Number => field_rev FieldType::Number => field_rev
.get_type_option_entry::<NumberTypeOption>(field_type)? .get_type_option_entry::<NumberTypeOptionPB>(field_type)?
.decode_cell_data(cell_data.into(), s_field_type, field_rev), .decode_cell_data(cell_data.into(), s_field_type, field_rev),
FieldType::DateTime => field_rev FieldType::DateTime => field_rev
.get_type_option_entry::<DateTypeOption>(field_type)? .get_type_option_entry::<DateTypeOptionPB>(field_type)?
.decode_cell_data(cell_data.into(), s_field_type, field_rev), .decode_cell_data(cell_data.into(), s_field_type, field_rev),
FieldType::SingleSelect => field_rev FieldType::SingleSelect => field_rev
.get_type_option_entry::<SingleSelectTypeOptionPB>(field_type)? .get_type_option_entry::<SingleSelectTypeOptionPB>(field_type)?
@ -115,7 +119,7 @@ pub fn try_decode_cell_data(
.get_type_option_entry::<CheckboxTypeOption>(field_type)? .get_type_option_entry::<CheckboxTypeOption>(field_type)?
.decode_cell_data(cell_data.into(), s_field_type, field_rev), .decode_cell_data(cell_data.into(), s_field_type, field_rev),
FieldType::URL => field_rev FieldType::URL => field_rev
.get_type_option_entry::<URLTypeOption>(field_type)? .get_type_option_entry::<URLTypeOptionPB>(field_type)?
.decode_cell_data(cell_data.into(), s_field_type, field_rev), .decode_cell_data(cell_data.into(), s_field_type, field_rev),
}; };
Some(data) Some(data)

View File

@ -90,13 +90,13 @@ pub trait TypeOptionBuilder {
pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box<dyn TypeOptionBuilder> { pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box<dyn TypeOptionBuilder> {
let s: String = match field_type { let s: String = match field_type {
FieldType::RichText => RichTextTypeOption::default().into(), FieldType::RichText => RichTextTypeOptionPB::default().into(),
FieldType::Number => NumberTypeOption::default().into(), FieldType::Number => NumberTypeOptionPB::default().into(),
FieldType::DateTime => DateTypeOption::default().into(), FieldType::DateTime => DateTypeOptionPB::default().into(),
FieldType::SingleSelect => SingleSelectTypeOptionPB::default().into(), FieldType::SingleSelect => SingleSelectTypeOptionPB::default().into(),
FieldType::MultiSelect => MultiSelectTypeOptionPB::default().into(), FieldType::MultiSelect => MultiSelectTypeOptionPB::default().into(),
FieldType::Checkbox => CheckboxTypeOption::default().into(), FieldType::Checkbox => CheckboxTypeOption::default().into(),
FieldType::URL => URLTypeOption::default().into(), FieldType::URL => URLTypeOptionPB::default().into(),
}; };
type_option_builder_from_json_str(&s, field_type) type_option_builder_from_json_str(&s, field_type)

View File

@ -9,7 +9,7 @@ mod tests {
#[test] #[test]
fn date_type_option_date_format_test() { fn date_type_option_date_format_test() {
let mut type_option = DateTypeOption::default(); let mut type_option = DateTypeOptionPB::default();
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build(); let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
for date_format in DateFormat::iter() { for date_format in DateFormat::iter() {
type_option.date_format = date_format; type_option.date_format = date_format;
@ -32,7 +32,7 @@ mod tests {
#[test] #[test]
fn date_type_option_different_time_format_test() { fn date_type_option_different_time_format_test() {
let mut type_option = DateTypeOption::default(); let mut type_option = DateTypeOptionPB::default();
let field_type = FieldType::DateTime; let field_type = FieldType::DateTime;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
@ -66,7 +66,7 @@ mod tests {
#[test] #[test]
fn date_type_option_invalid_date_str_test() { fn date_type_option_invalid_date_str_test() {
let type_option = DateTypeOption::default(); let type_option = DateTypeOptionPB::default();
let field_type = FieldType::DateTime; let field_type = FieldType::DateTime;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_date(&type_option, "abc", None, "", &field_rev); assert_date(&type_option, "abc", None, "", &field_rev);
@ -75,7 +75,7 @@ mod tests {
#[test] #[test]
#[should_panic] #[should_panic]
fn date_type_option_invalid_include_time_str_test() { fn date_type_option_invalid_include_time_str_test() {
let mut type_option = DateTypeOption::new(); let mut type_option = DateTypeOptionPB::new();
type_option.include_time = true; type_option.include_time = true;
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build(); let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
@ -90,7 +90,7 @@ mod tests {
#[test] #[test]
fn date_type_option_empty_include_time_str_test() { fn date_type_option_empty_include_time_str_test() {
let mut type_option = DateTypeOption::new(); let mut type_option = DateTypeOptionPB::new();
type_option.include_time = true; type_option.include_time = true;
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build(); let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
@ -101,7 +101,7 @@ mod tests {
#[test] #[test]
#[should_panic] #[should_panic]
fn date_type_option_twelve_hours_include_time_str_in_twenty_four_hours_format() { fn date_type_option_twelve_hours_include_time_str_in_twenty_four_hours_format() {
let mut type_option = DateTypeOption::new(); let mut type_option = DateTypeOptionPB::new();
type_option.include_time = true; type_option.include_time = true;
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build(); let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
@ -114,7 +114,7 @@ mod tests {
); );
} }
fn assert_date<T: ToString>( fn assert_date<T: ToString>(
type_option: &DateTypeOption, type_option: &DateTypeOptionPB,
timestamp: T, timestamp: T,
include_time_str: Option<String>, include_time_str: Option<String>,
expected_str: &str, expected_str: &str,
@ -133,7 +133,7 @@ mod tests {
); );
} }
fn decode_cell_data(encoded_data: String, type_option: &DateTypeOption, field_rev: &FieldRevision) -> String { fn decode_cell_data(encoded_data: String, type_option: &DateTypeOptionPB, field_rev: &FieldRevision) -> String {
let decoded_data = type_option let decoded_data = type_option
.decode_cell_data(encoded_data.into(), &FieldType::DateTime, field_rev) .decode_cell_data(encoded_data.into(), &FieldType::DateTime, field_rev)
.unwrap() .unwrap()

View File

@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize};
// Date // Date
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
pub struct DateTypeOption { pub struct DateTypeOptionPB {
#[pb(index = 1)] #[pb(index = 1)]
pub date_format: DateFormat, pub date_format: DateFormat,
@ -24,9 +24,9 @@ pub struct DateTypeOption {
#[pb(index = 3)] #[pb(index = 3)]
pub include_time: bool, pub include_time: bool,
} }
impl_type_option!(DateTypeOption, FieldType::DateTime); impl_type_option!(DateTypeOptionPB, FieldType::DateTime);
impl DateTypeOption { impl DateTypeOptionPB {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
@ -116,7 +116,7 @@ impl DateTypeOption {
} }
} }
impl CellDisplayable<DateTimestamp> for DateTypeOption { impl CellDisplayable<DateTimestamp> for DateTypeOptionPB {
fn display_data( fn display_data(
&self, &self,
cell_data: CellData<DateTimestamp>, cell_data: CellData<DateTimestamp>,
@ -129,7 +129,7 @@ impl CellDisplayable<DateTimestamp> for DateTypeOption {
} }
} }
impl CellDataOperation<DateTimestamp, DateCellChangesetPB> for DateTypeOption { impl CellDataOperation<DateTimestamp, DateCellChangesetPB> for DateTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<DateTimestamp>, cell_data: CellData<DateTimestamp>,
@ -169,9 +169,9 @@ impl CellDataOperation<DateTimestamp, DateCellChangesetPB> for DateTypeOption {
} }
#[derive(Default)] #[derive(Default)]
pub struct DateTypeOptionBuilder(DateTypeOption); pub struct DateTypeOptionBuilder(DateTypeOptionPB);
impl_into_box_type_option_builder!(DateTypeOptionBuilder); impl_into_box_type_option_builder!(DateTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOption); impl_builder_from_json_str_and_from_bytes!(DateTypeOptionBuilder, DateTypeOptionPB);
impl DateTypeOptionBuilder { impl DateTypeOptionBuilder {
pub fn date_format(mut self, date_format: DateFormat) -> Self { pub fn date_format(mut self, date_format: DateFormat) -> Self {

View File

@ -3,14 +3,14 @@ mod tests {
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::CellDataOperation; use crate::services::cell::CellDataOperation;
use crate::services::field::FieldBuilder; use crate::services::field::FieldBuilder;
use crate::services::field::{strip_currency_symbol, NumberFormat, NumberTypeOption}; use crate::services::field::{strip_currency_symbol, NumberFormat, NumberTypeOptionPB};
use flowy_grid_data_model::revision::FieldRevision; use flowy_grid_data_model::revision::FieldRevision;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
/// Testing when the input is not a number. /// Testing when the input is not a number.
#[test] #[test]
fn number_type_option_invalid_input_test() { fn number_type_option_invalid_input_test() {
let type_option = NumberTypeOption::default(); let type_option = NumberTypeOptionPB::default();
let field_type = FieldType::Number; let field_type = FieldType::Number;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
@ -33,7 +33,7 @@ mod tests {
/// Format the input number to the corresponding format string. /// Format the input number to the corresponding format string.
#[test] #[test]
fn number_type_option_format_number_test() { fn number_type_option_format_number_test() {
let mut type_option = NumberTypeOption::default(); let mut type_option = NumberTypeOptionPB::default();
let field_type = FieldType::Number; let field_type = FieldType::Number;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
@ -63,7 +63,7 @@ mod tests {
/// Format the input String to the corresponding format string. /// Format the input String to the corresponding format string.
#[test] #[test]
fn number_type_option_format_str_test() { fn number_type_option_format_str_test() {
let mut type_option = NumberTypeOption::default(); let mut type_option = NumberTypeOptionPB::default();
let field_type = FieldType::Number; let field_type = FieldType::Number;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
@ -101,7 +101,7 @@ mod tests {
/// Carry out the sign positive to input number /// Carry out the sign positive to input number
#[test] #[test]
fn number_description_sign_test() { fn number_description_sign_test() {
let mut type_option = NumberTypeOption { let mut type_option = NumberTypeOptionPB {
sign_positive: false, sign_positive: false,
..Default::default() ..Default::default()
}; };
@ -129,7 +129,7 @@ mod tests {
} }
fn assert_number( fn assert_number(
type_option: &NumberTypeOption, type_option: &NumberTypeOptionPB,
input_str: &str, input_str: &str,
expected_str: &str, expected_str: &str,
field_type: &FieldType, field_type: &FieldType,

View File

@ -14,9 +14,9 @@ use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
#[derive(Default)] #[derive(Default)]
pub struct NumberTypeOptionBuilder(NumberTypeOption); pub struct NumberTypeOptionBuilder(NumberTypeOptionPB);
impl_into_box_type_option_builder!(NumberTypeOptionBuilder); impl_into_box_type_option_builder!(NumberTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption); impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOptionPB);
impl NumberTypeOptionBuilder { impl NumberTypeOptionBuilder {
pub fn name(mut self, name: &str) -> Self { pub fn name(mut self, name: &str) -> Self {
@ -52,7 +52,7 @@ impl TypeOptionBuilder for NumberTypeOptionBuilder {
// Number // Number
#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)] #[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
pub struct NumberTypeOption { pub struct NumberTypeOptionPB {
#[pb(index = 1)] #[pb(index = 1)]
pub format: NumberFormat, pub format: NumberFormat,
@ -68,9 +68,9 @@ pub struct NumberTypeOption {
#[pb(index = 5)] #[pb(index = 5)]
pub name: String, pub name: String,
} }
impl_type_option!(NumberTypeOption, FieldType::Number); impl_type_option!(NumberTypeOptionPB, FieldType::Number);
impl NumberTypeOption { impl NumberTypeOptionPB {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
@ -102,7 +102,7 @@ pub(crate) fn strip_currency_symbol<T: ToString>(s: T) -> String {
s s
} }
impl CellDataOperation<String, String> for NumberTypeOption { impl CellDataOperation<String, String> for NumberTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<String>, cell_data: CellData<String>,
@ -132,11 +132,11 @@ impl CellDataOperation<String, String> for NumberTypeOption {
} }
} }
impl std::default::Default for NumberTypeOption { impl std::default::Default for NumberTypeOptionPB {
fn default() -> Self { fn default() -> Self {
let format = NumberFormat::default(); let format = NumberFormat::default();
let symbol = format.symbol(); let symbol = format.symbol();
NumberTypeOption { NumberTypeOptionPB {
format, format,
scale: 0, scale: 0,
symbol, symbol,

View File

@ -12,9 +12,9 @@ use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDat
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Default)] #[derive(Default)]
pub struct RichTextTypeOptionBuilder(RichTextTypeOption); pub struct RichTextTypeOptionBuilder(RichTextTypeOptionPB);
impl_into_box_type_option_builder!(RichTextTypeOptionBuilder); impl_into_box_type_option_builder!(RichTextTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOption); impl_builder_from_json_str_and_from_bytes!(RichTextTypeOptionBuilder, RichTextTypeOptionPB);
impl TypeOptionBuilder for RichTextTypeOptionBuilder { impl TypeOptionBuilder for RichTextTypeOptionBuilder {
fn field_type(&self) -> FieldType { fn field_type(&self) -> FieldType {
@ -27,13 +27,13 @@ impl TypeOptionBuilder for RichTextTypeOptionBuilder {
} }
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)] #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
pub struct RichTextTypeOption { pub struct RichTextTypeOptionPB {
#[pb(index = 1)] #[pb(index = 1)]
data: String, //It's not used yet data: String, //It's not used yet
} }
impl_type_option!(RichTextTypeOption, FieldType::RichText); impl_type_option!(RichTextTypeOptionPB, FieldType::RichText);
impl CellDisplayable<String> for RichTextTypeOption { impl CellDisplayable<String> for RichTextTypeOptionPB {
fn display_data( fn display_data(
&self, &self,
cell_data: CellData<String>, cell_data: CellData<String>,
@ -45,7 +45,7 @@ impl CellDisplayable<String> for RichTextTypeOption {
} }
} }
impl CellDataOperation<String, String> for RichTextTypeOption { impl CellDataOperation<String, String> for RichTextTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<String>, cell_data: CellData<String>,
@ -114,7 +114,7 @@ mod tests {
#[test] #[test]
fn text_description_test() { fn text_description_test() {
let type_option = RichTextTypeOption::default(); let type_option = RichTextTypeOptionPB::default();
// date // date
let field_type = FieldType::DateTime; let field_type = FieldType::DateTime;

View File

@ -3,14 +3,14 @@ mod tests {
use crate::entities::FieldType; use crate::entities::FieldType;
use crate::services::cell::{CellData, CellDataOperation}; use crate::services::cell::{CellData, CellDataOperation};
use crate::services::field::{FieldBuilder, URLCellDataParser}; use crate::services::field::{FieldBuilder, URLCellDataParser};
use crate::services::field::{URLCellDataPB, URLTypeOption}; use crate::services::field::{URLCellDataPB, URLTypeOptionPB};
use flowy_grid_data_model::revision::FieldRevision; use flowy_grid_data_model::revision::FieldRevision;
/// The expected_str will equal to the input string, but the expected_url will be empty if there's no /// The expected_str will equal to the input string, but the expected_url will be empty if there's no
/// http url in the input string. /// http url in the input string.
#[test] #[test]
fn url_type_option_does_not_contain_url_test() { fn url_type_option_does_not_contain_url_test() {
let type_option = URLTypeOption::default(); let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL; let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url(&type_option, "123", "123", "", &field_type, &field_rev); assert_url(&type_option, "123", "123", "", &field_type, &field_rev);
@ -21,7 +21,7 @@ mod tests {
/// if there's a http url in the input string. /// if there's a http url in the input string.
#[test] #[test]
fn url_type_option_contains_url_test() { fn url_type_option_contains_url_test() {
let type_option = URLTypeOption::default(); let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL; let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url( assert_url(
@ -46,7 +46,7 @@ mod tests {
/// if there's a http url and some words following it in the input string. /// if there's a http url and some words following it in the input string.
#[test] #[test]
fn url_type_option_contains_url_with_string_after_test() { fn url_type_option_contains_url_with_string_after_test() {
let type_option = URLTypeOption::default(); let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL; let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url( assert_url(
@ -71,7 +71,7 @@ mod tests {
/// if there's a http url and special words following it in the input string. /// if there's a http url and special words following it in the input string.
#[test] #[test]
fn url_type_option_contains_url_with_special_string_after_test() { fn url_type_option_contains_url_with_special_string_after_test() {
let type_option = URLTypeOption::default(); let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL; let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url( assert_url(
@ -96,7 +96,7 @@ mod tests {
/// if there's a level4 url in the input string. /// if there's a level4 url in the input string.
#[test] #[test]
fn level4_url_type_test() { fn level4_url_type_test() {
let type_option = URLTypeOption::default(); let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL; let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url( assert_url(
@ -121,7 +121,7 @@ mod tests {
/// urls with different top level domains. /// urls with different top level domains.
#[test] #[test]
fn different_top_level_domains_test() { fn different_top_level_domains_test() {
let type_option = URLTypeOption::default(); let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL; let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build(); let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url( assert_url(
@ -162,7 +162,7 @@ mod tests {
} }
fn assert_url( fn assert_url(
type_option: &URLTypeOption, type_option: &URLTypeOptionPB,
input_str: &str, input_str: &str,
expected_str: &str, expected_str: &str,
expected_url: &str, expected_url: &str,
@ -177,7 +177,7 @@ mod tests {
fn decode_cell_data<T: Into<CellData<URLCellDataPB>>>( fn decode_cell_data<T: Into<CellData<URLCellDataPB>>>(
encoded_data: T, encoded_data: T,
type_option: &URLTypeOption, type_option: &URLTypeOptionPB,
field_rev: &FieldRevision, field_rev: &FieldRevision,
field_type: &FieldType, field_type: &FieldType,
) -> URLCellDataPB { ) -> URLCellDataPB {

View File

@ -11,9 +11,9 @@ use lazy_static::lazy_static;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Default)] #[derive(Default)]
pub struct URLTypeOptionBuilder(URLTypeOption); pub struct URLTypeOptionBuilder(URLTypeOptionPB);
impl_into_box_type_option_builder!(URLTypeOptionBuilder); impl_into_box_type_option_builder!(URLTypeOptionBuilder);
impl_builder_from_json_str_and_from_bytes!(URLTypeOptionBuilder, URLTypeOption); impl_builder_from_json_str_and_from_bytes!(URLTypeOptionBuilder, URLTypeOptionPB);
impl TypeOptionBuilder for URLTypeOptionBuilder { impl TypeOptionBuilder for URLTypeOptionBuilder {
fn field_type(&self) -> FieldType { fn field_type(&self) -> FieldType {
@ -26,13 +26,13 @@ impl TypeOptionBuilder for URLTypeOptionBuilder {
} }
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)] #[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
pub struct URLTypeOption { pub struct URLTypeOptionPB {
#[pb(index = 1)] #[pb(index = 1)]
data: String, //It's not used yet. data: String, //It's not used yet.
} }
impl_type_option!(URLTypeOption, FieldType::URL); impl_type_option!(URLTypeOptionPB, FieldType::URL);
impl CellDisplayable<URLCellDataPB> for URLTypeOption { impl CellDisplayable<URLCellDataPB> for URLTypeOptionPB {
fn display_data( fn display_data(
&self, &self,
cell_data: CellData<URLCellDataPB>, cell_data: CellData<URLCellDataPB>,
@ -44,7 +44,7 @@ impl CellDisplayable<URLCellDataPB> for URLTypeOption {
} }
} }
impl CellDataOperation<URLCellDataPB, String> for URLTypeOption { impl CellDataOperation<URLCellDataPB, String> for URLTypeOptionPB {
fn decode_cell_data( fn decode_cell_data(
&self, &self,
cell_data: CellData<URLCellDataPB>, cell_data: CellData<URLCellDataPB>,

View File

@ -1,5 +1,6 @@
use crate::entities::{ use crate::entities::{
FieldType, GridCheckboxFilter, GridDateFilter, GridNumberFilter, GridSelectOptionFilter, GridTextFilter, CheckboxFilterConfigurationPB, DateFilterConfigurationPB, FieldType, NumberFilterConfigurationPB,
SelectOptionFilterConfigurationPB, TextFilterConfigurationPB,
}; };
use dashmap::DashMap; use dashmap::DashMap;
use flowy_grid_data_model::revision::{FieldRevision, RowRevision}; use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
@ -58,12 +59,12 @@ impl FilterResult {
#[derive(Default)] #[derive(Default)]
pub(crate) struct FilterCache { pub(crate) struct FilterCache {
pub(crate) text_filter: DashMap<FilterId, GridTextFilter>, pub(crate) text_filter: DashMap<FilterId, TextFilterConfigurationPB>,
pub(crate) url_filter: DashMap<FilterId, GridTextFilter>, pub(crate) url_filter: DashMap<FilterId, TextFilterConfigurationPB>,
pub(crate) number_filter: DashMap<FilterId, GridNumberFilter>, pub(crate) number_filter: DashMap<FilterId, NumberFilterConfigurationPB>,
pub(crate) date_filter: DashMap<FilterId, GridDateFilter>, pub(crate) date_filter: DashMap<FilterId, DateFilterConfigurationPB>,
pub(crate) select_option_filter: DashMap<FilterId, GridSelectOptionFilter>, pub(crate) select_option_filter: DashMap<FilterId, SelectOptionFilterConfigurationPB>,
pub(crate) checkbox_filter: DashMap<FilterId, GridCheckboxFilter>, pub(crate) checkbox_filter: DashMap<FilterId, CheckboxFilterConfigurationPB>,
} }
impl FilterCache { impl FilterCache {
@ -117,28 +118,34 @@ pub(crate) async fn refresh_filter_cache(
let field_type: FieldType = field_rev.field_type_rev.into(); let field_type: FieldType = field_rev.field_type_rev.into();
match &field_type { match &field_type {
FieldType::RichText => { FieldType::RichText => {
let _ = cache.text_filter.insert(filter_id, GridTextFilter::from(filter_rev)); let _ = cache
.text_filter
.insert(filter_id, TextFilterConfigurationPB::from(filter_rev));
} }
FieldType::Number => { FieldType::Number => {
let _ = cache let _ = cache
.number_filter .number_filter
.insert(filter_id, GridNumberFilter::from(filter_rev)); .insert(filter_id, NumberFilterConfigurationPB::from(filter_rev));
} }
FieldType::DateTime => { FieldType::DateTime => {
let _ = cache.date_filter.insert(filter_id, GridDateFilter::from(filter_rev)); let _ = cache
.date_filter
.insert(filter_id, DateFilterConfigurationPB::from(filter_rev));
} }
FieldType::SingleSelect | FieldType::MultiSelect => { FieldType::SingleSelect | FieldType::MultiSelect => {
let _ = cache let _ = cache
.select_option_filter .select_option_filter
.insert(filter_id, GridSelectOptionFilter::from(filter_rev)); .insert(filter_id, SelectOptionFilterConfigurationPB::from(filter_rev));
} }
FieldType::Checkbox => { FieldType::Checkbox => {
let _ = cache let _ = cache
.checkbox_filter .checkbox_filter
.insert(filter_id, GridCheckboxFilter::from(filter_rev)); .insert(filter_id, CheckboxFilterConfigurationPB::from(filter_rev));
} }
FieldType::URL => { FieldType::URL => {
let _ = cache.url_filter.insert(filter_id, GridTextFilter::from(filter_rev)); let _ = cache
.url_filter
.insert(filter_id, TextFilterConfigurationPB::from(filter_rev));
} }
} }
} }

View File

@ -3,8 +3,8 @@ use crate::entities::{FieldType, GridBlockChangesetPB};
use crate::services::block_manager::GridBlockManager; use crate::services::block_manager::GridBlockManager;
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellFilterOperation};
use crate::services::field::{ use crate::services::field::{
CheckboxTypeOption, DateTypeOption, MultiSelectTypeOptionPB, NumberTypeOption, RichTextTypeOption, CheckboxTypeOption, DateTypeOptionPB, MultiSelectTypeOptionPB, NumberTypeOptionPB, RichTextTypeOptionPB,
SingleSelectTypeOptionPB, URLTypeOption, SingleSelectTypeOptionPB, URLTypeOptionPB,
}; };
use crate::services::filter::filter_cache::{ use crate::services::filter::filter_cache::{
refresh_filter_cache, FilterCache, FilterId, FilterResult, FilterResultCache, refresh_filter_cache, FilterCache, FilterId, FilterResult, FilterResultCache,
@ -182,7 +182,7 @@ fn filter_cell(
FieldType::RichText => filter_cache.text_filter.get(&filter_id).and_then(|filter| { FieldType::RichText => filter_cache.text_filter.get(&filter_id).and_then(|filter| {
Some( Some(
field_rev field_rev
.get_type_option_entry::<RichTextTypeOption>(field_type_rev)? .get_type_option_entry::<RichTextTypeOptionPB>(field_type_rev)?
.apply_filter(any_cell_data, filter.value()) .apply_filter(any_cell_data, filter.value())
.ok(), .ok(),
) )
@ -190,7 +190,7 @@ fn filter_cell(
FieldType::Number => filter_cache.number_filter.get(&filter_id).and_then(|filter| { FieldType::Number => filter_cache.number_filter.get(&filter_id).and_then(|filter| {
Some( Some(
field_rev field_rev
.get_type_option_entry::<NumberTypeOption>(field_type_rev)? .get_type_option_entry::<NumberTypeOptionPB>(field_type_rev)?
.apply_filter(any_cell_data, filter.value()) .apply_filter(any_cell_data, filter.value())
.ok(), .ok(),
) )
@ -198,7 +198,7 @@ fn filter_cell(
FieldType::DateTime => filter_cache.date_filter.get(&filter_id).and_then(|filter| { FieldType::DateTime => filter_cache.date_filter.get(&filter_id).and_then(|filter| {
Some( Some(
field_rev field_rev
.get_type_option_entry::<DateTypeOption>(field_type_rev)? .get_type_option_entry::<DateTypeOptionPB>(field_type_rev)?
.apply_filter(any_cell_data, filter.value()) .apply_filter(any_cell_data, filter.value())
.ok(), .ok(),
) )
@ -230,7 +230,7 @@ fn filter_cell(
FieldType::URL => filter_cache.url_filter.get(&filter_id).and_then(|filter| { FieldType::URL => filter_cache.url_filter.get(&filter_id).and_then(|filter| {
Some( Some(
field_rev field_rev
.get_type_option_entry::<URLTypeOption>(field_type_rev)? .get_type_option_entry::<URLTypeOptionPB>(field_type_rev)?
.apply_filter(any_cell_data, filter.value()) .apply_filter(any_cell_data, filter.value())
.ok(), .ok(),
) )

View File

@ -1,9 +1,9 @@
use crate::entities::{CheckboxCondition, GridCheckboxFilter}; use crate::entities::{CheckboxCondition, CheckboxFilterConfigurationPB};
use crate::services::cell::{AnyCellData, CellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{CheckboxCellData, CheckboxTypeOption}; use crate::services::field::{CheckboxCellData, CheckboxTypeOption};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
impl GridCheckboxFilter { impl CheckboxFilterConfigurationPB {
pub fn is_visible(&self, cell_data: &CheckboxCellData) -> bool { pub fn is_visible(&self, cell_data: &CheckboxCellData) -> bool {
let is_check = cell_data.is_check(); let is_check = cell_data.is_check();
match self.condition { match self.condition {
@ -13,8 +13,8 @@ impl GridCheckboxFilter {
} }
} }
impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption { impl CellFilterOperation<CheckboxFilterConfigurationPB> for CheckboxTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridCheckboxFilter) -> FlowyResult<bool> { fn apply_filter(&self, any_cell_data: AnyCellData, filter: &CheckboxFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_checkbox() { if !any_cell_data.is_checkbox() {
return Ok(true); return Ok(true);
} }
@ -26,13 +26,13 @@ impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::entities::{CheckboxCondition, GridCheckboxFilter}; use crate::entities::{CheckboxCondition, CheckboxFilterConfigurationPB};
use crate::services::field::CheckboxCellData; use crate::services::field::CheckboxCellData;
use std::str::FromStr; use std::str::FromStr;
#[test] #[test]
fn checkbox_filter_is_check_test() { fn checkbox_filter_is_check_test() {
let checkbox_filter = GridCheckboxFilter { let checkbox_filter = CheckboxFilterConfigurationPB {
condition: CheckboxCondition::IsChecked, condition: CheckboxCondition::IsChecked,
}; };
for (value, visible) in [("true", true), ("yes", true), ("false", false), ("no", false)] { for (value, visible) in [("true", true), ("yes", true), ("false", false), ("no", false)] {
@ -43,7 +43,7 @@ mod tests {
#[test] #[test]
fn checkbox_filter_is_uncheck_test() { fn checkbox_filter_is_uncheck_test() {
let checkbox_filter = GridCheckboxFilter { let checkbox_filter = CheckboxFilterConfigurationPB {
condition: CheckboxCondition::IsUnChecked, condition: CheckboxCondition::IsUnChecked,
}; };
for (value, visible) in [("false", true), ("no", true), ("true", false), ("yes", false)] { for (value, visible) in [("false", true), ("no", true), ("true", false), ("yes", false)] {

View File

@ -1,9 +1,9 @@
use crate::entities::{DateFilterCondition, GridDateFilter}; use crate::entities::{DateFilterCondition, DateFilterConfigurationPB};
use crate::services::cell::{AnyCellData, CellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{DateTimestamp, DateTypeOption}; use crate::services::field::{DateTimestamp, DateTypeOptionPB};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
impl GridDateFilter { impl DateFilterConfigurationPB {
pub fn is_visible<T: Into<i64>>(&self, cell_timestamp: T) -> bool { pub fn is_visible<T: Into<i64>>(&self, cell_timestamp: T) -> bool {
if self.start.is_none() { if self.start.is_none() {
return false; return false;
@ -29,8 +29,8 @@ impl GridDateFilter {
} }
} }
impl CellFilterOperation<GridDateFilter> for DateTypeOption { impl CellFilterOperation<DateFilterConfigurationPB> for DateTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridDateFilter) -> FlowyResult<bool> { fn apply_filter(&self, any_cell_data: AnyCellData, filter: &DateFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_date() { if !any_cell_data.is_date() {
return Ok(true); return Ok(true);
} }
@ -43,11 +43,11 @@ impl CellFilterOperation<GridDateFilter> for DateTypeOption {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#![allow(clippy::all)] #![allow(clippy::all)]
use crate::entities::{DateFilterCondition, GridDateFilter}; use crate::entities::{DateFilterCondition, DateFilterConfigurationPB};
#[test] #[test]
fn date_filter_is_test() { fn date_filter_is_test() {
let filter = GridDateFilter { let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateIs, condition: DateFilterCondition::DateIs,
start: Some(123), start: Some(123),
end: None, end: None,
@ -59,7 +59,7 @@ mod tests {
} }
#[test] #[test]
fn date_filter_before_test() { fn date_filter_before_test() {
let filter = GridDateFilter { let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateBefore, condition: DateFilterCondition::DateBefore,
start: Some(123), start: Some(123),
end: None, end: None,
@ -71,7 +71,7 @@ mod tests {
} }
#[test] #[test]
fn date_filter_before_or_on_test() { fn date_filter_before_or_on_test() {
let filter = GridDateFilter { let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateOnOrBefore, condition: DateFilterCondition::DateOnOrBefore,
start: Some(123), start: Some(123),
end: None, end: None,
@ -83,7 +83,7 @@ mod tests {
} }
#[test] #[test]
fn date_filter_after_test() { fn date_filter_after_test() {
let filter = GridDateFilter { let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateAfter, condition: DateFilterCondition::DateAfter,
start: Some(123), start: Some(123),
end: None, end: None,
@ -95,7 +95,7 @@ mod tests {
} }
#[test] #[test]
fn date_filter_within_test() { fn date_filter_within_test() {
let filter = GridDateFilter { let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateWithIn, condition: DateFilterCondition::DateWithIn,
start: Some(123), start: Some(123),
end: Some(130), end: Some(130),

View File

@ -1,12 +1,12 @@
use crate::entities::{GridNumberFilter, NumberFilterCondition}; use crate::entities::{NumberFilterCondition, NumberFilterConfigurationPB};
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellFilterOperation};
use crate::services::field::{NumberCellData, NumberTypeOption}; use crate::services::field::{NumberCellData, NumberTypeOptionPB};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
use rust_decimal::prelude::Zero; use rust_decimal::prelude::Zero;
use rust_decimal::Decimal; use rust_decimal::Decimal;
use std::str::FromStr; use std::str::FromStr;
impl GridNumberFilter { impl NumberFilterConfigurationPB {
pub fn is_visible(&self, num_cell_data: &NumberCellData) -> bool { pub fn is_visible(&self, num_cell_data: &NumberCellData) -> bool {
if self.content.is_none() { if self.content.is_none() {
return false; return false;
@ -31,8 +31,8 @@ impl GridNumberFilter {
} }
} }
impl CellFilterOperation<GridNumberFilter> for NumberTypeOption { impl CellFilterOperation<NumberFilterConfigurationPB> for NumberTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridNumberFilter) -> FlowyResult<bool> { fn apply_filter(&self, any_cell_data: AnyCellData, filter: &NumberFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_number() { if !any_cell_data.is_number() {
return Ok(true); return Ok(true);
} }
@ -46,11 +46,11 @@ impl CellFilterOperation<GridNumberFilter> for NumberTypeOption {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::entities::{GridNumberFilter, NumberFilterCondition}; use crate::entities::{NumberFilterCondition, NumberFilterConfigurationPB};
use crate::services::field::{NumberCellData, NumberFormat}; use crate::services::field::{NumberCellData, NumberFormat};
#[test] #[test]
fn number_filter_equal_test() { fn number_filter_equal_test() {
let number_filter = GridNumberFilter { let number_filter = NumberFilterConfigurationPB {
condition: NumberFilterCondition::Equal, condition: NumberFilterCondition::Equal,
content: Some("123".to_owned()), content: Some("123".to_owned()),
}; };
@ -68,7 +68,7 @@ mod tests {
} }
#[test] #[test]
fn number_filter_greater_than_test() { fn number_filter_greater_than_test() {
let number_filter = GridNumberFilter { let number_filter = NumberFilterConfigurationPB {
condition: NumberFilterCondition::GreaterThan, condition: NumberFilterCondition::GreaterThan,
content: Some("12".to_owned()), content: Some("12".to_owned()),
}; };
@ -80,7 +80,7 @@ mod tests {
#[test] #[test]
fn number_filter_less_than_test() { fn number_filter_less_than_test() {
let number_filter = GridNumberFilter { let number_filter = NumberFilterConfigurationPB {
condition: NumberFilterCondition::LessThan, condition: NumberFilterCondition::LessThan,
content: Some("100".to_owned()), content: Some("100".to_owned()),
}; };

View File

@ -1,12 +1,12 @@
#![allow(clippy::needless_collect)] #![allow(clippy::needless_collect)]
use crate::entities::{GridSelectOptionFilter, SelectOptionCondition}; use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB};
use crate::services::cell::{AnyCellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellFilterOperation};
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB}; use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
use crate::services::field::{SelectOptionOperation, SelectedSelectOptions}; use crate::services::field::{SelectOptionOperation, SelectedSelectOptions};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
impl GridSelectOptionFilter { impl SelectOptionFilterConfigurationPB {
pub fn is_visible(&self, selected_options: &SelectedSelectOptions) -> bool { pub fn is_visible(&self, selected_options: &SelectedSelectOptions) -> bool {
let selected_option_ids: Vec<&String> = selected_options.options.iter().map(|option| &option.id).collect(); let selected_option_ids: Vec<&String> = selected_options.options.iter().map(|option| &option.id).collect();
match self.condition { match self.condition {
@ -39,8 +39,12 @@ impl GridSelectOptionFilter {
} }
} }
impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOptionPB { impl CellFilterOperation<SelectOptionFilterConfigurationPB> for MultiSelectTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> { fn apply_filter(
&self,
any_cell_data: AnyCellData,
filter: &SelectOptionFilterConfigurationPB,
) -> FlowyResult<bool> {
if !any_cell_data.is_multi_select() { if !any_cell_data.is_multi_select() {
return Ok(true); return Ok(true);
} }
@ -50,8 +54,12 @@ impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOptionPB {
} }
} }
impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOptionPB { impl CellFilterOperation<SelectOptionFilterConfigurationPB> for SingleSelectTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> { fn apply_filter(
&self,
any_cell_data: AnyCellData,
filter: &SelectOptionFilterConfigurationPB,
) -> FlowyResult<bool> {
if !any_cell_data.is_single_select() { if !any_cell_data.is_single_select() {
return Ok(true); return Ok(true);
} }
@ -63,7 +71,7 @@ impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOptionPB {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#![allow(clippy::all)] #![allow(clippy::all)]
use crate::entities::{GridSelectOptionFilter, SelectOptionCondition}; use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB};
use crate::services::field::selection_type_option::{SelectOptionPB, SelectedSelectOptions}; use crate::services::field::selection_type_option::{SelectOptionPB, SelectedSelectOptions};
#[test] #[test]
@ -72,7 +80,7 @@ mod tests {
let option_2 = SelectOptionPB::new("B"); let option_2 = SelectOptionPB::new("B");
let option_3 = SelectOptionPB::new("C"); let option_3 = SelectOptionPB::new("C");
let filter_1 = GridSelectOptionFilter { let filter_1 = SelectOptionFilterConfigurationPB {
condition: SelectOptionCondition::OptionIs, condition: SelectOptionCondition::OptionIs,
option_ids: vec![option_1.id.clone(), option_2.id.clone()], option_ids: vec![option_1.id.clone(), option_2.id.clone()],
}; };

View File

@ -1,9 +1,9 @@
use crate::entities::{GridTextFilter, TextFilterCondition}; use crate::entities::{TextFilterCondition, TextFilterConfigurationPB};
use crate::services::cell::{AnyCellData, CellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{RichTextTypeOption, TextCellData}; use crate::services::field::{RichTextTypeOptionPB, TextCellData};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
impl GridTextFilter { impl TextFilterConfigurationPB {
pub fn is_visible<T: AsRef<str>>(&self, cell_data: T) -> bool { pub fn is_visible<T: AsRef<str>>(&self, cell_data: T) -> bool {
let cell_data = cell_data.as_ref(); let cell_data = cell_data.as_ref();
let s = cell_data.to_lowercase(); let s = cell_data.to_lowercase();
@ -24,8 +24,8 @@ impl GridTextFilter {
} }
} }
impl CellFilterOperation<GridTextFilter> for RichTextTypeOption { impl CellFilterOperation<TextFilterConfigurationPB> for RichTextTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> { fn apply_filter(&self, any_cell_data: AnyCellData, filter: &TextFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_text() { if !any_cell_data.is_text() {
return Ok(true); return Ok(true);
} }
@ -38,11 +38,11 @@ impl CellFilterOperation<GridTextFilter> for RichTextTypeOption {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#![allow(clippy::all)] #![allow(clippy::all)]
use crate::entities::{GridTextFilter, TextFilterCondition}; use crate::entities::{TextFilterCondition, TextFilterConfigurationPB};
#[test] #[test]
fn text_filter_equal_test() { fn text_filter_equal_test() {
let text_filter = GridTextFilter { let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::Is, condition: TextFilterCondition::Is,
content: Some("appflowy".to_owned()), content: Some("appflowy".to_owned()),
}; };
@ -54,7 +54,7 @@ mod tests {
} }
#[test] #[test]
fn text_filter_start_with_test() { fn text_filter_start_with_test() {
let text_filter = GridTextFilter { let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::StartsWith, condition: TextFilterCondition::StartsWith,
content: Some("appflowy".to_owned()), content: Some("appflowy".to_owned()),
}; };
@ -66,7 +66,7 @@ mod tests {
#[test] #[test]
fn text_filter_end_with_test() { fn text_filter_end_with_test() {
let text_filter = GridTextFilter { let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::EndsWith, condition: TextFilterCondition::EndsWith,
content: Some("appflowy".to_owned()), content: Some("appflowy".to_owned()),
}; };
@ -77,7 +77,7 @@ mod tests {
} }
#[test] #[test]
fn text_filter_empty_test() { fn text_filter_empty_test() {
let text_filter = GridTextFilter { let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::TextIsEmpty, condition: TextFilterCondition::TextIsEmpty,
content: Some("appflowy".to_owned()), content: Some("appflowy".to_owned()),
}; };
@ -87,7 +87,7 @@ mod tests {
} }
#[test] #[test]
fn text_filter_contain_test() { fn text_filter_contain_test() {
let text_filter = GridTextFilter { let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::Contains, condition: TextFilterCondition::Contains,
content: Some("appflowy".to_owned()), content: Some("appflowy".to_owned()),
}; };

View File

@ -1,10 +1,10 @@
use crate::entities::GridTextFilter; use crate::entities::TextFilterConfigurationPB;
use crate::services::cell::{AnyCellData, CellData, CellFilterOperation}; use crate::services::cell::{AnyCellData, CellData, CellFilterOperation};
use crate::services::field::{TextCellData, URLTypeOption}; use crate::services::field::{TextCellData, URLTypeOptionPB};
use flowy_error::FlowyResult; use flowy_error::FlowyResult;
impl CellFilterOperation<GridTextFilter> for URLTypeOption { impl CellFilterOperation<TextFilterConfigurationPB> for URLTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> { fn apply_filter(&self, any_cell_data: AnyCellData, filter: &TextFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_url() { if !any_cell_data.is_url() {
return Ok(true); return Ok(true);
} }

View File

@ -452,7 +452,7 @@ impl GridRevisionEditor {
pub async fn get_grid_setting(&self) -> FlowyResult<GridSettingPB> { pub async fn get_grid_setting(&self) -> FlowyResult<GridSettingPB> {
let read_guard = self.grid_pad.read().await; let read_guard = self.grid_pad.read().await;
let grid_setting_rev = read_guard.get_grid_setting_rev(); let grid_setting_rev = read_guard.get_setting_rev();
let field_revs = read_guard.get_field_revs(None)?; let field_revs = read_guard.get_field_revs(None)?;
let grid_setting = make_grid_setting(grid_setting_rev, &field_revs); let grid_setting = make_grid_setting(grid_setting_rev, &field_revs);
Ok(grid_setting) Ok(grid_setting)
@ -564,8 +564,9 @@ impl GridRevisionEditor {
}) })
} }
pub async fn get_group(&self) -> FlowyResult<RepeatedGridGroupPB> { pub async fn load_groups(&self) -> FlowyResult<RepeatedGridGroupPB> {
todo!() let groups = self.group_service.load_groups().await.unwrap_or(vec![]);
Ok(RepeatedGridGroupPB { items: groups })
} }
async fn modify<F>(&self, f: F) -> FlowyResult<()> async fn modify<F>(&self, f: F) -> FlowyResult<()>

View File

@ -1,5 +1,13 @@
use crate::entities::{
CheckboxGroupConfigurationPB, DateGroupConfigurationPB, FieldType, GroupPB, NumberGroupConfigurationPB,
SelectOptionGroupConfigurationPB, TextGroupConfigurationPB, UrlGroupConfigurationPB,
};
use crate::services::block_manager::GridBlockManager; use crate::services::block_manager::GridBlockManager;
use crate::services::cell::{decode_any_cell_data, CellBytes};
use crate::services::grid_editor_task::GridServiceTaskScheduler; use crate::services::grid_editor_task::GridServiceTaskScheduler;
use bytes::Bytes;
use flowy_error::FlowyResult;
use flowy_grid_data_model::revision::{CellRevision, FieldRevision, GroupConfigurationRevision, RowRevision};
use flowy_sync::client_grid::GridRevisionPad; use flowy_sync::client_grid::GridRevisionPad;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
@ -26,4 +34,116 @@ impl GridGroupService {
block_manager, block_manager,
} }
} }
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 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 groups = match field_type {
FieldType::RichText => {
let generator = GroupGenerator::<TextGroupConfigurationPB>::from_configuration(configuration);
}
FieldType::Number => {
let generator = GroupGenerator::<NumberGroupConfigurationPB>::from_configuration(configuration);
}
FieldType::DateTime => {
let generator = GroupGenerator::<DateGroupConfigurationPB>::from_configuration(configuration);
}
FieldType::SingleSelect => {
let generator = GroupGenerator::<SelectOptionGroupConfigurationPB>::from_configuration(configuration);
}
FieldType::MultiSelect => {
let generator = GroupGenerator::<SelectOptionGroupConfigurationPB>::from_configuration(configuration);
}
FieldType::Checkbox => {
let generator = GroupGenerator::<CheckboxGroupConfigurationPB>::from_configuration(configuration);
}
FieldType::URL => {
let generator = GroupGenerator::<UrlGroupConfigurationPB>::from_configuration(configuration);
}
};
None
}
}
pub struct GroupGenerator<T> {
field_id: String,
groups: Vec<Group>,
configuration: Option<T>,
}
pub struct Group {
row_ids: Vec<String>,
content: String,
}
impl<T> GroupGenerator<T>
where
T: TryFrom<Bytes, Error = protobuf::ProtobufError>,
{
pub fn from_configuration(configuration: GroupConfigurationRevision) -> FlowyResult<Self> {
let bytes = Bytes::from(configuration.content.unwrap_or(vec![]));
Self::from_bytes(&configuration.field_id, bytes)
}
pub fn from_bytes(field_id: &str, bytes: Bytes) -> FlowyResult<Self> {
let configuration = if bytes.is_empty() {
None
} else {
Some(T::try_from(bytes)?)
};
Ok(Self {
field_id: field_id.to_owned(),
groups: vec![],
configuration,
})
}
}
pub trait GroupConfiguration {
fn should_group(&self, content: &str, cell_bytes: CellBytes) -> bool;
}
impl<T> GroupGenerator<T>
where
T: GroupConfiguration,
{
pub fn group_row(&mut self, field_rev: &Arc<FieldRevision>, row: &RowRevision) {
if self.configuration.is_none() {
return;
}
let configuration = self.configuration.as_ref().unwrap();
if let Some(cell_rev) = row.cells.get(&self.field_id) {
for group in self.groups.iter_mut() {
let cell_rev: CellRevision = cell_rev.clone();
let cell_bytes = decode_any_cell_data(cell_rev.data, field_rev);
if configuration.should_group(&group.content, cell_bytes) {
group.row_ids.push(row.id.clone());
}
}
}
}
}
fn find_group_field(field_revs: &[Arc<FieldRevision>]) -> Option<&Arc<FieldRevision>> {
field_revs.iter().find(|field_rev| {
let field_type: FieldType = field_rev.field_type_rev.into();
field_type.can_be_group()
})
} }

View File

@ -0,0 +1,17 @@
use crate::entities::CheckboxGroupConfigurationPB;
use crate::services::cell::{AnyCellData, CellData, CellGroupOperation};
use crate::services::field::{CheckboxCellData, CheckboxTypeOption};
use flowy_error::FlowyResult;
impl CellGroupOperation for CheckboxTypeOption {
fn apply_group(&self, any_cell_data: AnyCellData, content: &str) -> FlowyResult<bool> {
if !any_cell_data.is_checkbox() {
return Ok(true);
}
let cell_data: CellData<CheckboxCellData> = any_cell_data.into();
let checkbox_cell_data = cell_data.try_into_inner()?;
// Ok(checkbox_cell_data.as_ref() == content)
todo!()
}
}

View File

@ -0,0 +1,11 @@
mod checkbox_group;
mod date_group;
mod number_group;
mod select_option_group;
mod text_group;
pub use checkbox_group::*;
pub use date_group::*;
pub use number_group::*;
pub use select_option_group::*;
pub use text_group::*;

View File

@ -0,0 +1,8 @@
use crate::entities::SelectOptionGroupConfigurationPB;
use crate::services::field::SelectedSelectOptions;
impl SelectOptionGroupConfigurationPB {
pub fn is_visible(&self, selected_options: &SelectedSelectOptions) -> bool {
return true;
}
}

View File

@ -1,3 +1,5 @@
mod group_service; mod group_service;
mod impls;
pub(crate) use group_service::*; pub(crate) use group_service::*;
pub(crate) use impls::*;

View File

@ -170,7 +170,7 @@ impl GridRowTest {
FieldType::Number => { FieldType::Number => {
let field_rev = self.editor.get_field_rev(&cell_id.field_id).await.unwrap(); let field_rev = self.editor.get_field_rev(&cell_id.field_id).await.unwrap();
let number_type_option = field_rev let number_type_option = field_rev
.get_type_option_entry::<NumberTypeOption>(FieldType::Number.into()) .get_type_option_entry::<NumberTypeOptionPB>(FieldType::Number.into())
.unwrap(); .unwrap();
let cell_data = self let cell_data = self
.editor .editor

View File

@ -12,7 +12,7 @@ pub fn create_text_field(grid_id: &str) -> (InsertFieldParams, FieldRevision) {
let cloned_field_rev = field_rev.clone(); let cloned_field_rev = field_rev.clone();
let type_option_data = field_rev let type_option_data = field_rev
.get_type_option_entry::<RichTextTypeOption>(field_rev.field_type_rev) .get_type_option_entry::<RichTextTypeOptionPB>(field_rev.field_type_rev)
.unwrap() .unwrap()
.protobuf_bytes() .protobuf_bytes()
.to_vec(); .to_vec();

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)]
pub struct GridFilterRevision { pub struct FilterConfigurationRevision {
pub id: String, pub id: String,
pub field_id: String, pub field_id: String,
pub condition: u8, pub condition: u8,

View File

@ -1,8 +1,10 @@
use crate::revision::FieldTypeRevision;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct GridGroupRevision { pub struct GroupConfigurationRevision {
pub id: String, pub id: String,
pub field_id: String, pub field_id: String,
pub sub_field_id: Option<String>, pub field_type_rev: FieldTypeRevision,
pub content: Option<Vec<u8>>,
} }

View File

@ -171,6 +171,7 @@ impl FieldRevision {
pub fn get_type_option_entry<T: TypeOptionDataDeserializer>(&self, field_type_rev: FieldTypeRevision) -> Option<T> { pub fn get_type_option_entry<T: TypeOptionDataDeserializer>(&self, field_type_rev: FieldTypeRevision) -> Option<T> {
let id = field_type_rev.to_string(); let id = field_type_rev.to_string();
// TODO: cache the deserialized type option
self.type_options.get(&id).map(|s| T::from_json_str(s)) self.type_options.get(&id).map(|s| T::from_json_str(s))
} }

View File

@ -1,5 +1,5 @@
use crate::revision::filter_rev::GridFilterRevision; use crate::revision::filter_rev::FilterConfigurationRevision;
use crate::revision::grid_group::GridGroupRevision; use crate::revision::grid_group::GroupConfigurationRevision;
use crate::revision::{FieldRevision, FieldTypeRevision}; use crate::revision::{FieldRevision, FieldTypeRevision};
use indexmap::IndexMap; use indexmap::IndexMap;
use nanoid::nanoid; use nanoid::nanoid;
@ -21,29 +21,29 @@ pub fn gen_grid_sort_id() -> String {
nanoid!(6) nanoid!(6)
} }
pub type GridFilters = SettingContainer<GridFilterRevision>; pub type FilterConfigurations = SettingConfiguration<FilterConfigurationRevision>;
pub type GridFilterRevisionMap = GridObjectRevisionMap<GridFilterRevision>; pub type FilterConfigurationRevisionMap = GridObjectRevisionMap<FilterConfigurationRevision>;
pub type FiltersByFieldId = HashMap<String, Vec<Arc<GridFilterRevision>>>; pub type FilterConfigurationsByFieldId = HashMap<String, Vec<Arc<FilterConfigurationRevision>>>;
// //
pub type GridGroups = SettingContainer<GridGroupRevision>; pub type GroupConfigurations = SettingConfiguration<GroupConfigurationRevision>;
pub type GridGroupRevisionMap = GridObjectRevisionMap<GridGroupRevision>; pub type GroupConfigurationRevisionMap = GridObjectRevisionMap<GroupConfigurationRevision>;
pub type GroupsByFieldId = HashMap<String, Vec<Arc<GridGroupRevision>>>; pub type GroupConfigurationsByFieldId = HashMap<String, Vec<Arc<GroupConfigurationRevision>>>;
// //
pub type GridSorts = SettingContainer<GridSortRevision>; pub type SortConfigurations = SettingConfiguration<SortConfigurationRevision>;
pub type GridSortRevisionMap = GridObjectRevisionMap<GridSortRevision>; pub type SortConfigurationRevisionMap = GridObjectRevisionMap<SortConfigurationRevision>;
pub type SortsByFieldId = HashMap<String, Vec<Arc<GridSortRevision>>>; pub type SortConfigurationsByFieldId = HashMap<String, Vec<Arc<SortConfigurationRevision>>>;
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
pub struct GridSettingRevision { pub struct GridSettingRevision {
pub layout: GridLayoutRevision, pub layout: GridLayoutRevision,
pub filters: GridFilters, pub filters: FilterConfigurations,
#[serde(default)] #[serde(default)]
pub groups: GridGroups, pub groups: GroupConfigurations,
#[serde(skip)] #[serde(skip)]
pub sorts: GridSorts, pub sorts: SortConfigurations,
} }
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)] #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
@ -67,7 +67,7 @@ impl std::default::Default for GridLayoutRevision {
} }
impl GridSettingRevision { impl GridSettingRevision {
pub fn get_all_groups(&self, field_revs: &[Arc<FieldRevision>]) -> Option<GroupsByFieldId> { pub fn get_all_groups(&self, field_revs: &[Arc<FieldRevision>]) -> Option<GroupConfigurationsByFieldId> {
self.groups.get_all_objects(&self.layout, field_revs) self.groups.get_all_objects(&self.layout, field_revs)
} }
@ -76,7 +76,7 @@ impl GridSettingRevision {
layout: &GridLayoutRevision, layout: &GridLayoutRevision,
field_id: &str, field_id: &str,
field_type_rev: &FieldTypeRevision, field_type_rev: &FieldTypeRevision,
) -> Option<Vec<Arc<GridGroupRevision>>> { ) -> Option<Vec<Arc<GroupConfigurationRevision>>> {
self.groups.get_objects(layout, field_id, field_type_rev) self.groups.get_objects(layout, field_id, field_type_rev)
} }
@ -85,7 +85,7 @@ impl GridSettingRevision {
layout: &GridLayoutRevision, layout: &GridLayoutRevision,
field_id: &str, field_id: &str,
field_type: &FieldTypeRevision, field_type: &FieldTypeRevision,
) -> Option<&mut Vec<Arc<GridGroupRevision>>> { ) -> Option<&mut Vec<Arc<GroupConfigurationRevision>>> {
self.groups.get_mut_objects(layout, field_id, field_type) self.groups.get_mut_objects(layout, field_id, field_type)
} }
@ -94,12 +94,13 @@ impl GridSettingRevision {
layout: &GridLayoutRevision, layout: &GridLayoutRevision,
field_id: &str, field_id: &str,
field_type: &FieldTypeRevision, field_type: &FieldTypeRevision,
group_rev: GridGroupRevision, group_rev: GroupConfigurationRevision,
) { ) {
self.groups.remove_all(layout);
self.groups.insert_object(layout, field_id, field_type, group_rev); self.groups.insert_object(layout, field_id, field_type, group_rev);
} }
pub fn get_all_filters(&self, field_revs: &[Arc<FieldRevision>]) -> Option<FiltersByFieldId> { pub fn get_all_filters(&self, field_revs: &[Arc<FieldRevision>]) -> Option<FilterConfigurationsByFieldId> {
self.filters.get_all_objects(&self.layout, field_revs) self.filters.get_all_objects(&self.layout, field_revs)
} }
@ -108,7 +109,7 @@ impl GridSettingRevision {
layout: &GridLayoutRevision, layout: &GridLayoutRevision,
field_id: &str, field_id: &str,
field_type_rev: &FieldTypeRevision, field_type_rev: &FieldTypeRevision,
) -> Option<Vec<Arc<GridFilterRevision>>> { ) -> Option<Vec<Arc<FilterConfigurationRevision>>> {
self.filters.get_objects(layout, field_id, field_type_rev) self.filters.get_objects(layout, field_id, field_type_rev)
} }
@ -117,7 +118,7 @@ impl GridSettingRevision {
layout: &GridLayoutRevision, layout: &GridLayoutRevision,
field_id: &str, field_id: &str,
field_type: &FieldTypeRevision, field_type: &FieldTypeRevision,
) -> Option<&mut Vec<Arc<GridFilterRevision>>> { ) -> Option<&mut Vec<Arc<FilterConfigurationRevision>>> {
self.filters.get_mut_objects(layout, field_id, field_type) self.filters.get_mut_objects(layout, field_id, field_type)
} }
@ -126,25 +127,25 @@ impl GridSettingRevision {
layout: &GridLayoutRevision, layout: &GridLayoutRevision,
field_id: &str, field_id: &str,
field_type: &FieldTypeRevision, field_type: &FieldTypeRevision,
filter_rev: GridFilterRevision, filter_rev: FilterConfigurationRevision,
) { ) {
self.filters.insert_object(layout, field_id, field_type, filter_rev); self.filters.insert_object(layout, field_id, field_type, filter_rev);
} }
pub fn get_all_sort(&self) -> Option<SortsByFieldId> { pub fn get_all_sort(&self) -> Option<SortConfigurationsByFieldId> {
None None
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct GridSortRevision { pub struct SortConfigurationRevision {
pub id: String, pub id: String,
pub field_id: Option<String>, pub field_id: Option<String>,
} }
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
#[serde(transparent)] #[serde(transparent)]
pub struct SettingContainer<T> pub struct SettingConfiguration<T>
where where
T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static,
{ {
@ -157,7 +158,7 @@ where
inner: IndexMap<GridLayoutRevision, IndexMap<String, GridObjectRevisionMap<T>>>, inner: IndexMap<GridLayoutRevision, IndexMap<String, GridObjectRevisionMap<T>>>,
} }
impl<T> SettingContainer<T> impl<T> SettingConfiguration<T>
where where
T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static, T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static,
{ {
@ -229,6 +230,12 @@ where
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push(Arc::new(object)) .push(Arc::new(object))
} }
pub fn remove_all(&mut self, layout: &GridLayoutRevision) {
if let Some(object_rev_map_by_field_id) = self.inner.get_mut(layout) {
object_rev_map_by_field_id.clear()
}
}
} }
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]

View File

@ -2,10 +2,8 @@ mod filter_rev;
mod grid_group; mod grid_group;
mod grid_rev; mod grid_rev;
mod grid_setting_rev; mod grid_setting_rev;
mod grid_sort;
pub use filter_rev::*; pub use filter_rev::*;
pub use grid_group::*; pub use grid_group::*;
pub use grid_rev::*; pub use grid_rev::*;
pub use grid_setting_rev::*; pub use grid_setting_rev::*;
pub use grid_sort::*;

View File

@ -8,6 +8,6 @@ fn grid_default_serde_test() {
let json = serde_json::to_string(&grid).unwrap(); let json = serde_json::to_string(&grid).unwrap();
assert_eq!( assert_eq!(
json, json,
r#"{"grid_id":"1","fields":[],"blocks":[],"setting":{"layout":0,"filters":[]}}"# r#"{"grid_id":"1","fields":[],"blocks":[],"setting":{"layout":0,"filters":[],"groups":[]}}"#
) )
} }

View File

@ -6,9 +6,9 @@ use crate::errors::{internal_error, CollaborateError, CollaborateResult};
use crate::util::{cal_diff, make_delta_from_revisions}; use crate::util::{cal_diff, make_delta_from_revisions};
use bytes::Bytes; use bytes::Bytes;
use flowy_grid_data_model::revision::{ use flowy_grid_data_model::revision::{
gen_block_id, gen_grid_filter_id, gen_grid_group_id, gen_grid_id, gen_grid_sort_id, FieldRevision, gen_block_id, gen_grid_filter_id, gen_grid_group_id, gen_grid_id, FieldRevision, FieldTypeRevision,
FieldTypeRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridFilterRevision, GridGroupRevision, FilterConfigurationRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridLayoutRevision,
GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision, GridRevision, GridSettingRevision, GroupConfigurationRevision,
}; };
use lib_infra::util::move_vec_element; use lib_infra::util::move_vec_element;
use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder}; use lib_ot::core::{OperationTransform, PhantomAttributes, TextDelta, TextDeltaBuilder};
@ -341,7 +341,7 @@ impl GridRevisionPad {
}) })
} }
pub fn get_grid_setting_rev(&self) -> &GridSettingRevision { pub fn get_setting_rev(&self) -> &GridSettingRevision {
&self.grid_rev.setting &self.grid_rev.setting
} }
@ -350,7 +350,7 @@ impl GridRevisionPad {
&self, &self,
layout: Option<&GridLayoutRevision>, layout: Option<&GridLayoutRevision>,
field_ids: Option<Vec<String>>, field_ids: Option<Vec<String>>,
) -> Option<Vec<Arc<GridFilterRevision>>> { ) -> Option<Vec<Arc<FilterConfigurationRevision>>> {
let mut filter_revs = vec![]; let mut filter_revs = vec![];
let layout_ty = layout.unwrap_or(&self.grid_rev.setting.layout); let layout_ty = layout.unwrap_or(&self.grid_rev.setting.layout);
let field_revs = self.get_field_revs(None).ok()?; let field_revs = self.get_field_revs(None).ok()?;
@ -419,7 +419,7 @@ impl GridRevisionPad {
groups.retain(|filter| filter.id != params.group_id); groups.retain(|filter| filter.id != params.group_id);
} }
} }
if let Some(sort) = changeset.insert_sort { if let Some(_sort) = changeset.insert_sort {
// let rev = GridSortRevision { // let rev = GridSortRevision {
// id: gen_grid_sort_id(), // id: gen_grid_sort_id(),
// field_id: sort.field_id, // field_id: sort.field_id,
@ -434,7 +434,7 @@ impl GridRevisionPad {
is_changed = Some(()) is_changed = Some(())
} }
if let Some(delete_sort_id) = changeset.delete_sort { if let Some(_delete_sort_id) = changeset.delete_sort {
// match grid_rev.setting.sorts.get_mut(&layout_rev) { // match grid_rev.setting.sorts.get_mut(&layout_rev) {
// Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id), // Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id),
// None => { // None => {
@ -559,19 +559,20 @@ impl std::default::Default for GridRevisionPad {
} }
} }
fn make_filter_revision(params: &CreateGridFilterParams) -> GridFilterRevision { fn make_filter_revision(params: &CreateGridFilterParams) -> FilterConfigurationRevision {
GridFilterRevision { FilterConfigurationRevision {
id: gen_grid_filter_id(), id: gen_grid_filter_id(),
field_id: params.field_id.clone(), field_id: params.field_id.clone(),
condition: params.condition.clone(), condition: params.condition,
content: params.content.clone(), content: params.content.clone(),
} }
} }
fn make_group_revision(params: &CreateGridGroupParams) -> GridGroupRevision { fn make_group_revision(params: &CreateGridGroupParams) -> GroupConfigurationRevision {
GridGroupRevision { GroupConfigurationRevision {
id: gen_grid_group_id(), id: gen_grid_group_id(),
field_id: params.field_id.clone(), field_id: params.field_id.clone(),
sub_field_id: params.sub_field_id.clone(), field_type_rev: params.field_type_rev.clone(),
content: params.content.clone(),
} }
} }

View File

@ -31,8 +31,8 @@ pub struct DeleteFilterParams {
pub struct CreateGridGroupParams { pub struct CreateGridGroupParams {
pub field_id: String, pub field_id: String,
pub sub_field_id: Option<String>,
pub field_type_rev: FieldTypeRevision, pub field_type_rev: FieldTypeRevision,
pub content: Option<Vec<u8>>,
} }
pub struct DeleteGroupParams { pub struct DeleteGroupParams {