mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: database field type option (#4136)
* refactor: include field type option in FieldPB * refactor: adapt changes on flutter * refactor: adapt changes on new tauri grid * refactor: adapt changes on old tauri grid/board * chore: merge
This commit is contained in:
@ -4,13 +4,9 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/base/drag_handler.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_cal_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_cell_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/mobile_date_editor.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:dartz/dartz.dart' hide State;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -41,17 +37,6 @@ class MobileDateCellEditScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
||||
late final Future<Either<dynamic, FlowyError>> typeOptionFuture;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
typeOptionFuture = widget.controller.getTypeOption(
|
||||
DateTypeOptionDataParser(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.showAsFullScreen ? _buildFullScreen() : _buildNotFullScreen();
|
||||
@ -64,7 +49,9 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
||||
LocaleKeys.titleBar_date.tr(),
|
||||
),
|
||||
),
|
||||
body: _buildBody(),
|
||||
body: _DateCellEditBody(
|
||||
dateCellController: widget.controller,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -86,7 +73,9 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
||||
),
|
||||
_buildHeader(),
|
||||
Expanded(
|
||||
child: _buildBody(),
|
||||
child: _DateCellEditBody(
|
||||
dateCellController: widget.controller,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -94,36 +83,6 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return FutureBuilder<Either<dynamic, FlowyError>>(
|
||||
future: typeOptionFuture,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data;
|
||||
if (data == null) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
);
|
||||
}
|
||||
|
||||
return data.fold(
|
||||
(dateTypeOptionPB) {
|
||||
return _DateCellEditBody(
|
||||
dateCellController: widget.controller,
|
||||
dateTypeOptionPB: dateTypeOptionPB,
|
||||
);
|
||||
},
|
||||
(err) {
|
||||
Log.error(err);
|
||||
return FlowyMobileStateContainer.error(
|
||||
title: LocaleKeys.grid_field_failedToLoadDate.tr(),
|
||||
errorMsg: err.toString(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeader() {
|
||||
const iconWidth = 30.0;
|
||||
const height = 44.0;
|
||||
@ -160,20 +119,16 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
||||
class _DateCellEditBody extends StatelessWidget {
|
||||
const _DateCellEditBody({
|
||||
required this.dateCellController,
|
||||
required this.dateTypeOptionPB,
|
||||
});
|
||||
|
||||
final DateCellController dateCellController;
|
||||
final DateTypeOptionPB dateTypeOptionPB;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => DateCellCalendarBloc(
|
||||
dateTypeOptionPB: dateTypeOptionPB,
|
||||
cellData: dateCellController.getCellData(),
|
||||
create: (context) => DateCellEditorBloc(
|
||||
cellController: dateCellController,
|
||||
)..add(const DateCellCalendarEvent.initial()),
|
||||
)..add(const DateCellEditorEvent.initial()),
|
||||
child: const Column(
|
||||
children: [
|
||||
FlowyOptionDecorateBox(
|
||||
@ -217,7 +172,7 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<DateCellCalendarBloc, DateCellCalendarState>(
|
||||
return BlocBuilder<DateCellEditorBloc, DateCellEditorState>(
|
||||
builder: (context, state) {
|
||||
final startDay = state.dateStr;
|
||||
final endDay = state.endDateStr;
|
||||
@ -306,7 +261,7 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
final bloc = context.read<DateCellCalendarBloc>();
|
||||
final bloc = context.read<DateCellEditorBloc>();
|
||||
await showMobileBottomSheet(
|
||||
context,
|
||||
builder: (context) {
|
||||
@ -331,8 +286,8 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
|
||||
if (_selectedTime != null) {
|
||||
bloc.add(
|
||||
isStartDay
|
||||
? DateCellCalendarEvent.setTime(_selectedTime!)
|
||||
: DateCellCalendarEvent.setEndTime(_selectedTime!),
|
||||
? DateCellEditorEvent.setTime(_selectedTime!)
|
||||
: DateCellEditorEvent.setEndTime(_selectedTime!),
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -361,7 +316,7 @@ class _EndDateSwitch extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocSelector<DateCellCalendarBloc, DateCellCalendarState, bool>(
|
||||
return BlocSelector<DateCellEditorBloc, DateCellEditorState, bool>(
|
||||
selector: (state) => state.isRange,
|
||||
builder: (context, isRange) {
|
||||
return FlowyOptionTile.toggle(
|
||||
@ -369,8 +324,8 @@ class _EndDateSwitch extends StatelessWidget {
|
||||
isSelected: isRange,
|
||||
onValueChanged: (value) {
|
||||
context
|
||||
.read<DateCellCalendarBloc>()
|
||||
.add(DateCellCalendarEvent.setIsRange(value));
|
||||
.read<DateCellEditorBloc>()
|
||||
.add(DateCellEditorEvent.setIsRange(value));
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -383,7 +338,7 @@ class _IncludeTimeSwitch extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocSelector<DateCellCalendarBloc, DateCellCalendarState, bool>(
|
||||
return BlocSelector<DateCellEditorBloc, DateCellEditorState, bool>(
|
||||
selector: (state) => state.includeTime,
|
||||
builder: (context, includeTime) {
|
||||
return FlowyOptionTile.toggle(
|
||||
@ -392,8 +347,8 @@ class _IncludeTimeSwitch extends StatelessWidget {
|
||||
isSelected: includeTime,
|
||||
onValueChanged: (value) {
|
||||
context
|
||||
.read<DateCellCalendarBloc>()
|
||||
.add(DateCellCalendarEvent.setIncludeTime(value));
|
||||
.read<DateCellEditorBloc>()
|
||||
.add(DateCellEditorEvent.setIncludeTime(value));
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -420,7 +375,7 @@ class _TimeTextFieldState extends State<_TimeTextField> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<DateCellCalendarBloc, DateCellCalendarState>(
|
||||
return BlocConsumer<DateCellEditorBloc, DateCellEditorState>(
|
||||
listener: (context, state) {
|
||||
_textController.text =
|
||||
widget.isEndTime ? state.endTimeStr ?? "" : state.timeStr ?? "";
|
||||
@ -437,10 +392,10 @@ class _TimeTextFieldState extends State<_TimeTextField> {
|
||||
),
|
||||
keyboardType: TextInputType.datetime,
|
||||
onFieldSubmitted: (timeStr) {
|
||||
context.read<DateCellCalendarBloc>().add(
|
||||
context.read<DateCellEditorBloc>().add(
|
||||
widget.isEndTime
|
||||
? DateCellCalendarEvent.setEndTime(timeStr)
|
||||
: DateCellCalendarEvent.setTime(timeStr),
|
||||
? DateCellEditorEvent.setEndTime(timeStr)
|
||||
: DateCellEditorEvent.setTime(timeStr),
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -463,8 +418,8 @@ class _ClearDateButton extends StatelessWidget {
|
||||
return FlowyOptionTile.text(
|
||||
text: LocaleKeys.grid_field_clearDate.tr(),
|
||||
onTap: () => context
|
||||
.read<DateCellCalendarBloc>()
|
||||
.add(const DateCellCalendarEvent.clearDate()),
|
||||
.read<DateCellEditorBloc>()
|
||||
.add(const DateCellEditorEvent.clearDate()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -28,19 +28,12 @@ class MobileEditPropertyScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
|
||||
late Future<FieldOptionValues?> future;
|
||||
|
||||
FieldOptionValues? optionValues;
|
||||
late FieldOptionValues optionValues;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
future = FieldOptionValues.get(
|
||||
viewId: widget.viewId,
|
||||
fieldId: widget.field.id,
|
||||
fieldType: widget.field.fieldType,
|
||||
);
|
||||
optionValues = FieldOptionValues.fromField(field: widget.field);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -66,39 +59,30 @@ class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: FutureBuilder<FieldOptionValues?>(
|
||||
future: future,
|
||||
builder: (context, snapshot) {
|
||||
final optionValues = snapshot.data;
|
||||
if (optionValues == null) {
|
||||
return const Center(child: CircularProgressIndicator.adaptive());
|
||||
}
|
||||
return FieldOptionEditor(
|
||||
mode: FieldOptionMode.edit,
|
||||
isPrimary: widget.field.isPrimary,
|
||||
defaultValues: optionValues,
|
||||
onOptionValuesChanged: (optionValues) {
|
||||
this.optionValues = optionValues;
|
||||
},
|
||||
onAction: (action) {
|
||||
final service = FieldServices(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
switch (action) {
|
||||
case FieldOptionAction.delete:
|
||||
service.delete();
|
||||
break;
|
||||
case FieldOptionAction.duplicate:
|
||||
service.duplicate();
|
||||
break;
|
||||
case FieldOptionAction.hide:
|
||||
service.hide();
|
||||
break;
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
body: FieldOptionEditor(
|
||||
mode: FieldOptionMode.edit,
|
||||
isPrimary: widget.field.isPrimary,
|
||||
defaultValues: optionValues,
|
||||
onOptionValuesChanged: (optionValues) {
|
||||
this.optionValues = optionValues;
|
||||
},
|
||||
onAction: (action) {
|
||||
final service = FieldServices(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
switch (action) {
|
||||
case FieldOptionAction.delete:
|
||||
service.delete();
|
||||
break;
|
||||
case FieldOptionAction.duplicate:
|
||||
service.duplicate();
|
||||
break;
|
||||
case FieldOptionAction.hide:
|
||||
service.hide();
|
||||
break;
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -9,7 +9,7 @@ import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/w
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/number_format_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart';
|
||||
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date/date_time_format.dart';
|
||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
|
||||
import 'package:appflowy/util/field_type_extension.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
@ -94,39 +94,30 @@ class FieldOptionValues {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<FieldOptionValues?> get({
|
||||
required String viewId,
|
||||
required String fieldId,
|
||||
required FieldType fieldType,
|
||||
}) async {
|
||||
final service = FieldBackendService(viewId: viewId, fieldId: fieldId);
|
||||
final result = await service.getFieldTypeOptionData(fieldType: fieldType);
|
||||
return result.fold(
|
||||
(option) {
|
||||
final type = option.field_2.fieldType;
|
||||
final buffer = option.typeOptionData;
|
||||
return FieldOptionValues(
|
||||
type: type,
|
||||
name: option.field_2.name,
|
||||
numberFormat: type == FieldType.Number
|
||||
? NumberTypeOptionPB.fromBuffer(buffer).format
|
||||
: null,
|
||||
dateFormate: type == FieldType.DateTime
|
||||
? DateTypeOptionPB.fromBuffer(buffer).dateFormat
|
||||
: null,
|
||||
timeFormat: type == FieldType.DateTime
|
||||
? DateTypeOptionPB.fromBuffer(buffer).timeFormat
|
||||
: null,
|
||||
selectOption: switch (type) {
|
||||
FieldType.SingleSelect =>
|
||||
SingleSelectTypeOptionPB.fromBuffer(buffer).options,
|
||||
FieldType.MultiSelect =>
|
||||
MultiSelectTypeOptionPB.fromBuffer(buffer).options,
|
||||
_ => [],
|
||||
},
|
||||
);
|
||||
factory FieldOptionValues.fromField({
|
||||
required FieldPB field,
|
||||
}) {
|
||||
final fieldType = field.fieldType;
|
||||
final buffer = field.typeOptionData;
|
||||
return FieldOptionValues(
|
||||
type: fieldType,
|
||||
name: field.name,
|
||||
numberFormat: fieldType == FieldType.Number
|
||||
? NumberTypeOptionPB.fromBuffer(buffer).format
|
||||
: null,
|
||||
dateFormate: fieldType == FieldType.DateTime
|
||||
? DateTypeOptionPB.fromBuffer(buffer).dateFormat
|
||||
: null,
|
||||
timeFormat: fieldType == FieldType.DateTime
|
||||
? DateTypeOptionPB.fromBuffer(buffer).timeFormat
|
||||
: null,
|
||||
selectOption: switch (fieldType) {
|
||||
FieldType.SingleSelect =>
|
||||
SingleSelectTypeOptionPB.fromBuffer(buffer).options,
|
||||
FieldType.MultiSelect =>
|
||||
MultiSelectTypeOptionPB.fromBuffer(buffer).options,
|
||||
_ => [],
|
||||
},
|
||||
(error) => null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user