Skip to content

Commit 9b7d38b

Browse files
authored
feat(flutter_desktop): allow filtering by date end (AppFlowy-IO#6399)
1 parent a8a8502 commit 9b7d38b

File tree

16 files changed

+586
-204
lines changed

16 files changed

+586
-204
lines changed

frontend/appflowy_flutter/integration_test/desktop/database/database_filter_test.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
12
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/checkbox.dart';
23
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart';
34
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
@@ -151,11 +152,11 @@ void main() {
151152

152153
await tester.tapFilterButtonInGrid('date');
153154
await tester.tapDateFilterButtonInGrid();
154-
await tester.tapDateFilterCondition(DateFilterConditionPB.DateBefore);
155+
await tester.tapDateFilterCondition(DateTimeFilterCondition.before);
155156
tester.assertNumberOfRowsInGridPage(7);
156157

157158
await tester.tapDateFilterButtonInGrid();
158-
await tester.tapDateFilterCondition(DateFilterConditionPB.DateIsEmpty);
159+
await tester.tapDateFilterCondition(DateTimeFilterCondition.isEmpty);
159160
tester.assertNumberOfRowsInGridPage(3);
160161

161162
await tester.pumpAndSettle();

frontend/appflowy_flutter/integration_test/shared/database_test_op.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:io';
22

3+
import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
34
import 'package:flutter/gestures.dart';
45
import 'package:flutter/material.dart';
56
import 'package:flutter/services.dart';
@@ -1135,7 +1136,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
11351136
await tapButton(button);
11361137
}
11371138

1138-
Future<void> tapDateFilterCondition(DateFilterConditionPB condition) async {
1139+
Future<void> tapDateFilterCondition(DateTimeFilterCondition condition) async {
11391140
final button = find.descendant(
11401141
of: find.byType(HoverButton),
11411142
matching: find.text(condition.filterName),

frontend/appflowy_flutter/lib/plugins/database/application/field/filter_entities.dart

Lines changed: 108 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:typed_data';
22

3+
import 'package:appflowy/generated/locale_keys.g.dart';
34
import 'package:appflowy/plugins/database/application/field/field_info.dart';
45
import 'package:appflowy/plugins/database/grid/application/filter/select_option_loader.dart';
56
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/checkbox.dart';
@@ -10,6 +11,7 @@ import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choic
1011
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart';
1112
import 'package:appflowy/util/int64_extension.dart';
1213
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
14+
import 'package:easy_localization/easy_localization.dart';
1315
import 'package:fixnum/fixnum.dart';
1416

1517
abstract class DatabaseFilter {
@@ -319,6 +321,67 @@ final class SelectOptionFilter extends DatabaseFilter {
319321
}
320322
}
321323

324+
enum DateTimeFilterCondition {
325+
on,
326+
before,
327+
after,
328+
onOrBefore,
329+
onOrAfter,
330+
between,
331+
isEmpty,
332+
isNotEmpty;
333+
334+
DateFilterConditionPB toPB(bool isStart) {
335+
return isStart
336+
? switch (this) {
337+
on => DateFilterConditionPB.DateStartsOn,
338+
before => DateFilterConditionPB.DateStartsBefore,
339+
after => DateFilterConditionPB.DateStartsAfter,
340+
onOrBefore => DateFilterConditionPB.DateStartsOnOrBefore,
341+
onOrAfter => DateFilterConditionPB.DateStartsOnOrAfter,
342+
between => DateFilterConditionPB.DateStartsBetween,
343+
isEmpty => DateFilterConditionPB.DateStartIsEmpty,
344+
isNotEmpty => DateFilterConditionPB.DateStartIsNotEmpty,
345+
}
346+
: switch (this) {
347+
on => DateFilterConditionPB.DateEndsOn,
348+
before => DateFilterConditionPB.DateEndsBefore,
349+
after => DateFilterConditionPB.DateEndsAfter,
350+
onOrBefore => DateFilterConditionPB.DateEndsOnOrBefore,
351+
onOrAfter => DateFilterConditionPB.DateEndsOnOrAfter,
352+
between => DateFilterConditionPB.DateEndsBetween,
353+
isEmpty => DateFilterConditionPB.DateEndIsEmpty,
354+
isNotEmpty => DateFilterConditionPB.DateEndIsNotEmpty,
355+
};
356+
}
357+
358+
String get choiceChipPrefix {
359+
return switch (this) {
360+
on => "",
361+
before => LocaleKeys.grid_dateFilter_choicechipPrefix_before.tr(),
362+
after => LocaleKeys.grid_dateFilter_choicechipPrefix_after.tr(),
363+
onOrBefore => LocaleKeys.grid_dateFilter_choicechipPrefix_onOrBefore.tr(),
364+
onOrAfter => LocaleKeys.grid_dateFilter_choicechipPrefix_onOrAfter.tr(),
365+
between => LocaleKeys.grid_dateFilter_choicechipPrefix_between.tr(),
366+
isEmpty => LocaleKeys.grid_dateFilter_choicechipPrefix_isEmpty.tr(),
367+
isNotEmpty => LocaleKeys.grid_dateFilter_choicechipPrefix_isNotEmpty.tr(),
368+
};
369+
}
370+
371+
String get filterName {
372+
return switch (this) {
373+
on => LocaleKeys.grid_dateFilter_is.tr(),
374+
before => LocaleKeys.grid_dateFilter_before.tr(),
375+
after => LocaleKeys.grid_dateFilter_after.tr(),
376+
onOrBefore => LocaleKeys.grid_dateFilter_onOrBefore.tr(),
377+
onOrAfter => LocaleKeys.grid_dateFilter_onOrAfter.tr(),
378+
between => LocaleKeys.grid_dateFilter_between.tr(),
379+
isEmpty => LocaleKeys.grid_dateFilter_empty.tr(),
380+
isNotEmpty => LocaleKeys.grid_dateFilter_notEmpty.tr(),
381+
};
382+
}
383+
}
384+
322385
final class DateTimeFilter extends DatabaseFilter {
323386
const DateTimeFilter({
324387
required super.filterId,
@@ -341,12 +404,19 @@ final class DateTimeFilter extends DatabaseFilter {
341404
@override
342405
String getDescription(FieldInfo field) {
343406
return switch (condition) {
344-
DateFilterConditionPB.DateIsEmpty ||
345-
DateFilterConditionPB.DateIsNotEmpty =>
346-
condition.filterName,
347-
DateFilterConditionPB.DateWithIn =>
348-
"${condition.filterName} ${start?.defaultFormat ?? ""} - ${end?.defaultFormat ?? ""}",
349-
_ => "${condition.filterName} ${timestamp?.defaultFormat ?? ""}"
407+
DateFilterConditionPB.DateStartIsEmpty ||
408+
DateFilterConditionPB.DateStartIsNotEmpty ||
409+
DateFilterConditionPB.DateEndIsEmpty ||
410+
DateFilterConditionPB.DateEndIsNotEmpty =>
411+
condition.toCondition().choiceChipPrefix,
412+
DateFilterConditionPB.DateStartsOn ||
413+
DateFilterConditionPB.DateEndsOn =>
414+
timestamp?.defaultFormat ?? "",
415+
DateFilterConditionPB.DateStartsBetween ||
416+
DateFilterConditionPB.DateEndsBetween =>
417+
"${condition.toCondition().choiceChipPrefix} ${start?.defaultFormat ?? ""} - ${end?.defaultFormat ?? ""}",
418+
_ =>
419+
"${condition.toCondition().choiceChipPrefix} ${timestamp?.defaultFormat ?? ""}"
350420
};
351421
}
352422

@@ -359,41 +429,62 @@ final class DateTimeFilter extends DatabaseFilter {
359429
}
360430

361431
switch (condition) {
362-
case DateFilterConditionPB.DateIs:
363-
case DateFilterConditionPB.DateBefore:
364-
case DateFilterConditionPB.DateOnOrBefore:
365-
case DateFilterConditionPB.DateAfter:
366-
case DateFilterConditionPB.DateOnOrAfter:
432+
case DateFilterConditionPB.DateStartsOn:
433+
case DateFilterConditionPB.DateStartsBefore:
434+
case DateFilterConditionPB.DateStartsOnOrBefore:
435+
case DateFilterConditionPB.DateStartsAfter:
436+
case DateFilterConditionPB.DateStartsOnOrAfter:
437+
case DateFilterConditionPB.DateEndsOn:
438+
case DateFilterConditionPB.DateEndsBefore:
439+
case DateFilterConditionPB.DateEndsOnOrBefore:
440+
case DateFilterConditionPB.DateEndsAfter:
441+
case DateFilterConditionPB.DateEndsOnOrAfter:
367442
if (timestamp != null) {
368443
filterPB.timestamp = dateTimeToInt(timestamp!);
369444
}
370445
break;
371-
case DateFilterConditionPB.DateWithIn:
446+
case DateFilterConditionPB.DateStartsBetween:
447+
case DateFilterConditionPB.DateEndsBetween:
372448
if (start != null) {
373449
filterPB.start = dateTimeToInt(start!);
374450
}
375451
if (end != null) {
376452
filterPB.end = dateTimeToInt(end!);
377453
}
454+
break;
378455
default:
379456
break;
380457
}
381458

382459
return filterPB.writeToBuffer();
383460
}
384461

385-
DateTimeFilter copyWith({
386-
DateFilterConditionPB? condition,
387-
DateTime? timestamp,
462+
DateTimeFilter copyWithCondition({
463+
required bool isStart,
464+
required DateTimeFilterCondition condition,
388465
}) {
389466
return DateTimeFilter(
390467
filterId: filterId,
391468
fieldId: fieldId,
392469
fieldType: fieldType,
470+
condition: condition.toPB(isStart),
393471
start: start,
394472
end: end,
395-
condition: condition ?? this.condition,
396-
timestamp: timestamp ?? this.timestamp,
473+
timestamp: timestamp,
474+
);
475+
}
476+
477+
DateTimeFilter copyWithTimestamp({
478+
required DateTime timestamp,
479+
}) {
480+
return DateTimeFilter(
481+
filterId: filterId,
482+
fieldId: fieldId,
483+
fieldType: fieldType,
484+
condition: condition,
485+
start: start,
486+
end: end,
487+
timestamp: timestamp,
397488
);
398489
}
399490

frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_editor_bloc.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class FilterEditorBloc extends Bloc<FilterEditorEvent, FilterEditorState> {
115115
final timestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;
116116
return _filterBackendSvc.insertDateFilter(
117117
fieldId: fieldId,
118-
condition: DateFilterConditionPB.DateIs,
118+
condition: DateFilterConditionPB.DateStartsOn,
119119
timestamp: timestamp,
120120
);
121121
case FieldType.MultiSelect:

0 commit comments

Comments
 (0)