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 '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/presentation/widgets/header/type_option/builder.dart';
import 'package:appflowy_board/appflowy_board.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
@ -57,8 +56,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
didReceiveGridUpdate: (GridPB grid) {
emit(state.copyWith(grid: Some(grid)));
},
groupByField: (FieldPB field) {
emit(state.copyWith(groupField: Some(field)));
didReceiveGroups: (List<GroupPB> groups) {
emit(state.copyWith(groups: groups));
},
);
},
@ -83,50 +82,20 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
add(BoardEvent.didReceiveGridUpdate(grid));
}
},
onFieldsChanged: (fields) {
if (!isClosed) {
_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) {
onGroupChanged: (groups) {
List<AFBoardColumnData> columns = groups.map((group) {
return AFBoardColumnData(
id: option.id,
desc: option.name,
customData: option,
id: group.groupId,
desc: group.desc,
customData: group,
);
}).toList();
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 {
const factory BoardEvent.initial() = InitialGrid;
const factory BoardEvent.createRow() = _CreateRow;
const factory BoardEvent.groupByField(FieldPB field) = _GroupByField;
const factory BoardEvent.didReceiveGroups(List<GroupPB> groups) =
_DidReceiveGroup;
const factory BoardEvent.didReceiveGridUpdate(
GridPB grid,
) = _DidReceiveGridUpdate;
@ -158,14 +128,14 @@ class BoardState with _$BoardState {
const factory BoardState({
required String gridId,
required Option<GridPB> grid,
required Option<FieldPB> groupField,
required List<GroupPB> groups,
required List<RowInfo> rowInfos,
required GridLoadingState loadingState,
}) = _BoardState;
factory BoardState.initial(String gridId) => BoardState(
rowInfos: [],
groupField: none(),
groups: [],
grid: none(),
gridId: gridId,
loadingState: const _Loading(),

View File

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

View File

@ -518,6 +518,14 @@ pub enum FieldType {
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 {
fn default() -> Self {
FieldType::RichText
@ -549,35 +557,39 @@ impl FieldType {
}
pub fn is_number(&self) -> bool {
self == &FieldType::Number
self == &NUMBER_FIELD
}
pub fn is_text(&self) -> bool {
self == &FieldType::RichText
self == &RICH_TEXT_FIELD
}
pub fn is_checkbox(&self) -> bool {
self == &FieldType::Checkbox
self == &CHECKBOX_FIELD
}
pub fn is_date(&self) -> bool {
self == &FieldType::DateTime
self == &DATE_FIELD
}
pub fn is_single_select(&self) -> bool {
self == &FieldType::SingleSelect
self == &SINGLE_SELECT_FIELD
}
pub fn is_multi_select(&self) -> bool {
self == &FieldType::MultiSelect
self == &MULTI_SELECT_FIELD
}
pub fn is_url(&self) -> bool {
self == &FieldType::URL
self == &URL_FIELD
}
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_error::ErrorCode;
use flowy_grid_data_model::revision::GridFilterRevision;
use flowy_grid_data_model::revision::FilterConfigurationRevision;
use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridCheckboxFilter {
pub struct CheckboxFilterConfigurationPB {
#[pb(index = 1)]
pub condition: CheckboxCondition,
}
@ -40,9 +40,9 @@ impl std::convert::TryFrom<u8> for CheckboxCondition {
}
}
impl std::convert::From<Arc<GridFilterRevision>> for GridCheckboxFilter {
fn from(rev: Arc<GridFilterRevision>) -> Self {
GridCheckboxFilter {
impl std::convert::From<Arc<FilterConfigurationRevision>> for CheckboxFilterConfigurationPB {
fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
CheckboxFilterConfigurationPB {
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_error::ErrorCode;
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 std::str::FromStr;
use std::sync::Arc;
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct GridDateFilter {
pub struct DateFilterConfigurationPB {
#[pb(index = 1)]
pub condition: DateFilterCondition,
@ -120,10 +120,10 @@ impl std::convert::TryFrom<u8> for DateFilterCondition {
}
}
}
impl std::convert::From<Arc<GridFilterRevision>> for GridDateFilter {
fn from(rev: Arc<GridFilterRevision>) -> Self {
impl std::convert::From<Arc<FilterConfigurationRevision>> for DateFilterConfigurationPB {
fn from(rev: Arc<FilterConfigurationRevision>) -> Self {
let condition = DateFilterCondition::try_from(rev.condition).unwrap_or(DateFilterCondition::DateIs);
let mut filter = GridDateFilter {
let mut filter = DateFilterConfigurationPB {
condition,
..Default::default()
};

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@ use crate::entities::{
use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode;
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 std::convert::TryInto;
use std::sync::Arc;
@ -22,14 +22,14 @@ pub struct RepeatedGridConfigurationFilterPB {
pub items: Vec<GridFilterConfiguration>,
}
impl std::convert::From<&GridFilterRevision> for GridFilterConfiguration {
fn from(rev: &GridFilterRevision) -> Self {
impl std::convert::From<&FilterConfigurationRevision> for GridFilterConfiguration {
fn from(rev: &FilterConfigurationRevision) -> Self {
Self { id: rev.id.clone() }
}
}
impl std::convert::From<Vec<Arc<GridFilterRevision>>> for RepeatedGridConfigurationFilterPB {
fn from(revs: Vec<Arc<GridFilterRevision>>) -> Self {
impl std::convert::From<Vec<Arc<FilterConfigurationRevision>>> for RepeatedGridConfigurationFilterPB {
fn from(revs: Vec<Arc<FilterConfigurationRevision>>) -> Self {
RepeatedGridConfigurationFilterPB {
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_error::ErrorCode;
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 std::convert::TryInto;
use std::sync::Arc;
@ -14,17 +14,13 @@ pub struct GridGroupConfigurationPB {
#[pb(index = 2)]
pub group_field_id: String,
#[pb(index = 3, one_of)]
pub sub_group_field_id: Option<String>,
}
impl std::convert::From<&GridGroupRevision> for GridGroupConfigurationPB {
fn from(rev: &GridGroupRevision) -> Self {
impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationPB {
fn from(rev: &GroupConfigurationRevision) -> Self {
GridGroupConfigurationPB {
id: rev.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)]
pub struct RepeatedGridGroupPB {
#[pb(index = 1)]
items: Vec<GroupPB>,
pub(crate) items: Vec<GroupPB>,
}
#[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 {
fn from(revs: Vec<Arc<GridGroupRevision>>) -> Self {
impl std::convert::From<Vec<Arc<GroupConfigurationRevision>>> for RepeatedGridGroupConfigurationPB {
fn from(revs: Vec<Arc<GroupConfigurationRevision>>) -> Self {
RepeatedGridGroupConfigurationPB {
items: revs.iter().map(|rev| rev.as_ref().into()).collect(),
}
@ -72,11 +68,11 @@ pub struct CreateGridGroupPayloadPB {
#[pb(index = 1)]
pub field_id: String,
#[pb(index = 2, one_of)]
pub sub_field_id: Option<String>,
#[pb(index = 3)]
#[pb(index = 2)]
pub field_type: FieldType,
#[pb(index = 3, one_of)]
pub content: Option<Vec<u8>>,
}
impl TryInto<CreateGridGroupParams> for CreateGridGroupPayloadPB {
@ -87,15 +83,10 @@ impl TryInto<CreateGridGroupParams> for CreateGridGroupPayloadPB {
.map_err(|_| ErrorCode::FieldIdIsEmpty)?
.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 {
field_id,
sub_field_id,
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 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 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_error::ErrorCode;
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 std::convert::TryInto;
use std::sync::Arc;
@ -15,8 +15,8 @@ pub struct GridSort {
pub field_id: Option<String>,
}
impl std::convert::From<&GridSortRevision> for GridSort {
fn from(rev: &GridSortRevision) -> Self {
impl std::convert::From<&SortConfigurationRevision> for GridSort {
fn from(rev: &SortConfigurationRevision) -> Self {
GridSort {
id: rev.id.clone(),
@ -31,8 +31,8 @@ pub struct RepeatedGridSortPB {
pub items: Vec<GridSort>,
}
impl std::convert::From<Vec<Arc<GridSortRevision>>> for RepeatedGridSortPB {
fn from(revs: Vec<Arc<GridSortRevision>>) -> Self {
impl std::convert::From<Vec<Arc<SortConfigurationRevision>>> for RepeatedGridSortPB {
fn from(revs: Vec<Arc<SortConfigurationRevision>>) -> Self {
RepeatedGridSortPB {
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)]
pub(crate) async fn get_group_handler(
pub(crate) async fn get_groups_handler(
data: Data<GridIdPB>,
manager: AppData<Arc<GridManager>>,
) -> DataResult<RepeatedGridGroupPB, FlowyError> {
let params: GridIdPB = data.into_inner();
let editor = manager.get_grid_editor(&params.value)?;
let group = editor.get_group().await?;
let group = editor.load_groups().await?;
data_result(group)
}

View File

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

View File

@ -11,6 +11,10 @@ pub trait CellFilterOperation<T> {
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.
pub trait CellDisplayable<CD> {
fn display_data(
@ -55,15 +59,15 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
let changeset = changeset.to_string();
let field_type = field_rev.field_type_rev.into();
let s = match field_type {
FieldType::RichText => RichTextTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::Number => NumberTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::DateTime => DateTypeOption::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::RichText => RichTextTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::Number => NumberTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::DateTime => DateTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev),
FieldType::SingleSelect => {
SingleSelectTypeOptionPB::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::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())
@ -97,13 +101,13 @@ pub fn try_decode_cell_data(
let field_type: FieldTypeRevision = t_field_type.into();
let data = match t_field_type {
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),
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),
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),
FieldType::SingleSelect => field_rev
.get_type_option_entry::<SingleSelectTypeOptionPB>(field_type)?
@ -115,7 +119,7 @@ pub fn try_decode_cell_data(
.get_type_option_entry::<CheckboxTypeOption>(field_type)?
.decode_cell_data(cell_data.into(), s_field_type, 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),
};
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> {
let s: String = match field_type {
FieldType::RichText => RichTextTypeOption::default().into(),
FieldType::Number => NumberTypeOption::default().into(),
FieldType::DateTime => DateTypeOption::default().into(),
FieldType::RichText => RichTextTypeOptionPB::default().into(),
FieldType::Number => NumberTypeOptionPB::default().into(),
FieldType::DateTime => DateTypeOptionPB::default().into(),
FieldType::SingleSelect => SingleSelectTypeOptionPB::default().into(),
FieldType::MultiSelect => MultiSelectTypeOptionPB::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)

View File

@ -9,7 +9,7 @@ mod tests {
#[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();
for date_format in DateFormat::iter() {
type_option.date_format = date_format;
@ -32,7 +32,7 @@ mod tests {
#[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_rev = FieldBuilder::from_field_type(&field_type).build();
@ -66,7 +66,7 @@ mod tests {
#[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_rev = FieldBuilder::from_field_type(&field_type).build();
assert_date(&type_option, "abc", None, "", &field_rev);
@ -75,7 +75,7 @@ mod tests {
#[test]
#[should_panic]
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;
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
@ -90,7 +90,7 @@ mod tests {
#[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;
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
@ -101,7 +101,7 @@ mod tests {
#[test]
#[should_panic]
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;
let field_rev = FieldBuilder::from_field_type(&FieldType::DateTime).build();
@ -114,7 +114,7 @@ mod tests {
);
}
fn assert_date<T: ToString>(
type_option: &DateTypeOption,
type_option: &DateTypeOptionPB,
timestamp: T,
include_time_str: Option<String>,
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
.decode_cell_data(encoded_data.into(), &FieldType::DateTime, field_rev)
.unwrap()

View File

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

View File

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

View File

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

View File

@ -12,9 +12,9 @@ use flowy_grid_data_model::revision::{CellRevision, FieldRevision, TypeOptionDat
use serde::{Deserialize, Serialize};
#[derive(Default)]
pub struct RichTextTypeOptionBuilder(RichTextTypeOption);
pub struct RichTextTypeOptionBuilder(RichTextTypeOptionPB);
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 {
fn field_type(&self) -> FieldType {
@ -27,13 +27,13 @@ impl TypeOptionBuilder for RichTextTypeOptionBuilder {
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
pub struct RichTextTypeOption {
pub struct RichTextTypeOptionPB {
#[pb(index = 1)]
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(
&self,
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(
&self,
cell_data: CellData<String>,
@ -114,7 +114,7 @@ mod tests {
#[test]
fn text_description_test() {
let type_option = RichTextTypeOption::default();
let type_option = RichTextTypeOptionPB::default();
// date
let field_type = FieldType::DateTime;

View File

@ -3,14 +3,14 @@ mod tests {
use crate::entities::FieldType;
use crate::services::cell::{CellData, CellDataOperation};
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;
/// 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.
#[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_rev = FieldBuilder::from_field_type(&field_type).build();
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.
#[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_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url(
@ -46,7 +46,7 @@ mod tests {
/// if there's a http url and some words following it in the input string.
#[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_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url(
@ -71,7 +71,7 @@ mod tests {
/// if there's a http url and special words following it in the input string.
#[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_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url(
@ -96,7 +96,7 @@ mod tests {
/// if there's a level4 url in the input string.
#[test]
fn level4_url_type_test() {
let type_option = URLTypeOption::default();
let type_option = URLTypeOptionPB::default();
let field_type = FieldType::URL;
let field_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url(
@ -121,7 +121,7 @@ mod tests {
/// urls with 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_rev = FieldBuilder::from_field_type(&field_type).build();
assert_url(
@ -162,7 +162,7 @@ mod tests {
}
fn assert_url(
type_option: &URLTypeOption,
type_option: &URLTypeOptionPB,
input_str: &str,
expected_str: &str,
expected_url: &str,
@ -177,7 +177,7 @@ mod tests {
fn decode_cell_data<T: Into<CellData<URLCellDataPB>>>(
encoded_data: T,
type_option: &URLTypeOption,
type_option: &URLTypeOptionPB,
field_rev: &FieldRevision,
field_type: &FieldType,
) -> URLCellDataPB {

View File

@ -11,9 +11,9 @@ use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
#[derive(Default)]
pub struct URLTypeOptionBuilder(URLTypeOption);
pub struct URLTypeOptionBuilder(URLTypeOptionPB);
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 {
fn field_type(&self) -> FieldType {
@ -26,13 +26,13 @@ impl TypeOptionBuilder for URLTypeOptionBuilder {
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
pub struct URLTypeOption {
pub struct URLTypeOptionPB {
#[pb(index = 1)]
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(
&self,
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(
&self,
cell_data: CellData<URLCellDataPB>,

View File

@ -1,5 +1,6 @@
use crate::entities::{
FieldType, GridCheckboxFilter, GridDateFilter, GridNumberFilter, GridSelectOptionFilter, GridTextFilter,
CheckboxFilterConfigurationPB, DateFilterConfigurationPB, FieldType, NumberFilterConfigurationPB,
SelectOptionFilterConfigurationPB, TextFilterConfigurationPB,
};
use dashmap::DashMap;
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
@ -58,12 +59,12 @@ impl FilterResult {
#[derive(Default)]
pub(crate) struct FilterCache {
pub(crate) text_filter: DashMap<FilterId, GridTextFilter>,
pub(crate) url_filter: DashMap<FilterId, GridTextFilter>,
pub(crate) number_filter: DashMap<FilterId, GridNumberFilter>,
pub(crate) date_filter: DashMap<FilterId, GridDateFilter>,
pub(crate) select_option_filter: DashMap<FilterId, GridSelectOptionFilter>,
pub(crate) checkbox_filter: DashMap<FilterId, GridCheckboxFilter>,
pub(crate) text_filter: DashMap<FilterId, TextFilterConfigurationPB>,
pub(crate) url_filter: DashMap<FilterId, TextFilterConfigurationPB>,
pub(crate) number_filter: DashMap<FilterId, NumberFilterConfigurationPB>,
pub(crate) date_filter: DashMap<FilterId, DateFilterConfigurationPB>,
pub(crate) select_option_filter: DashMap<FilterId, SelectOptionFilterConfigurationPB>,
pub(crate) checkbox_filter: DashMap<FilterId, CheckboxFilterConfigurationPB>,
}
impl FilterCache {
@ -117,28 +118,34 @@ pub(crate) async fn refresh_filter_cache(
let field_type: FieldType = field_rev.field_type_rev.into();
match &field_type {
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 => {
let _ = cache
.number_filter
.insert(filter_id, GridNumberFilter::from(filter_rev));
.insert(filter_id, NumberFilterConfigurationPB::from(filter_rev));
}
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 => {
let _ = cache
.select_option_filter
.insert(filter_id, GridSelectOptionFilter::from(filter_rev));
.insert(filter_id, SelectOptionFilterConfigurationPB::from(filter_rev));
}
FieldType::Checkbox => {
let _ = cache
.checkbox_filter
.insert(filter_id, GridCheckboxFilter::from(filter_rev));
.insert(filter_id, CheckboxFilterConfigurationPB::from(filter_rev));
}
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::cell::{AnyCellData, CellFilterOperation};
use crate::services::field::{
CheckboxTypeOption, DateTypeOption, MultiSelectTypeOptionPB, NumberTypeOption, RichTextTypeOption,
SingleSelectTypeOptionPB, URLTypeOption,
CheckboxTypeOption, DateTypeOptionPB, MultiSelectTypeOptionPB, NumberTypeOptionPB, RichTextTypeOptionPB,
SingleSelectTypeOptionPB, URLTypeOptionPB,
};
use crate::services::filter::filter_cache::{
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| {
Some(
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())
.ok(),
)
@ -190,7 +190,7 @@ fn filter_cell(
FieldType::Number => filter_cache.number_filter.get(&filter_id).and_then(|filter| {
Some(
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())
.ok(),
)
@ -198,7 +198,7 @@ fn filter_cell(
FieldType::DateTime => filter_cache.date_filter.get(&filter_id).and_then(|filter| {
Some(
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())
.ok(),
)
@ -230,7 +230,7 @@ fn filter_cell(
FieldType::URL => filter_cache.url_filter.get(&filter_id).and_then(|filter| {
Some(
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())
.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::field::{CheckboxCellData, CheckboxTypeOption};
use flowy_error::FlowyResult;
impl GridCheckboxFilter {
impl CheckboxFilterConfigurationPB {
pub fn is_visible(&self, cell_data: &CheckboxCellData) -> bool {
let is_check = cell_data.is_check();
match self.condition {
@ -13,8 +13,8 @@ impl GridCheckboxFilter {
}
}
impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridCheckboxFilter) -> FlowyResult<bool> {
impl CellFilterOperation<CheckboxFilterConfigurationPB> for CheckboxTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &CheckboxFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_checkbox() {
return Ok(true);
}
@ -26,13 +26,13 @@ impl CellFilterOperation<GridCheckboxFilter> for CheckboxTypeOption {
#[cfg(test)]
mod tests {
use crate::entities::{CheckboxCondition, GridCheckboxFilter};
use crate::entities::{CheckboxCondition, CheckboxFilterConfigurationPB};
use crate::services::field::CheckboxCellData;
use std::str::FromStr;
#[test]
fn checkbox_filter_is_check_test() {
let checkbox_filter = GridCheckboxFilter {
let checkbox_filter = CheckboxFilterConfigurationPB {
condition: CheckboxCondition::IsChecked,
};
for (value, visible) in [("true", true), ("yes", true), ("false", false), ("no", false)] {
@ -43,7 +43,7 @@ mod tests {
#[test]
fn checkbox_filter_is_uncheck_test() {
let checkbox_filter = GridCheckboxFilter {
let checkbox_filter = CheckboxFilterConfigurationPB {
condition: CheckboxCondition::IsUnChecked,
};
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::field::{DateTimestamp, DateTypeOption};
use crate::services::field::{DateTimestamp, DateTypeOptionPB};
use flowy_error::FlowyResult;
impl GridDateFilter {
impl DateFilterConfigurationPB {
pub fn is_visible<T: Into<i64>>(&self, cell_timestamp: T) -> bool {
if self.start.is_none() {
return false;
@ -29,8 +29,8 @@ impl GridDateFilter {
}
}
impl CellFilterOperation<GridDateFilter> for DateTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridDateFilter) -> FlowyResult<bool> {
impl CellFilterOperation<DateFilterConfigurationPB> for DateTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &DateFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_date() {
return Ok(true);
}
@ -43,11 +43,11 @@ impl CellFilterOperation<GridDateFilter> for DateTypeOption {
#[cfg(test)]
mod tests {
#![allow(clippy::all)]
use crate::entities::{DateFilterCondition, GridDateFilter};
use crate::entities::{DateFilterCondition, DateFilterConfigurationPB};
#[test]
fn date_filter_is_test() {
let filter = GridDateFilter {
let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateIs,
start: Some(123),
end: None,
@ -59,7 +59,7 @@ mod tests {
}
#[test]
fn date_filter_before_test() {
let filter = GridDateFilter {
let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateBefore,
start: Some(123),
end: None,
@ -71,7 +71,7 @@ mod tests {
}
#[test]
fn date_filter_before_or_on_test() {
let filter = GridDateFilter {
let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateOnOrBefore,
start: Some(123),
end: None,
@ -83,7 +83,7 @@ mod tests {
}
#[test]
fn date_filter_after_test() {
let filter = GridDateFilter {
let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateAfter,
start: Some(123),
end: None,
@ -95,7 +95,7 @@ mod tests {
}
#[test]
fn date_filter_within_test() {
let filter = GridDateFilter {
let filter = DateFilterConfigurationPB {
condition: DateFilterCondition::DateWithIn,
start: Some(123),
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::field::{NumberCellData, NumberTypeOption};
use crate::services::field::{NumberCellData, NumberTypeOptionPB};
use flowy_error::FlowyResult;
use rust_decimal::prelude::Zero;
use rust_decimal::Decimal;
use std::str::FromStr;
impl GridNumberFilter {
impl NumberFilterConfigurationPB {
pub fn is_visible(&self, num_cell_data: &NumberCellData) -> bool {
if self.content.is_none() {
return false;
@ -31,8 +31,8 @@ impl GridNumberFilter {
}
}
impl CellFilterOperation<GridNumberFilter> for NumberTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridNumberFilter) -> FlowyResult<bool> {
impl CellFilterOperation<NumberFilterConfigurationPB> for NumberTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &NumberFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_number() {
return Ok(true);
}
@ -46,11 +46,11 @@ impl CellFilterOperation<GridNumberFilter> for NumberTypeOption {
#[cfg(test)]
mod tests {
use crate::entities::{GridNumberFilter, NumberFilterCondition};
use crate::entities::{NumberFilterCondition, NumberFilterConfigurationPB};
use crate::services::field::{NumberCellData, NumberFormat};
#[test]
fn number_filter_equal_test() {
let number_filter = GridNumberFilter {
let number_filter = NumberFilterConfigurationPB {
condition: NumberFilterCondition::Equal,
content: Some("123".to_owned()),
};
@ -68,7 +68,7 @@ mod tests {
}
#[test]
fn number_filter_greater_than_test() {
let number_filter = GridNumberFilter {
let number_filter = NumberFilterConfigurationPB {
condition: NumberFilterCondition::GreaterThan,
content: Some("12".to_owned()),
};
@ -80,7 +80,7 @@ mod tests {
#[test]
fn number_filter_less_than_test() {
let number_filter = GridNumberFilter {
let number_filter = NumberFilterConfigurationPB {
condition: NumberFilterCondition::LessThan,
content: Some("100".to_owned()),
};

View File

@ -1,12 +1,12 @@
#![allow(clippy::needless_collect)]
use crate::entities::{GridSelectOptionFilter, SelectOptionCondition};
use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB};
use crate::services::cell::{AnyCellData, CellFilterOperation};
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
use crate::services::field::{SelectOptionOperation, SelectedSelectOptions};
use flowy_error::FlowyResult;
impl GridSelectOptionFilter {
impl SelectOptionFilterConfigurationPB {
pub fn is_visible(&self, selected_options: &SelectedSelectOptions) -> bool {
let selected_option_ids: Vec<&String> = selected_options.options.iter().map(|option| &option.id).collect();
match self.condition {
@ -39,8 +39,12 @@ impl GridSelectOptionFilter {
}
}
impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
impl CellFilterOperation<SelectOptionFilterConfigurationPB> for MultiSelectTypeOptionPB {
fn apply_filter(
&self,
any_cell_data: AnyCellData,
filter: &SelectOptionFilterConfigurationPB,
) -> FlowyResult<bool> {
if !any_cell_data.is_multi_select() {
return Ok(true);
}
@ -50,8 +54,12 @@ impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOptionPB {
}
}
impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
impl CellFilterOperation<SelectOptionFilterConfigurationPB> for SingleSelectTypeOptionPB {
fn apply_filter(
&self,
any_cell_data: AnyCellData,
filter: &SelectOptionFilterConfigurationPB,
) -> FlowyResult<bool> {
if !any_cell_data.is_single_select() {
return Ok(true);
}
@ -63,7 +71,7 @@ impl CellFilterOperation<GridSelectOptionFilter> for SingleSelectTypeOptionPB {
#[cfg(test)]
mod tests {
#![allow(clippy::all)]
use crate::entities::{GridSelectOptionFilter, SelectOptionCondition};
use crate::entities::{SelectOptionCondition, SelectOptionFilterConfigurationPB};
use crate::services::field::selection_type_option::{SelectOptionPB, SelectedSelectOptions};
#[test]
@ -72,7 +80,7 @@ mod tests {
let option_2 = SelectOptionPB::new("B");
let option_3 = SelectOptionPB::new("C");
let filter_1 = GridSelectOptionFilter {
let filter_1 = SelectOptionFilterConfigurationPB {
condition: SelectOptionCondition::OptionIs,
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::field::{RichTextTypeOption, TextCellData};
use crate::services::field::{RichTextTypeOptionPB, TextCellData};
use flowy_error::FlowyResult;
impl GridTextFilter {
impl TextFilterConfigurationPB {
pub fn is_visible<T: AsRef<str>>(&self, cell_data: T) -> bool {
let cell_data = cell_data.as_ref();
let s = cell_data.to_lowercase();
@ -24,8 +24,8 @@ impl GridTextFilter {
}
}
impl CellFilterOperation<GridTextFilter> for RichTextTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> {
impl CellFilterOperation<TextFilterConfigurationPB> for RichTextTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &TextFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_text() {
return Ok(true);
}
@ -38,11 +38,11 @@ impl CellFilterOperation<GridTextFilter> for RichTextTypeOption {
#[cfg(test)]
mod tests {
#![allow(clippy::all)]
use crate::entities::{GridTextFilter, TextFilterCondition};
use crate::entities::{TextFilterCondition, TextFilterConfigurationPB};
#[test]
fn text_filter_equal_test() {
let text_filter = GridTextFilter {
let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::Is,
content: Some("appflowy".to_owned()),
};
@ -54,7 +54,7 @@ mod tests {
}
#[test]
fn text_filter_start_with_test() {
let text_filter = GridTextFilter {
let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::StartsWith,
content: Some("appflowy".to_owned()),
};
@ -66,7 +66,7 @@ mod tests {
#[test]
fn text_filter_end_with_test() {
let text_filter = GridTextFilter {
let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::EndsWith,
content: Some("appflowy".to_owned()),
};
@ -77,7 +77,7 @@ mod tests {
}
#[test]
fn text_filter_empty_test() {
let text_filter = GridTextFilter {
let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::TextIsEmpty,
content: Some("appflowy".to_owned()),
};
@ -87,7 +87,7 @@ mod tests {
}
#[test]
fn text_filter_contain_test() {
let text_filter = GridTextFilter {
let text_filter = TextFilterConfigurationPB {
condition: TextFilterCondition::Contains,
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::field::{TextCellData, URLTypeOption};
use crate::services::field::{TextCellData, URLTypeOptionPB};
use flowy_error::FlowyResult;
impl CellFilterOperation<GridTextFilter> for URLTypeOption {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridTextFilter) -> FlowyResult<bool> {
impl CellFilterOperation<TextFilterConfigurationPB> for URLTypeOptionPB {
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &TextFilterConfigurationPB) -> FlowyResult<bool> {
if !any_cell_data.is_url() {
return Ok(true);
}

View File

@ -452,7 +452,7 @@ impl GridRevisionEditor {
pub async fn get_grid_setting(&self) -> FlowyResult<GridSettingPB> {
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 grid_setting = make_grid_setting(grid_setting_rev, &field_revs);
Ok(grid_setting)
@ -564,8 +564,9 @@ impl GridRevisionEditor {
})
}
pub async fn get_group(&self) -> FlowyResult<RepeatedGridGroupPB> {
todo!()
pub async fn load_groups(&self) -> FlowyResult<RepeatedGridGroupPB> {
let groups = self.group_service.load_groups().await.unwrap_or(vec![]);
Ok(RepeatedGridGroupPB { items: groups })
}
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::cell::{decode_any_cell_data, CellBytes};
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 std::sync::Arc;
use tokio::sync::RwLock;
@ -26,4 +34,116 @@ impl GridGroupService {
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 impls;
pub(crate) use group_service::*;
pub(crate) use impls::*;

View File

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

View File

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

View File

@ -1,8 +1,10 @@
use crate::revision::FieldTypeRevision;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct GridGroupRevision {
pub struct GroupConfigurationRevision {
pub 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> {
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))
}

View File

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

View File

@ -2,10 +2,8 @@ mod filter_rev;
mod grid_group;
mod grid_rev;
mod grid_setting_rev;
mod grid_sort;
pub use filter_rev::*;
pub use grid_group::*;
pub use grid_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();
assert_eq!(
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 bytes::Bytes;
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,
FieldTypeRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridFilterRevision, GridGroupRevision,
GridLayoutRevision, GridRevision, GridSettingRevision, GridSortRevision,
gen_block_id, gen_grid_filter_id, gen_grid_group_id, gen_grid_id, FieldRevision, FieldTypeRevision,
FilterConfigurationRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridLayoutRevision,
GridRevision, GridSettingRevision, GroupConfigurationRevision,
};
use lib_infra::util::move_vec_element;
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
}
@ -350,7 +350,7 @@ impl GridRevisionPad {
&self,
layout: Option<&GridLayoutRevision>,
field_ids: Option<Vec<String>>,
) -> Option<Vec<Arc<GridFilterRevision>>> {
) -> Option<Vec<Arc<FilterConfigurationRevision>>> {
let mut filter_revs = vec![];
let layout_ty = layout.unwrap_or(&self.grid_rev.setting.layout);
let field_revs = self.get_field_revs(None).ok()?;
@ -419,7 +419,7 @@ impl GridRevisionPad {
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 {
// id: gen_grid_sort_id(),
// field_id: sort.field_id,
@ -434,7 +434,7 @@ impl GridRevisionPad {
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) {
// Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id),
// None => {
@ -559,19 +559,20 @@ impl std::default::Default for GridRevisionPad {
}
}
fn make_filter_revision(params: &CreateGridFilterParams) -> GridFilterRevision {
GridFilterRevision {
fn make_filter_revision(params: &CreateGridFilterParams) -> FilterConfigurationRevision {
FilterConfigurationRevision {
id: gen_grid_filter_id(),
field_id: params.field_id.clone(),
condition: params.condition.clone(),
condition: params.condition,
content: params.content.clone(),
}
}
fn make_group_revision(params: &CreateGridGroupParams) -> GridGroupRevision {
GridGroupRevision {
fn make_group_revision(params: &CreateGridGroupParams) -> GroupConfigurationRevision {
GroupConfigurationRevision {
id: gen_grid_group_id(),
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 field_id: String,
pub sub_field_id: Option<String>,
pub field_type_rev: FieldTypeRevision,
pub content: Option<Vec<u8>>,
}
pub struct DeleteGroupParams {