From 3dddd907b08a9dd50e36afb83de5d724265bd558 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 15 Nov 2022 10:47:51 +0800 Subject: [PATCH 1/3] chore: create filter bloc --- .../grid/application/filter/filter_bloc.dart | 0 .../application/filter/filter_service.dart | 118 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart create mode 100644 frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart new file mode 100644 index 0000000000..c1f0d3ca24 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart @@ -0,0 +1,118 @@ +import 'package:dartz/dartz.dart'; +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_filter.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart'; + +class FilterFFIService { + final String viewId; + const FilterFFIService({required this.viewId}); + + Future> createTextFilter({ + required String fieldId, + required TextFilterCondition condition, + String content = "", + }) { + return createFilter( + fieldId: fieldId, + fieldType: FieldType.RichText, + condition: condition.value, + content: content, + ); + } + + Future> createCheckboxFilter({ + required String fieldId, + required CheckboxFilterCondition condition, + }) { + return createFilter( + fieldId: fieldId, + fieldType: FieldType.Checkbox, + condition: condition.value, + ); + } + + Future> createNumberFilter({ + required String fieldId, + required NumberFilterCondition condition, + String content = "", + }) { + return createFilter( + fieldId: fieldId, + fieldType: FieldType.Checkbox, + condition: condition.value, + content: content, + ); + } + + Future> createDateFilter({ + required String fieldId, + required DateFilterCondition condition, + String content = "", + }) { + throw UnimplementedError(); + } + + Future> createURLFilter({ + required String fieldId, + required TextFilterCondition condition, + String content = "", + }) { + return createFilter( + fieldId: fieldId, + fieldType: FieldType.URL, + condition: condition.value, + content: content, + ); + } + + Future> createSingleSelectFilter({ + required String fieldId, + required SelectOptionCondition condition, + List optionIds = const [], + }) { + return createFilter( + fieldId: fieldId, + fieldType: FieldType.SingleSelect, + condition: condition.value, + ); + } + + Future> createMultiSelectFilter({ + required String fieldId, + required SelectOptionCondition condition, + List optionIds = const [], + }) { + return createFilter( + fieldId: fieldId, + fieldType: FieldType.MultiSelect, + condition: condition.value, + ); + } + + Future> createFilter({ + required String fieldId, + required FieldType fieldType, + required int condition, + String content = "", + }) { + TextFilterCondition.DoesNotContain.value; + + final insertFilterPayload = CreateFilterPayloadPB.create() + ..fieldId = fieldId + ..fieldType = fieldType + ..condition = condition + ..content = content; + + final payload = GridSettingChangesetPB.create() + ..gridId = viewId + ..insertFilter = insertFilterPayload; + return GridEventUpdateGridSetting(payload).send(); + } +} From f1ac38dd59fab873fab16bdedbb7fd2f40276a49 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 15 Nov 2022 13:04:30 +0800 Subject: [PATCH 2/3] chore: add filter service --- .../application/filter/filter_service.dart | 73 ++++++++++++++----- .../src/entities/filter_entities/util.rs | 47 ++++++++---- .../tests/grid/filter_test/script.rs | 42 +++++++---- .../grid/filter_test/text_filter_test.rs | 8 +- shared-lib/flowy-error-code/src/code.rs | 3 + 5 files changed, 122 insertions(+), 51 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart index c1f0d3ca24..b0b60d29aa 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart @@ -1,14 +1,15 @@ import 'package:dartz/dartz.dart'; 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_filter.pbenum.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbserver.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart'; +import 'package:fixnum/fixnum.dart' as $fixnum; class FilterFFIService { final String viewId; @@ -19,11 +20,14 @@ class FilterFFIService { required TextFilterCondition condition, String content = "", }) { + final filter = TextFilterPB() + ..condition = condition + ..content = content; + return createFilter( fieldId: fieldId, fieldType: FieldType.RichText, - condition: condition.value, - content: content, + data: filter.writeToBuffer(), ); } @@ -31,10 +35,12 @@ class FilterFFIService { required String fieldId, required CheckboxFilterCondition condition, }) { + final filter = CheckboxFilterPB()..condition = condition; + return createFilter( fieldId: fieldId, fieldType: FieldType.Checkbox, - condition: condition.value, + data: filter.writeToBuffer(), ); } @@ -43,20 +49,42 @@ class FilterFFIService { required NumberFilterCondition condition, String content = "", }) { + final filter = NumberFilterPB() + ..condition = condition + ..content = content; + return createFilter( fieldId: fieldId, - fieldType: FieldType.Checkbox, - condition: condition.value, - content: content, + fieldType: FieldType.Number, + data: filter.writeToBuffer(), ); } Future> createDateFilter({ required String fieldId, required DateFilterCondition condition, - String content = "", + int? start, + int? end, + int? timestamp, }) { - throw UnimplementedError(); + var filter = DateFilterPB(); + if (timestamp != null) { + filter.timestamp = $fixnum.Int64(timestamp); + } else { + if (start != null && end != null) { + filter.start = $fixnum.Int64(start); + filter.end = $fixnum.Int64(end); + } else { + throw Exception( + "Start and end should not be null if the timestamp is null"); + } + } + + return createFilter( + fieldId: fieldId, + fieldType: FieldType.DateTime, + data: filter.writeToBuffer(), + ); } Future> createURLFilter({ @@ -64,11 +92,14 @@ class FilterFFIService { required TextFilterCondition condition, String content = "", }) { + final filter = TextFilterPB() + ..condition = condition + ..content = content; + return createFilter( fieldId: fieldId, fieldType: FieldType.URL, - condition: condition.value, - content: content, + data: filter.writeToBuffer(), ); } @@ -77,10 +108,14 @@ class FilterFFIService { required SelectOptionCondition condition, List optionIds = const [], }) { + final filter = SelectOptionFilterPB() + ..condition = condition + ..optionIds.addAll(optionIds); + return createFilter( fieldId: fieldId, fieldType: FieldType.SingleSelect, - condition: condition.value, + data: filter.writeToBuffer(), ); } @@ -89,26 +124,28 @@ class FilterFFIService { required SelectOptionCondition condition, List optionIds = const [], }) { + final filter = SelectOptionFilterPB() + ..condition = condition + ..optionIds.addAll(optionIds); + return createFilter( fieldId: fieldId, fieldType: FieldType.MultiSelect, - condition: condition.value, + data: filter.writeToBuffer(), ); } Future> createFilter({ required String fieldId, required FieldType fieldType, - required int condition, - String content = "", + required List data, }) { TextFilterCondition.DoesNotContain.value; final insertFilterPayload = CreateFilterPayloadPB.create() ..fieldId = fieldId ..fieldType = fieldType - ..condition = condition - ..content = content; + ..data = data; final payload = GridSettingChangesetPB.create() ..gridId = viewId diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs index e3c44c67a3..f5edaa4657 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs @@ -1,9 +1,10 @@ use crate::entities::parser::NotEmptyStr; use crate::entities::{ - CheckboxFilterCondition, DateFilterCondition, FieldType, NumberFilterCondition, SelectOptionCondition, - TextFilterCondition, + CheckboxFilterPB, DateFilterContent, DateFilterPB, FieldType, NumberFilterPB, SelectOptionFilterPB, TextFilterPB, }; +use crate::services::field::SelectOptionIds; use crate::services::filter::FilterType; +use bytes::Bytes; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use grid_rev_model::{FieldRevision, FieldTypeRevision, FilterRevision}; @@ -89,20 +90,17 @@ pub struct CreateFilterPayloadPB { pub field_type: FieldType, #[pb(index = 3)] - pub condition: u32, - - #[pb(index = 4)] - pub content: String, + pub data: Vec, } impl CreateFilterPayloadPB { #[allow(dead_code)] - pub fn new>(field_rev: &FieldRevision, condition: T, content: String) -> Self { + pub fn new>(field_rev: &FieldRevision, data: T) -> Self { + let data = data.try_into().unwrap_or_else(|_| Bytes::new()); Self { field_id: field_rev.id.clone(), field_type: field_rev.ty.into(), - condition: condition.into(), - content, + data: data.to_vec(), } } } @@ -114,22 +112,39 @@ impl TryInto for CreateFilterPayloadPB { let field_id = NotEmptyStr::parse(self.field_id) .map_err(|_| ErrorCode::FieldIdIsEmpty)? .0; - let condition = self.condition as u8; + let condition; + let mut content = "".to_string(); + let bytes: &[u8] = self.data.as_ref(); + match self.field_type { FieldType::RichText | FieldType::URL => { - let _ = TextFilterCondition::try_from(condition)?; + let filter = TextFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?; + condition = filter.condition as u8; + content = filter.content; } FieldType::Checkbox => { - let _ = CheckboxFilterCondition::try_from(condition)?; + let filter = CheckboxFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?; + condition = filter.condition as u8; } FieldType::Number => { - let _ = NumberFilterCondition::try_from(condition)?; + let filter = NumberFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?; + condition = filter.condition as u8; + content = filter.content; } FieldType::DateTime => { - let _ = DateFilterCondition::try_from(condition)?; + let filter = DateFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?; + condition = filter.condition as u8; + content = DateFilterContent { + start: filter.start, + end: filter.end, + timestamp: filter.timestamp, + } + .to_string(); } FieldType::SingleSelect | FieldType::MultiSelect => { - let _ = SelectOptionCondition::try_from(condition)?; + let filter = SelectOptionFilterPB::try_from(bytes).map_err(|_| ErrorCode::ProtobufSerde)?; + condition = filter.condition as u8; + content = SelectOptionIds::from(filter.option_ids).to_string(); } } @@ -137,7 +152,7 @@ impl TryInto for CreateFilterPayloadPB { field_id, field_type_rev: self.field_type.into(), condition, - content: self.content, + content, }) } } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs index 395cc19501..53308307fb 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/script.rs @@ -3,8 +3,9 @@ #![allow(dead_code)] #![allow(unused_imports)] +use bytes::Bytes; use futures::TryFutureExt; -use flowy_grid::entities::{CreateFilterParams, CreateFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB, RowPB, TextFilterCondition, FieldType, NumberFilterCondition, CheckboxFilterCondition, DateFilterCondition, DateFilterContent, SelectOptionCondition}; +use flowy_grid::entities::{CreateFilterParams, CreateFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB, RowPB, TextFilterCondition, FieldType, NumberFilterCondition, CheckboxFilterCondition, DateFilterCondition, DateFilterContent, SelectOptionCondition, TextFilterPB, NumberFilterPB, CheckboxFilterPB, DateFilterPB, SelectOptionFilterPB}; use flowy_grid::services::field::SelectOptionIds; use flowy_grid::services::setting::GridSettingChangesetBuilder; use grid_rev_model::{FieldRevision, FieldTypeRevision}; @@ -85,49 +86,60 @@ impl GridFilterTest { self.insert_filter(payload).await; } FilterScript::CreateTextFilter { condition, content} => { + let field_rev = self.get_field_rev(FieldType::RichText); + let text_filter= TextFilterPB { + condition, + content + }; let payload = - CreateFilterPayloadPB::new(field_rev, condition, content); + CreateFilterPayloadPB::new(field_rev, text_filter); self.insert_filter(payload).await; } FilterScript::CreateNumberFilter {condition, content} => { let field_rev = self.get_field_rev(FieldType::Number); + let number_filter = NumberFilterPB { + condition, + content + }; let payload = - CreateFilterPayloadPB::new(field_rev, condition, content); + CreateFilterPayloadPB::new(field_rev, number_filter); self.insert_filter(payload).await; } FilterScript::CreateCheckboxFilter {condition} => { let field_rev = self.get_field_rev(FieldType::Checkbox); + let checkbox_filter = CheckboxFilterPB { + condition + }; let payload = - CreateFilterPayloadPB::new(field_rev, condition, "".to_string()); + CreateFilterPayloadPB::new(field_rev, checkbox_filter); self.insert_filter(payload).await; } FilterScript::CreateDateFilter { condition, start, end, timestamp} => { let field_rev = self.get_field_rev(FieldType::DateTime); - let content = DateFilterContent { + let date_filter = DateFilterPB { + condition, start, end, - timestamp, - }.to_string(); - let payload = - CreateFilterPayloadPB::new(field_rev, condition, content); + timestamp + }; + let payload = + CreateFilterPayloadPB::new(field_rev, date_filter); self.insert_filter(payload).await; } FilterScript::CreateMultiSelectFilter { condition, option_ids} => { let field_rev = self.get_field_rev(FieldType::MultiSelect); - let content = - SelectOptionIds::from(option_ids).to_string(); + let filter = SelectOptionFilterPB { condition, option_ids }; let payload = - CreateFilterPayloadPB::new(field_rev, condition, content); + CreateFilterPayloadPB::new(field_rev, filter); self.insert_filter(payload).await; } FilterScript::CreateSingleSelectFilter { condition, option_ids} => { let field_rev = self.get_field_rev(FieldType::SingleSelect); - let content = - SelectOptionIds::from(option_ids).to_string(); + let filter = SelectOptionFilterPB { condition, option_ids }; let payload = - CreateFilterPayloadPB::new(field_rev, condition, content); + CreateFilterPayloadPB::new(field_rev, filter); self.insert_filter(payload).await; } FilterScript::AssertFilterCount { count } => { diff --git a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs index e5e361651e..19d103dd4f 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/filter_test/text_filter_test.rs @@ -1,6 +1,6 @@ use crate::grid::filter_test::script::FilterScript::*; use crate::grid::filter_test::script::*; -use flowy_grid::entities::{CreateFilterPayloadPB, FieldType, TextFilterCondition}; +use flowy_grid::entities::{CreateFilterPayloadPB, FieldType, TextFilterCondition, TextFilterPB}; use flowy_grid::services::filter::FilterType; #[tokio::test] @@ -73,7 +73,11 @@ async fn grid_filter_ends_with_text_test() { async fn grid_filter_delete_test() { let mut test = GridFilterTest::new().await; let field_rev = test.get_field_rev(FieldType::RichText).clone(); - let payload = CreateFilterPayloadPB::new(&field_rev, TextFilterCondition::TextIsEmpty, "".to_string()); + let text_filter = TextFilterPB { + condition: TextFilterCondition::TextIsEmpty, + content: "".to_string(), + }; + let payload = CreateFilterPayloadPB::new(&field_rev, text_filter); let scripts = vec![ InsertFilter { payload }, AssertFilterCount { count: 1 }, diff --git a/shared-lib/flowy-error-code/src/code.rs b/shared-lib/flowy-error-code/src/code.rs index 2cbe7ffc28..c2c95caab1 100644 --- a/shared-lib/flowy-error-code/src/code.rs +++ b/shared-lib/flowy-error-code/src/code.rs @@ -129,6 +129,9 @@ pub enum ErrorCode { #[display(fmt = "Serde")] Serde = 1001, + #[display(fmt = "Protobuf serde")] + ProtobufSerde = 1002, + #[display(fmt = "Out of bounds")] OutOfBounds = 10001, } From 0ee27097cee3534a4c20fe73f9c03bededde3fe5 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 15 Nov 2022 23:17:01 +0800 Subject: [PATCH 3/3] chore: add fitler bloc test --- .../board/application/group_controller.dart | 2 +- .../board/application/group_listener.dart | 4 +- .../grid/application/filter/filter_bloc.dart | 206 ++++++++++++++++++ .../application/filter/filter_listener.dart | 53 +++++ .../application/filter/filter_service.dart | 49 ++++- .../bloc_test/grid_test/filter_bloc_test.dart | 64 ++++++ .../test/bloc_test/grid_test/util.dart | 6 + .../flowy-grid/src/dart_notification.rs | 1 + .../filter_entities/checkbox_filter.rs | 4 +- .../entities/filter_entities/date_filter.rs | 4 +- .../filter_entities/filter_changeset.rs | 31 +++ .../src/entities/filter_entities/mod.rs | 2 + .../entities/filter_entities/number_filter.rs | 4 +- .../filter_entities/select_option_filter.rs | 4 +- .../entities/filter_entities/text_filter.rs | 4 +- .../src/entities/filter_entities/util.rs | 38 +++- .../group_entities/group_changeset.rs | 6 +- .../src/entities/setting_entities.rs | 5 +- .../rust-lib/flowy-grid/src/event_handler.rs | 13 ++ frontend/rust-lib/flowy-grid/src/event_map.rs | 4 + .../src/services/filter/controller.rs | 12 +- .../src/services/grid_view_editor.rs | 54 +++-- .../src/services/grid_view_manager.rs | 2 +- .../flowy-grid/src/services/group/action.rs | 18 +- .../src/services/group/controller.rs | 16 +- .../controller_impls/checkbox_controller.rs | 16 +- .../controller_impls/default_controller.rs | 8 +- .../multi_select_controller.rs | 12 +- .../single_select_controller.rs | 12 +- .../select_option_controller/util.rs | 14 +- shared-lib/grid-rev-model/src/filter_rev.rs | 2 + 31 files changed, 578 insertions(+), 92 deletions(-) create mode 100644 frontend/app_flowy/lib/plugins/grid/application/filter/filter_listener.dart create mode 100644 frontend/app_flowy/test/bloc_test/grid_test/filter_bloc_test.dart create mode 100644 frontend/rust-lib/flowy-grid/src/entities/filter_entities/filter_changeset.rs diff --git a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart index 6a148c0312..8db9fad4fd 100644 --- a/frontend/app_flowy/lib/plugins/board/application/group_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/group_controller.dart @@ -39,7 +39,7 @@ class GroupController { void startListening() { _listener.start(onGroupChanged: (result) { result.fold( - (GroupChangesetPB changeset) { + (GroupRowsNotificationPB changeset) { for (final deletedRow in changeset.deletedRows) { group.rows.removeWhere((rowPB) => rowPB.id == deletedRow); delegate.removeRow(group, deletedRow); diff --git a/frontend/app_flowy/lib/plugins/board/application/group_listener.dart b/frontend/app_flowy/lib/plugins/board/application/group_listener.dart index e3b626af07..8d0d48bddb 100644 --- a/frontend/app_flowy/lib/plugins/board/application/group_listener.dart +++ b/frontend/app_flowy/lib/plugins/board/application/group_listener.dart @@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart'; -typedef UpdateGroupNotifiedValue = Either; +typedef UpdateGroupNotifiedValue = Either; class GroupListener { final GroupPB group; @@ -34,7 +34,7 @@ class GroupListener { case GridNotification.DidUpdateGroup: result.fold( (payload) => _groupNotifier?.value = - left(GroupChangesetPB.fromBuffer(payload)), + left(GroupRowsNotificationPB.fromBuffer(payload)), (error) => _groupNotifier?.value = right(error), ); break; diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart index e69de29bb2..425263ba94 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_bloc.dart @@ -0,0 +1,206 @@ +import 'package:app_flowy/plugins/grid/application/filter/filter_listener.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pbserver.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'filter_service.dart'; + +part 'filter_bloc.freezed.dart'; + +class GridFilterBloc extends Bloc { + final String viewId; + final FilterFFIService _ffiService; + final FilterListener _listener; + GridFilterBloc({required this.viewId}) + : _ffiService = FilterFFIService(viewId: viewId), + _listener = FilterListener(viewId: viewId), + super(GridFilterState.initial()) { + on( + (event, emit) async { + event.when( + initial: () async { + _startListening(); + await _loadFilters(); + }, + deleteFilter: ( + String fieldId, + String filterId, + FieldType fieldType, + ) { + _ffiService.deleteFilter( + fieldId: fieldId, + filterId: filterId, + fieldType: fieldType, + ); + }, + didReceiveFilters: (filters) { + emit(state.copyWith(filters: filters)); + }, + createCheckboxFilter: ( + String fieldId, + CheckboxFilterCondition condition, + ) { + _ffiService.createCheckboxFilter( + fieldId: fieldId, + condition: condition, + ); + }, + createNumberFilter: ( + String fieldId, + NumberFilterCondition condition, + String content, + ) { + _ffiService.createNumberFilter( + fieldId: fieldId, + condition: condition, + content: content, + ); + }, + createTextFilter: ( + String fieldId, + TextFilterCondition condition, + String content, + ) { + _ffiService.createTextFilter( + fieldId: fieldId, + condition: condition, + ); + }, + createDateFilter: ( + String fieldId, + DateFilterCondition condition, + int timestamp, + ) { + _ffiService.createDateFilter( + fieldId: fieldId, + condition: condition, + timestamp: timestamp, + ); + }, + createDateFilterInRange: ( + String fieldId, + DateFilterCondition condition, + int start, + int end, + ) { + _ffiService.createDateFilter( + fieldId: fieldId, + condition: condition, + start: start, + end: end, + ); + }, + ); + }, + ); + } + + void _startListening() { + _listener.start(onFilterChanged: (result) { + result.fold( + (changeset) { + final List filters = List.from(state.filters); + + // Deletes the filters + final deleteFilterIds = + changeset.deleteFilters.map((e) => e.id).toList(); + filters.retainWhere( + (element) => !deleteFilterIds.contains(element.id), + ); + + // Inserts the new fitler if it's not exist + for (final newFilter in changeset.insertFilters) { + final index = + filters.indexWhere((element) => element.id == newFilter.id); + if (index == -1) { + filters.add(newFilter); + } + } + + if (!isClosed) { + add(GridFilterEvent.didReceiveFilters(filters)); + } + }, + (err) => Log.error(err), + ); + }); + } + + Future _loadFilters() async { + final result = await _ffiService.getAllFilters(); + result.fold( + (filters) { + if (!isClosed) { + add(GridFilterEvent.didReceiveFilters(filters)); + } + }, + (err) => Log.error(err), + ); + } + + @override + Future close() async { + await _listener.stop(); + return super.close(); + } +} + +@freezed +class GridFilterEvent with _$GridFilterEvent { + const factory GridFilterEvent.initial() = _Initial; + const factory GridFilterEvent.didReceiveFilters(List filters) = + _DidReceiveFilters; + + const factory GridFilterEvent.deleteFilter({ + required String fieldId, + required String filterId, + required FieldType fieldType, + }) = _DeleteFilter; + + const factory GridFilterEvent.createTextFilter({ + required String fieldId, + required TextFilterCondition condition, + required String content, + }) = _CreateTextFilter; + + const factory GridFilterEvent.createCheckboxFilter({ + required String fieldId, + required CheckboxFilterCondition condition, + }) = _CreateCheckboxFilter; + + const factory GridFilterEvent.createNumberFilter({ + required String fieldId, + required NumberFilterCondition condition, + required String content, + }) = _CreateCheckboxFitler; + + const factory GridFilterEvent.createDateFilter({ + required String fieldId, + required DateFilterCondition condition, + required int start, + }) = _CreateDateFitler; + + const factory GridFilterEvent.createDateFilterInRange({ + required String fieldId, + required DateFilterCondition condition, + required int start, + required int end, + }) = _CreateDateFitlerInRange; +} + +@freezed +class GridFilterState with _$GridFilterState { + const factory GridFilterState({ + required List filters, + }) = _GridFilterState; + + factory GridFilterState.initial() => const GridFilterState( + filters: [], + ); +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_listener.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_listener.dart new file mode 100644 index 0000000000..475f2de61d --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_listener.dart @@ -0,0 +1,53 @@ +import 'dart:typed_data'; + +import 'package:app_flowy/core/grid_notification.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/filter_changeset.pb.dart'; +import 'package:dartz/dartz.dart'; + +typedef UpdateFilterNotifiedValue + = Either; + +class FilterListener { + final String viewId; + + PublishNotifier? _filterNotifier = + PublishNotifier(); + GridNotificationListener? _listener; + FilterListener({required this.viewId}); + + void start({ + required void Function(UpdateFilterNotifiedValue) onFilterChanged, + }) { + _filterNotifier?.addPublishListener(onFilterChanged); + _listener = GridNotificationListener( + objectId: viewId, + handler: _handler, + ); + } + + void _handler( + GridNotification ty, + Either result, + ) { + switch (ty) { + case GridNotification.DidUpdateFilter: + result.fold( + (payload) => _filterNotifier?.value = + left(FilterChangesetNotificationPB.fromBuffer(payload)), + (error) => _filterNotifier?.value = right(error), + ); + break; + default: + break; + } + } + + Future stop() async { + await _listener?.stop(); + _filterNotifier?.dispose(); + _filterNotifier = null; + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart index b0b60d29aa..4cb703bcd3 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/filter/filter_service.dart @@ -1,9 +1,11 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_filter.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_filter.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart'; @@ -15,6 +17,17 @@ class FilterFFIService { final String viewId; const FilterFFIService({required this.viewId}); + Future, FlowyError>> getAllFilters() { + final payload = GridIdPB()..value = viewId; + + return GridEventGetAllFilters(payload).send().then((result) { + return result.fold( + (repeated) => left(repeated.items), + (r) => right(r), + ); + }); + } + Future> createTextFilter({ required String fieldId, required TextFilterCondition condition, @@ -150,6 +163,40 @@ class FilterFFIService { final payload = GridSettingChangesetPB.create() ..gridId = viewId ..insertFilter = insertFilterPayload; - return GridEventUpdateGridSetting(payload).send(); + return GridEventUpdateGridSetting(payload).send().then((result) { + return result.fold( + (l) => left(l), + (err) { + Log.error(err); + return right(err); + }, + ); + }); + } + + Future> deleteFilter({ + required String fieldId, + required String filterId, + required FieldType fieldType, + }) { + TextFilterCondition.DoesNotContain.value; + + final deleteFilterPayload = DeleteFilterPayloadPB.create() + ..fieldId = fieldId + ..filterId = filterId + ..fieldType = fieldType; + + final payload = GridSettingChangesetPB.create() + ..gridId = viewId + ..deleteFilter = deleteFilterPayload; + return GridEventUpdateGridSetting(payload).send().then((result) { + return result.fold( + (l) => left(l), + (err) { + Log.error(err); + return right(err); + }, + ); + }); } } diff --git a/frontend/app_flowy/test/bloc_test/grid_test/filter_bloc_test.dart b/frontend/app_flowy/test/bloc_test/grid_test/filter_bloc_test.dart new file mode 100644 index 0000000000..307663cf7c --- /dev/null +++ b/frontend/app_flowy/test/bloc_test/grid_test/filter_bloc_test.dart @@ -0,0 +1,64 @@ +import 'package:app_flowy/plugins/grid/application/filter/filter_bloc.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:bloc_test/bloc_test.dart'; +import 'util.dart'; + +void main() { + late AppFlowyGridTest gridTest; + setUpAll(() async { + gridTest = await AppFlowyGridTest.ensureInitialized(); + }); + + group('$GridFilterBloc', () { + setUp(() async { + await gridTest.createTestGrid(); + }); + blocTest( + "create a text filter", + build: () => GridFilterBloc(viewId: gridTest.gridView.id) + ..add(const GridFilterEvent.initial()), + act: (bloc) async { + final textField = gridTest.textFieldContext(); + bloc.add( + GridFilterEvent.createTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""), + ); + }, + wait: const Duration(milliseconds: 300), + verify: (bloc) { + assert(bloc.state.filters.length == 1); + }, + ); + + blocTest( + "delete a text filter", + build: () => GridFilterBloc(viewId: gridTest.gridView.id) + ..add(const GridFilterEvent.initial()), + act: (bloc) async { + final textField = gridTest.textFieldContext(); + bloc.add( + GridFilterEvent.createTextFilter( + fieldId: textField.id, + condition: TextFilterCondition.TextIsEmpty, + content: ""), + ); + await gridResponseFuture(); + final filter = bloc.state.filters.first; + bloc.add( + GridFilterEvent.deleteFilter( + fieldId: textField.id, + filterId: filter.id, + fieldType: textField.fieldType, + ), + ); + }, + wait: const Duration(milliseconds: 300), + verify: (bloc) { + assert(bloc.state.filters.isEmpty); + }, + ); + }); +} diff --git a/frontend/app_flowy/test/bloc_test/grid_test/util.dart b/frontend/app_flowy/test/bloc_test/grid_test/util.dart index e6bec24aeb..26bdfefab4 100644 --- a/frontend/app_flowy/test/bloc_test/grid_test/util.dart +++ b/frontend/app_flowy/test/bloc_test/grid_test/util.dart @@ -157,6 +157,12 @@ class AppFlowyGridTest { return GridFieldCellContext(gridId: gridView.id, field: field); } + GridFieldContext textFieldContext() { + final fieldContext = fieldContexts + .firstWhere((element) => element.fieldType == FieldType.RichText); + return fieldContext; + } + Future createTestGrid() async { final app = await unitTest.createTestApp(); final builder = GridPluginBuilder(); diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 6e47dfceb9..07a83f5c32 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -14,6 +14,7 @@ pub enum GridNotification { DidUpdateGroupView = 60, DidUpdateGroup = 61, DidGroupByNewField = 62, + DidUpdateFilter = 63, DidUpdateGridSetting = 70, } diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs index 724850fd85..5dc4ebd80b 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/checkbox_filter.rs @@ -40,8 +40,8 @@ impl std::convert::TryFrom for CheckboxFilterCondition { } } -impl std::convert::From> for CheckboxFilterPB { - fn from(rev: Arc) -> Self { +impl std::convert::From<&FilterRevision> for CheckboxFilterPB { + fn from(rev: &FilterRevision) -> Self { CheckboxFilterPB { condition: CheckboxFilterCondition::try_from(rev.condition).unwrap_or(CheckboxFilterCondition::IsChecked), } diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/date_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/date_filter.rs index b1098f7e3e..049aa81df1 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/date_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/date_filter.rs @@ -81,8 +81,8 @@ impl std::convert::TryFrom for DateFilterCondition { } } } -impl std::convert::From> for DateFilterPB { - fn from(rev: Arc) -> Self { +impl std::convert::From<&FilterRevision> for DateFilterPB { + fn from(rev: &FilterRevision) -> Self { let condition = DateFilterCondition::try_from(rev.condition).unwrap_or(DateFilterCondition::DateIs); let mut filter = DateFilterPB { condition, diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/filter_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/filter_changeset.rs new file mode 100644 index 0000000000..3d928426b2 --- /dev/null +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/filter_changeset.rs @@ -0,0 +1,31 @@ +use crate::entities::{FilterPB, InsertedRowPB, RepeatedFilterPB, RowPB}; +use flowy_derive::ProtoBuf; + +#[derive(Debug, Default, ProtoBuf)] +pub struct FilterChangesetNotificationPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2)] + pub insert_filters: Vec, + + #[pb(index = 3)] + pub delete_filters: Vec, +} + +impl FilterChangesetNotificationPB { + pub fn from_insert(view_id: &str, filters: Vec) -> Self { + Self { + view_id: view_id.to_string(), + insert_filters: filters, + delete_filters: Default::default(), + } + } + pub fn from_delete(view_id: &str, filters: Vec) -> Self { + Self { + view_id: view_id.to_string(), + insert_filters: Default::default(), + delete_filters: filters, + } + } +} diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/mod.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/mod.rs index bb033f5600..435dac56f2 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/mod.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/mod.rs @@ -1,5 +1,6 @@ mod checkbox_filter; mod date_filter; +mod filter_changeset; mod number_filter; mod select_option_filter; mod text_filter; @@ -7,6 +8,7 @@ mod util; pub use checkbox_filter::*; pub use date_filter::*; +pub use filter_changeset::*; pub use number_filter::*; pub use select_option_filter::*; pub use text_filter::*; diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs index 1322a2decd..f02eb9b5cf 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/number_filter.rs @@ -55,8 +55,8 @@ impl std::convert::TryFrom for NumberFilterCondition { } } -impl std::convert::From> for NumberFilterPB { - fn from(rev: Arc) -> Self { +impl std::convert::From<&FilterRevision> for NumberFilterPB { + fn from(rev: &FilterRevision) -> Self { NumberFilterPB { condition: NumberFilterCondition::try_from(rev.condition).unwrap_or(NumberFilterCondition::Equal), content: rev.content.clone(), diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs index 3a8796bfc4..e2a5a93856 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/select_option_filter.rs @@ -48,8 +48,8 @@ impl std::convert::TryFrom for SelectOptionCondition { } } -impl std::convert::From> for SelectOptionFilterPB { - fn from(rev: Arc) -> Self { +impl std::convert::From<&FilterRevision> for SelectOptionFilterPB { + fn from(rev: &FilterRevision) -> Self { let ids = SelectOptionIds::from(rev.content.clone()); SelectOptionFilterPB { condition: SelectOptionCondition::try_from(rev.condition).unwrap_or(SelectOptionCondition::OptionIs), diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs index fcac562a8f..14b79eb463 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/text_filter.rs @@ -55,8 +55,8 @@ impl std::convert::TryFrom for TextFilterCondition { } } -impl std::convert::From> for TextFilterPB { - fn from(rev: Arc) -> Self { +impl std::convert::From<&FilterRevision> for TextFilterPB { + fn from(rev: &FilterRevision) -> Self { TextFilterPB { condition: TextFilterCondition::try_from(rev.condition).unwrap_or(TextFilterCondition::Is), content: rev.content.clone(), diff --git a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs index f5edaa4657..662ad75b04 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/filter_entities/util.rs @@ -15,29 +15,49 @@ use std::sync::Arc; pub struct FilterPB { #[pb(index = 1)] pub id: String, -} -#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct RepeatedGridFilterConfigurationPB { - #[pb(index = 1)] - pub items: Vec, + #[pb(index = 2)] + pub ty: FieldType, + + #[pb(index = 3)] + pub data: Vec, } impl std::convert::From<&FilterRevision> for FilterPB { fn from(rev: &FilterRevision) -> Self { - Self { id: rev.id.clone() } + let field_type: FieldType = rev.field_type_rev.into(); + let bytes: Bytes = match field_type { + FieldType::RichText => TextFilterPB::from(rev).try_into().unwrap(), + FieldType::Number => NumberFilterPB::from(rev).try_into().unwrap(), + FieldType::DateTime => DateFilterPB::from(rev).try_into().unwrap(), + FieldType::SingleSelect => SelectOptionFilterPB::from(rev).try_into().unwrap(), + FieldType::MultiSelect => SelectOptionFilterPB::from(rev).try_into().unwrap(), + FieldType::Checkbox => CheckboxFilterPB::from(rev).try_into().unwrap(), + FieldType::URL => TextFilterPB::from(rev).try_into().unwrap(), + }; + Self { + id: rev.id.clone(), + ty: rev.field_type_rev.into(), + data: bytes.to_vec(), + } } } -impl std::convert::From>> for RepeatedGridFilterConfigurationPB { +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct RepeatedFilterPB { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::convert::From>> for RepeatedFilterPB { fn from(revs: Vec>) -> Self { - RepeatedGridFilterConfigurationPB { + RepeatedFilterPB { items: revs.into_iter().map(|rev| rev.as_ref().into()).collect(), } } } -impl std::convert::From> for RepeatedGridFilterConfigurationPB { +impl std::convert::From> for RepeatedFilterPB { fn from(items: Vec) -> Self { Self { items } } diff --git a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs index c9aa176567..b0f6056ad0 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/group_entities/group_changeset.rs @@ -5,7 +5,7 @@ use flowy_error::ErrorCode; use std::fmt::Formatter; #[derive(Debug, Default, ProtoBuf)] -pub struct GroupChangesetPB { +pub struct GroupRowsNotificationPB { #[pb(index = 1)] pub group_id: String, @@ -22,7 +22,7 @@ pub struct GroupChangesetPB { pub updated_rows: Vec, } -impl std::fmt::Display for GroupChangesetPB { +impl std::fmt::Display for GroupRowsNotificationPB { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { for inserted_row in &self.inserted_rows { let _ = f.write_fmt(format_args!( @@ -39,7 +39,7 @@ impl std::fmt::Display for GroupChangesetPB { } } -impl GroupChangesetPB { +impl GroupRowsNotificationPB { pub fn is_empty(&self) -> bool { self.group_name.is_none() && self.inserted_rows.is_empty() diff --git a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs index 89686c04c4..fbeb2117d6 100644 --- a/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-grid/src/entities/setting_entities.rs @@ -1,8 +1,7 @@ use crate::entities::parser::NotEmptyStr; use crate::entities::{ CreateFilterParams, CreateFilterPayloadPB, DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, - DeleteGroupPayloadPB, InsertGroupParams, InsertGroupPayloadPB, RepeatedGridFilterConfigurationPB, - RepeatedGridGroupConfigurationPB, + DeleteGroupPayloadPB, InsertGroupParams, InsertGroupPayloadPB, RepeatedFilterPB, RepeatedGridGroupConfigurationPB, }; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use flowy_error::ErrorCode; @@ -21,7 +20,7 @@ pub struct GridSettingPB { pub layout_type: GridLayout, #[pb(index = 3)] - pub filter_configurations: RepeatedGridFilterConfigurationPB, + pub filter_configurations: RepeatedFilterPB, #[pb(index = 4)] pub group_configurations: RepeatedGridGroupConfigurationPB, diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 3bfb87117a..5e05912485 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -61,6 +61,19 @@ pub(crate) async fn update_grid_setting_handler( Ok(()) } +#[tracing::instrument(level = "trace", skip(data, manager), err)] +pub(crate) async fn get_all_filters_handler( + data: Data, + manager: AppData>, +) -> DataResult { + let grid_id: GridIdPB = data.into_inner(); + let editor = manager.open_grid(grid_id).await?; + let filters = RepeatedFilterPB { + items: editor.get_all_filters().await?, + }; + data_result(filters) +} + #[tracing::instrument(level = "debug", skip(data, manager), err)] pub(crate) async fn get_grid_blocks_handler( data: Data, diff --git a/frontend/rust-lib/flowy-grid/src/event_map.rs b/frontend/rust-lib/flowy-grid/src/event_map.rs index c407b19c2a..bb80c35973 100644 --- a/frontend/rust-lib/flowy-grid/src/event_map.rs +++ b/frontend/rust-lib/flowy-grid/src/event_map.rs @@ -12,6 +12,7 @@ pub fn create(grid_manager: Arc) -> Module { .event(GridEvent::GetGridBlocks, get_grid_blocks_handler) .event(GridEvent::GetGridSetting, get_grid_setting_handler) .event(GridEvent::UpdateGridSetting, update_grid_setting_handler) + .event(GridEvent::GetAllFilters, get_all_filters_handler) // Field .event(GridEvent::GetFields, get_fields_handler) .event(GridEvent::UpdateField, update_field_handler) @@ -78,6 +79,9 @@ pub enum GridEvent { #[event(input = "GridSettingChangesetPB")] UpdateGridSetting = 3, + #[event(input = "GridIdPB", output = "RepeatedFilterPB")] + GetAllFilters = 4, + /// [GetFields] event is used to get the grid's settings. /// /// The event handler accepts a [GetFieldPayloadPB] and returns a [RepeatedFieldPB] diff --git a/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs b/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs index 62f7b9375b..7756820dcf 100644 --- a/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/filter/controller.rs @@ -181,37 +181,37 @@ impl FilterController { let _ = self .filter_map .text_filter - .insert(filter_type, TextFilterPB::from(filter_rev)); + .insert(filter_type, TextFilterPB::from(filter_rev.as_ref())); } FieldType::Number => { let _ = self .filter_map .number_filter - .insert(filter_type, NumberFilterPB::from(filter_rev)); + .insert(filter_type, NumberFilterPB::from(filter_rev.as_ref())); } FieldType::DateTime => { let _ = self .filter_map .date_filter - .insert(filter_type, DateFilterPB::from(filter_rev)); + .insert(filter_type, DateFilterPB::from(filter_rev.as_ref())); } FieldType::SingleSelect | FieldType::MultiSelect => { let _ = self .filter_map .select_option_filter - .insert(filter_type, SelectOptionFilterPB::from(filter_rev)); + .insert(filter_type, SelectOptionFilterPB::from(filter_rev.as_ref())); } FieldType::Checkbox => { let _ = self .filter_map .checkbox_filter - .insert(filter_type, CheckboxFilterPB::from(filter_rev)); + .insert(filter_type, CheckboxFilterPB::from(filter_rev.as_ref())); } FieldType::URL => { let _ = self .filter_map .url_filter - .insert(filter_type, TextFilterPB::from(filter_rev)); + .insert(filter_type, TextFilterPB::from(filter_rev.as_ref())); } } } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index f1e4b5f52d..f003e6e4ca 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -132,8 +132,8 @@ impl GridViewRevisionEditor { index, is_new: true, }; - let changeset = GroupChangesetPB::insert(group_id.clone(), vec![inserted_row]); - self.notify_did_update_group(changeset).await; + let changeset = GroupRowsNotificationPB::insert(group_id.clone(), vec![inserted_row]); + self.notify_did_update_group_rows(changeset).await; } } } @@ -150,7 +150,7 @@ impl GridViewRevisionEditor { tracing::trace!("Delete row in view changeset: {:?}", changesets); if let Some(changesets) = changesets { for changeset in changesets { - self.notify_did_update_group(changeset).await; + self.notify_did_update_group_rows(changeset).await; } } } @@ -164,7 +164,7 @@ impl GridViewRevisionEditor { if let Some(changesets) = changesets { for changeset in changesets { - self.notify_did_update_group(changeset).await; + self.notify_did_update_group_rows(changeset).await; } } } @@ -175,7 +175,7 @@ impl GridViewRevisionEditor { row_changeset: &mut RowChangeset, to_group_id: &str, to_row_id: Option, - ) -> Vec { + ) -> Vec { let changesets = self .mut_group_controller(|group_controller, field_rev| { let move_row_context = MoveGroupRowContext { @@ -252,9 +252,12 @@ impl GridViewRevisionEditor { self.pad.read().await.get_all_filters(&field_revs) } - pub(crate) async fn get_view_filters(&self, filter_id: &FilterType) -> Vec> { - let field_type_rev: FieldTypeRevision = filter_id.field_type.clone().into(); - self.pad.read().await.get_filters(&filter_id.field_id, &field_type_rev) + pub(crate) async fn get_view_filters(&self, filter_type: &FilterType) -> Vec> { + let field_type_rev: FieldTypeRevision = filter_type.field_type.clone().into(); + self.pad + .read() + .await + .get_filters(&filter_type.field_id, &field_type_rev) } /// Initialize new group when grouping by a new field @@ -290,14 +293,16 @@ impl GridViewRevisionEditor { pub(crate) async fn insert_view_filter(&self, params: CreateFilterParams) -> FlowyResult<()> { let filter_type = FilterType::from(¶ms); + let filter_rev = FilterRevision { + id: gen_grid_filter_id(), + field_id: params.field_id.clone(), + field_type_rev: params.field_type_rev, + condition: params.condition, + content: params.content, + }; + let filter_pb = FilterPB::from(&filter_rev); let _ = self .modify(|pad| { - let filter_rev = FilterRevision { - id: gen_grid_filter_id(), - field_id: params.field_id.clone(), - condition: params.condition, - content: params.content, - }; let changeset = pad.insert_filter(¶ms.field_id, ¶ms.field_type_rev, filter_rev)?; Ok(changeset) }) @@ -309,12 +314,20 @@ impl GridViewRevisionEditor { .apply_changeset(FilterChangeset::from_insert(filter_type)) .await; + let changeset = FilterChangesetNotificationPB::from_insert(&self.view_id, vec![filter_pb]); + self.notify_did_update_filter(changeset).await; Ok(()) } pub(crate) async fn delete_view_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> { let filter_type = params.filter_type; let field_type_rev = filter_type.field_type_rev(); + let filters = self + .get_view_filters(&filter_type) + .await + .into_iter() + .map(|filter| FilterPB::from(filter.as_ref())) + .collect(); let _ = self .modify(|pad| { let changeset = pad.delete_filter(¶ms.filter_id, &filter_type.field_id, &field_type_rev)?; @@ -327,6 +340,9 @@ impl GridViewRevisionEditor { .await .apply_changeset(FilterChangeset::from_delete(filter_type)) .await; + + let changeset = FilterChangesetNotificationPB::from_delete(&self.view_id, filters); + self.notify_did_update_filter(changeset).await; Ok(()) } @@ -394,8 +410,14 @@ impl GridViewRevisionEditor { .send(); } - pub async fn notify_did_update_group(&self, changeset: GroupChangesetPB) { - send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup) + pub async fn notify_did_update_group_rows(&self, payload: GroupRowsNotificationPB) { + send_dart_notification(&payload.group_id, GridNotification::DidUpdateGroup) + .payload(payload) + .send(); + } + + pub async fn notify_did_update_filter(&self, changeset: FilterChangesetNotificationPB) { + send_dart_notification(&changeset.view_id, GridNotification::DidUpdateFilter) .payload(changeset) .send(); } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 8a254b4229..d653c7a25b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -168,7 +168,7 @@ impl GridViewManager { } for group_changeset in group_changesets { - view_editor.notify_did_update_group(group_changeset).await; + view_editor.notify_did_update_group_rows(group_changeset).await; } Ok(()) diff --git a/frontend/rust-lib/flowy-grid/src/services/group/action.rs b/frontend/rust-lib/flowy-grid/src/services/group/action.rs index e0a0f3169d..17d0f9cc06 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/action.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupChangesetPB, GroupViewChangesetPB}; +use crate::entities::{GroupRowsNotificationPB, GroupViewChangesetPB}; use crate::services::cell::CellDataIsEmpty; use crate::services::group::controller::MoveGroupRowContext; use crate::services::group::Group; @@ -31,13 +31,17 @@ pub trait GroupControllerCustomActions: Send + Sync { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, - ) -> Vec; + ) -> Vec; /// Deletes the row from the group - fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; + fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec; /// Move row from one group to another - fn move_row(&mut self, cell_data: &Self::CellDataType, context: MoveGroupRowContext) -> Vec; + fn move_row( + &mut self, + cell_data: &Self::CellDataType, + context: MoveGroupRowContext, + ) -> Vec; } /// Defines the shared actions any group controller can perform. @@ -62,17 +66,17 @@ pub trait GroupControllerSharedActions: Send + Sync { &mut self, row_rev: &RowRevision, field_rev: &FieldRevision, - ) -> FlowyResult>; + ) -> FlowyResult>; /// Remove the row from the group if the row gets deleted fn did_delete_delete_row( &mut self, row_rev: &RowRevision, field_rev: &FieldRevision, - ) -> FlowyResult>; + ) -> FlowyResult>; /// Move the row from one group to another group - fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult>; + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult>; /// Update the group if the corresponding field is changed fn did_update_group_field(&mut self, field_rev: &FieldRevision) -> FlowyResult>; diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs index 64b59988eb..00624c0651 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, InsertedRowPB, RowPB}; +use crate::entities::{GroupRowsNotificationPB, GroupViewChangesetPB, InsertedRowPB, RowPB}; use crate::services::cell::{decode_any_cell_data, CellBytesParser, CellDataIsEmpty}; use crate::services::group::action::{GroupControllerCustomActions, GroupControllerSharedActions}; use crate::services::group::configuration::GroupContext; @@ -89,8 +89,8 @@ where fn update_default_group( &mut self, row_rev: &RowRevision, - other_group_changesets: &[GroupChangesetPB], - ) -> Option { + other_group_changesets: &[GroupRowsNotificationPB], + ) -> Option { let default_group = self.group_ctx.get_mut_no_status_group()?; // [other_group_inserted_row] contains all the inserted rows except the default group. @@ -113,7 +113,7 @@ where }) .collect::>(); - let mut changeset = GroupChangesetPB::new(default_group.id.clone()); + let mut changeset = GroupRowsNotificationPB::new(default_group.id.clone()); if !default_group_inserted_row.is_empty() { changeset.inserted_rows.push(InsertedRowPB::new(row_rev.into())); default_group.add_row(row_rev.into()); @@ -222,7 +222,7 @@ where &mut self, row_rev: &RowRevision, field_rev: &FieldRevision, - ) -> FlowyResult> { + ) -> FlowyResult> { if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; let cell_data = cell_bytes.parser::

()?; @@ -244,7 +244,7 @@ where &mut self, row_rev: &RowRevision, field_rev: &FieldRevision, - ) -> FlowyResult> { + ) -> FlowyResult> { // if the cell_rev is none, then the row must in the default group. if let Some(cell_rev) = row_rev.cells.get(&self.field_id) { let cell_bytes = decode_any_cell_data(cell_rev.data.clone(), field_rev).1; @@ -264,7 +264,7 @@ where if !no_status_group.contains_row(&row_rev.id) { tracing::error!("The row: {} should be in the no status group", row_rev.id); } - Ok(vec![GroupChangesetPB::delete( + Ok(vec![GroupRowsNotificationPB::delete( no_status_group.id.clone(), vec![row_rev.id.clone()], )]) @@ -273,7 +273,7 @@ where } #[tracing::instrument(level = "trace", skip_all, err)] - fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult> { + fn move_group_row(&mut self, context: MoveGroupRowContext) -> FlowyResult> { let cell_rev = match context.row_rev.cells.get(&self.field_id) { Some(cell_rev) => Some(cell_rev.clone()), None => self.default_cell_rev(), diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs index 0a6ff487fb..d021847eea 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/checkbox_controller.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupChangesetPB, InsertedRowPB, RowPB}; +use crate::entities::{GroupRowsNotificationPB, InsertedRowPB, RowPB}; use crate::services::field::{CheckboxCellData, CheckboxCellDataParser, CheckboxTypeOptionPB, CHECK, UNCHECK}; use crate::services::group::action::GroupControllerCustomActions; use crate::services::group::configuration::GroupContext; @@ -37,10 +37,10 @@ impl GroupControllerCustomActions for CheckboxGroupController { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, - ) -> Vec { + ) -> Vec { let mut changesets = vec![]; self.group_ctx.iter_mut_status_groups(|group| { - let mut changeset = GroupChangesetPB::new(group.id.clone()); + let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); let is_not_contained = !group.contains_row(&row_rev.id); if group.id == CHECK { if cell_data.is_uncheck() { @@ -79,10 +79,10 @@ impl GroupControllerCustomActions for CheckboxGroupController { changesets } - fn delete_row(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec { + fn delete_row(&mut self, row_rev: &RowRevision, _cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.group_ctx.iter_mut_groups(|group| { - let mut changeset = GroupChangesetPB::new(group.id.clone()); + let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); if group.contains_row(&row_rev.id) { changeset.deleted_rows.push(row_rev.id.clone()); group.remove_row(&row_rev.id); @@ -95,7 +95,11 @@ impl GroupControllerCustomActions for CheckboxGroupController { changesets } - fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { + fn move_row( + &mut self, + _cell_data: &Self::CellDataType, + mut context: MoveGroupRowContext, + ) -> Vec { let mut group_changeset = vec![]; self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs index eaa2d96b57..47b536c443 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/default_controller.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupChangesetPB, GroupViewChangesetPB, RowPB}; +use crate::entities::{GroupRowsNotificationPB, GroupViewChangesetPB, RowPB}; use crate::services::group::action::GroupControllerSharedActions; use crate::services::group::{Group, GroupController, MoveGroupRowContext}; use flowy_error::FlowyResult; @@ -59,7 +59,7 @@ impl GroupControllerSharedActions for DefaultGroupController { &mut self, _row_rev: &RowRevision, _field_rev: &FieldRevision, - ) -> FlowyResult> { + ) -> FlowyResult> { Ok(vec![]) } @@ -67,11 +67,11 @@ impl GroupControllerSharedActions for DefaultGroupController { &mut self, _row_rev: &RowRevision, _field_rev: &FieldRevision, - ) -> FlowyResult> { + ) -> FlowyResult> { Ok(vec![]) } - fn move_group_row(&mut self, _context: MoveGroupRowContext) -> FlowyResult> { + fn move_group_row(&mut self, _context: MoveGroupRowContext) -> FlowyResult> { todo!() } diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index 193390ef25..298e05affa 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupChangesetPB, RowPB}; +use crate::entities::{GroupRowsNotificationPB, RowPB}; use crate::services::cell::insert_select_option_cell; use crate::services::field::{MultiSelectTypeOptionPB, SelectOptionCellDataPB, SelectOptionCellDataParser}; use crate::services::group::action::GroupControllerCustomActions; @@ -30,7 +30,7 @@ impl GroupControllerCustomActions for MultiSelectGroupController { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, - ) -> Vec { + ) -> Vec { let mut changesets = vec![]; self.group_ctx.iter_mut_status_groups(|group| { if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row_rev) { @@ -40,7 +40,7 @@ impl GroupControllerCustomActions for MultiSelectGroupController { changesets } - fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.group_ctx.iter_mut_status_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { @@ -50,7 +50,11 @@ impl GroupControllerCustomActions for MultiSelectGroupController { changesets } - fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { + fn move_row( + &mut self, + _cell_data: &Self::CellDataType, + mut context: MoveGroupRowContext, + ) -> Vec { let mut group_changeset = vec![]; self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index fcae75d2b6..0f3f671c8f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -1,4 +1,4 @@ -use crate::entities::{GroupChangesetPB, RowPB}; +use crate::entities::{GroupRowsNotificationPB, RowPB}; use crate::services::cell::insert_select_option_cell; use crate::services::field::{SelectOptionCellDataPB, SelectOptionCellDataParser, SingleSelectTypeOptionPB}; use crate::services::group::action::GroupControllerCustomActions; @@ -30,7 +30,7 @@ impl GroupControllerCustomActions for SingleSelectGroupController { &mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType, - ) -> Vec { + ) -> Vec { let mut changesets = vec![]; self.group_ctx.iter_mut_status_groups(|group| { if let Some(changeset) = add_or_remove_select_option_row(group, cell_data, row_rev) { @@ -40,7 +40,7 @@ impl GroupControllerCustomActions for SingleSelectGroupController { changesets } - fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { + fn delete_row(&mut self, row_rev: &RowRevision, cell_data: &Self::CellDataType) -> Vec { let mut changesets = vec![]; self.group_ctx.iter_mut_status_groups(|group| { if let Some(changeset) = remove_select_option_row(group, cell_data, row_rev) { @@ -50,7 +50,11 @@ impl GroupControllerCustomActions for SingleSelectGroupController { changesets } - fn move_row(&mut self, _cell_data: &Self::CellDataType, mut context: MoveGroupRowContext) -> Vec { + fn move_row( + &mut self, + _cell_data: &Self::CellDataType, + mut context: MoveGroupRowContext, + ) -> Vec { let mut group_changeset = vec![]; self.group_ctx.iter_mut_groups(|group| { if let Some(changeset) = move_group_row(group, &mut context) { diff --git a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs index fab7a57902..7772ba3624 100644 --- a/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs +++ b/frontend/rust-lib/flowy-grid/src/services/group/controller_impls/select_option_controller/util.rs @@ -1,4 +1,4 @@ -use crate::entities::{FieldType, GroupChangesetPB, InsertedRowPB, RowPB}; +use crate::entities::{FieldType, GroupRowsNotificationPB, InsertedRowPB, RowPB}; use crate::services::cell::{insert_checkbox_cell, insert_select_option_cell}; use crate::services::field::{SelectOptionCellDataPB, SelectOptionPB, CHECK}; use crate::services::group::configuration::GroupContext; @@ -12,8 +12,8 @@ pub fn add_or_remove_select_option_row( group: &mut Group, cell_data: &SelectOptionCellDataPB, row_rev: &RowRevision, -) -> Option { - let mut changeset = GroupChangesetPB::new(group.id.clone()); +) -> Option { + let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); if cell_data.select_options.is_empty() { if group.contains_row(&row_rev.id) { changeset.deleted_rows.push(row_rev.id.clone()); @@ -45,8 +45,8 @@ pub fn remove_select_option_row( group: &mut Group, cell_data: &SelectOptionCellDataPB, row_rev: &RowRevision, -) -> Option { - let mut changeset = GroupChangesetPB::new(group.id.clone()); +) -> Option { + let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); cell_data.select_options.iter().for_each(|option| { if option.id == group.id && group.contains_row(&row_rev.id) { changeset.deleted_rows.push(row_rev.id.clone()); @@ -61,8 +61,8 @@ pub fn remove_select_option_row( } } -pub fn move_group_row(group: &mut Group, context: &mut MoveGroupRowContext) -> Option { - let mut changeset = GroupChangesetPB::new(group.id.clone()); +pub fn move_group_row(group: &mut Group, context: &mut MoveGroupRowContext) -> Option { + let mut changeset = GroupRowsNotificationPB::new(group.id.clone()); let MoveGroupRowContext { row_rev, row_changeset, diff --git a/shared-lib/grid-rev-model/src/filter_rev.rs b/shared-lib/grid-rev-model/src/filter_rev.rs index b48791b02f..4bf6d30de6 100644 --- a/shared-lib/grid-rev-model/src/filter_rev.rs +++ b/shared-lib/grid-rev-model/src/filter_rev.rs @@ -1,9 +1,11 @@ +use crate::FieldTypeRevision; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] pub struct FilterRevision { pub id: String, pub field_id: String, + pub field_type_rev: FieldTypeRevision, pub condition: u8, #[serde(default)] pub content: String,