Skip to content

Commit 5a837a9

Browse files
authored
fix: number and select filter logic (#4828)
* fix: number and select option filter bugs * chore: rename filter condition enum and variants
1 parent 1a34366 commit 5a837a9

File tree

57 files changed

+1320
-1248
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1320
-1248
lines changed

frontend/.vscode/tasks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@
257257
"label": "AF: Tauri UI Dev",
258258
"type": "shell",
259259
"isBackground": true,
260-
"command": "pnpm run sync:i18n && pnpm run dev",
260+
"command": "pnpm sync:i18n && pnpm run dev",
261261
"options": {
262262
"cwd": "${workspaceFolder}/appflowy_tauri"
263263
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ void main() {
103103
// select the option 's4'
104104
await tester.tapOptionFilterWithName('s4');
105105

106-
// The row with 's4' or 's5' should be shown.
107-
await tester.assertNumberOfRowsInGridPage(2);
106+
// The row with 's4' should be shown.
107+
await tester.assertNumberOfRowsInGridPage(1);
108108

109109
await tester.pumpAndSettle();
110110
});

frontend/appflowy_flutter/lib/plugins/database/domain/filter_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class FilterBackendService {
171171
Future<FlowyResult<void, FlowyError>> insertSelectOptionFilter({
172172
required String fieldId,
173173
required FieldType fieldType,
174-
required SelectOptionConditionPB condition,
174+
required SelectOptionFilterConditionPB condition,
175175
String? filterId,
176176
List<String> optionIds = const [],
177177
}) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class GridCreateFilterBloc
114114
case FieldType.MultiSelect:
115115
return _filterBackendSvc.insertSelectOptionFilter(
116116
fieldId: fieldId,
117-
condition: SelectOptionConditionPB.OptionIs,
117+
condition: SelectOptionFilterConditionPB.OptionContains,
118118
fieldType: FieldType.MultiSelect,
119119
);
120120
case FieldType.Checklist:
@@ -130,19 +130,19 @@ class GridCreateFilterBloc
130130
case FieldType.RichText:
131131
return _filterBackendSvc.insertTextFilter(
132132
fieldId: fieldId,
133-
condition: TextFilterConditionPB.Contains,
133+
condition: TextFilterConditionPB.TextContains,
134134
content: '',
135135
);
136136
case FieldType.SingleSelect:
137137
return _filterBackendSvc.insertSelectOptionFilter(
138138
fieldId: fieldId,
139-
condition: SelectOptionConditionPB.OptionIs,
139+
condition: SelectOptionFilterConditionPB.OptionIs,
140140
fieldType: FieldType.SingleSelect,
141141
);
142142
case FieldType.URL:
143143
return _filterBackendSvc.insertURLFilter(
144144
fieldId: fieldId,
145-
condition: TextFilterConditionPB.Contains,
145+
condition: TextFilterConditionPB.TextContains,
146146
);
147147
default:
148148
throw UnimplementedError();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class SelectOptionFilterEditorBloc
3838
_startListening();
3939
_loadOptions();
4040
},
41-
updateCondition: (SelectOptionConditionPB condition) {
41+
updateCondition: (SelectOptionFilterConditionPB condition) {
4242
_filterBackendSvc.insertSelectOptionFilter(
4343
filterId: filterInfo.filter.id,
4444
fieldId: filterInfo.fieldInfo.id,
@@ -117,7 +117,7 @@ class SelectOptionFilterEditorEvent with _$SelectOptionFilterEditorEvent {
117117
FilterPB filter,
118118
) = _DidReceiveFilter;
119119
const factory SelectOptionFilterEditorEvent.updateCondition(
120-
SelectOptionConditionPB condition,
120+
SelectOptionFilterConditionPB condition,
121121
) = _UpdateCondition;
122122
const factory SelectOptionFilterEditorEvent.updateContent(
123123
List<String> optionIds,

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
2-
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
2+
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
33
import 'package:flutter_bloc/flutter_bloc.dart';
44
import 'package:freezed_annotation/freezed_annotation.dart';
55

@@ -24,9 +24,12 @@ class SelectOptionFilterListBloc<T>
2424
_startListening();
2525
_loadOptions();
2626
},
27-
selectOption: (option) {
28-
final selectedOptionIds = Set<String>.from(state.selectedOptionIds);
29-
selectedOptionIds.add(option.id);
27+
selectOption: (option, condition) {
28+
final selectedOptionIds = delegate.selectOption(
29+
state.selectedOptionIds,
30+
option.id,
31+
condition,
32+
);
3033

3134
_updateSelectOptions(
3235
selectedOptionIds: selectedOptionIds,
@@ -116,6 +119,7 @@ class SelectOptionFilterListEvent with _$SelectOptionFilterListEvent {
116119
const factory SelectOptionFilterListEvent.initial() = _Initial;
117120
const factory SelectOptionFilterListEvent.selectOption(
118121
SelectOptionPB option,
122+
SelectOptionFilterConditionPB condition,
119123
) = _SelectOption;
120124
const factory SelectOptionFilterListEvent.unselectOption(
121125
SelectOptionPB option,
Lines changed: 50 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import 'package:appflowy/generated/flowy_svgs.g.dart';
22
import 'package:appflowy/generated/locale_keys.g.dart';
3+
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/condition_button.dart';
4+
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/filter_info.dart';
35
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
6+
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
47
import 'package:appflowy_popover/appflowy_popover.dart';
58
import 'package:easy_localization/easy_localization.dart';
6-
7-
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
8-
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pb.dart';
9-
import 'package:flutter/material.dart';
10-
11-
import '../../condition_button.dart';
12-
import '../../filter_info.dart';
9+
import 'package:flutter/widgets.dart';
1310

1411
class SelectOptionFilterConditionList extends StatelessWidget {
1512
const SelectOptionFilterConditionList({
@@ -21,7 +18,7 @@ class SelectOptionFilterConditionList extends StatelessWidget {
2118

2219
final FilterInfo filterInfo;
2320
final PopoverMutex popoverMutex;
24-
final Function(SelectOptionConditionPB) onCondition;
21+
final Function(SelectOptionFilterConditionPB) onCondition;
2522

2623
@override
2724
Widget build(BuildContext context) {
@@ -30,18 +27,17 @@ class SelectOptionFilterConditionList extends StatelessWidget {
3027
asBarrier: true,
3128
mutex: popoverMutex,
3229
direction: PopoverDirection.bottomWithCenterAligned,
33-
actions: SelectOptionConditionPB.values
30+
actions: _conditionsForFieldType(filterInfo.fieldInfo.fieldType)
3431
.map(
3532
(action) => ConditionWrapper(
3633
action,
3734
selectOptionFilter.condition == action,
38-
filterInfo.fieldInfo.fieldType,
3935
),
4036
)
4137
.toList(),
4238
buildChild: (controller) {
4339
return ConditionButton(
44-
conditionName: filterName(selectOptionFilter),
40+
conditionName: selectOptionFilter.condition.i18n,
4541
onTap: () => controller.show(),
4642
);
4743
},
@@ -52,69 +48,62 @@ class SelectOptionFilterConditionList extends StatelessWidget {
5248
);
5349
}
5450

55-
String filterName(SelectOptionFilterPB filter) {
56-
if (filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) {
57-
return filter.condition.singleSelectFilterName;
58-
} else {
59-
return filter.condition.multiSelectFilterName;
60-
}
51+
List<SelectOptionFilterConditionPB> _conditionsForFieldType(
52+
FieldType fieldType,
53+
) {
54+
// SelectOptionFilterConditionPB.values is not in order
55+
return switch (fieldType) {
56+
FieldType.SingleSelect => [
57+
SelectOptionFilterConditionPB.OptionIs,
58+
SelectOptionFilterConditionPB.OptionIsNot,
59+
SelectOptionFilterConditionPB.OptionIsEmpty,
60+
SelectOptionFilterConditionPB.OptionIsNotEmpty,
61+
],
62+
FieldType.MultiSelect => [
63+
SelectOptionFilterConditionPB.OptionContains,
64+
SelectOptionFilterConditionPB.OptionDoesNotContain,
65+
SelectOptionFilterConditionPB.OptionIs,
66+
SelectOptionFilterConditionPB.OptionIsNot,
67+
SelectOptionFilterConditionPB.OptionIsEmpty,
68+
SelectOptionFilterConditionPB.OptionIsNotEmpty,
69+
],
70+
_ => [],
71+
};
6172
}
6273
}
6374

6475
class ConditionWrapper extends ActionCell {
65-
ConditionWrapper(this.inner, this.isSelected, this.fieldType);
76+
ConditionWrapper(this.inner, this.isSelected);
6677

67-
final SelectOptionConditionPB inner;
78+
final SelectOptionFilterConditionPB inner;
6879
final bool isSelected;
69-
final FieldType fieldType;
7080

7181
@override
7282
Widget? rightIcon(Color iconColor) {
73-
if (isSelected) {
74-
return const FlowySvg(FlowySvgs.check_s);
75-
} else {
76-
return null;
77-
}
83+
return isSelected ? const FlowySvg(FlowySvgs.check_s) : null;
7884
}
7985

8086
@override
81-
String get name {
82-
if (fieldType == FieldType.SingleSelect) {
83-
return inner.singleSelectFilterName;
84-
} else {
85-
return inner.multiSelectFilterName;
86-
}
87-
}
87+
String get name => inner.i18n;
8888
}
8989

90-
extension SelectOptionConditionPBExtension on SelectOptionConditionPB {
91-
String get singleSelectFilterName {
92-
switch (this) {
93-
case SelectOptionConditionPB.OptionIs:
94-
return LocaleKeys.grid_singleSelectOptionFilter_is.tr();
95-
case SelectOptionConditionPB.OptionIsEmpty:
96-
return LocaleKeys.grid_singleSelectOptionFilter_isEmpty.tr();
97-
case SelectOptionConditionPB.OptionIsNot:
98-
return LocaleKeys.grid_singleSelectOptionFilter_isNot.tr();
99-
case SelectOptionConditionPB.OptionIsNotEmpty:
100-
return LocaleKeys.grid_singleSelectOptionFilter_isNotEmpty.tr();
101-
default:
102-
return "";
103-
}
104-
}
105-
106-
String get multiSelectFilterName {
107-
switch (this) {
108-
case SelectOptionConditionPB.OptionIs:
109-
return LocaleKeys.grid_multiSelectOptionFilter_contains.tr();
110-
case SelectOptionConditionPB.OptionIsEmpty:
111-
return LocaleKeys.grid_multiSelectOptionFilter_isEmpty.tr();
112-
case SelectOptionConditionPB.OptionIsNot:
113-
return LocaleKeys.grid_multiSelectOptionFilter_doesNotContain.tr();
114-
case SelectOptionConditionPB.OptionIsNotEmpty:
115-
return LocaleKeys.grid_multiSelectOptionFilter_isNotEmpty.tr();
116-
default:
117-
return "";
118-
}
90+
extension SelectOptionFilterConditionPBExtension
91+
on SelectOptionFilterConditionPB {
92+
String get i18n {
93+
return switch (this) {
94+
SelectOptionFilterConditionPB.OptionIs =>
95+
LocaleKeys.grid_selectOptionFilter_is.tr(),
96+
SelectOptionFilterConditionPB.OptionIsNot =>
97+
LocaleKeys.grid_selectOptionFilter_isNot.tr(),
98+
SelectOptionFilterConditionPB.OptionContains =>
99+
LocaleKeys.grid_selectOptionFilter_isNot.tr(),
100+
SelectOptionFilterConditionPB.OptionDoesNotContain =>
101+
LocaleKeys.grid_selectOptionFilter_isNot.tr(),
102+
SelectOptionFilterConditionPB.OptionIsEmpty =>
103+
LocaleKeys.grid_selectOptionFilter_isEmpty.tr(),
104+
SelectOptionFilterConditionPB.OptionIsNotEmpty =>
105+
LocaleKeys.grid_selectOptionFilter_isNotEmpty.tr(),
106+
_ => "",
107+
};
119108
}
120109
}

frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/option_list.dart

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:appflowy/generated/flowy_svgs.g.dart';
2+
import 'package:appflowy/plugins/database/grid/application/filter/select_option_filter_bloc.dart';
23
import 'package:appflowy/plugins/database/grid/application/filter/select_option_filter_list_bloc.dart';
34
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
45
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/filter_info.dart';
@@ -90,9 +91,16 @@ class _SelectOptionFilterCellState extends State<SelectOptionFilterCell> {
9091
.read<SelectOptionFilterListBloc>()
9192
.add(SelectOptionFilterListEvent.unselectOption(widget.option));
9293
} else {
93-
context
94-
.read<SelectOptionFilterListBloc>()
95-
.add(SelectOptionFilterListEvent.selectOption(widget.option));
94+
context.read<SelectOptionFilterListBloc>().add(
95+
SelectOptionFilterListEvent.selectOption(
96+
widget.option,
97+
context
98+
.read<SelectOptionFilterEditorBloc>()
99+
.state
100+
.filter
101+
.condition,
102+
),
103+
);
96104
}
97105
},
98106
children: [

frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,10 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
101101
SliverToBoxAdapter(child: _buildFilterPanel(context, state)),
102102
];
103103

104-
if (state.filter.condition != SelectOptionConditionPB.OptionIsEmpty &&
104+
if (state.filter.condition !=
105+
SelectOptionFilterConditionPB.OptionIsEmpty &&
105106
state.filter.condition !=
106-
SelectOptionConditionPB.OptionIsNotEmpty) {
107+
SelectOptionFilterConditionPB.OptionIsNotEmpty) {
107108
slivers.add(const SliverToBoxAdapter(child: VSpace(4)));
108109
slivers.add(
109110
SliverToBoxAdapter(

frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import 'package:appflowy/plugins/database/application/field/type_option/type_option_data_parser.dart';
22
import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/filter_info.dart';
3-
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
3+
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
44

55
abstract class SelectOptionFilterDelegate {
66
List<SelectOptionPB> loadOptions();
7+
8+
Set<String> selectOption(
9+
Set<String> currentOptionIds,
10+
String optionId,
11+
SelectOptionFilterConditionPB condition,
12+
);
713
}
814

915
class SingleSelectOptionFilterDelegateImpl
@@ -17,6 +23,22 @@ class SingleSelectOptionFilterDelegateImpl
1723
final parser = SingleSelectTypeOptionDataParser();
1824
return parser.fromBuffer(filterInfo.fieldInfo.field.typeOptionData).options;
1925
}
26+
27+
@override
28+
Set<String> selectOption(
29+
Set<String> currentOptionIds,
30+
String optionId,
31+
SelectOptionFilterConditionPB condition,
32+
) {
33+
final selectOptionIds = Set<String>.from(currentOptionIds);
34+
35+
if (condition == SelectOptionFilterConditionPB.OptionIsNot ||
36+
selectOptionIds.isEmpty) {
37+
selectOptionIds.add(optionId);
38+
}
39+
40+
return selectOptionIds;
41+
}
2042
}
2143

2244
class MultiSelectOptionFilterDelegateImpl
@@ -30,4 +52,12 @@ class MultiSelectOptionFilterDelegateImpl
3052
final parser = MultiSelectTypeOptionDataParser();
3153
return parser.fromBuffer(filterInfo.fieldInfo.field.typeOptionData).options;
3254
}
55+
56+
@override
57+
Set<String> selectOption(
58+
Set<String> currentOptionIds,
59+
String optionId,
60+
SelectOptionFilterConditionPB condition,
61+
) =>
62+
Set<String>.from(currentOptionIds)..add(optionId);
3363
}

0 commit comments

Comments
 (0)