chore: add filter service

This commit is contained in:
nathan 2022-11-15 13:04:30 +08:00
parent 3dddd907b0
commit f1ac38dd59
5 changed files with 122 additions and 51 deletions

View File

@ -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<Either<Unit, FlowyError>> 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<Either<Unit, FlowyError>> 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<String> 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<String> optionIds = const [],
}) {
final filter = SelectOptionFilterPB()
..condition = condition
..optionIds.addAll(optionIds);
return createFilter(
fieldId: fieldId,
fieldType: FieldType.MultiSelect,
condition: condition.value,
data: filter.writeToBuffer(),
);
}
Future<Either<Unit, FlowyError>> createFilter({
required String fieldId,
required FieldType fieldType,
required int condition,
String content = "",
required List<int> data,
}) {
TextFilterCondition.DoesNotContain.value;
final insertFilterPayload = CreateFilterPayloadPB.create()
..fieldId = fieldId
..fieldType = fieldType
..condition = condition
..content = content;
..data = data;
final payload = GridSettingChangesetPB.create()
..gridId = viewId

View File

@ -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<u8>,
}
impl CreateFilterPayloadPB {
#[allow(dead_code)]
pub fn new<T: Into<u32>>(field_rev: &FieldRevision, condition: T, content: String) -> Self {
pub fn new<T: TryInto<Bytes, Error = ::protobuf::ProtobufError>>(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<CreateFilterParams> 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<CreateFilterParams> for CreateFilterPayloadPB {
field_id,
field_type_rev: self.field_type.into(),
condition,
content: self.content,
content,
})
}
}

View File

@ -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 } => {

View File

@ -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 },

View File

@ -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,
}