mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-08 12:07:54 -06:00
WIP - Refactoring date range picker dialog
This commit is contained in:
@@ -0,0 +1,158 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
|
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/widgets/form_builder_fields/form_builder_relative_date_range_field.dart';
|
||||||
|
import 'package:paperless_mobile/generated/l10n.dart';
|
||||||
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
|
|
||||||
|
class ExtendedDateRangeDialog extends StatefulWidget {
|
||||||
|
final DateRangeQuery initialValue;
|
||||||
|
final String Function(DateRangeQuery query) stringTransformer;
|
||||||
|
const ExtendedDateRangeDialog({
|
||||||
|
super.key,
|
||||||
|
required this.initialValue,
|
||||||
|
required this.stringTransformer,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ExtendedDateRangeDialog> createState() =>
|
||||||
|
_ExtendedDateRangeDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExtendedDateRangeDialogState extends State<ExtendedDateRangeDialog> {
|
||||||
|
static const String _fkAbsoluteBefore = 'absoluteBefore';
|
||||||
|
static const String _fkAbsoluteAfter = 'absoluteAfter';
|
||||||
|
static const String _fkRelative = 'relative';
|
||||||
|
|
||||||
|
final _formKey = GlobalKey<FormBuilderState>();
|
||||||
|
late DateRangeType _selectedDateRangeType;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedDateRangeType = (widget.initialValue is RelativeDateRangeQuery)
|
||||||
|
? DateRangeType.relative
|
||||||
|
: DateRangeType.absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text("Select date range"),
|
||||||
|
content: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Hint: You can either specify absolute values by selecting concrete dates, or you can specify a time range relative to today.",
|
||||||
|
style: Theme.of(context).textTheme.caption,
|
||||||
|
),
|
||||||
|
_buildDateRangeQueryTypeSelection(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
switch (_selectedDateRangeType) {
|
||||||
|
case DateRangeType.absolute:
|
||||||
|
return _buildAbsoluteDateRangeForm();
|
||||||
|
case DateRangeType.relative:
|
||||||
|
return FormBuilderRelativeDateRangePicker(
|
||||||
|
initialValue:
|
||||||
|
widget.initialValue is RelativeDateRangeQuery
|
||||||
|
? widget.initialValue as RelativeDateRangeQuery
|
||||||
|
: const RelativeDateRangeQuery(
|
||||||
|
1,
|
||||||
|
DateRangeUnit.month,
|
||||||
|
),
|
||||||
|
name: _fkRelative,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text(S.of(context).genericActionCancelLabel),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: Text(S.of(context).genericActionSaveLabel),
|
||||||
|
onPressed: () {
|
||||||
|
_formKey.currentState?.save();
|
||||||
|
if (_formKey.currentState?.validate() ?? false) {
|
||||||
|
final values = _formKey.currentState!.value;
|
||||||
|
final query = _buildQuery(values);
|
||||||
|
Navigator.pop(context, query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDateRangeQueryTypeSelection() {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
ChoiceChip(
|
||||||
|
label: Text('Absolute'),
|
||||||
|
selected: _selectedDateRangeType == DateRangeType.absolute,
|
||||||
|
onSelected: (value) =>
|
||||||
|
setState(() => _selectedDateRangeType = DateRangeType.absolute),
|
||||||
|
).paddedOnly(right: 8.0),
|
||||||
|
ChoiceChip(
|
||||||
|
label: Text('Relative'),
|
||||||
|
selected: _selectedDateRangeType == DateRangeType.relative,
|
||||||
|
onSelected: (value) =>
|
||||||
|
setState(() => _selectedDateRangeType = DateRangeType.relative),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAbsoluteDateRangeForm() {
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
FormBuilderDateTimePicker(
|
||||||
|
name: _fkAbsoluteAfter,
|
||||||
|
initialDate: widget.initialValue is AbsoluteDateRangeQuery
|
||||||
|
? (widget.initialValue as AbsoluteDateRangeQuery).after
|
||||||
|
: null,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: S.of(context).extendedDateRangePickerAfterLabel,
|
||||||
|
),
|
||||||
|
inputType: InputType.date,
|
||||||
|
),
|
||||||
|
FormBuilderDateTimePicker(
|
||||||
|
name: _fkAbsoluteBefore,
|
||||||
|
initialDate: widget.initialValue is AbsoluteDateRangeQuery
|
||||||
|
? (widget.initialValue as AbsoluteDateRangeQuery).before
|
||||||
|
: null,
|
||||||
|
inputType: InputType.date,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: S.of(context).extendedDateRangePickerBeforeLabel,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateRangeQuery? _buildQuery(Map<String, dynamic> values) {
|
||||||
|
if (_selectedDateRangeType == DateRangeType.absolute) {
|
||||||
|
return AbsoluteDateRangeQuery(
|
||||||
|
after: values[_fkAbsoluteAfter],
|
||||||
|
before: values[_fkAbsoluteBefore],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return values[_fkRelative] as RelativeDateRangeQuery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DateRangeType {
|
||||||
|
absolute,
|
||||||
|
relative;
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/widgets/form_builder_fields/extended_date_range_dialog.dart';
|
||||||
|
import 'package:paperless_mobile/generated/l10n.dart';
|
||||||
|
|
||||||
|
class FormBuilderExtendedDateRangePicker extends StatefulWidget {
|
||||||
|
final String name;
|
||||||
|
final String labelText;
|
||||||
|
final DateRangeQuery initialValue;
|
||||||
|
|
||||||
|
const FormBuilderExtendedDateRangePicker({
|
||||||
|
super.key,
|
||||||
|
required this.name,
|
||||||
|
required this.labelText,
|
||||||
|
required this.initialValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<FormBuilderExtendedDateRangePicker> createState() =>
|
||||||
|
_FormBuilderExtendedDateRangePickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FormBuilderExtendedDateRangePickerState
|
||||||
|
extends State<FormBuilderExtendedDateRangePicker> {
|
||||||
|
late final TextEditingController _textEditingController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_textEditingController = TextEditingController(
|
||||||
|
text: _dateRangeQueryToString(widget.initialValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FormBuilderField<DateRangeQuery>(
|
||||||
|
name: widget.name,
|
||||||
|
initialValue: widget.initialValue,
|
||||||
|
onChanged: (query) {
|
||||||
|
_textEditingController.text =
|
||||||
|
_dateRangeQueryToString(query ?? const UnsetDateRangeQuery());
|
||||||
|
},
|
||||||
|
builder: (field) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
controller: _textEditingController,
|
||||||
|
readOnly: true,
|
||||||
|
onTap: () => _showExtendedDateRangePicker(field),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: const Icon(Icons.date_range),
|
||||||
|
labelText: widget.labelText,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildExtendedQueryOptions(field),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildExtendedQueryOptions(FormFieldState<DateRangeQuery> field) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 64,
|
||||||
|
child: ListView.separated(
|
||||||
|
itemCount: _options.length,
|
||||||
|
separatorBuilder: (context, index) => const SizedBox(width: 8.0),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final option = _options[index];
|
||||||
|
return FilterChip(
|
||||||
|
label: Text(option.title),
|
||||||
|
onSelected: (isSelected) => isSelected
|
||||||
|
? field.didChange(option.value)
|
||||||
|
: field.didChange(const UnsetDateRangeQuery()),
|
||||||
|
selected: field.value == option.value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<_ExtendedDateRangeQueryOption> get _options => [
|
||||||
|
_ExtendedDateRangeQueryOption(
|
||||||
|
S.of(context).extendedDateRangePickerLastWeeksLabel(1),
|
||||||
|
const RelativeDateRangeQuery(1, DateRangeUnit.week),
|
||||||
|
),
|
||||||
|
_ExtendedDateRangeQueryOption(
|
||||||
|
S.of(context).extendedDateRangePickerLastMonthsLabel(1),
|
||||||
|
const RelativeDateRangeQuery(1, DateRangeUnit.month),
|
||||||
|
),
|
||||||
|
_ExtendedDateRangeQueryOption(
|
||||||
|
S.of(context).extendedDateRangePickerLastMonthsLabel(3),
|
||||||
|
const RelativeDateRangeQuery(3, DateRangeUnit.month),
|
||||||
|
),
|
||||||
|
_ExtendedDateRangeQueryOption(
|
||||||
|
S.of(context).extendedDateRangePickerLastYearsLabel(1),
|
||||||
|
const RelativeDateRangeQuery(1, DateRangeUnit.year),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
String _dateRangeQueryToString(DateRangeQuery query) {
|
||||||
|
if (query is UnsetDateRangeQuery) {
|
||||||
|
return '';
|
||||||
|
} else if (query is AbsoluteDateRangeQuery) {
|
||||||
|
if (query.before != null && query.after != null) {
|
||||||
|
return '${DateFormat.yMd(query.after)} – ${DateFormat.yMd(query.before)}';
|
||||||
|
}
|
||||||
|
if (query.before != null) {
|
||||||
|
return '${S.of(context).extendedDateRangePickerBeforeLabel} ${DateFormat.yMd(query.before)}';
|
||||||
|
}
|
||||||
|
if (query.after != null) {
|
||||||
|
return '${S.of(context).extendedDateRangePickerAfterLabel} ${DateFormat.yMd(query.after)}';
|
||||||
|
}
|
||||||
|
} else if (query is RelativeDateRangeQuery) {
|
||||||
|
switch (query.unit) {
|
||||||
|
case DateRangeUnit.day:
|
||||||
|
return S
|
||||||
|
.of(context)
|
||||||
|
.extendedDateRangePickerLastDaysLabel(query.offset);
|
||||||
|
case DateRangeUnit.week:
|
||||||
|
return S
|
||||||
|
.of(context)
|
||||||
|
.extendedDateRangePickerLastWeeksLabel(query.offset);
|
||||||
|
case DateRangeUnit.month:
|
||||||
|
return S
|
||||||
|
.of(context)
|
||||||
|
.extendedDateRangePickerLastMonthsLabel(query.offset);
|
||||||
|
case DateRangeUnit.year:
|
||||||
|
return S
|
||||||
|
.of(context)
|
||||||
|
.extendedDateRangePickerLastYearsLabel(query.offset);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showExtendedDateRangePicker(
|
||||||
|
FormFieldState<DateRangeQuery> field,
|
||||||
|
) async {
|
||||||
|
final query = await showDialog<DateRangeQuery>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => ExtendedDateRangeDialog(
|
||||||
|
initialValue: field.value!,
|
||||||
|
stringTransformer: _dateRangeQueryToString,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (query != null) {
|
||||||
|
field.didChange(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExtendedDateRangeQueryOption {
|
||||||
|
final String title;
|
||||||
|
final RelativeDateRangeQuery value;
|
||||||
|
|
||||||
|
_ExtendedDateRangeQueryOption(this.title, this.value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
|
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/generated/l10n.dart';
|
||||||
|
|
||||||
|
class FormBuilderRelativeDateRangePicker extends StatefulWidget {
|
||||||
|
final String name;
|
||||||
|
final RelativeDateRangeQuery initialValue;
|
||||||
|
const FormBuilderRelativeDateRangePicker({
|
||||||
|
super.key,
|
||||||
|
required this.name,
|
||||||
|
required this.initialValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<FormBuilderRelativeDateRangePicker> createState() =>
|
||||||
|
_FormBuilderRelativeDateRangePickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FormBuilderRelativeDateRangePickerState
|
||||||
|
extends State<FormBuilderRelativeDateRangePicker> {
|
||||||
|
late int _offset;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_offset = widget.initialValue.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FormBuilderField<RelativeDateRangeQuery>(
|
||||||
|
name: widget.name,
|
||||||
|
initialValue: widget.initialValue,
|
||||||
|
builder: (field) => Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text("Last"),
|
||||||
|
SizedBox(
|
||||||
|
width: 70,
|
||||||
|
child: TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Offset",
|
||||||
|
),
|
||||||
|
initialValue: widget.initialValue.offset.toString(),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp(r"[1-9][0-9]*"))
|
||||||
|
],
|
||||||
|
validator: FormBuilderValidators.numeric(),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
onChanged: (value) {
|
||||||
|
final parsed = int.parse(value);
|
||||||
|
setState(() {
|
||||||
|
_offset = parsed;
|
||||||
|
});
|
||||||
|
field.didChange(field.value!.copyWith(offset: parsed));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 120,
|
||||||
|
child: DropdownButtonFormField<DateRangeUnit?>(
|
||||||
|
value: field.value?.unit,
|
||||||
|
items: DateRangeUnit.values
|
||||||
|
.map(
|
||||||
|
(unit) => DropdownMenuItem(
|
||||||
|
child: Text(
|
||||||
|
_dateRangeUnitToLocalizedString(
|
||||||
|
unit,
|
||||||
|
_offset,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
value: unit,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
onChanged: (value) =>
|
||||||
|
field.didChange(field.value!.copyWith(unit: value)),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Amount",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _dateRangeUnitToLocalizedString(DateRangeUnit unit, int? count) {
|
||||||
|
switch (unit) {
|
||||||
|
case DateRangeUnit.day:
|
||||||
|
return S.of(context).extendedDateRangePickerDayText(count ?? 1);
|
||||||
|
case DateRangeUnit.week:
|
||||||
|
return S.of(context).extendedDateRangePickerWeekText(count ?? 1);
|
||||||
|
case DateRangeUnit.month:
|
||||||
|
return S.of(context).extendedDateRangePickerMonthText(count ?? 1);
|
||||||
|
case DateRangeUnit.year:
|
||||||
|
return S.of(context).extendedDateRangePickerYearText(count ?? 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -162,7 +162,7 @@ class _DocumentUploadPreparationPageState
|
|||||||
S.of(context).documentCreatedPropertyLabel + " *",
|
S.of(context).documentCreatedPropertyLabel + " *",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
LabelFormField<DocumentType, DocumentTypeQuery>(
|
LabelFormField<DocumentType>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialName) =>
|
labelCreationWidgetBuilder: (initialName) =>
|
||||||
@@ -172,15 +172,13 @@ class _DocumentUploadPreparationPageState
|
|||||||
),
|
),
|
||||||
child: AddDocumentTypePage(initialName: initialName),
|
child: AddDocumentTypePage(initialName: initialName),
|
||||||
),
|
),
|
||||||
label: S.of(context).documentDocumentTypePropertyLabel + " *",
|
textFieldLabel:
|
||||||
|
S.of(context).documentDocumentTypePropertyLabel + " *",
|
||||||
name: DocumentModel.documentTypeKey,
|
name: DocumentModel.documentTypeKey,
|
||||||
state: state.documentTypes,
|
labelOptions: state.documentTypes,
|
||||||
queryParameterIdBuilder: DocumentTypeQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder:
|
|
||||||
DocumentTypeQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.description_outlined),
|
prefixIcon: const Icon(Icons.description_outlined),
|
||||||
),
|
),
|
||||||
LabelFormField<Correspondent, CorrespondentQuery>(
|
LabelFormField<Correspondent>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialName) =>
|
labelCreationWidgetBuilder: (initialName) =>
|
||||||
@@ -191,13 +189,10 @@ class _DocumentUploadPreparationPageState
|
|||||||
),
|
),
|
||||||
child: AddCorrespondentPage(initialName: initialName),
|
child: AddCorrespondentPage(initialName: initialName),
|
||||||
),
|
),
|
||||||
label:
|
textFieldLabel:
|
||||||
S.of(context).documentCorrespondentPropertyLabel + " *",
|
S.of(context).documentCorrespondentPropertyLabel + " *",
|
||||||
name: DocumentModel.correspondentKey,
|
name: DocumentModel.correspondentKey,
|
||||||
state: state.correspondents,
|
labelOptions: state.correspondents,
|
||||||
queryParameterIdBuilder: CorrespondentQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder:
|
|
||||||
CorrespondentQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.person_outline),
|
prefixIcon: const Icon(Icons.person_outline),
|
||||||
),
|
),
|
||||||
TagFormField(
|
TagFormField(
|
||||||
|
|||||||
@@ -96,26 +96,24 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
|
|
||||||
Widget _buildStoragePathFormField(
|
Widget _buildStoragePathFormField(
|
||||||
int? initialId, Map<int, StoragePath> options) {
|
int? initialId, Map<int, StoragePath> options) {
|
||||||
return LabelFormField<StoragePath, StoragePathQuery>(
|
return LabelFormField<StoragePath>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider.value(
|
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider.value(
|
||||||
value: RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
value: RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
||||||
child: AddStoragePathPage(initalValue: initialValue),
|
child: AddStoragePathPage(initalValue: initialValue),
|
||||||
),
|
),
|
||||||
label: S.of(context).documentStoragePathPropertyLabel,
|
textFieldLabel: S.of(context).documentStoragePathPropertyLabel,
|
||||||
state: options,
|
labelOptions: options,
|
||||||
initialValue: StoragePathQuery.fromId(initialId),
|
initialValue: IdQueryParameter.fromId(initialId),
|
||||||
name: fkStoragePath,
|
name: fkStoragePath,
|
||||||
queryParameterIdBuilder: StoragePathQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder: StoragePathQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.folder_outlined),
|
prefixIcon: const Icon(Icons.folder_outlined),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCorrespondentFormField(
|
Widget _buildCorrespondentFormField(
|
||||||
int? initialId, Map<int, Correspondent> options) {
|
int? initialId, Map<int, Correspondent> options) {
|
||||||
return LabelFormField<Correspondent, CorrespondentQuery>(
|
return LabelFormField<Correspondent>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider.value(
|
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider.value(
|
||||||
@@ -124,19 +122,17 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
),
|
),
|
||||||
child: AddCorrespondentPage(initialName: initialValue),
|
child: AddCorrespondentPage(initialName: initialValue),
|
||||||
),
|
),
|
||||||
label: S.of(context).documentCorrespondentPropertyLabel,
|
textFieldLabel: S.of(context).documentCorrespondentPropertyLabel,
|
||||||
state: options,
|
labelOptions: options,
|
||||||
initialValue: CorrespondentQuery.fromId(initialId),
|
initialValue: IdQueryParameter.fromId(initialId),
|
||||||
name: fkCorrespondent,
|
name: fkCorrespondent,
|
||||||
queryParameterIdBuilder: CorrespondentQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder: CorrespondentQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.person_outlined),
|
prefixIcon: const Icon(Icons.person_outlined),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDocumentTypeFormField(
|
Widget _buildDocumentTypeFormField(
|
||||||
int? initialId, Map<int, DocumentType> options) {
|
int? initialId, Map<int, DocumentType> options) {
|
||||||
return LabelFormField<DocumentType, DocumentTypeQuery>(
|
return LabelFormField<DocumentType>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (currentInput) => RepositoryProvider.value(
|
labelCreationWidgetBuilder: (currentInput) => RepositoryProvider.value(
|
||||||
@@ -147,12 +143,10 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
initialName: currentInput,
|
initialName: currentInput,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
label: S.of(context).documentDocumentTypePropertyLabel,
|
textFieldLabel: S.of(context).documentDocumentTypePropertyLabel,
|
||||||
initialValue: DocumentTypeQuery.fromId(initialId),
|
initialValue: IdQueryParameter.fromId(initialId),
|
||||||
state: options,
|
labelOptions: options,
|
||||||
name: fkDocumentType,
|
name: fkDocumentType,
|
||||||
queryParameterIdBuilder: DocumentTypeQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder: DocumentTypeQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.description_outlined),
|
prefixIcon: const Icon(Icons.description_outlined),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
expand: false,
|
expand: false,
|
||||||
snap: true,
|
snap: true,
|
||||||
initialChildSize: .9,
|
initialChildSize: .9,
|
||||||
|
maxChildSize: .9,
|
||||||
builder: (context, controller) => LabelsBlocProvider(
|
builder: (context, controller) => LabelsBlocProvider(
|
||||||
child: DocumentFilterPanel(
|
child: DocumentFilterPanel(
|
||||||
initialFilter: _documentsCubit.state.filter,
|
initialFilter: _documentsCubit.state.filter,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/widgets/form_builder_fields/form_builder_extended_date_range_picker.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/search/query_type_form_field.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/search/query_type_form_field.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||||
@@ -95,8 +96,13 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
style: Theme.of(context).textTheme.caption,
|
style: Theme.of(context).textTheme.caption,
|
||||||
),
|
),
|
||||||
).padded(),
|
).padded(),
|
||||||
_buildCreatedDateRangePickerFormField(),
|
FormBuilderExtendedDateRangePicker(
|
||||||
_buildAddedDateRangePickerFormField(),
|
name: DocumentModel.createdKey,
|
||||||
|
initialValue: widget.initialFilter.created,
|
||||||
|
labelText: S.of(context).documentCreatedPropertyLabel,
|
||||||
|
).padded(),
|
||||||
|
// _buildCreatedDateRangePickerFormField(),
|
||||||
|
// _buildAddedDateRangePickerFormField(),
|
||||||
_buildCorrespondentFormField().padded(),
|
_buildCorrespondentFormField().padded(),
|
||||||
_buildDocumentTypeFormField().padded(),
|
_buildDocumentTypeFormField().padded(),
|
||||||
_buildStoragePathFormField().padded(),
|
_buildStoragePathFormField().padded(),
|
||||||
@@ -129,14 +135,12 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
Widget _buildDocumentTypeFormField() {
|
Widget _buildDocumentTypeFormField() {
|
||||||
return BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
return BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return LabelFormField<DocumentType, DocumentTypeQuery>(
|
return LabelFormField<DocumentType>(
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
name: fkDocumentType,
|
name: fkDocumentType,
|
||||||
state: state.labels,
|
labelOptions: state.labels,
|
||||||
label: S.of(context).documentDocumentTypePropertyLabel,
|
textFieldLabel: S.of(context).documentDocumentTypePropertyLabel,
|
||||||
initialValue: widget.initialFilter.documentType,
|
initialValue: widget.initialFilter.documentType,
|
||||||
queryParameterIdBuilder: DocumentTypeQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder: DocumentTypeQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.description_outlined),
|
prefixIcon: const Icon(Icons.description_outlined),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -146,14 +150,12 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
Widget _buildCorrespondentFormField() {
|
Widget _buildCorrespondentFormField() {
|
||||||
return BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
|
return BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return LabelFormField<Correspondent, CorrespondentQuery>(
|
return LabelFormField<Correspondent>(
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
name: fkCorrespondent,
|
name: fkCorrespondent,
|
||||||
state: state.labels,
|
labelOptions: state.labels,
|
||||||
label: S.of(context).documentCorrespondentPropertyLabel,
|
textFieldLabel: S.of(context).documentCorrespondentPropertyLabel,
|
||||||
initialValue: widget.initialFilter.correspondent,
|
initialValue: widget.initialFilter.correspondent,
|
||||||
queryParameterIdBuilder: CorrespondentQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder: CorrespondentQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.person_outline),
|
prefixIcon: const Icon(Icons.person_outline),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -163,14 +165,12 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
Widget _buildStoragePathFormField() {
|
Widget _buildStoragePathFormField() {
|
||||||
return BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
return BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return LabelFormField<StoragePath, StoragePathQuery>(
|
return LabelFormField<StoragePath>(
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
name: fkStoragePath,
|
name: fkStoragePath,
|
||||||
state: state.labels,
|
labelOptions: state.labels,
|
||||||
label: S.of(context).documentStoragePathPropertyLabel,
|
textFieldLabel: S.of(context).documentStoragePathPropertyLabel,
|
||||||
initialValue: widget.initialFilter.storagePath,
|
initialValue: widget.initialFilter.storagePath,
|
||||||
queryParameterIdBuilder: StoragePathQuery.fromId,
|
|
||||||
queryParameterNotAssignedBuilder: StoragePathQuery.notAssigned,
|
|
||||||
prefixIcon: const Icon(Icons.folder_outlined),
|
prefixIcon: const Icon(Icons.folder_outlined),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -209,187 +209,99 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDateRangePickerHelper(String formFieldKey) {
|
// Widget _buildCreatedDateRangePickerFormField() {
|
||||||
const spacer = SizedBox(width: 8.0);
|
// return Column(
|
||||||
return SizedBox(
|
// children: [
|
||||||
height: 64,
|
// FormBuilderDateRangePicker(
|
||||||
child: ListView(
|
// initialValue: _dateTimeRangeOfNullable(
|
||||||
scrollDirection: Axis.horizontal,
|
// widget.initialFilter.createdDateAfter,
|
||||||
children: [
|
// widget.initialFilter.createdDateBefore,
|
||||||
spacer,
|
// ),
|
||||||
ActionChip(
|
// // Workaround for theme data not being correctly passed to daterangepicker, see
|
||||||
label: Text(
|
// // https://github.com/flutter/flutter/issues/87580
|
||||||
S.of(context).documentFilterDateRangeLastSevenDaysLabel,
|
// pickerBuilder: (context, Widget? child) => Theme(
|
||||||
),
|
// data: Theme.of(context).copyWith(
|
||||||
onPressed: () {
|
// dialogBackgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
_formKey.currentState?.fields[formFieldKey]?.didChange(
|
// appBarTheme: Theme.of(context).appBarTheme.copyWith(
|
||||||
DateTimeRange(
|
// iconTheme:
|
||||||
start: DateUtils.addDaysToDate(DateTime.now(), -7),
|
// IconThemeData(color: Theme.of(context).primaryColor),
|
||||||
end: DateTime.now(),
|
// ),
|
||||||
),
|
// colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||||
);
|
// onPrimary: Theme.of(context).primaryColor,
|
||||||
},
|
// primary: Theme.of(context).colorScheme.primary,
|
||||||
),
|
// ),
|
||||||
spacer,
|
// ),
|
||||||
ActionChip(
|
// child: child!,
|
||||||
label: Text(
|
// ),
|
||||||
S.of(context).documentFilterDateRangeLastMonthLabel,
|
// format: DateFormat.yMMMd(Localizations.localeOf(context).toString()),
|
||||||
),
|
// fieldStartLabelText:
|
||||||
onPressed: () {
|
// S.of(context).documentFilterDateRangeFieldStartLabel,
|
||||||
final now = DateTime.now();
|
// fieldEndLabelText: S.of(context).documentFilterDateRangeFieldEndLabel,
|
||||||
final firstDayOfLastMonth =
|
// firstDate: DateTime.fromMicrosecondsSinceEpoch(0),
|
||||||
DateUtils.addMonthsToMonthDate(now, -1);
|
// lastDate: DateTime.now(),
|
||||||
_formKey.currentState?.fields[formFieldKey]?.didChange(
|
// name: fkCreatedAt,
|
||||||
DateTimeRange(
|
// decoration: InputDecoration(
|
||||||
start: DateTime(firstDayOfLastMonth.year,
|
// prefixIcon: const Icon(Icons.calendar_month_outlined),
|
||||||
firstDayOfLastMonth.month, now.day),
|
// labelText: S.of(context).documentCreatedPropertyLabel,
|
||||||
end: DateTime.now(),
|
// suffixIcon: IconButton(
|
||||||
),
|
// icon: const Icon(Icons.clear),
|
||||||
);
|
// onPressed: () {
|
||||||
},
|
// _formKey.currentState?.fields[fkCreatedAt]?.didChange(null);
|
||||||
),
|
// },
|
||||||
spacer,
|
// ),
|
||||||
ActionChip(
|
// ),
|
||||||
label: Text(
|
// ).paddedSymmetrically(horizontal: 8, vertical: 4.0),
|
||||||
S.of(context).documentFilterDateRangeLastThreeMonthsLabel,
|
// ],
|
||||||
),
|
// );
|
||||||
onPressed: () {
|
// }
|
||||||
final now = DateTime.now();
|
|
||||||
final firstDayOfLastMonth =
|
|
||||||
DateUtils.addMonthsToMonthDate(now, -3);
|
|
||||||
_formKey.currentState?.fields[formFieldKey]?.didChange(
|
|
||||||
DateTimeRange(
|
|
||||||
start: DateTime(
|
|
||||||
firstDayOfLastMonth.year,
|
|
||||||
firstDayOfLastMonth.month,
|
|
||||||
now.day,
|
|
||||||
),
|
|
||||||
end: DateTime.now(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
spacer,
|
|
||||||
ActionChip(
|
|
||||||
label: Text(
|
|
||||||
S.of(context).documentFilterDateRangeLastYearLabel,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
final now = DateTime.now();
|
|
||||||
final firstDayOfLastMonth =
|
|
||||||
DateUtils.addMonthsToMonthDate(now, -12);
|
|
||||||
_formKey.currentState?.fields[formFieldKey]?.didChange(
|
|
||||||
DateTimeRange(
|
|
||||||
start: DateTime(
|
|
||||||
firstDayOfLastMonth.year,
|
|
||||||
firstDayOfLastMonth.month,
|
|
||||||
now.day,
|
|
||||||
),
|
|
||||||
end: DateTime.now(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
spacer,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildCreatedDateRangePickerFormField() {
|
// Widget _buildAddedDateRangePickerFormField() {
|
||||||
return Column(
|
// return Column(
|
||||||
children: [
|
// children: [
|
||||||
FormBuilderDateRangePicker(
|
// FormBuilderDateRangePicker(
|
||||||
initialValue: _dateTimeRangeOfNullable(
|
// initialValue: _dateTimeRangeOfNullable(
|
||||||
widget.initialFilter.createdDateAfter,
|
// widget.initialFilter.addedDateAfter,
|
||||||
widget.initialFilter.createdDateBefore,
|
// widget.initialFilter.addedDateBefore,
|
||||||
),
|
// ),
|
||||||
// Workaround for theme data not being correctly passed to daterangepicker, see
|
// // Workaround for theme data not being correctly passed to daterangepicker, see
|
||||||
// https://github.com/flutter/flutter/issues/87580
|
// // https://github.com/flutter/flutter/issues/87580
|
||||||
pickerBuilder: (context, Widget? child) => Theme(
|
// pickerBuilder: (context, Widget? child) => Theme(
|
||||||
data: Theme.of(context).copyWith(
|
// data: Theme.of(context).copyWith(
|
||||||
dialogBackgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
// dialogBackgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
appBarTheme: Theme.of(context).appBarTheme.copyWith(
|
// appBarTheme: Theme.of(context).appBarTheme.copyWith(
|
||||||
iconTheme:
|
// iconTheme:
|
||||||
IconThemeData(color: Theme.of(context).primaryColor),
|
// IconThemeData(color: Theme.of(context).primaryColor),
|
||||||
),
|
// ),
|
||||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
// colorScheme: Theme.of(context).colorScheme.copyWith(
|
||||||
onPrimary: Theme.of(context).primaryColor,
|
// onPrimary: Theme.of(context).primaryColor,
|
||||||
primary: Theme.of(context).colorScheme.primary,
|
// primary: Theme.of(context).colorScheme.primary,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
child: child!,
|
// child: child!,
|
||||||
),
|
// ),
|
||||||
format: DateFormat.yMMMd(Localizations.localeOf(context).toString()),
|
// format: DateFormat.yMMMd(),
|
||||||
fieldStartLabelText:
|
// fieldStartLabelText:
|
||||||
S.of(context).documentFilterDateRangeFieldStartLabel,
|
// S.of(context).documentFilterDateRangeFieldStartLabel,
|
||||||
fieldEndLabelText: S.of(context).documentFilterDateRangeFieldEndLabel,
|
// fieldEndLabelText: S.of(context).documentFilterDateRangeFieldEndLabel,
|
||||||
firstDate: DateTime.fromMicrosecondsSinceEpoch(0),
|
// firstDate: DateTime.fromMicrosecondsSinceEpoch(0),
|
||||||
lastDate: DateTime.now(),
|
// lastDate: DateTime.now(),
|
||||||
name: fkCreatedAt,
|
// name: fkAddedAt,
|
||||||
decoration: InputDecoration(
|
// decoration: InputDecoration(
|
||||||
prefixIcon: const Icon(Icons.calendar_month_outlined),
|
// prefixIcon: const Icon(Icons.calendar_month_outlined),
|
||||||
labelText: S.of(context).documentCreatedPropertyLabel,
|
// labelText: S.of(context).documentAddedPropertyLabel,
|
||||||
suffixIcon: IconButton(
|
// suffixIcon: IconButton(
|
||||||
icon: const Icon(Icons.clear),
|
// icon: const Icon(Icons.clear),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
_formKey.currentState?.fields[fkCreatedAt]?.didChange(null);
|
// _formKey.currentState?.fields[fkAddedAt]?.didChange(null);
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
).paddedSymmetrically(horizontal: 8, vertical: 4.0),
|
// ).paddedSymmetrically(horizontal: 8),
|
||||||
_buildDateRangePickerHelper(fkCreatedAt),
|
// const SizedBox(height: 4.0),
|
||||||
],
|
// _buildDateRangePickerHelper(fkAddedAt),
|
||||||
);
|
// ],
|
||||||
}
|
// );
|
||||||
|
// }
|
||||||
Widget _buildAddedDateRangePickerFormField() {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
FormBuilderDateRangePicker(
|
|
||||||
initialValue: _dateTimeRangeOfNullable(
|
|
||||||
widget.initialFilter.addedDateAfter,
|
|
||||||
widget.initialFilter.addedDateBefore,
|
|
||||||
),
|
|
||||||
// Workaround for theme data not being correctly passed to daterangepicker, see
|
|
||||||
// https://github.com/flutter/flutter/issues/87580
|
|
||||||
pickerBuilder: (context, Widget? child) => Theme(
|
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
dialogBackgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
appBarTheme: Theme.of(context).appBarTheme.copyWith(
|
|
||||||
iconTheme:
|
|
||||||
IconThemeData(color: Theme.of(context).primaryColor),
|
|
||||||
),
|
|
||||||
colorScheme: Theme.of(context).colorScheme.copyWith(
|
|
||||||
onPrimary: Theme.of(context).primaryColor,
|
|
||||||
primary: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: child!,
|
|
||||||
),
|
|
||||||
format: DateFormat.yMMMd(),
|
|
||||||
fieldStartLabelText:
|
|
||||||
S.of(context).documentFilterDateRangeFieldStartLabel,
|
|
||||||
fieldEndLabelText: S.of(context).documentFilterDateRangeFieldEndLabel,
|
|
||||||
firstDate: DateTime.fromMicrosecondsSinceEpoch(0),
|
|
||||||
lastDate: DateTime.now(),
|
|
||||||
name: fkAddedAt,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
prefixIcon: const Icon(Icons.calendar_month_outlined),
|
|
||||||
labelText: S.of(context).documentAddedPropertyLabel,
|
|
||||||
suffixIcon: IconButton(
|
|
||||||
icon: const Icon(Icons.clear),
|
|
||||||
onPressed: () {
|
|
||||||
_formKey.currentState?.fields[fkAddedAt]?.didChange(null);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).paddedSymmetrically(horizontal: 8),
|
|
||||||
const SizedBox(height: 4.0),
|
|
||||||
_buildDateRangePickerHelper(fkAddedAt),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onApplyFilter() async {
|
void _onApplyFilter() async {
|
||||||
_formKey.currentState?.save();
|
_formKey.currentState?.save();
|
||||||
@@ -408,19 +320,17 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
DocumentFilter _assembleFilter() {
|
DocumentFilter _assembleFilter() {
|
||||||
final v = _formKey.currentState!.value;
|
final v = _formKey.currentState!.value;
|
||||||
return DocumentFilter(
|
return DocumentFilter(
|
||||||
createdDateBefore: (v[fkCreatedAt] as DateTimeRange?)?.end,
|
created: (v[fkCreatedAt] as DateRangeQuery),
|
||||||
createdDateAfter: (v[fkCreatedAt] as DateTimeRange?)?.start,
|
correspondent: v[fkCorrespondent] as IdQueryParameter? ??
|
||||||
correspondent: v[fkCorrespondent] as CorrespondentQuery? ??
|
|
||||||
DocumentFilter.initial.correspondent,
|
DocumentFilter.initial.correspondent,
|
||||||
documentType: v[fkDocumentType] as DocumentTypeQuery? ??
|
documentType: v[fkDocumentType] as IdQueryParameter? ??
|
||||||
DocumentFilter.initial.documentType,
|
DocumentFilter.initial.documentType,
|
||||||
storagePath: v[fkStoragePath] as StoragePathQuery? ??
|
storagePath: v[fkStoragePath] as IdQueryParameter? ??
|
||||||
DocumentFilter.initial.storagePath,
|
DocumentFilter.initial.storagePath,
|
||||||
tags:
|
tags:
|
||||||
v[DocumentModel.tagsKey] as TagsQuery? ?? DocumentFilter.initial.tags,
|
v[DocumentModel.tagsKey] as TagsQuery? ?? DocumentFilter.initial.tags,
|
||||||
queryText: v[fkQuery] as String?,
|
queryText: v[fkQuery] as String?,
|
||||||
addedDateBefore: (v[fkAddedAt] as DateTimeRange?)?.end,
|
added: (v[fkAddedAt] as DateRangeQuery),
|
||||||
addedDateAfter: (v[fkAddedAt] as DateTimeRange?)?.start,
|
|
||||||
queryType: v[QueryTypeFormField.fkQueryType] as QueryType,
|
queryType: v[QueryTypeFormField.fkQueryType] as QueryType,
|
||||||
asnQuery: widget.initialFilter.asnQuery,
|
asnQuery: widget.initialFilter.asnQuery,
|
||||||
page: 1,
|
page: 1,
|
||||||
|
|||||||
@@ -52,12 +52,12 @@ class CorrespondentWidget extends StatelessWidget {
|
|||||||
if (cubit.state.filter.correspondent.id == correspondentId) {
|
if (cubit.state.filter.correspondent.id == correspondentId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.copyWith(correspondent: const CorrespondentQuery.unset()),
|
filter.copyWith(correspondent: const IdQueryParameter.unset()),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(
|
(filter) => filter.copyWith(
|
||||||
correspondent: CorrespondentQuery.fromId(correspondentId)),
|
correspondent: IdQueryParameter.fromId(correspondentId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
afterSelected?.call();
|
afterSelected?.call();
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ class DocumentTypeWidget extends StatelessWidget {
|
|||||||
if (cubit.state.filter.documentType.id == documentTypeId) {
|
if (cubit.state.filter.documentType.id == documentTypeId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.copyWith(documentType: const DocumentTypeQuery.unset()),
|
filter.copyWith(documentType: const IdQueryParameter.unset()),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(
|
(filter) => filter.copyWith(
|
||||||
documentType: DocumentTypeQuery.fromId(documentTypeId)),
|
documentType: IdQueryParameter.fromId(documentTypeId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
afterSelected?.call();
|
afterSelected?.call();
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ class StoragePathWidget extends StatelessWidget {
|
|||||||
if (cubit.state.filter.correspondent.id == pathId) {
|
if (cubit.state.filter.correspondent.id == pathId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.copyWith(storagePath: const StoragePathQuery.unset()),
|
filter.copyWith(storagePath: const IdQueryParameter.unset()),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.copyWith(storagePath: StoragePathQuery.fromId(pathId)),
|
filter.copyWith(storagePath: IdQueryParameter.fromId(pathId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
afterSelected?.call();
|
afterSelected?.call();
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
),
|
),
|
||||||
child: LabelTabView<Correspondent>(
|
child: LabelTabView<Correspondent>(
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
correspondent: CorrespondentQuery.fromId(label.id),
|
correspondent: IdQueryParameter.fromId(label.id),
|
||||||
pageSize: label.documentCount ?? 0,
|
pageSize: label.documentCount ?? 0,
|
||||||
),
|
),
|
||||||
onEdit: _openEditCorrespondentPage,
|
onEdit: _openEditCorrespondentPage,
|
||||||
@@ -146,7 +146,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
),
|
),
|
||||||
child: LabelTabView<DocumentType>(
|
child: LabelTabView<DocumentType>(
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
documentType: DocumentTypeQuery.fromId(label.id),
|
documentType: IdQueryParameter.fromId(label.id),
|
||||||
pageSize: label.documentCount ?? 0,
|
pageSize: label.documentCount ?? 0,
|
||||||
),
|
),
|
||||||
onEdit: _openEditDocumentTypePage,
|
onEdit: _openEditDocumentTypePage,
|
||||||
@@ -194,7 +194,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
child: LabelTabView<StoragePath>(
|
child: LabelTabView<StoragePath>(
|
||||||
onEdit: _openEditStoragePathPage,
|
onEdit: _openEditStoragePathPage,
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
storagePath: StoragePathQuery.fromId(label.id),
|
storagePath: IdQueryParameter.fromId(label.id),
|
||||||
pageSize: label.documentCount ?? 0,
|
pageSize: label.documentCount ?? 0,
|
||||||
),
|
),
|
||||||
contentBuilder: (path) => Text(path.path ?? ""),
|
contentBuilder: (path) => Text(path.path ?? ""),
|
||||||
|
|||||||
@@ -9,31 +9,26 @@ import 'package:paperless_mobile/generated/l10n.dart';
|
|||||||
/// Form field allowing to select labels (i.e. correspondent, documentType)
|
/// Form field allowing to select labels (i.e. correspondent, documentType)
|
||||||
/// [T] is the label type (e.g. [DocumentType], [Correspondent], ...), [R] is the return type (e.g. [CorrespondentQuery], ...).
|
/// [T] is the label type (e.g. [DocumentType], [Correspondent], ...), [R] is the return type (e.g. [CorrespondentQuery], ...).
|
||||||
///
|
///
|
||||||
class LabelFormField<T extends Label, R extends IdQueryParameter>
|
class LabelFormField<T extends Label> extends StatefulWidget {
|
||||||
extends StatefulWidget {
|
|
||||||
final Widget prefixIcon;
|
final Widget prefixIcon;
|
||||||
final Map<int, T> state;
|
final Map<int, T> labelOptions;
|
||||||
final FormBuilderState? formBuilderState;
|
final FormBuilderState? formBuilderState;
|
||||||
final IdQueryParameter? initialValue;
|
final IdQueryParameter? initialValue;
|
||||||
final String name;
|
final String name;
|
||||||
final String label;
|
final String textFieldLabel;
|
||||||
final FormFieldValidator? validator;
|
final FormFieldValidator? validator;
|
||||||
final Widget Function(String)? labelCreationWidgetBuilder;
|
final Widget Function(String initialName)? labelCreationWidgetBuilder;
|
||||||
final R Function() queryParameterNotAssignedBuilder;
|
|
||||||
final R Function(int? id) queryParameterIdBuilder;
|
|
||||||
final bool notAssignedSelectable;
|
final bool notAssignedSelectable;
|
||||||
final void Function(R?)? onChanged;
|
final void Function(IdQueryParameter?)? onChanged;
|
||||||
|
|
||||||
const LabelFormField({
|
const LabelFormField({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.state,
|
required this.labelOptions,
|
||||||
this.validator,
|
this.validator,
|
||||||
this.initialValue,
|
this.initialValue,
|
||||||
required this.label,
|
required this.textFieldLabel,
|
||||||
this.labelCreationWidgetBuilder,
|
this.labelCreationWidgetBuilder,
|
||||||
required this.queryParameterNotAssignedBuilder,
|
|
||||||
required this.queryParameterIdBuilder,
|
|
||||||
required this.formBuilderState,
|
required this.formBuilderState,
|
||||||
required this.prefixIcon,
|
required this.prefixIcon,
|
||||||
this.notAssignedSelectable = true,
|
this.notAssignedSelectable = true,
|
||||||
@@ -41,11 +36,10 @@ class LabelFormField<T extends Label, R extends IdQueryParameter>
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<LabelFormField<T, R>> createState() => _LabelFormFieldState<T, R>();
|
State<LabelFormField<T>> createState() => _LabelFormFieldState<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
class _LabelFormFieldState<T extends Label> extends State<LabelFormField<T>> {
|
||||||
extends State<LabelFormField<T, R>> {
|
|
||||||
bool _showCreationSuffixIcon = false;
|
bool _showCreationSuffixIcon = false;
|
||||||
late bool _showClearSuffixIcon;
|
late bool _showClearSuffixIcon;
|
||||||
|
|
||||||
@@ -54,12 +48,13 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_showClearSuffixIcon = widget.state.containsKey(widget.initialValue?.id);
|
_showClearSuffixIcon =
|
||||||
|
widget.labelOptions.containsKey(widget.initialValue?.id);
|
||||||
_textEditingController = TextEditingController(
|
_textEditingController = TextEditingController(
|
||||||
text: widget.state[widget.initialValue?.id]?.name ?? '',
|
text: widget.labelOptions[widget.initialValue?.id]?.name ?? '',
|
||||||
)..addListener(() {
|
)..addListener(() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_showCreationSuffixIcon = widget.state.values
|
_showCreationSuffixIcon = widget.labelOptions.values
|
||||||
.where(
|
.where(
|
||||||
(item) => item.name.toLowerCase().startsWith(
|
(item) => item.name.toLowerCase().startsWith(
|
||||||
_textEditingController.text.toLowerCase(),
|
_textEditingController.text.toLowerCase(),
|
||||||
@@ -74,7 +69,7 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isEnabled = widget.state.values.fold<bool>(
|
final isEnabled = widget.labelOptions.values.fold<bool>(
|
||||||
false,
|
false,
|
||||||
(previousValue, element) =>
|
(previousValue, element) =>
|
||||||
previousValue || (element.documentCount ?? 0) > 0) ||
|
previousValue || (element.documentCount ?? 0) > 0) ||
|
||||||
@@ -90,7 +85,7 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
TextStyle(color: Theme.of(context).disabledColor, fontSize: 18.0),
|
TextStyle(color: Theme.of(context).disabledColor, fontSize: 18.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
initialValue: widget.initialValue ?? widget.queryParameterIdBuilder(null),
|
initialValue: widget.initialValue ?? const IdQueryParameter.unset(),
|
||||||
name: widget.name,
|
name: widget.name,
|
||||||
suggestionsBoxDecoration: SuggestionsBoxDecoration(
|
suggestionsBoxDecoration: SuggestionsBoxDecoration(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@@ -103,7 +98,7 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
),
|
),
|
||||||
itemBuilder: (context, suggestion) => ListTile(
|
itemBuilder: (context, suggestion) => ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
widget.state[suggestion.id]?.name ??
|
widget.labelOptions[suggestion.id]?.name ??
|
||||||
S.of(context).labelNotAssignedText,
|
S.of(context).labelNotAssignedText,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
@@ -112,10 +107,10 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
style: ListTileStyle.list,
|
style: ListTileStyle.list,
|
||||||
),
|
),
|
||||||
suggestionsCallback: (pattern) {
|
suggestionsCallback: (pattern) {
|
||||||
final List<IdQueryParameter> suggestions = widget.state.entries
|
final List<IdQueryParameter> suggestions = widget.labelOptions.entries
|
||||||
.where(
|
.where(
|
||||||
(entry) =>
|
(entry) =>
|
||||||
widget.state[entry.key]!.name
|
widget.labelOptions[entry.key]!.name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.contains(pattern.toLowerCase()) ||
|
.contains(pattern.toLowerCase()) ||
|
||||||
pattern.isEmpty,
|
pattern.isEmpty,
|
||||||
@@ -125,34 +120,33 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
widget.labelCreationWidgetBuilder != null ||
|
widget.labelCreationWidgetBuilder != null ||
|
||||||
(entry.value.documentCount ?? 0) > 0,
|
(entry.value.documentCount ?? 0) > 0,
|
||||||
)
|
)
|
||||||
.map((entry) => widget.queryParameterIdBuilder(entry.key))
|
.map((entry) => IdQueryParameter.fromId(entry.key))
|
||||||
.toList();
|
.toList();
|
||||||
if (widget.notAssignedSelectable) {
|
if (widget.notAssignedSelectable) {
|
||||||
suggestions.insert(0, widget.queryParameterNotAssignedBuilder());
|
suggestions.insert(0, const IdQueryParameter.notAssigned());
|
||||||
}
|
}
|
||||||
return suggestions;
|
return suggestions;
|
||||||
},
|
},
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() => _showClearSuffixIcon = value?.isSet ?? false);
|
setState(() => _showClearSuffixIcon = value?.isSet ?? false);
|
||||||
widget.onChanged?.call(value as R);
|
widget.onChanged?.call(value);
|
||||||
},
|
},
|
||||||
controller: _textEditingController,
|
controller: _textEditingController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
prefixIcon: widget.prefixIcon,
|
prefixIcon: widget.prefixIcon,
|
||||||
label: Text(widget.label),
|
label: Text(widget.textFieldLabel),
|
||||||
hintText: _getLocalizedHint(context),
|
hintText: _getLocalizedHint(context),
|
||||||
suffixIcon: _buildSuffixIcon(context),
|
suffixIcon: _buildSuffixIcon(context),
|
||||||
),
|
),
|
||||||
selectionToTextTransformer: (suggestion) {
|
selectionToTextTransformer: (suggestion) {
|
||||||
if (suggestion == widget.queryParameterNotAssignedBuilder()) {
|
if (suggestion == const IdQueryParameter.notAssigned()) {
|
||||||
return S.of(context).labelNotAssignedText;
|
return S.of(context).labelNotAssignedText;
|
||||||
}
|
}
|
||||||
return widget.state[suggestion.id]?.name ?? "";
|
return widget.labelOptions[suggestion.id]?.name ?? "";
|
||||||
},
|
},
|
||||||
direction: AxisDirection.up,
|
direction: AxisDirection.up,
|
||||||
onSuggestionSelected: (suggestion) => widget
|
onSuggestionSelected: (suggestion) =>
|
||||||
.formBuilderState?.fields[widget.name]
|
widget.formBuilderState?.fields[widget.name]?.didChange(suggestion),
|
||||||
?.didChange(suggestion as R),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +155,7 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
final createdLabel = await showDialog(
|
final createdLabel = await showDialog<T>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => widget.labelCreationWidgetBuilder!(
|
builder: (context) => widget.labelCreationWidgetBuilder!(
|
||||||
_textEditingController.text,
|
_textEditingController.text,
|
||||||
@@ -170,7 +164,7 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
if (createdLabel != null) {
|
if (createdLabel != null) {
|
||||||
// If new label has been created, set form field value and text of this form field and unfocus keyboard (we assume user is done).
|
// If new label has been created, set form field value and text of this form field and unfocus keyboard (we assume user is done).
|
||||||
widget.formBuilderState?.fields[widget.name]
|
widget.formBuilderState?.fields[widget.name]
|
||||||
?.didChange(widget.queryParameterIdBuilder(createdLabel.id));
|
?.didChange(IdQueryParameter.fromId(createdLabel.id));
|
||||||
_textEditingController.text = createdLabel.name;
|
_textEditingController.text = createdLabel.name;
|
||||||
} else {
|
} else {
|
||||||
_reset();
|
_reset();
|
||||||
@@ -192,7 +186,7 @@ class _LabelFormFieldState<T extends Label, R extends IdQueryParameter>
|
|||||||
|
|
||||||
void _reset() {
|
void _reset() {
|
||||||
widget.formBuilderState?.fields[widget.name]?.didChange(
|
widget.formBuilderState?.fields[widget.name]?.didChange(
|
||||||
widget.queryParameterIdBuilder(null), // equivalnt to IdQueryParam.unset()
|
const IdQueryParameter.unset(),
|
||||||
);
|
);
|
||||||
_textEditingController.clear();
|
_textEditingController.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,18 +78,6 @@
|
|||||||
"@documentFilterAdvancedLabel": {},
|
"@documentFilterAdvancedLabel": {},
|
||||||
"documentFilterApplyFilterLabel": "Použít",
|
"documentFilterApplyFilterLabel": "Použít",
|
||||||
"@documentFilterApplyFilterLabel": {},
|
"@documentFilterApplyFilterLabel": {},
|
||||||
"documentFilterDateRangeFieldEndLabel": "Do",
|
|
||||||
"@documentFilterDateRangeFieldEndLabel": {},
|
|
||||||
"documentFilterDateRangeFieldStartLabel": "Od",
|
|
||||||
"@documentFilterDateRangeFieldStartLabel": {},
|
|
||||||
"documentFilterDateRangeLastMonthLabel": "Minulý měsíc",
|
|
||||||
"@documentFilterDateRangeLastMonthLabel": {},
|
|
||||||
"documentFilterDateRangeLastSevenDaysLabel": "Posledních 7 dní",
|
|
||||||
"@documentFilterDateRangeLastSevenDaysLabel": {},
|
|
||||||
"documentFilterDateRangeLastThreeMonthsLabel": "Poslední 3 měsíce",
|
|
||||||
"@documentFilterDateRangeLastThreeMonthsLabel": {},
|
|
||||||
"documentFilterDateRangeLastYearLabel": "Minulý rok",
|
|
||||||
"@documentFilterDateRangeLastYearLabel": {},
|
|
||||||
"documentFilterQueryOptionsAsnLabel": "ASČ",
|
"documentFilterQueryOptionsAsnLabel": "ASČ",
|
||||||
"@documentFilterQueryOptionsAsnLabel": {},
|
"@documentFilterQueryOptionsAsnLabel": {},
|
||||||
"documentFilterQueryOptionsExtendedLabel": "Prodloužené",
|
"documentFilterQueryOptionsExtendedLabel": "Prodloužené",
|
||||||
@@ -272,6 +260,64 @@
|
|||||||
"@errorMessageUnsupportedFileFormat": {},
|
"@errorMessageUnsupportedFileFormat": {},
|
||||||
"errorReportLabel": "NAHLÁSIT",
|
"errorReportLabel": "NAHLÁSIT",
|
||||||
"@errorReportLabel": {},
|
"@errorReportLabel": {},
|
||||||
|
"extendedDateRangePickerAfterLabel": "",
|
||||||
|
"@extendedDateRangePickerAfterLabel": {},
|
||||||
|
"extendedDateRangePickerBeforeLabel": "",
|
||||||
|
"@extendedDateRangePickerBeforeLabel": {},
|
||||||
|
"extendedDateRangePickerDayText": "{count, plural, other{}}",
|
||||||
|
"@extendedDateRangePickerDayText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerFromLabel": "Od",
|
||||||
|
"@extendedDateRangePickerFromLabel": {},
|
||||||
|
"extendedDateRangePickerLastDaysLabel": "{count, plural, zero{} one{} few{} many{} other{Posledních 7 dní}}",
|
||||||
|
"@extendedDateRangePickerLastDaysLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastMonthsLabel": "{count, plural, zero{} one{} few{} many{} other{Minulý měsíc}}",
|
||||||
|
"@extendedDateRangePickerLastMonthsLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastText": "",
|
||||||
|
"@extendedDateRangePickerLastText": {},
|
||||||
|
"extendedDateRangePickerLastWeeksLabel": "{count, plural, other{}}",
|
||||||
|
"@extendedDateRangePickerLastWeeksLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastYearsLabel": "{count, plural, zero{} one{} few{} many{} other{Minulý rok}}",
|
||||||
|
"@extendedDateRangePickerLastYearsLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerMonthText": "{count, plural, other{}}",
|
||||||
|
"@extendedDateRangePickerMonthText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerToLabel": "Do",
|
||||||
|
"@extendedDateRangePickerToLabel": {},
|
||||||
|
"extendedDateRangePickerWeekText": "{count, plural, other{}}",
|
||||||
|
"@extendedDateRangePickerWeekText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerYearText": "{count, plural, other{}}",
|
||||||
|
"@extendedDateRangePickerYearText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"genericActionCancelLabel": "Zrušit",
|
"genericActionCancelLabel": "Zrušit",
|
||||||
"@genericActionCancelLabel": {},
|
"@genericActionCancelLabel": {},
|
||||||
"genericActionCreateLabel": "Vytvořit",
|
"genericActionCreateLabel": "Vytvořit",
|
||||||
@@ -408,7 +454,7 @@
|
|||||||
"@savedViewShowOnDashboardLabel": {},
|
"@savedViewShowOnDashboardLabel": {},
|
||||||
"savedViewsLabel": "Uložené náhledy",
|
"savedViewsLabel": "Uložené náhledy",
|
||||||
"@savedViewsLabel": {},
|
"@savedViewsLabel": {},
|
||||||
"scannerPageImagePreviewTitle": "",
|
"scannerPageImagePreviewTitle": "Sken",
|
||||||
"@scannerPageImagePreviewTitle": {},
|
"@scannerPageImagePreviewTitle": {},
|
||||||
"serverInformationPaperlessVersionText": "Verze Paperless serveru",
|
"serverInformationPaperlessVersionText": "Verze Paperless serveru",
|
||||||
"@serverInformationPaperlessVersionText": {},
|
"@serverInformationPaperlessVersionText": {},
|
||||||
|
|||||||
@@ -78,18 +78,6 @@
|
|||||||
"@documentFilterAdvancedLabel": {},
|
"@documentFilterAdvancedLabel": {},
|
||||||
"documentFilterApplyFilterLabel": "Anwenden",
|
"documentFilterApplyFilterLabel": "Anwenden",
|
||||||
"@documentFilterApplyFilterLabel": {},
|
"@documentFilterApplyFilterLabel": {},
|
||||||
"documentFilterDateRangeFieldEndLabel": "Bis",
|
|
||||||
"@documentFilterDateRangeFieldEndLabel": {},
|
|
||||||
"documentFilterDateRangeFieldStartLabel": "Von",
|
|
||||||
"@documentFilterDateRangeFieldStartLabel": {},
|
|
||||||
"documentFilterDateRangeLastMonthLabel": "Letzter Monat",
|
|
||||||
"@documentFilterDateRangeLastMonthLabel": {},
|
|
||||||
"documentFilterDateRangeLastSevenDaysLabel": "Letzte 7 Tage",
|
|
||||||
"@documentFilterDateRangeLastSevenDaysLabel": {},
|
|
||||||
"documentFilterDateRangeLastThreeMonthsLabel": "Letzte 3 Monate",
|
|
||||||
"@documentFilterDateRangeLastThreeMonthsLabel": {},
|
|
||||||
"documentFilterDateRangeLastYearLabel": "Letztes Jahr",
|
|
||||||
"@documentFilterDateRangeLastYearLabel": {},
|
|
||||||
"documentFilterQueryOptionsAsnLabel": "ASN",
|
"documentFilterQueryOptionsAsnLabel": "ASN",
|
||||||
"@documentFilterQueryOptionsAsnLabel": {},
|
"@documentFilterQueryOptionsAsnLabel": {},
|
||||||
"documentFilterQueryOptionsExtendedLabel": "Erweitert",
|
"documentFilterQueryOptionsExtendedLabel": "Erweitert",
|
||||||
@@ -272,6 +260,64 @@
|
|||||||
"@errorMessageUnsupportedFileFormat": {},
|
"@errorMessageUnsupportedFileFormat": {},
|
||||||
"errorReportLabel": "MELDEN",
|
"errorReportLabel": "MELDEN",
|
||||||
"@errorReportLabel": {},
|
"@errorReportLabel": {},
|
||||||
|
"extendedDateRangePickerAfterLabel": "Nach",
|
||||||
|
"@extendedDateRangePickerAfterLabel": {},
|
||||||
|
"extendedDateRangePickerBeforeLabel": "Vor",
|
||||||
|
"@extendedDateRangePickerBeforeLabel": {},
|
||||||
|
"extendedDateRangePickerDayText": "{count, plural, zero{} one{Tag} other{Tage}}",
|
||||||
|
"@extendedDateRangePickerDayText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerFromLabel": "Von",
|
||||||
|
"@extendedDateRangePickerFromLabel": {},
|
||||||
|
"extendedDateRangePickerLastDaysLabel": "{count, plural, zero{} one{Gestern} other{Letzte {count} Tage}}",
|
||||||
|
"@extendedDateRangePickerLastDaysLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastMonthsLabel": "{count, plural, zero{} one{Letzter Monat} other{Letzte {count} Monate}}",
|
||||||
|
"@extendedDateRangePickerLastMonthsLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastText": "Letzte",
|
||||||
|
"@extendedDateRangePickerLastText": {},
|
||||||
|
"extendedDateRangePickerLastWeeksLabel": "{count, plural, zero{} one{Letzte Woche} other{Letzte {count} Wochen}}",
|
||||||
|
"@extendedDateRangePickerLastWeeksLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastYearsLabel": "{count, plural, zero{} one{Letztes Jahr} other{Letzte {count} Jahre}}",
|
||||||
|
"@extendedDateRangePickerLastYearsLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerMonthText": "{count, plural, zero{} one{Monat} other{Monate}}",
|
||||||
|
"@extendedDateRangePickerMonthText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerToLabel": "Bis",
|
||||||
|
"@extendedDateRangePickerToLabel": {},
|
||||||
|
"extendedDateRangePickerWeekText": "{count, plural, zero{} one{Woche} other{Wochen}}",
|
||||||
|
"@extendedDateRangePickerWeekText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerYearText": "{count, plural, zero{} one{Jahr} other{Jahre}}",
|
||||||
|
"@extendedDateRangePickerYearText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"genericActionCancelLabel": "Abbrechen",
|
"genericActionCancelLabel": "Abbrechen",
|
||||||
"@genericActionCancelLabel": {},
|
"@genericActionCancelLabel": {},
|
||||||
"genericActionCreateLabel": "Erstellen",
|
"genericActionCreateLabel": "Erstellen",
|
||||||
|
|||||||
@@ -78,18 +78,6 @@
|
|||||||
"@documentFilterAdvancedLabel": {},
|
"@documentFilterAdvancedLabel": {},
|
||||||
"documentFilterApplyFilterLabel": "Apply",
|
"documentFilterApplyFilterLabel": "Apply",
|
||||||
"@documentFilterApplyFilterLabel": {},
|
"@documentFilterApplyFilterLabel": {},
|
||||||
"documentFilterDateRangeFieldEndLabel": "To",
|
|
||||||
"@documentFilterDateRangeFieldEndLabel": {},
|
|
||||||
"documentFilterDateRangeFieldStartLabel": "From",
|
|
||||||
"@documentFilterDateRangeFieldStartLabel": {},
|
|
||||||
"documentFilterDateRangeLastMonthLabel": "Last Month",
|
|
||||||
"@documentFilterDateRangeLastMonthLabel": {},
|
|
||||||
"documentFilterDateRangeLastSevenDaysLabel": "Last 7 Days",
|
|
||||||
"@documentFilterDateRangeLastSevenDaysLabel": {},
|
|
||||||
"documentFilterDateRangeLastThreeMonthsLabel": "Last 3 Months",
|
|
||||||
"@documentFilterDateRangeLastThreeMonthsLabel": {},
|
|
||||||
"documentFilterDateRangeLastYearLabel": "Last Year",
|
|
||||||
"@documentFilterDateRangeLastYearLabel": {},
|
|
||||||
"documentFilterQueryOptionsAsnLabel": "ASN",
|
"documentFilterQueryOptionsAsnLabel": "ASN",
|
||||||
"@documentFilterQueryOptionsAsnLabel": {},
|
"@documentFilterQueryOptionsAsnLabel": {},
|
||||||
"documentFilterQueryOptionsExtendedLabel": "Extended",
|
"documentFilterQueryOptionsExtendedLabel": "Extended",
|
||||||
@@ -272,6 +260,64 @@
|
|||||||
"@errorMessageUnsupportedFileFormat": {},
|
"@errorMessageUnsupportedFileFormat": {},
|
||||||
"errorReportLabel": "REPORT",
|
"errorReportLabel": "REPORT",
|
||||||
"@errorReportLabel": {},
|
"@errorReportLabel": {},
|
||||||
|
"extendedDateRangePickerAfterLabel": "After",
|
||||||
|
"@extendedDateRangePickerAfterLabel": {},
|
||||||
|
"extendedDateRangePickerBeforeLabel": "Before",
|
||||||
|
"@extendedDateRangePickerBeforeLabel": {},
|
||||||
|
"extendedDateRangePickerDayText": "{count, plural, zero{} one{day} other{days}}",
|
||||||
|
"@extendedDateRangePickerDayText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerFromLabel": "From",
|
||||||
|
"@extendedDateRangePickerFromLabel": {},
|
||||||
|
"extendedDateRangePickerLastDaysLabel": "{count, plural, zero{} one{Yesterday} other{Last {count} days}}",
|
||||||
|
"@extendedDateRangePickerLastDaysLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastMonthsLabel": "{count, plural, zero{} one{Last month} other{Last {count} months}}",
|
||||||
|
"@extendedDateRangePickerLastMonthsLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastText": "Last",
|
||||||
|
"@extendedDateRangePickerLastText": {},
|
||||||
|
"extendedDateRangePickerLastWeeksLabel": "{count, plural, zero{} one{Last week} other{Last {count} weeks}}",
|
||||||
|
"@extendedDateRangePickerLastWeeksLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerLastYearsLabel": "{count, plural, zero{} one{Last year} other{Last {count} years}}",
|
||||||
|
"@extendedDateRangePickerLastYearsLabel": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerMonthText": "{count, plural, zero{} one{month} other{months}}",
|
||||||
|
"@extendedDateRangePickerMonthText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerToLabel": "To",
|
||||||
|
"@extendedDateRangePickerToLabel": {},
|
||||||
|
"extendedDateRangePickerWeekText": "{count, plural, zero{} one{week} other{weeks}}",
|
||||||
|
"@extendedDateRangePickerWeekText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extendedDateRangePickerYearText": "{count, plural, zero{} one{year} other{years}}",
|
||||||
|
"@extendedDateRangePickerYearText": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"genericActionCancelLabel": "Cancel",
|
"genericActionCancelLabel": "Cancel",
|
||||||
"@genericActionCancelLabel": {},
|
"@genericActionCancelLabel": {},
|
||||||
"genericActionCreateLabel": "Create",
|
"genericActionCreateLabel": "Create",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:paperless_api/src/constants.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/asn_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/correspondent_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/date_range_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/document_type_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/query_type.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/sort_field.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/sort_order.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/storage_path_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/tags_query.dart';
|
|
||||||
|
|
||||||
class DocumentFilter extends Equatable {
|
class DocumentFilter extends Equatable {
|
||||||
static const _oneDay = Duration(days: 1);
|
static const _oneDay = Duration(days: 1);
|
||||||
@@ -23,23 +14,24 @@ class DocumentFilter extends Equatable {
|
|||||||
|
|
||||||
final int pageSize;
|
final int pageSize;
|
||||||
final int page;
|
final int page;
|
||||||
final DocumentTypeQuery documentType;
|
final IdQueryParameter documentType;
|
||||||
final CorrespondentQuery correspondent;
|
final IdQueryParameter correspondent;
|
||||||
final StoragePathQuery storagePath;
|
final IdQueryParameter storagePath;
|
||||||
final AsnQuery asnQuery;
|
final IdQueryParameter asnQuery;
|
||||||
final TagsQuery tags;
|
final TagsQuery tags;
|
||||||
final SortField sortField;
|
final SortField sortField;
|
||||||
final SortOrder sortOrder;
|
final SortOrder sortOrder;
|
||||||
final DateRangeQuery added;
|
|
||||||
final DateRangeQuery created;
|
final DateRangeQuery created;
|
||||||
|
final DateRangeQuery added;
|
||||||
|
final DateRangeQuery modified;
|
||||||
final QueryType queryType;
|
final QueryType queryType;
|
||||||
final String? queryText;
|
final String? queryText;
|
||||||
|
|
||||||
const DocumentFilter({
|
const DocumentFilter({
|
||||||
this.documentType = const DocumentTypeQuery.unset(),
|
this.documentType = const IdQueryParameter.unset(),
|
||||||
this.correspondent = const CorrespondentQuery.unset(),
|
this.correspondent = const IdQueryParameter.unset(),
|
||||||
this.storagePath = const StoragePathQuery.unset(),
|
this.storagePath = const IdQueryParameter.unset(),
|
||||||
this.asnQuery = const AsnQuery.unset(),
|
this.asnQuery = const IdQueryParameter.unset(),
|
||||||
this.tags = const IdsTagsQuery(),
|
this.tags = const IdsTagsQuery(),
|
||||||
this.sortField = SortField.created,
|
this.sortField = SortField.created,
|
||||||
this.sortOrder = SortOrder.descending,
|
this.sortOrder = SortOrder.descending,
|
||||||
@@ -49,6 +41,7 @@ class DocumentFilter extends Equatable {
|
|||||||
this.queryText,
|
this.queryText,
|
||||||
this.added = const UnsetDateRangeQuery(),
|
this.added = const UnsetDateRangeQuery(),
|
||||||
this.created = const UnsetDateRangeQuery(),
|
this.created = const UnsetDateRangeQuery(),
|
||||||
|
this.modified = const UnsetDateRangeQuery(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, String> toQueryParameters() {
|
Map<String, String> toQueryParameters() {
|
||||||
@@ -57,13 +50,14 @@ class DocumentFilter extends Equatable {
|
|||||||
'page_size': pageSize.toString(),
|
'page_size': pageSize.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
params.addAll(documentType.toQueryParameter());
|
params.addAll(documentType.toQueryParameter('document_type'));
|
||||||
params.addAll(correspondent.toQueryParameter());
|
params.addAll(correspondent.toQueryParameter('correspondent'));
|
||||||
|
params.addAll(storagePath.toQueryParameter('storage_path'));
|
||||||
|
params.addAll(asnQuery.toQueryParameter('archive_serial_number'));
|
||||||
params.addAll(tags.toQueryParameter());
|
params.addAll(tags.toQueryParameter());
|
||||||
params.addAll(storagePath.toQueryParameter());
|
params.addAll(added.toQueryParameter(DateRangeQueryField.added));
|
||||||
params.addAll(asnQuery.toQueryParameter());
|
params.addAll(created.toQueryParameter(DateRangeQueryField.created));
|
||||||
params.addAll(added.toQueryParameter());
|
params.addAll(modified.toQueryParameter(DateRangeQueryField.modified));
|
||||||
params.addAll(created.toQueryParameter());
|
|
||||||
//TODO: Rework when implementing extended queries.
|
//TODO: Rework when implementing extended queries.
|
||||||
if (queryText?.isNotEmpty ?? false) {
|
if (queryText?.isNotEmpty ?? false) {
|
||||||
params.putIfAbsent(queryType.queryParam, () => queryText!);
|
params.putIfAbsent(queryType.queryParam, () => queryText!);
|
||||||
@@ -84,15 +78,16 @@ class DocumentFilter extends Equatable {
|
|||||||
int? pageSize,
|
int? pageSize,
|
||||||
int? page,
|
int? page,
|
||||||
bool? onlyNoDocumentType,
|
bool? onlyNoDocumentType,
|
||||||
DocumentTypeQuery? documentType,
|
IdQueryParameter? documentType,
|
||||||
CorrespondentQuery? correspondent,
|
IdQueryParameter? correspondent,
|
||||||
StoragePathQuery? storagePath,
|
IdQueryParameter? storagePath,
|
||||||
AsnQuery? asnQuery,
|
IdQueryParameter? asnQuery,
|
||||||
TagsQuery? tags,
|
TagsQuery? tags,
|
||||||
SortField? sortField,
|
SortField? sortField,
|
||||||
SortOrder? sortOrder,
|
SortOrder? sortOrder,
|
||||||
DateRangeQuery? added,
|
DateRangeQuery? added,
|
||||||
DateRangeQuery? created,
|
DateRangeQuery? created,
|
||||||
|
DateRangeQuery? modified,
|
||||||
QueryType? queryType,
|
QueryType? queryType,
|
||||||
String? queryText,
|
String? queryText,
|
||||||
}) {
|
}) {
|
||||||
@@ -105,11 +100,12 @@ class DocumentFilter extends Equatable {
|
|||||||
tags: tags ?? this.tags,
|
tags: tags ?? this.tags,
|
||||||
sortField: sortField ?? this.sortField,
|
sortField: sortField ?? this.sortField,
|
||||||
sortOrder: sortOrder ?? this.sortOrder,
|
sortOrder: sortOrder ?? this.sortOrder,
|
||||||
added: added ?? this.added,
|
|
||||||
queryType: queryType ?? this.queryType,
|
queryType: queryType ?? this.queryType,
|
||||||
queryText: queryText ?? this.queryText,
|
queryText: queryText ?? this.queryText,
|
||||||
asnQuery: asnQuery ?? this.asnQuery,
|
asnQuery: asnQuery ?? this.asnQuery,
|
||||||
|
added: added ?? this.added,
|
||||||
created: created ?? this.created,
|
created: created ?? this.created,
|
||||||
|
modified: modified ?? this.modified,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +135,9 @@ class DocumentFilter extends Equatable {
|
|||||||
correspondent != initial.correspondent,
|
correspondent != initial.correspondent,
|
||||||
storagePath != initial.storagePath,
|
storagePath != initial.storagePath,
|
||||||
tags != initial.tags,
|
tags != initial.tags,
|
||||||
(added != initial.added),
|
added != initial.added,
|
||||||
(created != initial.created),
|
created != initial.created,
|
||||||
|
modified != initial.modified,
|
||||||
asnQuery != initial.asnQuery,
|
asnQuery != initial.asnQuery,
|
||||||
(queryType != initial.queryType || queryText != initial.queryText),
|
(queryType != initial.queryType || queryText != initial.queryText),
|
||||||
].fold(0, (previousValue, element) => previousValue += element ? 1 : 0);
|
].fold(0, (previousValue, element) => previousValue += element ? 1 : 0);
|
||||||
@@ -158,6 +155,7 @@ class DocumentFilter extends Equatable {
|
|||||||
sortOrder,
|
sortOrder,
|
||||||
added,
|
added,
|
||||||
created,
|
created,
|
||||||
|
modified,
|
||||||
queryType,
|
queryType,
|
||||||
queryText,
|
queryText,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_api/src/constants.dart';
|
import 'package:paperless_api/src/constants.dart';
|
||||||
import 'package:paperless_api/src/models/document_filter.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/correspondent_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/date_range_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/document_type_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/query_type.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/storage_path_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/tags_query.dart';
|
|
||||||
|
|
||||||
class FilterRule with EquatableMixin {
|
class FilterRule with EquatableMixin {
|
||||||
static const int titleRule = 0;
|
static const int titleRule = 0;
|
||||||
@@ -57,9 +51,6 @@ class FilterRule with EquatableMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DocumentFilter applyToFilter(final DocumentFilter filter) {
|
DocumentFilter applyToFilter(final DocumentFilter filter) {
|
||||||
if (value == null) {
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
//TODO: Check in profiling mode if this is inefficient enough to cause stutters...
|
//TODO: Check in profiling mode if this is inefficient enough to cause stutters...
|
||||||
switch (ruleType) {
|
switch (ruleType) {
|
||||||
case titleRule:
|
case titleRule:
|
||||||
@@ -67,20 +58,20 @@ class FilterRule with EquatableMixin {
|
|||||||
case documentTypeRule:
|
case documentTypeRule:
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
documentType: value == null
|
documentType: value == null
|
||||||
? const DocumentTypeQuery.notAssigned()
|
? const IdQueryParameter.notAssigned()
|
||||||
: DocumentTypeQuery.fromId(int.parse(value!)),
|
: IdQueryParameter.fromId(int.parse(value!)),
|
||||||
);
|
);
|
||||||
case correspondentRule:
|
case correspondentRule:
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
correspondent: value == null
|
correspondent: value == null
|
||||||
? const CorrespondentQuery.notAssigned()
|
? const IdQueryParameter.notAssigned()
|
||||||
: CorrespondentQuery.fromId(int.parse(value!)),
|
: IdQueryParameter.fromId(int.parse(value!)),
|
||||||
);
|
);
|
||||||
case storagePathRule:
|
case storagePathRule:
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
storagePath: value == null
|
storagePath: value == null
|
||||||
? const StoragePathQuery.notAssigned()
|
? const IdQueryParameter.notAssigned()
|
||||||
: StoragePathQuery.fromId(int.parse(value!)),
|
: IdQueryParameter.fromId(int.parse(value!)),
|
||||||
);
|
);
|
||||||
case hasAnyTag:
|
case hasAnyTag:
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
@@ -101,48 +92,69 @@ class FilterRule with EquatableMixin {
|
|||||||
.withIdQueriesAdded([ExcludeTagIdQuery(int.parse(value!))]),
|
.withIdQueriesAdded([ExcludeTagIdQuery(int.parse(value!))]),
|
||||||
);
|
);
|
||||||
case createdBeforeRule:
|
case createdBeforeRule:
|
||||||
if (filter.created is FixedDateRangeQuery) {
|
if (filter.created is AbsoluteDateRangeQuery) {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
created: (filter.created as FixedDateRangeQuery)
|
created: (filter.created as AbsoluteDateRangeQuery)
|
||||||
.copyWith(before: DateTime.parse(value!)),
|
.copyWith(before: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
created:
|
created: AbsoluteDateRangeQuery(before: DateTime.parse(value!)),
|
||||||
FixedDateRangeQuery.created(before: DateTime.parse(value!)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case createdAfterRule:
|
case createdAfterRule:
|
||||||
if (filter.created is FixedDateRangeQuery) {
|
if (filter.created is AbsoluteDateRangeQuery) {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
created: (filter.created as FixedDateRangeQuery)
|
created: (filter.created as AbsoluteDateRangeQuery)
|
||||||
.copyWith(after: DateTime.parse(value!)),
|
.copyWith(after: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
created: FixedDateRangeQuery.created(after: DateTime.parse(value!)),
|
created: AbsoluteDateRangeQuery(after: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case addedBeforeRule:
|
case addedBeforeRule:
|
||||||
if (filter.added is FixedDateRangeQuery) {
|
if (filter.added is AbsoluteDateRangeQuery) {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
added: (filter.added as FixedDateRangeQuery)
|
added: (filter.added as AbsoluteDateRangeQuery)
|
||||||
.copyWith(before: DateTime.parse(value!)),
|
.copyWith(before: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
added: FixedDateRangeQuery.added(before: DateTime.parse(value!)),
|
added: AbsoluteDateRangeQuery(before: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case addedAfterRule:
|
case addedAfterRule:
|
||||||
if (filter.added is FixedDateRangeQuery) {
|
if (filter.added is AbsoluteDateRangeQuery) {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
added: (filter.added as FixedDateRangeQuery)
|
added: (filter.added as AbsoluteDateRangeQuery)
|
||||||
.copyWith(after: DateTime.parse(value!)),
|
.copyWith(after: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
added: FixedDateRangeQuery.added(after: DateTime.parse(value!)),
|
added: AbsoluteDateRangeQuery(after: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case modifiedBeforeRule:
|
||||||
|
if (filter.modified is AbsoluteDateRangeQuery) {
|
||||||
|
return filter.copyWith(
|
||||||
|
modified: (filter.modified as AbsoluteDateRangeQuery)
|
||||||
|
.copyWith(before: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return filter.copyWith(
|
||||||
|
modified: AbsoluteDateRangeQuery(before: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case modifiedAfterRule:
|
||||||
|
if (filter.modified is AbsoluteDateRangeQuery) {
|
||||||
|
return filter.copyWith(
|
||||||
|
modified: (filter.modified as AbsoluteDateRangeQuery)
|
||||||
|
.copyWith(after: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return filter.copyWith(
|
||||||
|
added: AbsoluteDateRangeQuery(after: DateTime.parse(value!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case titleAndContentRule:
|
case titleAndContentRule:
|
||||||
@@ -171,7 +183,7 @@ class FilterRule with EquatableMixin {
|
|||||||
switch (field) {
|
switch (field) {
|
||||||
case 'created':
|
case 'created':
|
||||||
newFilter = newFilter.copyWith(
|
newFilter = newFilter.copyWith(
|
||||||
created: LastNDateRangeQuery.created(
|
created: RelativeDateRangeQuery(
|
||||||
n,
|
n,
|
||||||
DateRangeUnit.values.byName(unit),
|
DateRangeUnit.values.byName(unit),
|
||||||
),
|
),
|
||||||
@@ -179,7 +191,7 @@ class FilterRule with EquatableMixin {
|
|||||||
break;
|
break;
|
||||||
case 'added':
|
case 'added':
|
||||||
newFilter = newFilter.copyWith(
|
newFilter = newFilter.copyWith(
|
||||||
created: LastNDateRangeQuery.added(
|
added: RelativeDateRangeQuery(
|
||||||
n,
|
n,
|
||||||
DateRangeUnit.values.byName(unit),
|
DateRangeUnit.values.byName(unit),
|
||||||
),
|
),
|
||||||
@@ -187,7 +199,7 @@ class FilterRule with EquatableMixin {
|
|||||||
break;
|
break;
|
||||||
case 'modified':
|
case 'modified':
|
||||||
newFilter = newFilter.copyWith(
|
newFilter = newFilter.copyWith(
|
||||||
created: LastNDateRangeQuery.modified(
|
modified: RelativeDateRangeQuery(
|
||||||
n,
|
n,
|
||||||
DateRangeUnit.values.byName(unit),
|
DateRangeUnit.values.byName(unit),
|
||||||
),
|
),
|
||||||
@@ -262,7 +274,7 @@ class FilterRule with EquatableMixin {
|
|||||||
|
|
||||||
// Parse created at
|
// Parse created at
|
||||||
final created = filter.created;
|
final created = filter.created;
|
||||||
if (created is FixedDateRangeQuery) {
|
if (created is AbsoluteDateRangeQuery) {
|
||||||
if (created.after != null) {
|
if (created.after != null) {
|
||||||
filterRules.add(
|
filterRules.add(
|
||||||
FilterRule(createdAfterRule, apiDateFormat.format(created.after!)),
|
FilterRule(createdAfterRule, apiDateFormat.format(created.after!)),
|
||||||
@@ -273,15 +285,16 @@ class FilterRule with EquatableMixin {
|
|||||||
FilterRule(createdBeforeRule, apiDateFormat.format(created.before!)),
|
FilterRule(createdBeforeRule, apiDateFormat.format(created.before!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (created is LastNDateRangeQuery) {
|
} else if (created is RelativeDateRangeQuery) {
|
||||||
filterRules.add(
|
filterRules.add(
|
||||||
FilterRule(extendedRule, created.toQueryParameter().values.first),
|
FilterRule(extendedRule,
|
||||||
|
created.toQueryParameter(DateRangeQueryField.created).values.first),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse added at
|
// Parse added at
|
||||||
final added = filter.added;
|
final added = filter.added;
|
||||||
if (added is FixedDateRangeQuery) {
|
if (added is AbsoluteDateRangeQuery) {
|
||||||
if (added.after != null) {
|
if (added.after != null) {
|
||||||
filterRules.add(
|
filterRules.add(
|
||||||
FilterRule(addedAfterRule, apiDateFormat.format(added.after!)),
|
FilterRule(addedAfterRule, apiDateFormat.format(added.after!)),
|
||||||
@@ -292,15 +305,16 @@ class FilterRule with EquatableMixin {
|
|||||||
FilterRule(addedBeforeRule, apiDateFormat.format(added.before!)),
|
FilterRule(addedBeforeRule, apiDateFormat.format(added.before!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (added is LastNDateRangeQuery) {
|
} else if (added is RelativeDateRangeQuery) {
|
||||||
filterRules.add(
|
filterRules.add(
|
||||||
FilterRule(extendedRule, added.toQueryParameter().values.first),
|
FilterRule(extendedRule,
|
||||||
|
added.toQueryParameter(DateRangeQueryField.added).values.first),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse modified at
|
// Parse modified at
|
||||||
final modified = filter.added;
|
final modified = filter.modified;
|
||||||
if (modified is FixedDateRangeQuery) {
|
if (modified is AbsoluteDateRangeQuery) {
|
||||||
if (modified.after != null) {
|
if (modified.after != null) {
|
||||||
filterRules.add(
|
filterRules.add(
|
||||||
FilterRule(modifiedAfterRule, apiDateFormat.format(modified.after!)),
|
FilterRule(modifiedAfterRule, apiDateFormat.format(modified.after!)),
|
||||||
@@ -312,9 +326,14 @@ class FilterRule with EquatableMixin {
|
|||||||
modifiedBeforeRule, apiDateFormat.format(modified.before!)),
|
modifiedBeforeRule, apiDateFormat.format(modified.before!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (modified is LastNDateRangeQuery) {
|
} else if (modified is RelativeDateRangeQuery) {
|
||||||
filterRules.add(
|
filterRules.add(
|
||||||
FilterRule(extendedRule, modified.toQueryParameter().values.first),
|
FilterRule(
|
||||||
|
extendedRule,
|
||||||
|
modified
|
||||||
|
.toQueryParameter(DateRangeQueryField.modified)
|
||||||
|
.values
|
||||||
|
.first),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,12 @@ export 'labels/label_model.dart';
|
|||||||
export 'labels/matching_algorithm.dart';
|
export 'labels/matching_algorithm.dart';
|
||||||
export 'labels/storage_path_model.dart';
|
export 'labels/storage_path_model.dart';
|
||||||
export 'labels/tag_model.dart';
|
export 'labels/tag_model.dart';
|
||||||
export 'query_parameters/asn_query.dart';
|
|
||||||
export 'query_parameters/correspondent_query.dart';
|
|
||||||
export 'query_parameters/document_type_query.dart';
|
|
||||||
export 'query_parameters/id_query_parameter.dart';
|
export 'query_parameters/id_query_parameter.dart';
|
||||||
export 'query_parameters/query_type.dart';
|
export 'query_parameters/query_type.dart';
|
||||||
export 'query_parameters/sort_field.dart';
|
export 'query_parameters/sort_field.dart';
|
||||||
export 'query_parameters/sort_order.dart';
|
export 'query_parameters/sort_order.dart';
|
||||||
export 'query_parameters/storage_path_query.dart';
|
|
||||||
export 'query_parameters/tags_query.dart';
|
export 'query_parameters/tags_query.dart';
|
||||||
|
export 'query_parameters/date_range_query.dart';
|
||||||
export 'bulk_edit_model.dart';
|
export 'bulk_edit_model.dart';
|
||||||
export 'document_filter.dart';
|
export 'document_filter.dart';
|
||||||
export 'document_meta_data_model.dart';
|
export 'document_meta_data_model.dart';
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:paperless_api/src/models/query_parameters/id_query_parameter.dart';
|
|
||||||
|
|
||||||
class AsnQuery extends IdQueryParameter {
|
|
||||||
const AsnQuery.fromId(super.id) : super.fromId();
|
|
||||||
const AsnQuery.unset() : super.unset();
|
|
||||||
const AsnQuery.notAssigned() : super.notAssigned();
|
|
||||||
const AsnQuery.anyAssigned() : super.anyAssigned();
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get queryParameterKey => 'archive_serial_number';
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:paperless_api/src/models/query_parameters/id_query_parameter.dart';
|
|
||||||
|
|
||||||
class CorrespondentQuery extends IdQueryParameter {
|
|
||||||
const CorrespondentQuery.fromId(super.id) : super.fromId();
|
|
||||||
const CorrespondentQuery.unset() : super.unset();
|
|
||||||
const CorrespondentQuery.notAssigned() : super.notAssigned();
|
|
||||||
const CorrespondentQuery.anyAssigned() : super.anyAssigned();
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get queryParameterKey => 'correspondent';
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ import 'package:paperless_api/src/constants.dart';
|
|||||||
|
|
||||||
abstract class DateRangeQuery extends Equatable {
|
abstract class DateRangeQuery extends Equatable {
|
||||||
const DateRangeQuery();
|
const DateRangeQuery();
|
||||||
Map<String, String> toQueryParameter();
|
Map<String, String> toQueryParameter(DateRangeQueryField field);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnsetDateRangeQuery extends DateRangeQuery {
|
class UnsetDateRangeQuery extends DateRangeQuery {
|
||||||
@@ -12,87 +12,74 @@ class UnsetDateRangeQuery extends DateRangeQuery {
|
|||||||
List<Object?> get props => [];
|
List<Object?> get props => [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, String> toQueryParameter() => const {};
|
Map<String, String> toQueryParameter(DateRangeQueryField field) => const {};
|
||||||
}
|
}
|
||||||
|
|
||||||
class FixedDateRangeQuery extends DateRangeQuery {
|
class AbsoluteDateRangeQuery extends DateRangeQuery {
|
||||||
final String _querySuffix;
|
|
||||||
|
|
||||||
final DateTime? after;
|
final DateTime? after;
|
||||||
final DateTime? before;
|
final DateTime? before;
|
||||||
|
|
||||||
const FixedDateRangeQuery._(this._querySuffix, {this.after, this.before})
|
const AbsoluteDateRangeQuery({this.after, this.before});
|
||||||
: assert(after != null || before != null);
|
|
||||||
|
|
||||||
const FixedDateRangeQuery.created({DateTime? after, DateTime? before})
|
|
||||||
: this._('created', after: after, before: before);
|
|
||||||
|
|
||||||
const FixedDateRangeQuery.added({DateTime? after, DateTime? before})
|
|
||||||
: this._('added', after: after, before: before);
|
|
||||||
|
|
||||||
const FixedDateRangeQuery.modified({DateTime? after, DateTime? before})
|
|
||||||
: this._('modified', after: after, before: before);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [_querySuffix, after, before];
|
List<Object?> get props => [after, before];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, String> toQueryParameter() {
|
Map<String, String> toQueryParameter(DateRangeQueryField field) {
|
||||||
final Map<String, String> params = {};
|
final Map<String, String> params = {};
|
||||||
|
|
||||||
// Add/subtract one day in the following because paperless uses gt/lt not gte/lte
|
// Add/subtract one day in the following because paperless uses gt/lt not gte/lte
|
||||||
if (after != null) {
|
if (after != null) {
|
||||||
params.putIfAbsent('${_querySuffix}__date__gt',
|
params.putIfAbsent('${field.name}__date__gt',
|
||||||
() => apiDateFormat.format(after!.subtract(const Duration(days: 1))));
|
() => apiDateFormat.format(after!.subtract(const Duration(days: 1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (before != null) {
|
if (before != null) {
|
||||||
params.putIfAbsent('${_querySuffix}__date__lt',
|
params.putIfAbsent('${field.name}__date__lt',
|
||||||
() => apiDateFormat.format(before!.add(const Duration(days: 1))));
|
() => apiDateFormat.format(before!.add(const Duration(days: 1))));
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedDateRangeQuery copyWith({
|
AbsoluteDateRangeQuery copyWith({
|
||||||
DateTime? before,
|
DateTime? before,
|
||||||
DateTime? after,
|
DateTime? after,
|
||||||
}) {
|
}) {
|
||||||
return FixedDateRangeQuery._(
|
return AbsoluteDateRangeQuery(
|
||||||
_querySuffix,
|
|
||||||
before: before ?? this.before,
|
before: before ?? this.before,
|
||||||
after: after ?? this.after,
|
after: after ?? this.after,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LastNDateRangeQuery extends DateRangeQuery {
|
class RelativeDateRangeQuery extends DateRangeQuery {
|
||||||
|
final int offset;
|
||||||
final DateRangeUnit unit;
|
final DateRangeUnit unit;
|
||||||
final int n;
|
|
||||||
final String _field;
|
|
||||||
|
|
||||||
const LastNDateRangeQuery._(
|
const RelativeDateRangeQuery(
|
||||||
this._field, {
|
this.offset,
|
||||||
required this.n,
|
this.unit,
|
||||||
required this.unit,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
const LastNDateRangeQuery.created(int n, DateRangeUnit unit)
|
|
||||||
: this._('created', unit: unit, n: n);
|
|
||||||
const LastNDateRangeQuery.added(int n, DateRangeUnit unit)
|
|
||||||
: this._('added', unit: unit, n: n);
|
|
||||||
const LastNDateRangeQuery.modified(int n, DateRangeUnit unit)
|
|
||||||
: this._('modified', unit: unit, n: n);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// TODO: implement props
|
List<Object?> get props => [offset, unit];
|
||||||
List<Object?> get props => [_field, n, unit];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, String> toQueryParameter() {
|
Map<String, String> toQueryParameter(DateRangeQueryField field) {
|
||||||
return {
|
return {
|
||||||
'query': '[$_field:$n ${unit.name} to now]',
|
'query': '[${field.name}:$offset ${unit.name} to now]',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RelativeDateRangeQuery copyWith({
|
||||||
|
int? offset,
|
||||||
|
DateRangeUnit? unit,
|
||||||
|
}) {
|
||||||
|
return RelativeDateRangeQuery(
|
||||||
|
offset ?? this.offset,
|
||||||
|
unit ?? this.unit,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DateRangeUnit {
|
enum DateRangeUnit {
|
||||||
@@ -101,3 +88,9 @@ enum DateRangeUnit {
|
|||||||
month,
|
month,
|
||||||
year;
|
year;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DateRangeQueryField {
|
||||||
|
created,
|
||||||
|
added,
|
||||||
|
modified;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:paperless_api/src/models/query_parameters/id_query_parameter.dart';
|
|
||||||
|
|
||||||
class DocumentTypeQuery extends IdQueryParameter {
|
|
||||||
const DocumentTypeQuery.fromId(super.id) : super.fromId();
|
|
||||||
const DocumentTypeQuery.unset() : super.unset();
|
|
||||||
const DocumentTypeQuery.notAssigned() : super.notAssigned();
|
|
||||||
const DocumentTypeQuery.anyAssigned() : super.anyAssigned();
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get queryParameterKey => 'document_type';
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
abstract class IdQueryParameter extends Equatable {
|
class IdQueryParameter extends Equatable {
|
||||||
final int? _assignmentStatus;
|
final int? _assignmentStatus;
|
||||||
final int? _id;
|
final int? _id;
|
||||||
|
|
||||||
@@ -28,16 +28,14 @@ abstract class IdQueryParameter extends Equatable {
|
|||||||
|
|
||||||
int? get id => _id;
|
int? get id => _id;
|
||||||
|
|
||||||
String get queryParameterKey;
|
Map<String, String> toQueryParameter(String field) {
|
||||||
|
|
||||||
Map<String, String> toQueryParameter() {
|
|
||||||
final Map<String, String> params = {};
|
final Map<String, String> params = {};
|
||||||
if (onlyNotAssigned || onlyAssigned) {
|
if (onlyNotAssigned || onlyAssigned) {
|
||||||
params.putIfAbsent(
|
params.putIfAbsent(
|
||||||
'${queryParameterKey}__isnull', () => _assignmentStatus!.toString());
|
'${field}__isnull', () => _assignmentStatus!.toString());
|
||||||
}
|
}
|
||||||
if (isSet) {
|
if (isSet) {
|
||||||
params.putIfAbsent("${queryParameterKey}__id", () => id!.toString());
|
params.putIfAbsent("${field}__id", () => id!.toString());
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:paperless_api/src/models/query_parameters/id_query_parameter.dart';
|
|
||||||
|
|
||||||
class StoragePathQuery extends IdQueryParameter {
|
|
||||||
const StoragePathQuery.fromId(super.id) : super.fromId();
|
|
||||||
const StoragePathQuery.unset() : super.unset();
|
|
||||||
const StoragePathQuery.notAssigned() : super.notAssigned();
|
|
||||||
const StoragePathQuery.anyAssigned() : super.anyAssigned();
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get queryParameterKey => 'storage_path';
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ import 'dart:math';
|
|||||||
import 'package:http/src/boundary_characters.dart';
|
import 'package:http/src/boundary_characters.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_api/src/constants.dart';
|
import 'package:paperless_api/src/constants.dart';
|
||||||
import 'package:paperless_api/src/models/bulk_edit_model.dart';
|
import 'package:paperless_api/src/models/bulk_edit_model.dart';
|
||||||
import 'package:paperless_api/src/models/document_filter.dart';
|
import 'package:paperless_api/src/models/document_filter.dart';
|
||||||
@@ -11,7 +12,6 @@ import 'package:paperless_api/src/models/document_meta_data_model.dart';
|
|||||||
import 'package:paperless_api/src/models/document_model.dart';
|
import 'package:paperless_api/src/models/document_model.dart';
|
||||||
import 'package:paperless_api/src/models/paged_search_result.dart';
|
import 'package:paperless_api/src/models/paged_search_result.dart';
|
||||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/asn_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/sort_field.dart';
|
import 'package:paperless_api/src/models/query_parameters/sort_field.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/sort_order.dart';
|
import 'package:paperless_api/src/models/query_parameters/sort_order.dart';
|
||||||
import 'package:paperless_api/src/models/similar_document_model.dart';
|
import 'package:paperless_api/src/models/similar_document_model.dart';
|
||||||
@@ -139,7 +139,7 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
final filterParams = filter.toQueryParameters();
|
final filterParams = filter.toQueryParameters();
|
||||||
final response = await baseClient.get(
|
final response = await baseClient.get(
|
||||||
Uri(
|
Uri(
|
||||||
path: "/api/documents/?$filterParams",
|
path: "/api/documents/",
|
||||||
queryParameters: filterParams,
|
queryParameters: filterParams,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -190,7 +190,7 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
const DocumentFilter asnQueryFilter = DocumentFilter(
|
const DocumentFilter asnQueryFilter = DocumentFilter(
|
||||||
sortField: SortField.archiveSerialNumber,
|
sortField: SortField.archiveSerialNumber,
|
||||||
sortOrder: SortOrder.descending,
|
sortOrder: SortOrder.descending,
|
||||||
asnQuery: AsnQuery.anyAssigned(),
|
asnQuery: IdQueryParameter.anyAssigned(),
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 1,
|
pageSize: 1,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
import 'package:paperless_api/src/models/document_filter.dart';
|
|
||||||
import 'package:paperless_api/src/models/filter_rule_model.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/correspondent_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/document_type_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/query_type.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/sort_field.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/sort_order.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/storage_path_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/query_parameters/tags_query.dart';
|
|
||||||
import 'package:paperless_api/src/models/saved_view_model.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('Validate parsing logic from [SavedView] to [DocumentFilter]:', () {
|
group('Validate parsing logic from [SavedView] to [DocumentFilter]:', () {
|
||||||
@@ -74,10 +65,10 @@ void main() {
|
|||||||
}).toDocumentFilter(),
|
}).toDocumentFilter(),
|
||||||
equals(
|
equals(
|
||||||
DocumentFilter.initial.copyWith(
|
DocumentFilter.initial.copyWith(
|
||||||
correspondent: const CorrespondentQuery.fromId(42),
|
correspondent: const IdQueryParameter.fromId(42),
|
||||||
documentType: const DocumentTypeQuery.fromId(69),
|
documentType: const IdQueryParameter.fromId(69),
|
||||||
storagePath: const StoragePathQuery.fromId(14),
|
storagePath: const IdQueryParameter.fromId(14),
|
||||||
tags: IdsTagsQuery(
|
tags: const IdsTagsQuery(
|
||||||
[
|
[
|
||||||
IncludeTagIdQuery(1),
|
IncludeTagIdQuery(1),
|
||||||
IncludeTagIdQuery(2),
|
IncludeTagIdQuery(2),
|
||||||
@@ -85,10 +76,14 @@ void main() {
|
|||||||
ExcludeTagIdQuery(4),
|
ExcludeTagIdQuery(4),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
createdDateBefore: DateTime.parse("2022-10-27"),
|
created: AbsoluteDateRangeQuery(
|
||||||
createdDateAfter: DateTime.parse("2022-09-27"),
|
before: DateTime.parse("2022-10-27"),
|
||||||
addedDateBefore: DateTime.parse("2022-09-26"),
|
after: DateTime.parse("2022-09-27"),
|
||||||
addedDateAfter: DateTime.parse("2000-01-01"),
|
),
|
||||||
|
added: AbsoluteDateRangeQuery(
|
||||||
|
before: DateTime.parse("2022-09-26"),
|
||||||
|
after: DateTime.parse("2000-01-01"),
|
||||||
|
),
|
||||||
sortField: SortField.created,
|
sortField: SortField.created,
|
||||||
sortOrder: SortOrder.descending,
|
sortOrder: SortOrder.descending,
|
||||||
queryText: "Never gonna give you up",
|
queryText: "Never gonna give you up",
|
||||||
@@ -114,8 +109,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Values are correctly parsed if not assigned.', () {
|
test('Values are correctly parsed if not assigned.', () {
|
||||||
expect(
|
final actual = SavedView.fromJson({
|
||||||
SavedView.fromJson({
|
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "test_name",
|
"name": "test_name",
|
||||||
"show_on_dashboard": false,
|
"show_on_dashboard": false,
|
||||||
@@ -140,13 +134,16 @@ void main() {
|
|||||||
'value': null,
|
'value': null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}).toDocumentFilter(),
|
}).toDocumentFilter();
|
||||||
equals(DocumentFilter.initial.copyWith(
|
final expected = DocumentFilter.initial.copyWith(
|
||||||
correspondent: const CorrespondentQuery.notAssigned(),
|
correspondent: const IdQueryParameter.notAssigned(),
|
||||||
documentType: const DocumentTypeQuery.notAssigned(),
|
documentType: const IdQueryParameter.notAssigned(),
|
||||||
storagePath: const StoragePathQuery.notAssigned(),
|
storagePath: const IdQueryParameter.notAssigned(),
|
||||||
tags: const OnlyNotAssignedTagsQuery(),
|
tags: const OnlyNotAssignedTagsQuery(),
|
||||||
)),
|
);
|
||||||
|
expect(
|
||||||
|
actual,
|
||||||
|
equals(expected),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -156,10 +153,10 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
SavedView.fromDocumentFilter(
|
SavedView.fromDocumentFilter(
|
||||||
DocumentFilter(
|
DocumentFilter(
|
||||||
correspondent: const CorrespondentQuery.fromId(1),
|
correspondent: const IdQueryParameter.fromId(1),
|
||||||
documentType: const DocumentTypeQuery.fromId(2),
|
documentType: const IdQueryParameter.fromId(2),
|
||||||
storagePath: const StoragePathQuery.fromId(3),
|
storagePath: const IdQueryParameter.fromId(3),
|
||||||
tags: IdsTagsQuery([
|
tags: const IdsTagsQuery([
|
||||||
IncludeTagIdQuery(4),
|
IncludeTagIdQuery(4),
|
||||||
IncludeTagIdQuery(5),
|
IncludeTagIdQuery(5),
|
||||||
ExcludeTagIdQuery(6),
|
ExcludeTagIdQuery(6),
|
||||||
@@ -168,10 +165,14 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
sortField: SortField.added,
|
sortField: SortField.added,
|
||||||
sortOrder: SortOrder.ascending,
|
sortOrder: SortOrder.ascending,
|
||||||
addedDateAfter: DateTime.parse("2020-01-01"),
|
created: AbsoluteDateRangeQuery(
|
||||||
addedDateBefore: DateTime.parse("2020-03-01"),
|
before: DateTime.parse("2020-04-01"),
|
||||||
createdDateAfter: DateTime.parse("2020-02-01"),
|
after: DateTime.parse("2020-02-01"),
|
||||||
createdDateBefore: DateTime.parse("2020-04-01"),
|
),
|
||||||
|
added: AbsoluteDateRangeQuery(
|
||||||
|
before: DateTime.parse("2020-03-01"),
|
||||||
|
after: DateTime.parse("2020-01-01"),
|
||||||
|
),
|
||||||
queryText: "Never gonna let you down",
|
queryText: "Never gonna let you down",
|
||||||
queryType: QueryType.title,
|
queryType: QueryType.title,
|
||||||
),
|
),
|
||||||
@@ -210,16 +211,14 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
SavedView.fromDocumentFilter(
|
SavedView.fromDocumentFilter(
|
||||||
const DocumentFilter(
|
const DocumentFilter(
|
||||||
correspondent: CorrespondentQuery.unset(),
|
correspondent: IdQueryParameter.unset(),
|
||||||
documentType: DocumentTypeQuery.unset(),
|
documentType: IdQueryParameter.unset(),
|
||||||
storagePath: StoragePathQuery.unset(),
|
storagePath: IdQueryParameter.unset(),
|
||||||
tags: IdsTagsQuery(),
|
tags: IdsTagsQuery(),
|
||||||
sortField: SortField.created,
|
sortField: SortField.created,
|
||||||
sortOrder: SortOrder.descending,
|
sortOrder: SortOrder.descending,
|
||||||
addedDateAfter: null,
|
added: UnsetDateRangeQuery(),
|
||||||
addedDateBefore: null,
|
created: UnsetDateRangeQuery(),
|
||||||
createdDateAfter: null,
|
|
||||||
createdDateBefore: null,
|
|
||||||
queryText: null,
|
queryText: null,
|
||||||
),
|
),
|
||||||
name: "test_name",
|
name: "test_name",
|
||||||
@@ -243,9 +242,9 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
SavedView.fromDocumentFilter(
|
SavedView.fromDocumentFilter(
|
||||||
const DocumentFilter(
|
const DocumentFilter(
|
||||||
correspondent: CorrespondentQuery.notAssigned(),
|
correspondent: IdQueryParameter.notAssigned(),
|
||||||
documentType: DocumentTypeQuery.notAssigned(),
|
documentType: IdQueryParameter.notAssigned(),
|
||||||
storagePath: StoragePathQuery.notAssigned(),
|
storagePath: IdQueryParameter.notAssigned(),
|
||||||
tags: OnlyNotAssignedTagsQuery(),
|
tags: OnlyNotAssignedTagsQuery(),
|
||||||
sortField: SortField.created,
|
sortField: SortField.created,
|
||||||
sortOrder: SortOrder.ascending,
|
sortOrder: SortOrder.ascending,
|
||||||
|
|||||||
Reference in New Issue
Block a user