瀏覽代碼

chore: add filter service

nathan 2 年之前
父節點
當前提交
f1ac38dd59

+ 55 - 18
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<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

+ 31 - 16
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<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,
         })
     }
 }

+ 27 - 15
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 } => {

+ 6 - 2
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 },

+ 3 - 0
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,
 }