mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: refactor multi-select type option and add GroupPB
This commit is contained in:
parent
29ea3c83c8
commit
aae2d96a4f
20
frontend/app_flowy/lib/plugins/board/application/group.dart
Normal file
20
frontend/app_flowy/lib/plugins/board/application/group.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
|
||||
class BoardGroupService {
|
||||
final String gridId;
|
||||
GridFieldPB? groupField;
|
||||
|
||||
BoardGroupService(this.gridId);
|
||||
|
||||
void setGroupField(GridFieldPB field) {
|
||||
groupField = field;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CanBeGroupField {
|
||||
String get groupContent;
|
||||
}
|
||||
|
||||
// class SingleSelectGroup extends CanBeGroupField {
|
||||
// final SingleSelectTypeOptionContext typeOptionContext;
|
||||
// }
|
@ -4,22 +4,29 @@ import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
|
||||
import 'dart:async';
|
||||
import 'select_option_type_option_bloc.dart';
|
||||
import 'type_option_context.dart';
|
||||
import 'type_option_data_controller.dart';
|
||||
import 'type_option_service.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
|
||||
class MultiSelectTypeOptionContext
|
||||
extends TypeOptionContext<MultiSelectTypeOption> with ISelectOptionAction {
|
||||
class MultiSelectAction with ISelectOptionAction {
|
||||
final String gridId;
|
||||
final String fieldId;
|
||||
final TypeOptionFFIService service;
|
||||
final MultiSelectTypeOptionContext typeOptionContext;
|
||||
|
||||
MultiSelectTypeOptionContext({
|
||||
required MultiSelectTypeOptionWidgetDataParser dataParser,
|
||||
required TypeOptionDataController dataController,
|
||||
}) : service = TypeOptionFFIService(
|
||||
gridId: dataController.gridId,
|
||||
fieldId: dataController.field.id,
|
||||
),
|
||||
super(dataParser: dataParser, dataController: dataController);
|
||||
MultiSelectAction({
|
||||
required this.gridId,
|
||||
required this.fieldId,
|
||||
required this.typeOptionContext,
|
||||
}) : service = TypeOptionFFIService(
|
||||
gridId: gridId,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
|
||||
MultiSelectTypeOptionPB get typeOption => typeOptionContext.typeOption;
|
||||
|
||||
set typeOption(MultiSelectTypeOptionPB newTypeOption) {
|
||||
typeOptionContext.typeOption = newTypeOption;
|
||||
}
|
||||
|
||||
@override
|
||||
List<SelectOptionPB> Function(SelectOptionPB) get deleteOption {
|
||||
|
@ -0,0 +1,195 @@
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
|
||||
import 'type_option_data_controller.dart';
|
||||
|
||||
abstract class TypeOptionDataParser<T> {
|
||||
T fromBuffer(List<int> buffer);
|
||||
}
|
||||
|
||||
// Number
|
||||
typedef NumberTypeOptionContext = TypeOptionContext<NumberTypeOption>;
|
||||
|
||||
class NumberTypeOptionWidgetDataParser
|
||||
extends TypeOptionDataParser<NumberTypeOption> {
|
||||
@override
|
||||
NumberTypeOption fromBuffer(List<int> buffer) {
|
||||
return NumberTypeOption.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// RichText
|
||||
typedef RichTextTypeOptionContext = TypeOptionContext<RichTextTypeOption>;
|
||||
|
||||
class RichTextTypeOptionWidgetDataParser
|
||||
extends TypeOptionDataParser<RichTextTypeOption> {
|
||||
@override
|
||||
RichTextTypeOption fromBuffer(List<int> buffer) {
|
||||
return RichTextTypeOption.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Checkbox
|
||||
typedef CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOption>;
|
||||
|
||||
class CheckboxTypeOptionWidgetDataParser
|
||||
extends TypeOptionDataParser<CheckboxTypeOption> {
|
||||
@override
|
||||
CheckboxTypeOption fromBuffer(List<int> buffer) {
|
||||
return CheckboxTypeOption.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// URL
|
||||
typedef URLTypeOptionContext = TypeOptionContext<URLTypeOption>;
|
||||
|
||||
class URLTypeOptionWidgetDataParser
|
||||
extends TypeOptionDataParser<URLTypeOption> {
|
||||
@override
|
||||
URLTypeOption fromBuffer(List<int> buffer) {
|
||||
return URLTypeOption.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Date
|
||||
typedef DateTypeOptionContext = TypeOptionContext<DateTypeOption>;
|
||||
|
||||
class DateTypeOptionDataParser extends TypeOptionDataParser<DateTypeOption> {
|
||||
@override
|
||||
DateTypeOption fromBuffer(List<int> buffer) {
|
||||
return DateTypeOption.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// SingleSelect
|
||||
typedef SingleSelectTypeOptionContext
|
||||
= TypeOptionContext<SingleSelectTypeOptionPB>;
|
||||
|
||||
class SingleSelectTypeOptionWidgetDataParser
|
||||
extends TypeOptionDataParser<SingleSelectTypeOptionPB> {
|
||||
@override
|
||||
SingleSelectTypeOptionPB fromBuffer(List<int> buffer) {
|
||||
return SingleSelectTypeOptionPB.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Multi-select
|
||||
typedef MultiSelectTypeOptionContext
|
||||
= TypeOptionContext<MultiSelectTypeOptionPB>;
|
||||
|
||||
class MultiSelectTypeOptionWidgetDataParser
|
||||
extends TypeOptionDataParser<MultiSelectTypeOptionPB> {
|
||||
@override
|
||||
MultiSelectTypeOptionPB fromBuffer(List<int> buffer) {
|
||||
return MultiSelectTypeOptionPB.fromBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeOptionContext<T extends GeneratedMessage> {
|
||||
T? _typeOptionObject;
|
||||
final TypeOptionDataParser<T> dataParser;
|
||||
final TypeOptionDataController _dataController;
|
||||
|
||||
TypeOptionContext({
|
||||
required this.dataParser,
|
||||
required TypeOptionDataController dataController,
|
||||
}) : _dataController = dataController;
|
||||
|
||||
String get gridId => _dataController.gridId;
|
||||
|
||||
String get fieldId => _dataController.field.id;
|
||||
|
||||
Future<void> loadTypeOptionData({
|
||||
required void Function(T) onCompleted,
|
||||
required void Function(FlowyError) onError,
|
||||
}) async {
|
||||
await _dataController.loadTypeOptionData().then((result) {
|
||||
result.fold((l) => null, (err) => onError(err));
|
||||
});
|
||||
|
||||
onCompleted(typeOption);
|
||||
}
|
||||
|
||||
T get typeOption {
|
||||
if (_typeOptionObject != null) {
|
||||
return _typeOptionObject!;
|
||||
}
|
||||
|
||||
final T object = _dataController.getTypeOption(dataParser);
|
||||
_typeOptionObject = object;
|
||||
return object;
|
||||
}
|
||||
|
||||
set typeOption(T typeOption) {
|
||||
_dataController.typeOptionData = typeOption.writeToBuffer();
|
||||
_typeOptionObject = typeOption;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TypeOptionFieldDelegate {
|
||||
void onFieldChanged(void Function(String) callback);
|
||||
void dispose();
|
||||
}
|
||||
|
||||
abstract class IFieldTypeOptionLoader {
|
||||
String get gridId;
|
||||
Future<Either<FieldTypeOptionDataPB, FlowyError>> load();
|
||||
|
||||
Future<Either<FieldTypeOptionDataPB, FlowyError>> switchToField(
|
||||
String fieldId, FieldType fieldType) {
|
||||
final payload = EditFieldPayloadPB.create()
|
||||
..gridId = gridId
|
||||
..fieldId = fieldId
|
||||
..fieldType = fieldType;
|
||||
|
||||
return GridEventSwitchToField(payload).send();
|
||||
}
|
||||
}
|
||||
|
||||
class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader {
|
||||
@override
|
||||
final String gridId;
|
||||
NewFieldTypeOptionLoader({
|
||||
required this.gridId,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<FieldTypeOptionDataPB, FlowyError>> load() {
|
||||
final payload = CreateFieldPayloadPB.create()
|
||||
..gridId = gridId
|
||||
..fieldType = FieldType.RichText;
|
||||
|
||||
return GridEventCreateFieldTypeOption(payload).send();
|
||||
}
|
||||
}
|
||||
|
||||
class FieldTypeOptionLoader extends IFieldTypeOptionLoader {
|
||||
@override
|
||||
final String gridId;
|
||||
final GridFieldPB field;
|
||||
|
||||
FieldTypeOptionLoader({
|
||||
required this.gridId,
|
||||
required this.field,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<FieldTypeOptionDataPB, FlowyError>> load() {
|
||||
final payload = GridFieldTypeOptionIdPB.create()
|
||||
..gridId = gridId
|
||||
..fieldId = field.id
|
||||
..fieldType = field.fieldType;
|
||||
|
||||
return GridEventGetFieldTypeOption(payload).send();
|
||||
}
|
||||
}
|
@ -92,11 +92,11 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
|
||||
);
|
||||
case FieldType.MultiSelect:
|
||||
return MultiSelectTypeOptionWidgetBuilder(
|
||||
makeTypeOptionContextWithDataController<MultiSelectTypeOption>(
|
||||
makeTypeOptionContextWithDataController<MultiSelectTypeOptionPB>(
|
||||
gridId: gridId,
|
||||
fieldType: fieldType,
|
||||
dataController: dataController,
|
||||
) as MultiSelectTypeOptionContext,
|
||||
),
|
||||
overlayDelegate,
|
||||
);
|
||||
case FieldType.Number:
|
||||
|
@ -9,7 +9,7 @@ class MultiSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
|
||||
final MultiSelectTypeOptionWidget _widget;
|
||||
|
||||
MultiSelectTypeOptionWidgetBuilder(
|
||||
MultiSelectTypeOptionContext typeOptionContext,
|
||||
MultiSelectAction typeOptionContext,
|
||||
TypeOptionOverlayDelegate overlayDelegate,
|
||||
) : _widget = MultiSelectTypeOptionWidget(
|
||||
typeOptionContext: typeOptionContext,
|
||||
@ -21,7 +21,7 @@ class MultiSelectTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder {
|
||||
}
|
||||
|
||||
class MultiSelectTypeOptionWidget extends TypeOptionWidget {
|
||||
final MultiSelectTypeOptionContext typeOptionContext;
|
||||
final MultiSelectAction typeOptionContext;
|
||||
final TypeOptionOverlayDelegate overlayDelegate;
|
||||
|
||||
const MultiSelectTypeOptionWidget({
|
||||
|
1
frontend/rust-lib/Cargo.lock
generated
1
frontend/rust-lib/Cargo.lock
generated
@ -981,6 +981,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -11,33 +11,33 @@ use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct GridFilter {
|
||||
pub struct GridFilterConfiguration {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct RepeatedGridFilterPB {
|
||||
pub struct RepeatedGridConfigurationFilterPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<GridFilter>,
|
||||
pub items: Vec<GridFilterConfiguration>,
|
||||
}
|
||||
|
||||
impl std::convert::From<&GridFilterRevision> for GridFilter {
|
||||
impl std::convert::From<&GridFilterRevision> for GridFilterConfiguration {
|
||||
fn from(rev: &GridFilterRevision) -> Self {
|
||||
Self { id: rev.id.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<Arc<GridFilterRevision>>> for RepeatedGridFilterPB {
|
||||
impl std::convert::From<Vec<Arc<GridFilterRevision>>> for RepeatedGridConfigurationFilterPB {
|
||||
fn from(revs: Vec<Arc<GridFilterRevision>>) -> Self {
|
||||
RepeatedGridFilterPB {
|
||||
RepeatedGridConfigurationFilterPB {
|
||||
items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<GridFilter>> for RepeatedGridFilterPB {
|
||||
fn from(items: Vec<GridFilter>) -> Self {
|
||||
impl std::convert::From<Vec<GridFilterConfiguration>> for RepeatedGridConfigurationFilterPB {
|
||||
fn from(items: Vec<GridFilterConfiguration>) -> Self {
|
||||
Self { items }
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::entities::FieldType;
|
||||
use crate::entities::{FieldType, GridRowPB};
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_error::ErrorCode;
|
||||
use flowy_grid_data_model::parser::NotEmptyStr;
|
||||
@ -8,7 +8,7 @@ use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct GridGroupPB {
|
||||
pub struct GridGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
@ -19,9 +19,9 @@ pub struct GridGroupPB {
|
||||
pub sub_group_field_id: Option<String>,
|
||||
}
|
||||
|
||||
impl std::convert::From<&GridGroupRevision> for GridGroupPB {
|
||||
impl std::convert::From<&GridGroupRevision> for GridGroupConfigurationPB {
|
||||
fn from(rev: &GridGroupRevision) -> Self {
|
||||
GridGroupPB {
|
||||
GridGroupConfigurationPB {
|
||||
id: rev.id.clone(),
|
||||
group_field_id: rev.field_id.clone(),
|
||||
sub_group_field_id: rev.sub_field_id.clone(),
|
||||
@ -29,21 +29,39 @@ impl std::convert::From<&GridGroupRevision> for GridGroupPB {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
#[derive(ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct RepeatedGridGroupPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<GridGroupPB>,
|
||||
groups: Vec<GroupPB>,
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<GridGroupPB>> for RepeatedGridGroupPB {
|
||||
fn from(items: Vec<GridGroupPB>) -> Self {
|
||||
#[derive(ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct GroupPB {
|
||||
#[pb(index = 1)]
|
||||
pub group_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub rows: Vec<GridRowPB>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct RepeatedGridGroupConfigurationPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<GridGroupConfigurationPB>,
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<GridGroupConfigurationPB>> for RepeatedGridGroupConfigurationPB {
|
||||
fn from(items: Vec<GridGroupConfigurationPB>) -> Self {
|
||||
Self { items }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<Arc<GridGroupRevision>>> for RepeatedGridGroupPB {
|
||||
impl std::convert::From<Vec<Arc<GridGroupRevision>>> for RepeatedGridGroupConfigurationPB {
|
||||
fn from(revs: Vec<Arc<GridGroupRevision>>) -> Self {
|
||||
RepeatedGridGroupPB {
|
||||
RepeatedGridGroupConfigurationPB {
|
||||
items: revs.iter().map(|rev| rev.as_ref().into()).collect(),
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::entities::{
|
||||
CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, CreateGridSortPayloadPB, DeleteFilterPayloadPB,
|
||||
DeleteGroupPayloadPB, RepeatedGridFilterPB, RepeatedGridGroupPB, RepeatedGridSortPB,
|
||||
DeleteGroupPayloadPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB, RepeatedGridSortPB,
|
||||
};
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::ErrorCode;
|
||||
@ -22,10 +22,10 @@ pub struct GridSettingPB {
|
||||
pub current_layout_type: GridLayoutType,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub filters_by_field_id: HashMap<String, RepeatedGridFilterPB>,
|
||||
pub filter_configuration_by_field_id: HashMap<String, RepeatedGridConfigurationFilterPB>,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub groups_by_field_id: HashMap<String, RepeatedGridGroupPB>,
|
||||
pub group_configuration_by_field_id: HashMap<String, RepeatedGridGroupConfigurationPB>,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub sorts_by_field_id: HashMap<String, RepeatedGridSortPB>,
|
||||
|
@ -405,3 +405,14 @@ pub(crate) async fn update_date_cell_handler(
|
||||
let _ = editor.update_cell(params.into()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||
pub(crate) async fn get_group_handler(
|
||||
data: Data<GridIdPB>,
|
||||
manager: AppData<Arc<GridManager>>,
|
||||
) -> DataResult<RepeatedGridGroupPB, FlowyError> {
|
||||
let params: GridIdPB = data.into_inner();
|
||||
let editor = manager.get_grid_editor(¶ms.value)?;
|
||||
let group = editor.get_group().await?;
|
||||
data_result(group)
|
||||
}
|
||||
|
@ -37,7 +37,9 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
|
||||
.event(GridEvent::GetSelectOptionCellData, get_select_option_handler)
|
||||
.event(GridEvent::UpdateSelectOptionCell, update_select_option_cell_handler)
|
||||
// Date
|
||||
.event(GridEvent::UpdateDateCell, update_date_cell_handler);
|
||||
.event(GridEvent::UpdateDateCell, update_date_cell_handler)
|
||||
// Group
|
||||
.event(GridEvent::GetGroup, update_date_cell_handler);
|
||||
|
||||
module
|
||||
}
|
||||
@ -204,4 +206,7 @@ pub enum GridEvent {
|
||||
/// will be used by the `update_cell` function.
|
||||
#[event(input = "DateChangesetPayloadPB")]
|
||||
UpdateDateCell = 80,
|
||||
|
||||
#[event(input = "GridIdPB", output = "RepeatedGridGroupPB")]
|
||||
GetGroup = 100,
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ pub fn apply_cell_data_changeset<C: ToString, T: AsRef<FieldRevision>>(
|
||||
FieldType::SingleSelect => {
|
||||
SingleSelectTypeOptionPB::from(field_rev).apply_changeset(changeset.into(), cell_rev)
|
||||
}
|
||||
FieldType::MultiSelect => MultiSelectTypeOption::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),
|
||||
}?;
|
||||
@ -109,7 +109,7 @@ pub fn try_decode_cell_data(
|
||||
.get_type_option_entry::<SingleSelectTypeOptionPB>(field_type)?
|
||||
.decode_cell_data(cell_data.into(), s_field_type, field_rev),
|
||||
FieldType::MultiSelect => field_rev
|
||||
.get_type_option_entry::<MultiSelectTypeOption>(field_type)?
|
||||
.get_type_option_entry::<MultiSelectTypeOptionPB>(field_type)?
|
||||
.decode_cell_data(cell_data.into(), s_field_type, field_rev),
|
||||
FieldType::Checkbox => field_rev
|
||||
.get_type_option_entry::<CheckboxTypeOption>(field_type)?
|
||||
|
@ -94,7 +94,7 @@ pub fn default_type_option_builder_from_type(field_type: &FieldType) -> Box<dyn
|
||||
FieldType::Number => NumberTypeOption::default().into(),
|
||||
FieldType::DateTime => DateTypeOption::default().into(),
|
||||
FieldType::SingleSelect => SingleSelectTypeOptionPB::default().into(),
|
||||
FieldType::MultiSelect => MultiSelectTypeOption::default().into(),
|
||||
FieldType::MultiSelect => MultiSelectTypeOptionPB::default().into(),
|
||||
FieldType::Checkbox => CheckboxTypeOption::default().into(),
|
||||
FieldType::URL => URLTypeOption::default().into(),
|
||||
};
|
||||
|
@ -14,16 +14,16 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
// Multiple select
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
|
||||
pub struct MultiSelectTypeOption {
|
||||
pub struct MultiSelectTypeOptionPB {
|
||||
#[pb(index = 1)]
|
||||
pub options: Vec<SelectOptionPB>,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub disable_color: bool,
|
||||
}
|
||||
impl_type_option!(MultiSelectTypeOption, FieldType::MultiSelect);
|
||||
impl_type_option!(MultiSelectTypeOptionPB, FieldType::MultiSelect);
|
||||
|
||||
impl SelectOptionOperation for MultiSelectTypeOption {
|
||||
impl SelectOptionOperation for MultiSelectTypeOptionPB {
|
||||
fn selected_select_option(&self, cell_data: CellData<SelectOptionIds>) -> SelectOptionCellDataPB {
|
||||
let select_options = make_selected_select_options(cell_data, &self.options);
|
||||
SelectOptionCellDataPB {
|
||||
@ -41,7 +41,7 @@ impl SelectOptionOperation for MultiSelectTypeOption {
|
||||
}
|
||||
}
|
||||
|
||||
impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSelectTypeOption {
|
||||
impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSelectTypeOptionPB {
|
||||
fn decode_cell_data(
|
||||
&self,
|
||||
cell_data: CellData<SelectOptionIds>,
|
||||
@ -93,9 +93,9 @@ impl CellDataOperation<SelectOptionIds, SelectOptionCellChangeset> for MultiSele
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOption);
|
||||
pub struct MultiSelectTypeOptionBuilder(MultiSelectTypeOptionPB);
|
||||
impl_into_box_type_option_builder!(MultiSelectTypeOptionBuilder);
|
||||
impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOption);
|
||||
impl_builder_from_json_str_and_from_bytes!(MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB);
|
||||
impl MultiSelectTypeOptionBuilder {
|
||||
pub fn option(mut self, opt: SelectOptionPB) -> Self {
|
||||
self.0.options.push(opt);
|
||||
@ -118,7 +118,7 @@ mod tests {
|
||||
use crate::services::cell::CellDataOperation;
|
||||
use crate::services::field::type_options::selection_type_option::*;
|
||||
use crate::services::field::FieldBuilder;
|
||||
use crate::services::field::{MultiSelectTypeOption, MultiSelectTypeOptionBuilder};
|
||||
use crate::services::field::{MultiSelectTypeOptionBuilder, MultiSelectTypeOptionPB};
|
||||
use flowy_grid_data_model::revision::FieldRevision;
|
||||
|
||||
#[test]
|
||||
@ -136,7 +136,7 @@ mod tests {
|
||||
.visibility(true)
|
||||
.build();
|
||||
|
||||
let type_option = MultiSelectTypeOption::from(&field_rev);
|
||||
let type_option = MultiSelectTypeOptionPB::from(&field_rev);
|
||||
|
||||
let option_ids = vec![google_option.id.clone(), facebook_option.id.clone()].join(SELECTION_IDS_SEPARATOR);
|
||||
let data = SelectOptionCellChangeset::from_insert(&option_ids).to_str();
|
||||
@ -170,7 +170,7 @@ mod tests {
|
||||
|
||||
fn assert_multi_select_options(
|
||||
cell_data: String,
|
||||
type_option: &MultiSelectTypeOption,
|
||||
type_option: &MultiSelectTypeOptionPB,
|
||||
field_rev: &FieldRevision,
|
||||
expected: Vec<SelectOptionPB>,
|
||||
) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::entities::{CellChangesetPB, FieldType, GridCellIdPB, GridCellIdParams};
|
||||
use crate::services::cell::{CellBytes, CellBytesParser, CellData, CellDisplayable, FromCellChangeset, FromCellString};
|
||||
use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB};
|
||||
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
||||
use bytes::Bytes;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_error::{internal_error, ErrorCode, FlowyResult};
|
||||
@ -130,7 +130,7 @@ pub fn select_option_operation(field_rev: &FieldRevision) -> FlowyResult<Box<dyn
|
||||
Ok(Box::new(type_option))
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let type_option = MultiSelectTypeOption::from(field_rev);
|
||||
let type_option = MultiSelectTypeOptionPB::from(field_rev);
|
||||
Ok(Box::new(type_option))
|
||||
}
|
||||
ty => {
|
||||
|
@ -159,7 +159,7 @@ mod tests {
|
||||
.option(google_option.clone())
|
||||
.option(facebook_option.clone());
|
||||
let multi_select_field_rev = FieldBuilder::new(multi_select).build();
|
||||
let multi_type_option = MultiSelectTypeOption::from(&multi_select_field_rev);
|
||||
let multi_type_option = MultiSelectTypeOptionPB::from(&multi_select_field_rev);
|
||||
let cell_data = multi_type_option
|
||||
.apply_changeset(cell_data_changeset.into(), None)
|
||||
.unwrap();
|
||||
|
@ -3,7 +3,7 @@ use crate::entities::{FieldType, GridBlockChangesetPB};
|
||||
use crate::services::block_manager::GridBlockManager;
|
||||
use crate::services::cell::{AnyCellData, CellFilterOperation};
|
||||
use crate::services::field::{
|
||||
CheckboxTypeOption, DateTypeOption, MultiSelectTypeOption, NumberTypeOption, RichTextTypeOption,
|
||||
CheckboxTypeOption, DateTypeOption, MultiSelectTypeOptionPB, NumberTypeOption, RichTextTypeOption,
|
||||
SingleSelectTypeOptionPB, URLTypeOption,
|
||||
};
|
||||
use crate::services::filter::filter_cache::{
|
||||
@ -22,8 +22,6 @@ use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub(crate) struct GridFilterService {
|
||||
#[allow(dead_code)]
|
||||
grid_id: String,
|
||||
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
||||
grid_pad: Arc<RwLock<GridRevisionPad>>,
|
||||
block_manager: Arc<GridBlockManager>,
|
||||
@ -36,12 +34,10 @@ impl GridFilterService {
|
||||
block_manager: Arc<GridBlockManager>,
|
||||
scheduler: S,
|
||||
) -> Self {
|
||||
let grid_id = grid_pad.read().await.grid_id();
|
||||
let scheduler = Arc::new(scheduler);
|
||||
let filter_cache = FilterCache::from_grid_pad(&grid_pad).await;
|
||||
let filter_result_cache = FilterResultCache::new();
|
||||
Self {
|
||||
grid_id,
|
||||
grid_pad,
|
||||
block_manager,
|
||||
scheduler,
|
||||
@ -134,8 +130,9 @@ impl GridFilterService {
|
||||
}
|
||||
|
||||
async fn notify(&self, changesets: Vec<GridBlockChangesetPB>) {
|
||||
let grid_id = self.grid_pad.read().await.grid_id();
|
||||
for changeset in changesets {
|
||||
send_dart_notification(&self.grid_id, GridNotification::DidUpdateGridBlock)
|
||||
send_dart_notification(&grid_id, GridNotification::DidUpdateGridBlock)
|
||||
.payload(changeset)
|
||||
.send();
|
||||
}
|
||||
@ -217,7 +214,7 @@ fn filter_cell(
|
||||
FieldType::MultiSelect => filter_cache.select_option_filter.get(&filter_id).and_then(|filter| {
|
||||
Some(
|
||||
field_rev
|
||||
.get_type_option_entry::<MultiSelectTypeOption>(field_type_rev)?
|
||||
.get_type_option_entry::<MultiSelectTypeOptionPB>(field_type_rev)?
|
||||
.apply_filter(any_cell_data, filter.value())
|
||||
.ok(),
|
||||
)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::entities::{GridSelectOptionFilter, SelectOptionCondition};
|
||||
use crate::services::cell::{AnyCellData, CellFilterOperation};
|
||||
use crate::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB};
|
||||
use crate::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
||||
use crate::services::field::{SelectOptionOperation, SelectedSelectOptions};
|
||||
use flowy_error::FlowyResult;
|
||||
|
||||
@ -39,7 +39,7 @@ impl GridSelectOptionFilter {
|
||||
}
|
||||
}
|
||||
|
||||
impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOption {
|
||||
impl CellFilterOperation<GridSelectOptionFilter> for MultiSelectTypeOptionPB {
|
||||
fn apply_filter(&self, any_cell_data: AnyCellData, filter: &GridSelectOptionFilter) -> FlowyResult<bool> {
|
||||
if !any_cell_data.is_multi_select() {
|
||||
return Ok(true);
|
||||
|
@ -61,7 +61,8 @@ impl GridRevisionEditor {
|
||||
let block_manager = Arc::new(GridBlockManager::new(grid_id, &user, block_meta_revs, persistence).await?);
|
||||
let filter_service =
|
||||
Arc::new(GridFilterService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await);
|
||||
let group_service = Arc::new(GridGroupService::new());
|
||||
let group_service =
|
||||
Arc::new(GridGroupService::new(grid_pad.clone(), block_manager.clone(), task_scheduler.clone()).await);
|
||||
let editor = Arc::new(Self {
|
||||
grid_id: grid_id.to_owned(),
|
||||
user,
|
||||
@ -455,14 +456,14 @@ impl GridRevisionEditor {
|
||||
Ok(grid_setting)
|
||||
}
|
||||
|
||||
pub async fn get_grid_filter(&self, layout_type: &GridLayoutType) -> FlowyResult<Vec<GridFilter>> {
|
||||
pub async fn get_grid_filter(&self, layout_type: &GridLayoutType) -> FlowyResult<Vec<GridFilterConfiguration>> {
|
||||
let read_guard = self.grid_pad.read().await;
|
||||
let layout_rev = layout_type.clone().into();
|
||||
match read_guard.get_filters(Some(&layout_rev), None) {
|
||||
Some(filter_revs) => Ok(filter_revs
|
||||
.iter()
|
||||
.map(|filter_rev| filter_rev.as_ref().into())
|
||||
.collect::<Vec<GridFilter>>()),
|
||||
.collect::<Vec<GridFilterConfiguration>>()),
|
||||
None => Ok(vec![]),
|
||||
}
|
||||
}
|
||||
@ -561,6 +562,10 @@ impl GridRevisionEditor {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_group(&self) -> FlowyResult<RepeatedGridGroupPB> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn modify<F>(&self, f: F) -> FlowyResult<()>
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut GridRevisionPad) -> FlowyResult<Option<GridChangeset>>,
|
||||
|
@ -1,7 +1,26 @@
|
||||
pub struct GridGroupService {}
|
||||
use crate::services::block_manager::GridBlockManager;
|
||||
use crate::services::grid_editor_task::GridServiceTaskScheduler;
|
||||
use flowy_sync::client_grid::GridRevisionPad;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub(crate) struct GridGroupService {
|
||||
scheduler: Arc<dyn GridServiceTaskScheduler>,
|
||||
grid_pad: Arc<RwLock<GridRevisionPad>>,
|
||||
block_manager: Arc<GridBlockManager>,
|
||||
}
|
||||
|
||||
impl GridGroupService {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
pub(crate) async fn new<S: GridServiceTaskScheduler>(
|
||||
grid_pad: Arc<RwLock<GridRevisionPad>>,
|
||||
block_manager: Arc<GridBlockManager>,
|
||||
scheduler: S,
|
||||
) -> Self {
|
||||
let scheduler = Arc::new(scheduler);
|
||||
Self {
|
||||
scheduler,
|
||||
grid_pad,
|
||||
block_manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::entities::{
|
||||
GridLayoutPB, GridLayoutType, GridSettingPB, RepeatedGridFilterPB, RepeatedGridGroupPB, RepeatedGridSortPB,
|
||||
GridLayoutPB, GridLayoutType, GridSettingPB, RepeatedGridConfigurationFilterPB, RepeatedGridGroupConfigurationPB,
|
||||
RepeatedGridSortPB,
|
||||
};
|
||||
use flowy_grid_data_model::revision::{FieldRevision, GridSettingRevision};
|
||||
use flowy_sync::entities::grid::{CreateGridFilterParams, DeleteFilterParams, GridSettingChangesetParams};
|
||||
@ -43,21 +44,21 @@ impl GridSettingChangesetBuilder {
|
||||
pub fn make_grid_setting(grid_setting_rev: &GridSettingRevision, field_revs: &[Arc<FieldRevision>]) -> GridSettingPB {
|
||||
let current_layout_type: GridLayoutType = grid_setting_rev.layout.clone().into();
|
||||
let filters_by_field_id = grid_setting_rev
|
||||
.get_all_filter(field_revs)
|
||||
.get_all_filters(field_revs)
|
||||
.map(|filters_by_field_id| {
|
||||
filters_by_field_id
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.into()))
|
||||
.collect::<HashMap<String, RepeatedGridFilterPB>>()
|
||||
.collect::<HashMap<String, RepeatedGridConfigurationFilterPB>>()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let groups_by_field_id = grid_setting_rev
|
||||
.get_all_group()
|
||||
.get_all_groups(field_revs)
|
||||
.map(|groups_by_field_id| {
|
||||
groups_by_field_id
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.into()))
|
||||
.collect::<HashMap<String, RepeatedGridGroupPB>>()
|
||||
.collect::<HashMap<String, RepeatedGridGroupConfigurationPB>>()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let sorts_by_field_id = grid_setting_rev
|
||||
@ -73,8 +74,8 @@ pub fn make_grid_setting(grid_setting_rev: &GridSettingRevision, field_revs: &[A
|
||||
GridSettingPB {
|
||||
layouts: GridLayoutPB::all(),
|
||||
current_layout_type,
|
||||
filters_by_field_id,
|
||||
groups_by_field_id,
|
||||
filter_configuration_by_field_id: filters_by_field_id,
|
||||
group_configuration_by_field_id: groups_by_field_id,
|
||||
sorts_by_field_id,
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use flowy_grid::entities::FieldType;
|
||||
use std::sync::Arc;
|
||||
|
||||
use flowy_grid::services::field::{
|
||||
DateCellChangesetPB, MultiSelectTypeOption, SelectOptionPB, SingleSelectTypeOptionPB, SELECTION_IDS_SEPARATOR,
|
||||
DateCellChangesetPB, MultiSelectTypeOptionPB, SelectOptionPB, SingleSelectTypeOptionPB, SELECTION_IDS_SEPARATOR,
|
||||
};
|
||||
use flowy_grid::services::row::RowRevisionBuilder;
|
||||
use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
|
||||
@ -87,7 +87,7 @@ impl<'a> GridRowTestBuilder<'a> {
|
||||
F: Fn(Vec<SelectOptionPB>) -> Vec<SelectOptionPB>,
|
||||
{
|
||||
let multi_select_field = self.field_rev_with_type(&FieldType::MultiSelect);
|
||||
let type_option = MultiSelectTypeOption::from(&multi_select_field);
|
||||
let type_option = MultiSelectTypeOptionPB::from(&multi_select_field);
|
||||
let options = f(type_option.options);
|
||||
let ops_ids = options
|
||||
.iter()
|
||||
|
@ -3,7 +3,7 @@ use crate::grid::cell_test::script::GridCellTest;
|
||||
use crate::grid::field_test::util::make_date_cell_string;
|
||||
use flowy_grid::entities::{CellChangesetPB, FieldType};
|
||||
use flowy_grid::services::field::selection_type_option::SelectOptionCellChangeset;
|
||||
use flowy_grid::services::field::{MultiSelectTypeOption, SingleSelectTypeOptionPB};
|
||||
use flowy_grid::services::field::{MultiSelectTypeOptionPB, SingleSelectTypeOptionPB};
|
||||
|
||||
#[tokio::test]
|
||||
async fn grid_cell_update() {
|
||||
@ -28,7 +28,7 @@ async fn grid_cell_update() {
|
||||
SelectOptionCellChangeset::from_insert(&type_option.options.first().unwrap().id).to_str()
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let type_option = MultiSelectTypeOption::from(field_rev);
|
||||
let type_option = MultiSelectTypeOptionPB::from(field_rev);
|
||||
SelectOptionCellChangeset::from_insert(&type_option.options.first().unwrap().id).to_str()
|
||||
}
|
||||
FieldType::Checkbox => "1".to_string(),
|
||||
|
@ -75,7 +75,7 @@ impl GridEditorTest {
|
||||
.row_revs
|
||||
}
|
||||
|
||||
pub async fn grid_filters(&self) -> Vec<GridFilter> {
|
||||
pub async fn grid_filters(&self) -> Vec<GridFilterConfiguration> {
|
||||
let layout_type = GridLayoutType::Table;
|
||||
self.editor.get_grid_filter(&layout_type).await.unwrap()
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::grid::script::EditorScript::*;
|
||||
use crate::grid::script::*;
|
||||
use chrono::NaiveDateTime;
|
||||
use flowy_grid::services::field::{
|
||||
DateCellContentChangeset, DateCellData, MultiSelectTypeOption, SelectOption, SelectOptionCellContentChangeset,
|
||||
DateCellContentChangeset, DateCellData, MultiSelectTypeOptionPB, SelectOption, SelectOptionCellContentChangeset,
|
||||
SingleSelectTypeOption, SELECTION_IDS_SEPARATOR,
|
||||
};
|
||||
use flowy_grid::services::row::{decode_cell_data_from_type_option_cell_data, CreateRowMetaBuilder};
|
||||
@ -250,7 +250,7 @@ async fn grid_row_add_cells_test() {
|
||||
builder.add_select_option_cell(&field.id, option.id.clone()).unwrap();
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let type_option = MultiSelectTypeOption::from(field);
|
||||
let type_option = MultiSelectTypeOptionPB::from(field);
|
||||
let ops_ids = type_option
|
||||
.options
|
||||
.iter()
|
||||
@ -327,7 +327,7 @@ async fn grid_cell_update() {
|
||||
SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str()
|
||||
}
|
||||
FieldType::MultiSelect => {
|
||||
let type_option = MultiSelectTypeOption::from(field_meta);
|
||||
let type_option = MultiSelectTypeOptionPB::from(field_meta);
|
||||
SelectOptionCellContentChangeset::from_insert(&type_option.options.first().unwrap().id).to_str()
|
||||
}
|
||||
FieldType::Checkbox => "1".to_string(),
|
||||
|
1
shared-lib/Cargo.lock
generated
1
shared-lib/Cargo.lock
generated
@ -436,6 +436,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -13,6 +13,7 @@ serde_repr = "0.1"
|
||||
nanoid = "0.4.0"
|
||||
flowy-error-code = { path = "../flowy-error-code"}
|
||||
indexmap = {version = "1.8.1", features = ["serde"]}
|
||||
tracing = { version = "0.1", features = ["log"] }
|
||||
|
||||
[build-dependencies]
|
||||
lib-infra = { path = "../lib-infra", features = ["protobuf_file_gen"] }
|
||||
|
@ -1,7 +1,4 @@
|
||||
use crate::revision::FieldTypeRevision;
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)]
|
||||
pub struct GridFilterRevision {
|
||||
|
@ -1,7 +1,4 @@
|
||||
use crate::revision::FieldTypeRevision;
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
|
||||
pub struct GridGroupRevision {
|
@ -1,5 +1,5 @@
|
||||
use crate::revision::filter_rev::GridFilterRevision;
|
||||
use crate::revision::group_rev::GridGroupRevision;
|
||||
use crate::revision::grid_group::GridGroupRevision;
|
||||
use crate::revision::{FieldRevision, FieldTypeRevision};
|
||||
use indexmap::IndexMap;
|
||||
use nanoid::nanoid;
|
||||
@ -21,28 +21,28 @@ 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 GridGroups = SettingContainer<GridGroupRevision>;
|
||||
pub type GridGroupRevisionMap = GridObjectRevisionMap<GridGroupRevision>;
|
||||
pub type GroupsByFieldId = HashMap<String, Vec<Arc<GridGroupRevision>>>;
|
||||
//
|
||||
pub type GridSorts = SettingContainer<GridSortRevision>;
|
||||
pub type GridSortRevisionMap = GridObjectRevisionMap<GridSortRevision>;
|
||||
pub type SortsByFieldId = HashMap<String, Vec<Arc<GridSortRevision>>>;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
|
||||
pub struct GridSettingRevision {
|
||||
pub layout: GridLayoutRevision,
|
||||
|
||||
/// Each layout contains multiple key/value.
|
||||
/// Key: field_id
|
||||
/// Value: this value contains key/value.
|
||||
/// Key: FieldType,
|
||||
/// Value: the corresponding filters.
|
||||
#[serde(with = "indexmap::serde_seq")]
|
||||
filters: IndexMap<GridLayoutRevision, IndexMap<String, GridFilterRevisionMap>>,
|
||||
pub filters: GridFilters,
|
||||
|
||||
/// Each layout contains multiple key/value.
|
||||
/// Key: field_id
|
||||
/// Value: this value contains key/value.
|
||||
/// Key: FieldType,
|
||||
/// Value: the corresponding groups.
|
||||
#[serde(skip, with = "indexmap::serde_seq")]
|
||||
pub groups: IndexMap<GridLayoutRevision, IndexMap<String, GridGroupRevisionMap>>,
|
||||
pub groups: GridGroups,
|
||||
|
||||
#[serde(skip, with = "indexmap::serde_seq")]
|
||||
pub sorts: IndexMap<GridLayoutRevision, Vec<GridSortRevision>>,
|
||||
#[serde(skip)]
|
||||
pub sorts: GridSorts,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize_repr, Deserialize_repr)]
|
||||
@ -65,12 +65,18 @@ impl std::default::Default for GridLayoutRevision {
|
||||
}
|
||||
}
|
||||
|
||||
pub type FiltersByFieldId = HashMap<String, Vec<Arc<GridFilterRevision>>>;
|
||||
pub type GroupsByFieldId = HashMap<String, Vec<Arc<GridGroupRevision>>>;
|
||||
pub type SortsByFieldId = HashMap<String, Vec<Arc<GridSortRevision>>>;
|
||||
impl GridSettingRevision {
|
||||
pub fn get_all_group(&self) -> Option<GroupsByFieldId> {
|
||||
None
|
||||
pub fn get_all_groups(&self, field_revs: &[Arc<FieldRevision>]) -> Option<GroupsByFieldId> {
|
||||
self.groups.get_all_objects(&self.layout, field_revs)
|
||||
}
|
||||
|
||||
pub fn get_groups(
|
||||
&self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type_rev: &FieldTypeRevision,
|
||||
) -> Option<Vec<Arc<GridGroupRevision>>> {
|
||||
self.groups.get_objects(layout, field_id, field_type_rev)
|
||||
}
|
||||
|
||||
pub fn get_mut_groups(
|
||||
@ -79,10 +85,7 @@ impl GridSettingRevision {
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
) -> Option<&mut Vec<Arc<GridGroupRevision>>> {
|
||||
self.groups
|
||||
.get_mut(layout)
|
||||
.and_then(|group_rev_map_by_field_id| group_rev_map_by_field_id.get_mut(field_id))
|
||||
.and_then(|group_rev_map| group_rev_map.get_mut(field_type))
|
||||
self.groups.get_mut_objects(layout, field_id, field_type)
|
||||
}
|
||||
|
||||
pub fn insert_group(
|
||||
@ -90,59 +93,13 @@ impl GridSettingRevision {
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
filter_rev: GridGroupRevision,
|
||||
group_rev: GridGroupRevision,
|
||||
) {
|
||||
let filter_rev_map_by_field_id = self.groups.entry(layout.clone()).or_insert_with(IndexMap::new);
|
||||
let filter_rev_map = filter_rev_map_by_field_id
|
||||
.entry(field_id.to_string())
|
||||
.or_insert_with(GridGroupRevisionMap::new);
|
||||
|
||||
filter_rev_map
|
||||
.entry(field_type.to_owned())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(Arc::new(filter_rev))
|
||||
self.groups.insert_object(layout, field_id, field_type, group_rev);
|
||||
}
|
||||
|
||||
pub fn get_all_sort(&self) -> Option<SortsByFieldId> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Return the Filters of the current layout
|
||||
pub fn get_all_filter(&self, field_revs: &[Arc<FieldRevision>]) -> Option<FiltersByFieldId> {
|
||||
let layout = &self.layout;
|
||||
// Acquire the read lock of the filters.
|
||||
let filter_rev_map_by_field_id = self.filters.get(layout)?;
|
||||
// Get the filters according to the FieldType, so we need iterate the field_revs.
|
||||
let filters_by_field_id = field_revs
|
||||
.iter()
|
||||
.flat_map(|field_rev| {
|
||||
let field_type = &field_rev.field_type_rev;
|
||||
let field_id = &field_rev.id;
|
||||
|
||||
let filter_rev_map: &GridFilterRevisionMap = filter_rev_map_by_field_id.get(field_id)?;
|
||||
let filters: Vec<Arc<GridFilterRevision>> = filter_rev_map.get(field_type)?.clone();
|
||||
Some((field_rev.id.clone(), filters))
|
||||
})
|
||||
.collect::<FiltersByFieldId>();
|
||||
Some(filters_by_field_id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn get_filter_rev_map(&self, layout: &GridLayoutRevision, field_id: &str) -> Option<&GridFilterRevisionMap> {
|
||||
let filter_rev_map_by_field_id = self.filters.get(layout)?;
|
||||
filter_rev_map_by_field_id.get(field_id)
|
||||
}
|
||||
|
||||
pub fn get_mut_filters(
|
||||
&mut self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
) -> Option<&mut Vec<Arc<GridFilterRevision>>> {
|
||||
self.filters
|
||||
.get_mut(layout)
|
||||
.and_then(|filter_rev_map_by_field_id| filter_rev_map_by_field_id.get_mut(field_id))
|
||||
.and_then(|filter_rev_map| filter_rev_map.get_mut(field_type))
|
||||
pub fn get_all_filters(&self, field_revs: &[Arc<FieldRevision>]) -> Option<FiltersByFieldId> {
|
||||
self.filters.get_all_objects(&self.layout, field_revs)
|
||||
}
|
||||
|
||||
pub fn get_filters(
|
||||
@ -151,11 +108,16 @@ impl GridSettingRevision {
|
||||
field_id: &str,
|
||||
field_type_rev: &FieldTypeRevision,
|
||||
) -> Option<Vec<Arc<GridFilterRevision>>> {
|
||||
self.filters
|
||||
.get(layout)
|
||||
.and_then(|filter_rev_map_by_field_id| filter_rev_map_by_field_id.get(field_id))
|
||||
.and_then(|filter_rev_map| filter_rev_map.get(field_type_rev))
|
||||
.cloned()
|
||||
self.filters.get_objects(layout, field_id, field_type_rev)
|
||||
}
|
||||
|
||||
pub fn get_mut_filters(
|
||||
&mut self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
) -> Option<&mut Vec<Arc<GridFilterRevision>>> {
|
||||
self.filters.get_mut_objects(layout, field_id, field_type)
|
||||
}
|
||||
|
||||
pub fn insert_filter(
|
||||
@ -165,15 +127,11 @@ impl GridSettingRevision {
|
||||
field_type: &FieldTypeRevision,
|
||||
filter_rev: GridFilterRevision,
|
||||
) {
|
||||
let filter_rev_map_by_field_id = self.filters.entry(layout.clone()).or_insert_with(IndexMap::new);
|
||||
let filter_rev_map = filter_rev_map_by_field_id
|
||||
.entry(field_id.to_string())
|
||||
.or_insert_with(GridFilterRevisionMap::new);
|
||||
self.filters.insert_object(layout, field_id, field_type, filter_rev);
|
||||
}
|
||||
|
||||
filter_rev_map
|
||||
.entry(field_type.to_owned())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(Arc::new(filter_rev))
|
||||
pub fn get_all_sort(&self) -> Option<SortsByFieldId> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,8 +141,94 @@ pub struct GridSortRevision {
|
||||
pub field_id: Option<String>,
|
||||
}
|
||||
|
||||
pub type GridFilterRevisionMap = GridObjectRevisionMap<GridFilterRevision>;
|
||||
pub type GridGroupRevisionMap = GridObjectRevisionMap<GridGroupRevision>;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
|
||||
#[serde(transparent)]
|
||||
pub struct SettingContainer<T>
|
||||
where
|
||||
T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static,
|
||||
{
|
||||
/// Each layout contains multiple key/value.
|
||||
/// Key: field_id
|
||||
/// Value: this value contains key/value.
|
||||
/// Key: FieldType,
|
||||
/// Value: the corresponding objects.
|
||||
#[serde(with = "indexmap::serde_seq")]
|
||||
inner: IndexMap<GridLayoutRevision, IndexMap<String, GridObjectRevisionMap<T>>>,
|
||||
}
|
||||
|
||||
impl<T> SettingContainer<T>
|
||||
where
|
||||
T: Debug + Clone + Default + Eq + PartialEq + serde::Serialize + serde::de::DeserializeOwned + 'static,
|
||||
{
|
||||
pub fn get_mut_objects(
|
||||
&mut self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
) -> Option<&mut Vec<Arc<T>>> {
|
||||
let value = self
|
||||
.inner
|
||||
.get_mut(layout)
|
||||
.and_then(|object_rev_map_by_field_id| object_rev_map_by_field_id.get_mut(field_id))
|
||||
.and_then(|object_rev_map| object_rev_map.get_mut(field_type));
|
||||
if value.is_none() {
|
||||
tracing::warn!("Can't find the {:?} with", std::any::type_name::<T>());
|
||||
}
|
||||
value
|
||||
}
|
||||
pub fn get_objects(
|
||||
&self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type_rev: &FieldTypeRevision,
|
||||
) -> Option<Vec<Arc<T>>> {
|
||||
self.inner
|
||||
.get(layout)
|
||||
.and_then(|object_rev_map_by_field_id| object_rev_map_by_field_id.get(field_id))
|
||||
.and_then(|object_rev_map| object_rev_map.get(field_type_rev))
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn get_all_objects(
|
||||
&self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_revs: &[Arc<FieldRevision>],
|
||||
) -> Option<HashMap<String, Vec<Arc<T>>>> {
|
||||
// Acquire the read lock.
|
||||
let object_rev_map_by_field_id = self.inner.get(layout)?;
|
||||
// Get the objects according to the FieldType, so we need iterate the field_revs.
|
||||
let objects_by_field_id = field_revs
|
||||
.iter()
|
||||
.flat_map(|field_rev| {
|
||||
let field_type = &field_rev.field_type_rev;
|
||||
let field_id = &field_rev.id;
|
||||
|
||||
let object_rev_map = object_rev_map_by_field_id.get(field_id)?;
|
||||
let objects: Vec<Arc<T>> = object_rev_map.get(field_type)?.clone();
|
||||
Some((field_rev.id.clone(), objects))
|
||||
})
|
||||
.collect::<HashMap<String, Vec<Arc<T>>>>();
|
||||
Some(objects_by_field_id)
|
||||
}
|
||||
|
||||
pub fn insert_object(
|
||||
&mut self,
|
||||
layout: &GridLayoutRevision,
|
||||
field_id: &str,
|
||||
field_type: &FieldTypeRevision,
|
||||
object: T,
|
||||
) {
|
||||
let object_rev_map_by_field_id = self.inner.entry(layout.clone()).or_insert_with(IndexMap::new);
|
||||
let object_rev_map = object_rev_map_by_field_id
|
||||
.entry(field_id.to_string())
|
||||
.or_insert_with(GridObjectRevisionMap::<T>::new);
|
||||
|
||||
object_rev_map
|
||||
.entry(field_type.to_owned())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(Arc::new(object))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, Eq, PartialEq)]
|
||||
#[serde(transparent)]
|
||||
|
@ -1,9 +1,11 @@
|
||||
mod filter_rev;
|
||||
mod grid_group;
|
||||
mod grid_rev;
|
||||
mod grid_setting_rev;
|
||||
mod group_rev;
|
||||
mod grid_sort;
|
||||
|
||||
pub use filter_rev::*;
|
||||
pub use grid_group::*;
|
||||
pub use grid_rev::*;
|
||||
pub use grid_setting_rev::*;
|
||||
pub use group_rev::*;
|
||||
pub use grid_sort::*;
|
||||
|
@ -457,7 +457,6 @@ mod tests {
|
||||
AppRevision, FolderRevision, TrashRevision, ViewRevision, WorkspaceRevision,
|
||||
};
|
||||
use lib_ot::core::{OperationTransform, TextDelta, TextDeltaBuilder};
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn folder_add_workspace() {
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::entities::grid::{FieldChangesetParams, GridSettingChangesetParams};
|
||||
use crate::entities::grid::{
|
||||
CreateGridFilterParams, CreateGridGroupParams, FieldChangesetParams, GridSettingChangesetParams,
|
||||
};
|
||||
use crate::entities::revision::{md5, RepeatedRevision, Revision};
|
||||
use crate::errors::{internal_error, CollaborateError, CollaborateResult};
|
||||
use crate::util::{cal_diff, make_delta_from_revisions};
|
||||
@ -380,88 +382,65 @@ impl GridRevisionPad {
|
||||
self.modify_grid(|grid_rev| {
|
||||
let mut is_changed = None;
|
||||
let layout_rev = changeset.layout_type;
|
||||
|
||||
if let Some(params) = changeset.insert_filter {
|
||||
let filter_rev = GridFilterRevision {
|
||||
id: gen_grid_filter_id(),
|
||||
field_id: params.field_id.clone(),
|
||||
condition: params.condition,
|
||||
content: params.content,
|
||||
};
|
||||
|
||||
grid_rev
|
||||
.setting
|
||||
.insert_filter(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev, filter_rev);
|
||||
grid_rev.setting.insert_filter(
|
||||
&layout_rev,
|
||||
¶ms.field_id,
|
||||
¶ms.field_type_rev,
|
||||
make_filter_revision(¶ms),
|
||||
);
|
||||
|
||||
is_changed = Some(())
|
||||
}
|
||||
if let Some(params) = changeset.delete_filter {
|
||||
match grid_rev
|
||||
.setting
|
||||
.get_mut_filters(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev)
|
||||
if let Some(filters) =
|
||||
grid_rev
|
||||
.setting
|
||||
.get_mut_filters(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev)
|
||||
{
|
||||
Some(filters) => {
|
||||
filters.retain(|filter| filter.id != params.filter_id);
|
||||
}
|
||||
None => {
|
||||
tracing::warn!("Can't find the filter with {:?}", layout_rev);
|
||||
}
|
||||
filters.retain(|filter| filter.id != params.filter_id);
|
||||
}
|
||||
}
|
||||
if let Some(params) = changeset.insert_group {
|
||||
let group_rev = GridGroupRevision {
|
||||
id: gen_grid_group_id(),
|
||||
field_id: params.field_id.clone(),
|
||||
sub_field_id: params.sub_field_id,
|
||||
};
|
||||
|
||||
grid_rev
|
||||
.setting
|
||||
.insert_group(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev, group_rev);
|
||||
grid_rev.setting.insert_group(
|
||||
&layout_rev,
|
||||
¶ms.field_id,
|
||||
¶ms.field_type_rev,
|
||||
make_group_revision(¶ms),
|
||||
);
|
||||
is_changed = Some(());
|
||||
}
|
||||
if let Some(params) = changeset.delete_group {
|
||||
// match grid_rev.setting.groups.get_mut(&layout_rev) {
|
||||
// Some(groups) => groups.retain(|group| group.id != delete_group_id),
|
||||
// None => {
|
||||
// tracing::warn!("Can't find the group with {:?}", layout_rev);
|
||||
// }
|
||||
// }
|
||||
|
||||
match grid_rev
|
||||
.setting
|
||||
.get_mut_groups(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev)
|
||||
if let Some(groups) =
|
||||
grid_rev
|
||||
.setting
|
||||
.get_mut_groups(&layout_rev, ¶ms.field_id, ¶ms.field_type_rev)
|
||||
{
|
||||
Some(groups) => {
|
||||
groups.retain(|filter| filter.id != params.group_id);
|
||||
}
|
||||
None => {
|
||||
tracing::warn!("Can't find the group with {:?}", layout_rev);
|
||||
}
|
||||
groups.retain(|filter| filter.id != params.group_id);
|
||||
}
|
||||
}
|
||||
if let Some(sort) = changeset.insert_sort {
|
||||
let rev = GridSortRevision {
|
||||
id: gen_grid_sort_id(),
|
||||
field_id: sort.field_id,
|
||||
};
|
||||
|
||||
grid_rev
|
||||
.setting
|
||||
.sorts
|
||||
.entry(layout_rev.clone())
|
||||
.or_insert_with(std::vec::Vec::new)
|
||||
.push(rev);
|
||||
// let rev = GridSortRevision {
|
||||
// id: gen_grid_sort_id(),
|
||||
// field_id: sort.field_id,
|
||||
// };
|
||||
//
|
||||
// grid_rev
|
||||
// .setting
|
||||
// .sorts
|
||||
// .entry(layout_rev.clone())
|
||||
// .or_insert_with(std::vec::Vec::new)
|
||||
// .push(rev);
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
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 => {
|
||||
tracing::warn!("Can't find the sort with {:?}", layout_rev);
|
||||
}
|
||||
}
|
||||
// match grid_rev.setting.sorts.get_mut(&layout_rev) {
|
||||
// Some(sorts) => sorts.retain(|sort| sort.id != delete_sort_id),
|
||||
// None => {
|
||||
// tracing::warn!("Can't find the sort with {:?}", layout_rev);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Ok(is_changed)
|
||||
})
|
||||
@ -579,3 +558,20 @@ impl std::default::Default for GridRevisionPad {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_filter_revision(params: &CreateGridFilterParams) -> GridFilterRevision {
|
||||
GridFilterRevision {
|
||||
id: gen_grid_filter_id(),
|
||||
field_id: params.field_id.clone(),
|
||||
condition: params.condition.clone(),
|
||||
content: params.content.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_group_revision(params: &CreateGridGroupParams) -> GridGroupRevision {
|
||||
GridGroupRevision {
|
||||
id: gen_grid_group_id(),
|
||||
field_id: params.field_id.clone(),
|
||||
sub_field_id: params.sub_field_id.clone(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user