mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-19 03:47:44 +00:00
chore: multi select
This commit is contained in:
parent
4b27fef76e
commit
7c6a857a69
3
frontend/app_flowy/assets/images/grid/checkmark.svg
Normal file
3
frontend/app_flowy/assets/images/grid/checkmark.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="10" height="8" viewBox="0 0 10 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 5.2L2.84615 7L9 1" stroke="#00BCF0" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 198 B |
@ -221,8 +221,8 @@ void _resolveGridDeps(GetIt getIt) {
|
|||||||
(typeOption, fieldId) => SingleSelectTypeOptionBloc(typeOption, fieldId),
|
(typeOption, fieldId) => SingleSelectTypeOptionBloc(typeOption, fieldId),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<MultiSelectTypeOptionBloc, MultiSelectTypeOption, void>(
|
getIt.registerFactoryParam<MultiSelectTypeOptionBloc, MultiSelectTypeOption, String>(
|
||||||
(typeOption, _) => MultiSelectTypeOptionBloc(typeOption),
|
(typeOption, fieldId) => MultiSelectTypeOptionBloc(typeOption, fieldId),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<DateTypeOptionBloc, DateTypeOption, void>(
|
getIt.registerFactoryParam<DateTypeOptionBloc, DateTypeOption, void>(
|
||||||
|
|||||||
@ -1,18 +1,37 @@
|
|||||||
import 'dart:typed_data';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:protobuf/protobuf.dart';
|
||||||
|
import 'type_option_service.dart';
|
||||||
|
|
||||||
part 'multi_select_bloc.freezed.dart';
|
part 'multi_select_bloc.freezed.dart';
|
||||||
|
|
||||||
class MultiSelectTypeOptionBloc extends Bloc<MultiSelectTypeOptionEvent, MultiSelectTypeOptionState> {
|
class MultiSelectTypeOptionBloc extends Bloc<MultiSelectTypeOptionEvent, MultiSelectTypeOptionState> {
|
||||||
MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption) : super(MultiSelectTypeOptionState.initial(typeOption)) {
|
final TypeOptionService service;
|
||||||
|
|
||||||
|
MultiSelectTypeOptionBloc(MultiSelectTypeOption typeOption, String fieldId)
|
||||||
|
: service = TypeOptionService(fieldId: fieldId),
|
||||||
|
super(MultiSelectTypeOptionState.initial(typeOption)) {
|
||||||
on<MultiSelectTypeOptionEvent>(
|
on<MultiSelectTypeOptionEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
createOption: (_CreateOption value) {},
|
createOption: (_CreateOption value) async {
|
||||||
updateOptions: (_UpdateOptions value) async {},
|
final result = await service.createOption(value.optionName);
|
||||||
|
result.fold(
|
||||||
|
(option) {
|
||||||
|
emit(state.copyWith(typeOption: _insertOption(option)));
|
||||||
|
},
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
updateOption: (_UpdateOption value) async {
|
||||||
|
emit(state.copyWith(typeOption: _updateOption(value.option)));
|
||||||
|
},
|
||||||
|
deleteOption: (_DeleteOption value) {
|
||||||
|
emit(state.copyWith(typeOption: _deleteOption(value.option)));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -22,12 +41,40 @@ class MultiSelectTypeOptionBloc extends Bloc<MultiSelectTypeOptionEvent, MultiSe
|
|||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MultiSelectTypeOption _insertOption(SelectOption option) {
|
||||||
|
state.typeOption.freeze();
|
||||||
|
return state.typeOption.rebuild((typeOption) {
|
||||||
|
typeOption.options.insert(0, option);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiSelectTypeOption _updateOption(SelectOption option) {
|
||||||
|
state.typeOption.freeze();
|
||||||
|
return state.typeOption.rebuild((typeOption) {
|
||||||
|
final index = typeOption.options.indexWhere((element) => element.id == option.id);
|
||||||
|
if (index != -1) {
|
||||||
|
typeOption.options[index] = option;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiSelectTypeOption _deleteOption(SelectOption option) {
|
||||||
|
state.typeOption.freeze();
|
||||||
|
return state.typeOption.rebuild((typeOption) {
|
||||||
|
final index = typeOption.options.indexWhere((element) => element.id == option.id);
|
||||||
|
if (index != -1) {
|
||||||
|
typeOption.options.removeAt(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class MultiSelectTypeOptionEvent with _$MultiSelectTypeOptionEvent {
|
class MultiSelectTypeOptionEvent with _$MultiSelectTypeOptionEvent {
|
||||||
const factory MultiSelectTypeOptionEvent.createOption(String optionName) = _CreateOption;
|
const factory MultiSelectTypeOptionEvent.createOption(String optionName) = _CreateOption;
|
||||||
const factory MultiSelectTypeOptionEvent.updateOptions(List<SelectOption> options) = _UpdateOptions;
|
const factory MultiSelectTypeOptionEvent.updateOption(SelectOption option) = _UpdateOption;
|
||||||
|
const factory MultiSelectTypeOptionEvent.deleteOption(SelectOption option) = _DeleteOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
|||||||
@ -156,7 +156,7 @@ TypeOptionBuilder _makeTypeOptionBuild({
|
|||||||
case FieldType.SingleSelect:
|
case FieldType.SingleSelect:
|
||||||
return SingleSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate);
|
return SingleSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate);
|
||||||
case FieldType.MultiSelect:
|
case FieldType.MultiSelect:
|
||||||
return MultiSelectTypeOptionBuilder(data, overlayDelegate);
|
return MultiSelectTypeOptionBuilder(field.id, data, overlayDelegate, dataDelegate);
|
||||||
case FieldType.Number:
|
case FieldType.Number:
|
||||||
return NumberTypeOptionBuilder(data, overlayDelegate, dataDelegate);
|
return NumberTypeOptionBuilder(data, overlayDelegate, dataDelegate);
|
||||||
case FieldType.RichText:
|
case FieldType.RichText:
|
||||||
|
|||||||
@ -8,26 +8,45 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'option_pannel.dart';
|
import 'option_pannel.dart';
|
||||||
|
|
||||||
class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
|
class MultiSelectTypeOptionBuilder extends TypeOptionBuilder {
|
||||||
MultiSelectTypeOption typeOption;
|
MultiSelectTypeOptionWidget _widget;
|
||||||
TypeOptionOverlayDelegate delegate;
|
|
||||||
|
|
||||||
MultiSelectTypeOptionBuilder(TypeOptionData typeOptionData, this.delegate)
|
MultiSelectTypeOptionBuilder(
|
||||||
: typeOption = MultiSelectTypeOption.fromBuffer(typeOptionData);
|
String fieldId,
|
||||||
|
TypeOptionData typeOptionData,
|
||||||
|
TypeOptionOverlayDelegate overlayDelegate,
|
||||||
|
TypeOptionDataDelegate dataDelegate,
|
||||||
|
) : _widget = MultiSelectTypeOptionWidget(
|
||||||
|
fieldId: fieldId,
|
||||||
|
typeOption: MultiSelectTypeOption.fromBuffer(typeOptionData),
|
||||||
|
overlayDelegate: overlayDelegate,
|
||||||
|
dataDelegate: dataDelegate,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget? get customWidget => MultiSelectTypeOptionWidget(typeOption, delegate);
|
Widget? get customWidget => _widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiSelectTypeOptionWidget extends TypeOptionWidget {
|
class MultiSelectTypeOptionWidget extends TypeOptionWidget {
|
||||||
|
final String fieldId;
|
||||||
final MultiSelectTypeOption typeOption;
|
final MultiSelectTypeOption typeOption;
|
||||||
final TypeOptionOverlayDelegate overlayDelegate;
|
final TypeOptionOverlayDelegate overlayDelegate;
|
||||||
const MultiSelectTypeOptionWidget(this.typeOption, this.overlayDelegate, {Key? key}) : super(key: key);
|
final TypeOptionDataDelegate dataDelegate;
|
||||||
|
const MultiSelectTypeOptionWidget({
|
||||||
|
required this.fieldId,
|
||||||
|
required this.typeOption,
|
||||||
|
required this.overlayDelegate,
|
||||||
|
required this.dataDelegate,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => getIt<MultiSelectTypeOptionBloc>(param1: typeOption),
|
create: (context) => getIt<MultiSelectTypeOptionBloc>(param1: typeOption, param2: fieldId),
|
||||||
child: BlocBuilder<MultiSelectTypeOptionBloc, MultiSelectTypeOptionState>(
|
child: BlocConsumer<MultiSelectTypeOptionBloc, MultiSelectTypeOptionState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer());
|
||||||
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return OptionPannel(
|
return OptionPannel(
|
||||||
options: state.typeOption.options,
|
options: state.typeOption.options,
|
||||||
@ -37,9 +56,14 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget {
|
|||||||
createOptionCallback: (name) {
|
createOptionCallback: (name) {
|
||||||
context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.createOption(name));
|
context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.createOption(name));
|
||||||
},
|
},
|
||||||
updateOptionCallback: (updateOption) {},
|
updateOptionCallback: (updateOption) {
|
||||||
deleteOptionCallback: (deleteOption) {},
|
context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.updateOption(updateOption));
|
||||||
|
},
|
||||||
|
deleteOptionCallback: (deleteOption) {
|
||||||
|
context.read<MultiSelectTypeOptionBloc>().add(MultiSelectTypeOptionEvent.deleteOption(deleteOption));
|
||||||
|
},
|
||||||
overlayDelegate: overlayDelegate,
|
overlayDelegate: overlayDelegate,
|
||||||
|
key: ValueKey(state.typeOption.hashCode),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user