mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 22:57:12 -04:00
feat: support multi-select option filter (#1501)
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
parent
bc70b04110
commit
80d1cbabe0
16 changed files with 147 additions and 85 deletions
|
@ -529,7 +529,7 @@ class FieldInfo {
|
||||||
|
|
||||||
switch (_field.fieldType) {
|
switch (_field.fieldType) {
|
||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
// case FieldType.MultiSelect:
|
case FieldType.MultiSelect:
|
||||||
case FieldType.RichText:
|
case FieldType.RichText:
|
||||||
case FieldType.SingleSelect:
|
case FieldType.SingleSelect:
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -109,15 +109,16 @@ class TypeOptionContext<T extends GeneratedMessage> {
|
||||||
|
|
||||||
String get fieldId => _dataController.field.id;
|
String get fieldId => _dataController.field.id;
|
||||||
|
|
||||||
Future<void> loadTypeOptionData({
|
Future<T> loadTypeOptionData({
|
||||||
required void Function(T) onCompleted,
|
void Function(T)? onCompleted,
|
||||||
required void Function(FlowyError) onError,
|
required void Function(FlowyError) onError,
|
||||||
}) async {
|
}) async {
|
||||||
await _dataController.loadTypeOptionData().then((result) {
|
await _dataController.loadTypeOptionData().then((result) {
|
||||||
result.fold((l) => null, (err) => onError(err));
|
result.fold((l) => null, (err) => onError(err));
|
||||||
});
|
});
|
||||||
|
|
||||||
onCompleted(typeOption);
|
onCompleted?.call(typeOption);
|
||||||
|
return typeOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
T get typeOption {
|
T get typeOption {
|
||||||
|
|
|
@ -33,14 +33,14 @@ class TypeOptionDataController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> loadTypeOptionData() async {
|
Future<Either<TypeOptionPB, FlowyError>> loadTypeOptionData() async {
|
||||||
final result = await loader.load();
|
final result = await loader.load();
|
||||||
return result.fold(
|
return result.fold(
|
||||||
(data) {
|
(data) {
|
||||||
data.freeze();
|
data.freeze();
|
||||||
_data = data;
|
_data = data;
|
||||||
_fieldNotifier.value = data.field_2;
|
_fieldNotifier.value = data.field_2;
|
||||||
return left(unit);
|
return left(data);
|
||||||
},
|
},
|
||||||
(err) {
|
(err) {
|
||||||
Log.error(err);
|
Log.error(err);
|
||||||
|
|
|
@ -31,15 +31,15 @@ class CheckboxFilterEditorBloc
|
||||||
updateCondition: (CheckboxFilterCondition condition) {
|
updateCondition: (CheckboxFilterCondition condition) {
|
||||||
_ffiService.insertCheckboxFilter(
|
_ffiService.insertCheckboxFilter(
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
condition: condition,
|
condition: condition,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
delete: () {
|
delete: () {
|
||||||
_ffiService.deleteFilter(
|
_ffiService.deleteFilter(
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldType: filterInfo.field.fieldType,
|
fieldType: filterInfo.fieldInfo.fieldType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/builder.dart';
|
|
||||||
import 'package:flowy_sdk/log.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pbserver.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
@ -17,18 +15,16 @@ class SelectOptionFilterEditorBloc
|
||||||
final FilterInfo filterInfo;
|
final FilterInfo filterInfo;
|
||||||
final FilterFFIService _ffiService;
|
final FilterFFIService _ffiService;
|
||||||
final FilterListener _listener;
|
final FilterListener _listener;
|
||||||
final SingleSelectTypeOptionContext typeOptionContext;
|
final SelectOptionFilterDelegate delegate;
|
||||||
|
|
||||||
SelectOptionFilterEditorBloc({required this.filterInfo})
|
SelectOptionFilterEditorBloc({
|
||||||
: _ffiService = FilterFFIService(viewId: filterInfo.viewId),
|
required this.filterInfo,
|
||||||
|
required this.delegate,
|
||||||
|
}) : _ffiService = FilterFFIService(viewId: filterInfo.viewId),
|
||||||
_listener = FilterListener(
|
_listener = FilterListener(
|
||||||
viewId: filterInfo.viewId,
|
viewId: filterInfo.viewId,
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
),
|
),
|
||||||
typeOptionContext = makeSingleSelectTypeOptionContext(
|
|
||||||
gridId: filterInfo.viewId,
|
|
||||||
fieldPB: filterInfo.field.field,
|
|
||||||
),
|
|
||||||
super(SelectOptionFilterEditorState.initial(filterInfo)) {
|
super(SelectOptionFilterEditorState.initial(filterInfo)) {
|
||||||
on<SelectOptionFilterEditorEvent>(
|
on<SelectOptionFilterEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
|
@ -40,26 +36,26 @@ class SelectOptionFilterEditorBloc
|
||||||
updateCondition: (SelectOptionCondition condition) {
|
updateCondition: (SelectOptionCondition condition) {
|
||||||
_ffiService.insertSelectOptionFilter(
|
_ffiService.insertSelectOptionFilter(
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
condition: condition,
|
condition: condition,
|
||||||
optionIds: state.filter.optionIds,
|
optionIds: state.filter.optionIds,
|
||||||
fieldType: state.filterInfo.field.fieldType,
|
fieldType: state.filterInfo.fieldInfo.fieldType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
updateContent: (List<String> optionIds) {
|
updateContent: (List<String> optionIds) {
|
||||||
_ffiService.insertSelectOptionFilter(
|
_ffiService.insertSelectOptionFilter(
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
condition: state.filter.condition,
|
condition: state.filter.condition,
|
||||||
optionIds: optionIds,
|
optionIds: optionIds,
|
||||||
fieldType: state.filterInfo.field.fieldType,
|
fieldType: state.filterInfo.fieldInfo.fieldType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
delete: () {
|
delete: () {
|
||||||
_ffiService.deleteFilter(
|
_ffiService.deleteFilter(
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldType: filterInfo.field.fieldType,
|
fieldType: filterInfo.fieldInfo.fieldType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
|
@ -92,21 +88,17 @@ class SelectOptionFilterEditorBloc
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loadOptions() {
|
void _loadOptions() {
|
||||||
typeOptionContext.loadTypeOptionData(
|
delegate.loadOptions().then((options) {
|
||||||
onCompleted: (value) {
|
if (!isClosed) {
|
||||||
if (!isClosed) {
|
String filterDesc = '';
|
||||||
String filterDesc = '';
|
for (final option in options) {
|
||||||
for (final option in value.options) {
|
if (state.filter.optionIds.contains(option.id)) {
|
||||||
if (state.filter.optionIds.contains(option.id)) {
|
filterDesc += "${option.name} ";
|
||||||
filterDesc += "${option.name} ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
add(SelectOptionFilterEditorEvent.updateFilterDescription(
|
|
||||||
filterDesc));
|
|
||||||
}
|
}
|
||||||
},
|
add(SelectOptionFilterEditorEvent.updateFilterDescription(filterDesc));
|
||||||
onError: (error) => Log.error(error),
|
}
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/builder.dart';
|
|
||||||
import 'package:flowy_sdk/log.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
@ -12,16 +10,13 @@ part 'select_option_filter_list_bloc.freezed.dart';
|
||||||
|
|
||||||
class SelectOptionFilterListBloc<T>
|
class SelectOptionFilterListBloc<T>
|
||||||
extends Bloc<SelectOptionFilterListEvent, SelectOptionFilterListState> {
|
extends Bloc<SelectOptionFilterListEvent, SelectOptionFilterListState> {
|
||||||
final SingleSelectTypeOptionContext typeOptionContext;
|
final SelectOptionFilterDelegate delegate;
|
||||||
SelectOptionFilterListBloc({
|
SelectOptionFilterListBloc({
|
||||||
required String viewId,
|
required String viewId,
|
||||||
required FieldPB fieldPB,
|
required FieldPB fieldPB,
|
||||||
|
required this.delegate,
|
||||||
required List<String> selectedOptionIds,
|
required List<String> selectedOptionIds,
|
||||||
}) : typeOptionContext = makeSingleSelectTypeOptionContext(
|
}) : super(SelectOptionFilterListState.initial(selectedOptionIds)) {
|
||||||
gridId: viewId,
|
|
||||||
fieldPB: fieldPB,
|
|
||||||
),
|
|
||||||
super(SelectOptionFilterListState.initial(selectedOptionIds)) {
|
|
||||||
on<SelectOptionFilterListEvent>(
|
on<SelectOptionFilterListEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.when(
|
await event.when(
|
||||||
|
@ -103,14 +98,11 @@ class SelectOptionFilterListBloc<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loadOptions() {
|
void _loadOptions() {
|
||||||
typeOptionContext.loadTypeOptionData(
|
delegate.loadOptions().then((options) {
|
||||||
onCompleted: (value) {
|
if (!isClosed) {
|
||||||
if (!isClosed) {
|
add(SelectOptionFilterListEvent.didReceiveOptions(options));
|
||||||
add(SelectOptionFilterListEvent.didReceiveOptions(value.options));
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
onError: (error) => Log.error(error),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {}
|
void _startListening() {}
|
||||||
|
|
|
@ -31,7 +31,7 @@ class TextFilterEditorBloc
|
||||||
updateCondition: (TextFilterCondition condition) {
|
updateCondition: (TextFilterCondition condition) {
|
||||||
_ffiService.insertTextFilter(
|
_ffiService.insertTextFilter(
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
condition: condition,
|
condition: condition,
|
||||||
content: state.filter.content,
|
content: state.filter.content,
|
||||||
);
|
);
|
||||||
|
@ -39,16 +39,16 @@ class TextFilterEditorBloc
|
||||||
updateContent: (content) {
|
updateContent: (content) {
|
||||||
_ffiService.insertTextFilter(
|
_ffiService.insertTextFilter(
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
condition: state.filter.condition,
|
condition: state.filter.condition,
|
||||||
content: content,
|
content: content,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
delete: () {
|
delete: () {
|
||||||
_ffiService.deleteFilter(
|
_ffiService.deleteFilter(
|
||||||
fieldId: filterInfo.field.id,
|
fieldId: filterInfo.fieldInfo.id,
|
||||||
filterId: filterInfo.filter.id,
|
filterId: filterInfo.filter.id,
|
||||||
fieldType: filterInfo.field.fieldType,
|
fieldType: filterInfo.fieldInfo.fieldType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
didReceiveFilter: (FilterPB filter) {
|
didReceiveFilter: (FilterPB filter) {
|
||||||
|
|
|
@ -107,7 +107,7 @@ class _CheckboxFilterEditorState extends State<CheckboxFilterEditor> {
|
||||||
height: 20,
|
height: 20,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
FlowyText(state.filterInfo.field.name),
|
FlowyText(state.filterInfo.fieldInfo.name),
|
||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
CheckboxFilterConditionList(
|
CheckboxFilterConditionList(
|
||||||
filterInfo: state.filterInfo,
|
filterInfo: state.filterInfo,
|
||||||
|
|
|
@ -37,11 +37,11 @@ class ChoiceChipButton extends StatelessWidget {
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
decoration: decoration,
|
decoration: decoration,
|
||||||
useIntrinsicWidth: true,
|
useIntrinsicWidth: true,
|
||||||
text: FlowyText(filterInfo.field.name, fontSize: 12),
|
text: FlowyText(filterInfo.fieldInfo.name, fontSize: 12),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||||
radius: const BorderRadius.all(Radius.circular(14)),
|
radius: const BorderRadius.all(Radius.circular(14)),
|
||||||
leftIcon: svgWidget(
|
leftIcon: svgWidget(
|
||||||
filterInfo.field.fieldType.iconName(),
|
filterInfo.fieldInfo.fieldType.iconName(),
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
rightIcon: _ChoicechipFilterDesc(filterDesc: filterDesc),
|
rightIcon: _ChoicechipFilterDesc(filterDesc: filterDesc),
|
||||||
|
|
|
@ -32,7 +32,7 @@ class SelectOptionFilterConditionList extends StatelessWidget {
|
||||||
(action) => ConditionWrapper(
|
(action) => ConditionWrapper(
|
||||||
action,
|
action,
|
||||||
selectOptionFilter.condition == action,
|
selectOptionFilter.condition == action,
|
||||||
filterInfo.field.fieldType,
|
filterInfo.fieldInfo.fieldType,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
|
@ -50,7 +50,7 @@ class SelectOptionFilterConditionList extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
String filterName(SelectOptionFilterPB filter) {
|
String filterName(SelectOptionFilterPB filter) {
|
||||||
if (filterInfo.field.fieldType == FieldType.SingleSelect) {
|
if (filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) {
|
||||||
return filter.condition.singleSelectFilterName;
|
return filter.condition.singleSelectFilterName;
|
||||||
} else {
|
} else {
|
||||||
return filter.condition.multiSelectFilterName;
|
return filter.condition.multiSelectFilterName;
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
|
|
||||||
import 'package:app_flowy/plugins/grid/application/filter/select_option_filter_list_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/filter/select_option_filter_list_bloc.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart';
|
||||||
|
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pbenum.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import 'select_option_loader.dart';
|
||||||
|
|
||||||
class SelectOptionFilterList extends StatelessWidget {
|
class SelectOptionFilterList extends StatelessWidget {
|
||||||
final String viewId;
|
final FilterInfo filterInfo;
|
||||||
final FieldInfo fieldInfo;
|
|
||||||
final List<String> selectedOptionIds;
|
final List<String> selectedOptionIds;
|
||||||
final Function(List<String>) onSelectedOptions;
|
final Function(List<String>) onSelectedOptions;
|
||||||
const SelectOptionFilterList({
|
const SelectOptionFilterList({
|
||||||
required this.viewId,
|
required this.filterInfo,
|
||||||
required this.fieldInfo,
|
|
||||||
required this.selectedOptionIds,
|
required this.selectedOptionIds,
|
||||||
required this.onSelectedOptions,
|
required this.onSelectedOptions,
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -25,11 +26,27 @@ class SelectOptionFilterList extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => SelectOptionFilterListBloc(
|
create: (context) {
|
||||||
viewId: viewId,
|
late SelectOptionFilterListBloc bloc;
|
||||||
fieldPB: fieldInfo.field,
|
if (filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) {
|
||||||
selectedOptionIds: selectedOptionIds,
|
bloc = SelectOptionFilterListBloc(
|
||||||
)..add(const SelectOptionFilterListEvent.initial()),
|
viewId: filterInfo.viewId,
|
||||||
|
fieldPB: filterInfo.fieldInfo.field,
|
||||||
|
selectedOptionIds: selectedOptionIds,
|
||||||
|
delegate: SingleSelectOptionFilterDelegateImpl(filterInfo),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
bloc = SelectOptionFilterListBloc(
|
||||||
|
viewId: filterInfo.viewId,
|
||||||
|
fieldPB: filterInfo.fieldInfo.field,
|
||||||
|
selectedOptionIds: selectedOptionIds,
|
||||||
|
delegate: MultiSelectOptionFilterDelegateImpl(filterInfo),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bloc.add(const SelectOptionFilterListEvent.initial());
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
child:
|
child:
|
||||||
BlocListener<SelectOptionFilterListBloc, SelectOptionFilterListState>(
|
BlocListener<SelectOptionFilterListBloc, SelectOptionFilterListState>(
|
||||||
listenWhen: (previous, current) =>
|
listenWhen: (previous, current) =>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
@ -13,6 +14,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import '../choicechip.dart';
|
import '../choicechip.dart';
|
||||||
import 'condition_list.dart';
|
import 'condition_list.dart';
|
||||||
import 'option_list.dart';
|
import 'option_list.dart';
|
||||||
|
import 'select_option_loader.dart';
|
||||||
|
|
||||||
class SelectOptionFilterChoicechip extends StatefulWidget {
|
class SelectOptionFilterChoicechip extends StatefulWidget {
|
||||||
final FilterInfo filterInfo;
|
final FilterInfo filterInfo;
|
||||||
|
@ -30,8 +32,18 @@ class _SelectOptionFilterChoicechipState
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
bloc = SelectOptionFilterEditorBloc(filterInfo: widget.filterInfo)
|
if (widget.filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) {
|
||||||
..add(const SelectOptionFilterEditorEvent.initial());
|
bloc = SelectOptionFilterEditorBloc(
|
||||||
|
filterInfo: widget.filterInfo,
|
||||||
|
delegate: SingleSelectOptionFilterDelegateImpl(widget.filterInfo),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
bloc = SelectOptionFilterEditorBloc(
|
||||||
|
filterInfo: widget.filterInfo,
|
||||||
|
delegate: MultiSelectOptionFilterDelegateImpl(widget.filterInfo),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
bloc.add(const SelectOptionFilterEditorEvent.initial());
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +109,7 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
||||||
slivers.add(
|
slivers.add(
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: SelectOptionFilterList(
|
child: SelectOptionFilterList(
|
||||||
viewId: state.filterInfo.viewId,
|
filterInfo: state.filterInfo,
|
||||||
fieldInfo: state.filterInfo.field,
|
|
||||||
selectedOptionIds: state.filter.optionIds,
|
selectedOptionIds: state.filter.optionIds,
|
||||||
onSelectedOptions: (optionIds) {
|
onSelectedOptions: (optionIds) {
|
||||||
context.read<SelectOptionFilterEditorBloc>().add(
|
context.read<SelectOptionFilterEditorBloc>().add(
|
||||||
|
@ -129,7 +140,7 @@ class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
||||||
height: 20,
|
height: 20,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
FlowyText(state.filterInfo.field.name),
|
FlowyText(state.filterInfo.fieldInfo.name),
|
||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
SelectOptionFilterConditionList(
|
SelectOptionFilterConditionList(
|
||||||
filterInfo: state.filterInfo,
|
filterInfo: state.filterInfo,
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
||||||
|
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
|
||||||
|
import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/builder.dart';
|
||||||
|
import 'package:flowy_sdk/log.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||||
|
|
||||||
|
abstract class SelectOptionFilterDelegate {
|
||||||
|
Future<List<SelectOptionPB>> loadOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SingleSelectOptionFilterDelegateImpl
|
||||||
|
implements SelectOptionFilterDelegate {
|
||||||
|
final SingleSelectTypeOptionContext typeOptionContext;
|
||||||
|
|
||||||
|
SingleSelectOptionFilterDelegateImpl(FilterInfo filterInfo)
|
||||||
|
: typeOptionContext = makeSingleSelectTypeOptionContext(
|
||||||
|
gridId: filterInfo.viewId,
|
||||||
|
fieldPB: filterInfo.fieldInfo.field,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<SelectOptionPB>> loadOptions() {
|
||||||
|
return typeOptionContext
|
||||||
|
.loadTypeOptionData(
|
||||||
|
onError: (error) => Log.error(error),
|
||||||
|
)
|
||||||
|
.then((value) => value.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiSelectOptionFilterDelegateImpl
|
||||||
|
implements SelectOptionFilterDelegate {
|
||||||
|
final MultiSelectTypeOptionContext typeOptionContext;
|
||||||
|
|
||||||
|
MultiSelectOptionFilterDelegateImpl(FilterInfo filterInfo)
|
||||||
|
: typeOptionContext = makeMultiSelectTypeOptionContext(
|
||||||
|
gridId: filterInfo.viewId,
|
||||||
|
fieldPB: filterInfo.fieldInfo.field,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<SelectOptionPB>> loadOptions() {
|
||||||
|
return typeOptionContext
|
||||||
|
.loadTypeOptionData(
|
||||||
|
onError: (error) => Log.error(error),
|
||||||
|
)
|
||||||
|
.then((value) => value.options);
|
||||||
|
}
|
||||||
|
}
|
|
@ -120,7 +120,7 @@ class _TextFilterEditorState extends State<TextFilterEditor> {
|
||||||
height: 20,
|
height: 20,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
FlowyText(state.filterInfo.field.name),
|
FlowyText(state.filterInfo.fieldInfo.name),
|
||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
TextFilterConditionList(
|
TextFilterConditionList(
|
||||||
filterInfo: state.filterInfo,
|
filterInfo: state.filterInfo,
|
||||||
|
|
|
@ -9,15 +9,15 @@ import 'package:flowy_sdk/protobuf/flowy-grid/util.pb.dart';
|
||||||
class FilterInfo {
|
class FilterInfo {
|
||||||
final String viewId;
|
final String viewId;
|
||||||
final FilterPB filter;
|
final FilterPB filter;
|
||||||
final FieldInfo field;
|
final FieldInfo fieldInfo;
|
||||||
|
|
||||||
FilterInfo(this.viewId, this.filter, this.field);
|
FilterInfo(this.viewId, this.filter, this.fieldInfo);
|
||||||
|
|
||||||
FilterInfo copyWith({FilterPB? filter, FieldInfo? field}) {
|
FilterInfo copyWith({FilterPB? filter, FieldInfo? fieldInfo}) {
|
||||||
return FilterInfo(
|
return FilterInfo(
|
||||||
viewId,
|
viewId,
|
||||||
filter ?? this.filter,
|
filter ?? this.filter,
|
||||||
field ?? this.field,
|
fieldInfo ?? this.fieldInfo,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class FilterMenuItem extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildFilterChoicechip(FilterInfo filterInfo) {
|
Widget buildFilterChoicechip(FilterInfo filterInfo) {
|
||||||
switch (filterInfo.field.fieldType) {
|
switch (filterInfo.fieldInfo.fieldType) {
|
||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
return CheckboxFilterChoicechip(filterInfo: filterInfo);
|
return CheckboxFilterChoicechip(filterInfo: filterInfo);
|
||||||
case FieldType.DateTime:
|
case FieldType.DateTime:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue