mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #617 from AppFlowy-IO/feat/add_more_grid_documentation
This commit is contained in:
commit
c860d1bc0b
@ -1,3 +1,4 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
@ -6,27 +7,32 @@ import 'package:dartz/dartz.dart';
|
||||
part 'field_editor_bloc.freezed.dart';
|
||||
|
||||
class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
||||
final TypeOptionDataController dataController;
|
||||
|
||||
FieldEditorBloc({
|
||||
required String gridId,
|
||||
required String fieldName,
|
||||
required IFieldTypeOptionLoader fieldContextLoader,
|
||||
}) : super(FieldEditorState.initial(gridId, fieldName, fieldContextLoader)) {
|
||||
required IFieldTypeOptionLoader loader,
|
||||
}) : dataController = TypeOptionDataController(gridId: gridId, loader: loader),
|
||||
super(FieldEditorState.initial(gridId, fieldName)) {
|
||||
on<FieldEditorEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
initial: () async {
|
||||
final fieldContext = GridFieldContext(gridId: gridId, loader: fieldContextLoader);
|
||||
await fieldContext.loadData().then((result) {
|
||||
result.fold(
|
||||
(l) => emit(state.copyWith(fieldContext: Some(fieldContext), name: fieldContext.field.name)),
|
||||
(r) => null,
|
||||
);
|
||||
dataController.addFieldListener((field) {
|
||||
if (!isClosed) {
|
||||
add(FieldEditorEvent.didReceiveFieldChanged(field));
|
||||
}
|
||||
});
|
||||
await dataController.loadData();
|
||||
},
|
||||
updateName: (name) {
|
||||
state.fieldContext.fold(() => null, (fieldContext) => fieldContext.fieldName = name);
|
||||
dataController.fieldName = name;
|
||||
emit(state.copyWith(name: name));
|
||||
},
|
||||
didReceiveFieldChanged: (Field field) {
|
||||
emit(state.copyWith(field: Some(field)));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -42,6 +48,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
||||
class FieldEditorEvent with _$FieldEditorEvent {
|
||||
const factory FieldEditorEvent.initial() = _InitialField;
|
||||
const factory FieldEditorEvent.updateName(String name) = _UpdateName;
|
||||
const factory FieldEditorEvent.didReceiveFieldChanged(Field field) = _DidReceiveFieldChanged;
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -50,13 +57,17 @@ class FieldEditorState with _$FieldEditorState {
|
||||
required String gridId,
|
||||
required String errorText,
|
||||
required String name,
|
||||
required Option<GridFieldContext> fieldContext,
|
||||
required Option<Field> field,
|
||||
}) = _FieldEditorState;
|
||||
|
||||
factory FieldEditorState.initial(String gridId, String fieldName, IFieldTypeOptionLoader loader) => FieldEditorState(
|
||||
factory FieldEditorState.initial(
|
||||
String gridId,
|
||||
String fieldName,
|
||||
) =>
|
||||
FieldEditorState(
|
||||
gridId: gridId,
|
||||
fieldContext: none(),
|
||||
errorText: '',
|
||||
field: none(),
|
||||
name: fieldName,
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/notifier.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
@ -193,14 +194,14 @@ class FieldTypeOptionLoader extends IFieldTypeOptionLoader {
|
||||
}
|
||||
}
|
||||
|
||||
class GridFieldContext {
|
||||
class TypeOptionDataController {
|
||||
final String gridId;
|
||||
final IFieldTypeOptionLoader _loader;
|
||||
|
||||
late FieldTypeOptionData _data;
|
||||
ValueNotifier<Field>? _fieldNotifier;
|
||||
final PublishNotifier<Field> _fieldNotifier = PublishNotifier();
|
||||
|
||||
GridFieldContext({
|
||||
TypeOptionDataController({
|
||||
required this.gridId,
|
||||
required IFieldTypeOptionLoader loader,
|
||||
}) : _loader = loader;
|
||||
@ -211,13 +212,7 @@ class GridFieldContext {
|
||||
(data) {
|
||||
data.freeze();
|
||||
_data = data;
|
||||
|
||||
if (_fieldNotifier == null) {
|
||||
_fieldNotifier = ValueNotifier(data.field_2);
|
||||
} else {
|
||||
_fieldNotifier?.value = data.field_2;
|
||||
}
|
||||
|
||||
_fieldNotifier.value = data.field_2;
|
||||
return left(unit);
|
||||
},
|
||||
(err) {
|
||||
@ -260,9 +255,7 @@ class GridFieldContext {
|
||||
}
|
||||
});
|
||||
|
||||
if (_data.field_2 != _fieldNotifier?.value) {
|
||||
_fieldNotifier?.value = _data.field_2;
|
||||
}
|
||||
_fieldNotifier.value = _data.field_2;
|
||||
|
||||
FieldService.insertField(
|
||||
gridId: gridId,
|
||||
@ -292,11 +285,11 @@ class GridFieldContext {
|
||||
callback(field);
|
||||
}
|
||||
|
||||
_fieldNotifier?.addListener(listener);
|
||||
_fieldNotifier.addListener(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
void removeFieldListener(void Function() listener) {
|
||||
_fieldNotifier?.removeListener(listener);
|
||||
_fieldNotifier.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
@ -8,17 +8,17 @@ import 'field_service.dart';
|
||||
part 'field_type_option_edit_bloc.freezed.dart';
|
||||
|
||||
class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOptionEditState> {
|
||||
final GridFieldContext _fieldContext;
|
||||
final TypeOptionDataController _dataController;
|
||||
void Function()? _fieldListenFn;
|
||||
|
||||
FieldTypeOptionEditBloc(GridFieldContext fieldContext)
|
||||
: _fieldContext = fieldContext,
|
||||
super(FieldTypeOptionEditState.initial(fieldContext)) {
|
||||
FieldTypeOptionEditBloc(TypeOptionDataController dataController)
|
||||
: _dataController = dataController,
|
||||
super(FieldTypeOptionEditState.initial(dataController)) {
|
||||
on<FieldTypeOptionEditEvent>(
|
||||
(event, emit) async {
|
||||
event.when(
|
||||
initial: () {
|
||||
_fieldListenFn = fieldContext.addFieldListener((field) {
|
||||
_fieldListenFn = dataController.addFieldListener((field) {
|
||||
add(FieldTypeOptionEditEvent.didReceiveFieldUpdated(field));
|
||||
});
|
||||
},
|
||||
@ -33,7 +33,7 @@ class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOp
|
||||
@override
|
||||
Future<void> close() async {
|
||||
if (_fieldListenFn != null) {
|
||||
_fieldContext.removeFieldListener(_fieldListenFn!);
|
||||
_dataController.removeFieldListener(_fieldListenFn!);
|
||||
}
|
||||
return super.close();
|
||||
}
|
||||
@ -51,7 +51,7 @@ class FieldTypeOptionEditState with _$FieldTypeOptionEditState {
|
||||
required Field field,
|
||||
}) = _FieldTypeOptionEditState;
|
||||
|
||||
factory FieldTypeOptionEditState.initial(GridFieldContext fieldContext) => FieldTypeOptionEditState(
|
||||
factory FieldTypeOptionEditState.initial(TypeOptionDataController fieldContext) => FieldTypeOptionEditState(
|
||||
field: fieldContext.field,
|
||||
);
|
||||
}
|
||||
|
@ -13,12 +13,12 @@ class MultiSelectTypeOptionContext extends TypeOptionWidgetContext<MultiSelectTy
|
||||
|
||||
MultiSelectTypeOptionContext({
|
||||
required MultiSelectTypeOptionWidgetDataParser dataBuilder,
|
||||
required GridFieldContext fieldContext,
|
||||
required TypeOptionDataController dataController,
|
||||
}) : service = TypeOptionService(
|
||||
gridId: fieldContext.gridId,
|
||||
fieldId: fieldContext.field.id,
|
||||
gridId: dataController.gridId,
|
||||
fieldId: dataController.field.id,
|
||||
),
|
||||
super(dataParser: dataBuilder, fieldContext: fieldContext);
|
||||
super(dataParser: dataBuilder, dataController: dataController);
|
||||
|
||||
@override
|
||||
List<SelectOption> Function(SelectOption) get deleteOption {
|
||||
|
@ -13,12 +13,12 @@ class SingleSelectTypeOptionContext extends TypeOptionWidgetContext<SingleSelect
|
||||
|
||||
SingleSelectTypeOptionContext({
|
||||
required SingleSelectTypeOptionWidgetDataParser dataBuilder,
|
||||
required GridFieldContext fieldContext,
|
||||
required TypeOptionDataController fieldContext,
|
||||
}) : service = TypeOptionService(
|
||||
gridId: fieldContext.gridId,
|
||||
fieldId: fieldContext.field.id,
|
||||
),
|
||||
super(dataParser: dataBuilder, fieldContext: fieldContext);
|
||||
super(dataParser: dataBuilder, dataController: fieldContext);
|
||||
|
||||
@override
|
||||
List<SelectOption> Function(SelectOption) get deleteOption {
|
||||
|
@ -39,30 +39,30 @@ abstract class TypeOptionDataParser<T> {
|
||||
|
||||
class TypeOptionWidgetContext<T extends GeneratedMessage> {
|
||||
T? _typeOptionObject;
|
||||
final GridFieldContext _fieldContext;
|
||||
final TypeOptionDataController _dataController;
|
||||
final TypeOptionDataParser<T> dataParser;
|
||||
|
||||
TypeOptionWidgetContext({
|
||||
required this.dataParser,
|
||||
required GridFieldContext fieldContext,
|
||||
}) : _fieldContext = fieldContext;
|
||||
required TypeOptionDataController dataController,
|
||||
}) : _dataController = dataController;
|
||||
|
||||
String get gridId => _fieldContext.gridId;
|
||||
String get gridId => _dataController.gridId;
|
||||
|
||||
Field get field => _fieldContext.field;
|
||||
Field get field => _dataController.field;
|
||||
|
||||
T get typeOption {
|
||||
if (_typeOptionObject != null) {
|
||||
return _typeOptionObject!;
|
||||
}
|
||||
|
||||
final T object = dataParser.fromBuffer(_fieldContext.typeOptionData);
|
||||
final T object = dataParser.fromBuffer(_dataController.typeOptionData);
|
||||
_typeOptionObject = object;
|
||||
return object;
|
||||
}
|
||||
|
||||
set typeOption(T typeOption) {
|
||||
_fieldContext.typeOptionData = typeOption.writeToBuffer();
|
||||
_dataController.typeOptionData = typeOption.writeToBuffer();
|
||||
_typeOptionObject = typeOption;
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class GridFieldCell extends StatelessWidget {
|
||||
FieldEditor(
|
||||
gridId: state.gridId,
|
||||
fieldName: field.name,
|
||||
contextLoader: FieldTypeOptionLoader(
|
||||
typeOptionLoader: FieldTypeOptionLoader(
|
||||
gridId: state.gridId,
|
||||
field: field,
|
||||
),
|
||||
|
@ -14,11 +14,11 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||
final String gridId;
|
||||
final String fieldName;
|
||||
|
||||
final IFieldTypeOptionLoader contextLoader;
|
||||
final IFieldTypeOptionLoader typeOptionLoader;
|
||||
const FieldEditor({
|
||||
required this.gridId,
|
||||
required this.fieldName,
|
||||
required this.contextLoader,
|
||||
required this.typeOptionLoader,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -28,7 +28,7 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||
create: (context) => FieldEditorBloc(
|
||||
gridId: gridId,
|
||||
fieldName: fieldName,
|
||||
fieldContextLoader: contextLoader,
|
||||
loader: typeOptionLoader,
|
||||
)..add(const FieldEditorEvent.initial()),
|
||||
child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
||||
buildWhen: (p, c) => false,
|
||||
@ -80,11 +80,14 @@ class _FieldTypeOptionCell extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
||||
buildWhen: (p, c) => p.fieldContext != c.fieldContext,
|
||||
buildWhen: (p, c) => p.field != c.field,
|
||||
builder: (context, state) {
|
||||
return state.fieldContext.fold(
|
||||
return state.field.fold(
|
||||
() => const SizedBox(),
|
||||
(fieldContext) => FieldTypeOptionEditor(fieldContext: fieldContext),
|
||||
(fieldContext) {
|
||||
final dataController = context.read<FieldEditorBloc>().dataController;
|
||||
return FieldTypeOptionEditor(dataController: dataController);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -22,10 +22,10 @@ typedef SwitchToFieldCallback = Future<Either<FieldTypeOptionData, FlowyError>>
|
||||
);
|
||||
|
||||
class FieldTypeOptionEditor extends StatefulWidget {
|
||||
final GridFieldContext fieldContext;
|
||||
final TypeOptionDataController dataController;
|
||||
|
||||
const FieldTypeOptionEditor({
|
||||
required this.fieldContext,
|
||||
required this.dataController,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -39,10 +39,11 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => FieldTypeOptionEditBloc(widget.fieldContext)..add(const FieldTypeOptionEditEvent.initial()),
|
||||
create: (context) =>
|
||||
FieldTypeOptionEditBloc(widget.dataController)..add(const FieldTypeOptionEditEvent.initial()),
|
||||
child: BlocBuilder<FieldTypeOptionEditBloc, FieldTypeOptionEditState>(
|
||||
builder: (context, state) {
|
||||
List<Widget> children = [_switchFieldTypeButton(context, widget.fieldContext.field)];
|
||||
List<Widget> children = [_switchFieldTypeButton(context, widget.dataController.field)];
|
||||
final typeOptionWidget = _typeOptionWidget(context: context, state: state);
|
||||
|
||||
if (typeOptionWidget != null) {
|
||||
@ -68,7 +69,7 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
|
||||
hoverColor: theme.hover,
|
||||
onTap: () {
|
||||
final list = FieldTypeList(onSelectField: (newFieldType) {
|
||||
widget.fieldContext.switchToField(newFieldType);
|
||||
widget.dataController.switchToField(newFieldType);
|
||||
});
|
||||
_showOverlay(context, list);
|
||||
},
|
||||
@ -89,7 +90,7 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
|
||||
|
||||
return makeTypeOptionWidget(
|
||||
context: context,
|
||||
fieldContext: widget.fieldContext,
|
||||
dataController: widget.dataController,
|
||||
overlayDelegate: overlayDelegate,
|
||||
);
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ class CreateFieldButton extends StatelessWidget {
|
||||
onTap: () => FieldEditor(
|
||||
gridId: gridId,
|
||||
fieldName: "",
|
||||
contextLoader: NewFieldTypeOptionLoader(gridId: gridId),
|
||||
typeOptionLoader: NewFieldTypeOptionLoader(gridId: gridId),
|
||||
).show(context),
|
||||
leftIcon: svgWidget("home/add"),
|
||||
);
|
||||
|
@ -36,27 +36,27 @@ abstract class TypeOptionWidgetBuilder {
|
||||
|
||||
Widget? makeTypeOptionWidget({
|
||||
required BuildContext context,
|
||||
required GridFieldContext fieldContext,
|
||||
required TypeOptionDataController dataController,
|
||||
required TypeOptionOverlayDelegate overlayDelegate,
|
||||
}) {
|
||||
final builder = makeTypeOptionWidgetBuilder(fieldContext, overlayDelegate);
|
||||
final builder = makeTypeOptionWidgetBuilder(dataController, overlayDelegate);
|
||||
return builder.build(context);
|
||||
}
|
||||
|
||||
TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
|
||||
GridFieldContext fieldContext,
|
||||
TypeOptionDataController dataController,
|
||||
TypeOptionOverlayDelegate overlayDelegate,
|
||||
) {
|
||||
switch (fieldContext.field.fieldType) {
|
||||
switch (dataController.field.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
final context = CheckboxTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
dataController: dataController,
|
||||
dataParser: CheckboxTypeOptionWidgetDataParser(),
|
||||
);
|
||||
return CheckboxTypeOptionWidgetBuilder(context);
|
||||
case FieldType.DateTime:
|
||||
final context = DateTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
dataController: dataController,
|
||||
dataParser: DateTypeOptionDataParser(),
|
||||
);
|
||||
return DateTypeOptionWidgetBuilder(
|
||||
@ -65,7 +65,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
|
||||
);
|
||||
case FieldType.SingleSelect:
|
||||
final context = SingleSelectTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
fieldContext: dataController,
|
||||
dataBuilder: SingleSelectTypeOptionWidgetDataParser(),
|
||||
);
|
||||
return SingleSelectTypeOptionWidgetBuilder(
|
||||
@ -74,7 +74,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
|
||||
);
|
||||
case FieldType.MultiSelect:
|
||||
final context = MultiSelectTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
dataController: dataController,
|
||||
dataBuilder: MultiSelectTypeOptionWidgetDataParser(),
|
||||
);
|
||||
return MultiSelectTypeOptionWidgetBuilder(
|
||||
@ -83,7 +83,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
|
||||
);
|
||||
case FieldType.Number:
|
||||
final context = NumberTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
dataController: dataController,
|
||||
dataParser: NumberTypeOptionWidgetDataParser(),
|
||||
);
|
||||
return NumberTypeOptionWidgetBuilder(
|
||||
@ -92,14 +92,14 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
|
||||
);
|
||||
case FieldType.RichText:
|
||||
final context = RichTextTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
dataController: dataController,
|
||||
dataParser: RichTextTypeOptionWidgetDataParser(),
|
||||
);
|
||||
return RichTextTypeOptionWidgetBuilder(context);
|
||||
|
||||
case FieldType.URL:
|
||||
final context = URLTypeOptionContext(
|
||||
fieldContext: fieldContext,
|
||||
dataController: dataController,
|
||||
dataParser: URLTypeOptionWidgetDataParser(),
|
||||
);
|
||||
return URLTypeOptionWidgetBuilder(context);
|
||||
|
@ -183,7 +183,7 @@ class _RowDetailCell extends StatelessWidget {
|
||||
FieldEditor(
|
||||
gridId: cellId.gridId,
|
||||
fieldName: cellId.field.name,
|
||||
contextLoader: FieldTypeOptionLoader(
|
||||
typeOptionLoader: FieldTypeOptionLoader(
|
||||
gridId: cellId.gridId,
|
||||
field: cellId.field,
|
||||
),
|
||||
|
@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget {
|
||||
FieldEditor(
|
||||
gridId: gridId,
|
||||
fieldName: field.name,
|
||||
contextLoader: FieldTypeOptionLoader(gridId: gridId, field: field),
|
||||
typeOptionLoader: FieldTypeOptionLoader(gridId: gridId, field: field),
|
||||
).show(context, anchorDirection: AnchorDirection.bottomRight);
|
||||
},
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user