mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-13 04:12:16 -06:00
Implemented basics of extended queries
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
|
|||||||
import 'package:paperless_api/src/constants.dart';
|
import 'package:paperless_api/src/constants.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/asn_query.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/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/document_type_query.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/query_type.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_field.dart';
|
||||||
@@ -29,16 +30,12 @@ class DocumentFilter extends Equatable {
|
|||||||
final TagsQuery tags;
|
final TagsQuery tags;
|
||||||
final SortField sortField;
|
final SortField sortField;
|
||||||
final SortOrder sortOrder;
|
final SortOrder sortOrder;
|
||||||
final DateTime? addedDateAfter;
|
final DateRangeQuery added;
|
||||||
final DateTime? addedDateBefore;
|
final DateRangeQuery created;
|
||||||
final DateTime? createdDateAfter;
|
|
||||||
final DateTime? createdDateBefore;
|
|
||||||
final QueryType queryType;
|
final QueryType queryType;
|
||||||
final String? queryText;
|
final String? queryText;
|
||||||
|
|
||||||
const DocumentFilter({
|
const DocumentFilter({
|
||||||
this.createdDateAfter,
|
|
||||||
this.createdDateBefore,
|
|
||||||
this.documentType = const DocumentTypeQuery.unset(),
|
this.documentType = const DocumentTypeQuery.unset(),
|
||||||
this.correspondent = const CorrespondentQuery.unset(),
|
this.correspondent = const CorrespondentQuery.unset(),
|
||||||
this.storagePath = const StoragePathQuery.unset(),
|
this.storagePath = const StoragePathQuery.unset(),
|
||||||
@@ -48,53 +45,39 @@ class DocumentFilter extends Equatable {
|
|||||||
this.sortOrder = SortOrder.descending,
|
this.sortOrder = SortOrder.descending,
|
||||||
this.page = 1,
|
this.page = 1,
|
||||||
this.pageSize = 25,
|
this.pageSize = 25,
|
||||||
this.addedDateAfter,
|
|
||||||
this.addedDateBefore,
|
|
||||||
this.queryType = QueryType.titleAndContent,
|
this.queryType = QueryType.titleAndContent,
|
||||||
this.queryText,
|
this.queryText,
|
||||||
|
this.added = const UnsetDateRangeQuery(),
|
||||||
|
this.created = const UnsetDateRangeQuery(),
|
||||||
});
|
});
|
||||||
|
|
||||||
String toQueryString() {
|
Map<String, String> toQueryParameters() {
|
||||||
final StringBuffer sb = StringBuffer("page=$page&page_size=$pageSize");
|
Map<String, String> params = {
|
||||||
sb.write(documentType.toQueryParameter());
|
'page': page.toString(),
|
||||||
sb.write(correspondent.toQueryParameter());
|
'page_size': pageSize.toString(),
|
||||||
sb.write(tags.toQueryParameter());
|
};
|
||||||
sb.write(storagePath.toQueryParameter());
|
|
||||||
sb.write(asnQuery.toQueryParameter());
|
|
||||||
|
|
||||||
|
params.addAll(documentType.toQueryParameter());
|
||||||
|
params.addAll(correspondent.toQueryParameter());
|
||||||
|
params.addAll(tags.toQueryParameter());
|
||||||
|
params.addAll(storagePath.toQueryParameter());
|
||||||
|
params.addAll(asnQuery.toQueryParameter());
|
||||||
|
params.addAll(added.toQueryParameter());
|
||||||
|
params.addAll(created.toQueryParameter());
|
||||||
|
//TODO: Rework when implementing extended queries.
|
||||||
if (queryText?.isNotEmpty ?? false) {
|
if (queryText?.isNotEmpty ?? false) {
|
||||||
sb.write("&${queryType.queryParam}=$queryText");
|
params.putIfAbsent(queryType.queryParam, () => queryText!);
|
||||||
}
|
}
|
||||||
|
// Reverse ordering can also be encoded using &reverse=1
|
||||||
|
params.putIfAbsent(
|
||||||
|
'ordering', () => '${sortOrder.queryString}${sortField.queryString}');
|
||||||
|
|
||||||
sb.write("&ordering=${sortOrder.queryString}${sortField.queryString}");
|
return params;
|
||||||
|
|
||||||
// Add/subtract one day in the following because paperless uses gt/lt not gte/lte
|
|
||||||
if (addedDateAfter != null) {
|
|
||||||
sb.write(
|
|
||||||
"&added__date__gt=${apiDateFormat.format(addedDateAfter!.subtract(_oneDay))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addedDateBefore != null) {
|
|
||||||
sb.write(
|
|
||||||
"&added__date__lt=${apiDateFormat.format(addedDateBefore!.add(_oneDay))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (createdDateAfter != null) {
|
|
||||||
sb.write(
|
|
||||||
"&created__date__gt=${apiDateFormat.format(createdDateAfter!.subtract(_oneDay))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (createdDateBefore != null) {
|
|
||||||
sb.write(
|
|
||||||
"&created__date__lt=${apiDateFormat.format(createdDateBefore!.add(_oneDay))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return toQueryString();
|
return toQueryParameters().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentFilter copyWith({
|
DocumentFilter copyWith({
|
||||||
@@ -108,10 +91,8 @@ class DocumentFilter extends Equatable {
|
|||||||
TagsQuery? tags,
|
TagsQuery? tags,
|
||||||
SortField? sortField,
|
SortField? sortField,
|
||||||
SortOrder? sortOrder,
|
SortOrder? sortOrder,
|
||||||
DateTime? addedDateAfter,
|
DateRangeQuery? added,
|
||||||
DateTime? addedDateBefore,
|
DateRangeQuery? created,
|
||||||
DateTime? createdDateBefore,
|
|
||||||
DateTime? createdDateAfter,
|
|
||||||
QueryType? queryType,
|
QueryType? queryType,
|
||||||
String? queryText,
|
String? queryText,
|
||||||
}) {
|
}) {
|
||||||
@@ -124,13 +105,11 @@ 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,
|
||||||
addedDateAfter: addedDateAfter ?? this.addedDateAfter,
|
added: added ?? this.added,
|
||||||
addedDateBefore: addedDateBefore ?? this.addedDateBefore,
|
|
||||||
queryType: queryType ?? this.queryType,
|
queryType: queryType ?? this.queryType,
|
||||||
queryText: queryText ?? this.queryText,
|
queryText: queryText ?? this.queryText,
|
||||||
createdDateBefore: createdDateBefore ?? this.createdDateBefore,
|
|
||||||
createdDateAfter: createdDateAfter ?? this.createdDateAfter,
|
|
||||||
asnQuery: asnQuery ?? this.asnQuery,
|
asnQuery: asnQuery ?? this.asnQuery,
|
||||||
|
created: created ?? this.created,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,10 +139,8 @@ class DocumentFilter extends Equatable {
|
|||||||
correspondent != initial.correspondent,
|
correspondent != initial.correspondent,
|
||||||
storagePath != initial.storagePath,
|
storagePath != initial.storagePath,
|
||||||
tags != initial.tags,
|
tags != initial.tags,
|
||||||
(addedDateAfter != initial.addedDateAfter ||
|
(added != initial.added),
|
||||||
addedDateBefore != initial.addedDateBefore),
|
(created != initial.created),
|
||||||
(createdDateAfter != initial.createdDateAfter ||
|
|
||||||
createdDateBefore != initial.createdDateBefore),
|
|
||||||
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);
|
||||||
@@ -179,10 +156,8 @@ class DocumentFilter extends Equatable {
|
|||||||
tags,
|
tags,
|
||||||
sortField,
|
sortField,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
addedDateAfter,
|
added,
|
||||||
addedDateBefore,
|
created,
|
||||||
createdDateAfter,
|
|
||||||
createdDateBefore,
|
|
||||||
queryType,
|
queryType,
|
||||||
queryText,
|
queryText,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.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/document_filter.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/correspondent_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/document_type_query.dart';
|
||||||
import 'package:paperless_api/src/models/query_parameters/query_type.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/storage_path_query.dart';
|
||||||
@@ -18,6 +19,8 @@ class FilterRule with EquatableMixin {
|
|||||||
static const int createdAfterRule = 9;
|
static const int createdAfterRule = 9;
|
||||||
static const int addedBeforeRule = 13;
|
static const int addedBeforeRule = 13;
|
||||||
static const int addedAfterRule = 14;
|
static const int addedAfterRule = 14;
|
||||||
|
static const int modifiedBeforeRule = 15;
|
||||||
|
static const int modifiedAfterRule = 16;
|
||||||
static const int excludeTagsRule = 17;
|
static const int excludeTagsRule = 17;
|
||||||
static const int titleAndContentRule = 19;
|
static const int titleAndContentRule = 19;
|
||||||
static const int extendedRule = 20;
|
static const int extendedRule = 20;
|
||||||
@@ -28,14 +31,15 @@ class FilterRule with EquatableMixin {
|
|||||||
static const int _createdYearIs = 10;
|
static const int _createdYearIs = 10;
|
||||||
static const int _createdMonthIs = 11;
|
static const int _createdMonthIs = 11;
|
||||||
static const int _createdDayIs = 12;
|
static const int _createdDayIs = 12;
|
||||||
static const int _modifiedBefore = 15;
|
|
||||||
static const int _modifiedAfter = 16;
|
|
||||||
static const int _doesNotHaveAsn = 18;
|
static const int _doesNotHaveAsn = 18;
|
||||||
static const int _moreLikeThis = 21;
|
static const int _moreLikeThis = 21;
|
||||||
static const int _hasTagsIn = 22;
|
static const int _hasTagsIn = 22;
|
||||||
static const int _asnGreaterThan = 23;
|
static const int _asnGreaterThan = 23;
|
||||||
static const int _asnLessThan = 24;
|
static const int _asnLessThan = 24;
|
||||||
|
|
||||||
|
static const String _lastNDateRangeQueryRegex =
|
||||||
|
r"(?<field>created|added|modified):\[(?<n>-?\d+) (?<unit>day|week|month|year) to now\]";
|
||||||
|
|
||||||
final int ruleType;
|
final int ruleType;
|
||||||
final String? value;
|
final String? value;
|
||||||
|
|
||||||
@@ -53,6 +57,9 @@ 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:
|
||||||
@@ -94,34 +101,107 @@ class FilterRule with EquatableMixin {
|
|||||||
.withIdQueriesAdded([ExcludeTagIdQuery(int.parse(value!))]),
|
.withIdQueriesAdded([ExcludeTagIdQuery(int.parse(value!))]),
|
||||||
);
|
);
|
||||||
case createdBeforeRule:
|
case createdBeforeRule:
|
||||||
return filter.copyWith(
|
if (filter.created is FixedDateRangeQuery) {
|
||||||
createdDateBefore: value == null ? null : DateTime.parse(value!),
|
return filter.copyWith(
|
||||||
);
|
created: (filter.created as FixedDateRangeQuery)
|
||||||
|
.copyWith(before: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return filter.copyWith(
|
||||||
|
created:
|
||||||
|
FixedDateRangeQuery.created(before: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
case createdAfterRule:
|
case createdAfterRule:
|
||||||
return filter.copyWith(
|
if (filter.created is FixedDateRangeQuery) {
|
||||||
createdDateAfter: value == null ? null : DateTime.parse(value!),
|
return filter.copyWith(
|
||||||
);
|
created: (filter.created as FixedDateRangeQuery)
|
||||||
|
.copyWith(after: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return filter.copyWith(
|
||||||
|
created: FixedDateRangeQuery.created(after: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
case addedBeforeRule:
|
case addedBeforeRule:
|
||||||
return filter.copyWith(
|
if (filter.added is FixedDateRangeQuery) {
|
||||||
addedDateBefore: value == null ? null : DateTime.parse(value!),
|
return filter.copyWith(
|
||||||
);
|
added: (filter.added as FixedDateRangeQuery)
|
||||||
|
.copyWith(before: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return filter.copyWith(
|
||||||
|
added: FixedDateRangeQuery.added(before: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
case addedAfterRule:
|
case addedAfterRule:
|
||||||
return filter.copyWith(
|
if (filter.added is FixedDateRangeQuery) {
|
||||||
addedDateAfter: value == null ? null : DateTime.parse(value!),
|
return filter.copyWith(
|
||||||
);
|
added: (filter.added as FixedDateRangeQuery)
|
||||||
|
.copyWith(after: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return filter.copyWith(
|
||||||
|
added: FixedDateRangeQuery.added(after: DateTime.parse(value!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
case titleAndContentRule:
|
case titleAndContentRule:
|
||||||
return filter.copyWith(
|
return filter.copyWith(
|
||||||
queryText: value,
|
queryText: value,
|
||||||
queryType: QueryType.titleAndContent,
|
queryType: QueryType.titleAndContent,
|
||||||
);
|
);
|
||||||
case extendedRule:
|
case extendedRule:
|
||||||
|
_parseExtendedRule(filter);
|
||||||
return filter.copyWith(queryText: value, queryType: QueryType.extended);
|
return filter.copyWith(queryText: value, queryType: QueryType.extended);
|
||||||
//TODO: Add currently unused rules
|
|
||||||
default:
|
default:
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DocumentFilter _parseExtendedRule(final DocumentFilter filter) {
|
||||||
|
DocumentFilter newFilter = filter;
|
||||||
|
assert(value != null);
|
||||||
|
final dateRangeRegExp = RegExp(_lastNDateRangeQueryRegex);
|
||||||
|
if (dateRangeRegExp.hasMatch(value!)) {
|
||||||
|
final matches = dateRangeRegExp.allMatches(value!);
|
||||||
|
for (final match in matches) {
|
||||||
|
final field = match.namedGroup('field')!;
|
||||||
|
final n = int.parse(match.namedGroup('n')!);
|
||||||
|
final unit = match.namedGroup('unit')!;
|
||||||
|
switch (field) {
|
||||||
|
case 'created':
|
||||||
|
newFilter = newFilter.copyWith(
|
||||||
|
created: LastNDateRangeQuery.created(
|
||||||
|
n,
|
||||||
|
DateRangeUnit.values.byName(unit),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'added':
|
||||||
|
newFilter = newFilter.copyWith(
|
||||||
|
created: LastNDateRangeQuery.added(
|
||||||
|
n,
|
||||||
|
DateRangeUnit.values.byName(unit),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'modified':
|
||||||
|
newFilter = newFilter.copyWith(
|
||||||
|
created: LastNDateRangeQuery.modified(
|
||||||
|
n,
|
||||||
|
DateRangeUnit.values.byName(unit),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newFilter;
|
||||||
|
} else {
|
||||||
|
// Match other extended query types... currently not supported!
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Converts a [DocumentFilter] to a list of [FilterRule]s.
|
/// Converts a [DocumentFilter] to a list of [FilterRule]s.
|
||||||
///
|
///
|
||||||
@@ -179,22 +259,65 @@ class FilterRule with EquatableMixin {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filter.createdDateAfter != null) {
|
|
||||||
filterRules.add(FilterRule(
|
// Parse created at
|
||||||
createdAfterRule, apiDateFormat.format(filter.createdDateAfter!)));
|
final created = filter.created;
|
||||||
|
if (created is FixedDateRangeQuery) {
|
||||||
|
if (created.after != null) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(createdAfterRule, apiDateFormat.format(created.after!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (created.before != null) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(createdBeforeRule, apiDateFormat.format(created.before!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (created is LastNDateRangeQuery) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(extendedRule, created.toQueryParameter().values.first),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (filter.createdDateBefore != null) {
|
|
||||||
filterRules.add(FilterRule(
|
// Parse added at
|
||||||
createdBeforeRule, apiDateFormat.format(filter.createdDateBefore!)));
|
final added = filter.added;
|
||||||
|
if (added is FixedDateRangeQuery) {
|
||||||
|
if (added.after != null) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(addedAfterRule, apiDateFormat.format(added.after!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (added.before != null) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(addedBeforeRule, apiDateFormat.format(added.before!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (added is LastNDateRangeQuery) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(extendedRule, added.toQueryParameter().values.first),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (filter.addedDateAfter != null) {
|
|
||||||
filterRules.add(FilterRule(
|
// Parse modified at
|
||||||
addedAfterRule, apiDateFormat.format(filter.addedDateAfter!)));
|
final modified = filter.added;
|
||||||
}
|
if (modified is FixedDateRangeQuery) {
|
||||||
if (filter.addedDateBefore != null) {
|
if (modified.after != null) {
|
||||||
filterRules.add(FilterRule(
|
filterRules.add(
|
||||||
addedBeforeRule, apiDateFormat.format(filter.addedDateBefore!)));
|
FilterRule(modifiedAfterRule, apiDateFormat.format(modified.after!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (modified.before != null) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(
|
||||||
|
modifiedBeforeRule, apiDateFormat.format(modified.before!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (modified is LastNDateRangeQuery) {
|
||||||
|
filterRules.add(
|
||||||
|
FilterRule(extendedRule, modified.toQueryParameter().values.first),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return filterRules;
|
return filterRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:paperless_api/src/constants.dart';
|
||||||
|
|
||||||
|
abstract class DateRangeQuery extends Equatable {
|
||||||
|
const DateRangeQuery();
|
||||||
|
Map<String, String> toQueryParameter();
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnsetDateRangeQuery extends DateRangeQuery {
|
||||||
|
const UnsetDateRangeQuery();
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, String> toQueryParameter() => const {};
|
||||||
|
}
|
||||||
|
|
||||||
|
class FixedDateRangeQuery extends DateRangeQuery {
|
||||||
|
final String _querySuffix;
|
||||||
|
|
||||||
|
final DateTime? after;
|
||||||
|
final DateTime? before;
|
||||||
|
|
||||||
|
const FixedDateRangeQuery._(this._querySuffix, {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
|
||||||
|
List<Object?> get props => [_querySuffix, after, before];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, String> toQueryParameter() {
|
||||||
|
final Map<String, String> params = {};
|
||||||
|
|
||||||
|
// Add/subtract one day in the following because paperless uses gt/lt not gte/lte
|
||||||
|
if (after != null) {
|
||||||
|
params.putIfAbsent('${_querySuffix}__date__gt',
|
||||||
|
() => apiDateFormat.format(after!.subtract(const Duration(days: 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (before != null) {
|
||||||
|
params.putIfAbsent('${_querySuffix}__date__lt',
|
||||||
|
() => apiDateFormat.format(before!.add(const Duration(days: 1))));
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedDateRangeQuery copyWith({
|
||||||
|
DateTime? before,
|
||||||
|
DateTime? after,
|
||||||
|
}) {
|
||||||
|
return FixedDateRangeQuery._(
|
||||||
|
_querySuffix,
|
||||||
|
before: before ?? this.before,
|
||||||
|
after: after ?? this.after,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LastNDateRangeQuery extends DateRangeQuery {
|
||||||
|
final DateRangeUnit unit;
|
||||||
|
final int n;
|
||||||
|
final String _field;
|
||||||
|
|
||||||
|
const LastNDateRangeQuery._(
|
||||||
|
this._field, {
|
||||||
|
required this.n,
|
||||||
|
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
|
||||||
|
// TODO: implement props
|
||||||
|
List<Object?> get props => [_field, n, unit];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, String> toQueryParameter() {
|
||||||
|
return {
|
||||||
|
'query': '[$_field:$n ${unit.name} to now]',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DateRangeUnit {
|
||||||
|
day,
|
||||||
|
week,
|
||||||
|
month,
|
||||||
|
year;
|
||||||
|
}
|
||||||
@@ -30,14 +30,16 @@ abstract class IdQueryParameter extends Equatable {
|
|||||||
|
|
||||||
String get queryParameterKey;
|
String get queryParameterKey;
|
||||||
|
|
||||||
String toQueryParameter() {
|
Map<String, String> toQueryParameter() {
|
||||||
|
final Map<String, String> params = {};
|
||||||
if (onlyNotAssigned || onlyAssigned) {
|
if (onlyNotAssigned || onlyAssigned) {
|
||||||
return "&${queryParameterKey}__isnull=$_assignmentStatus";
|
params.putIfAbsent(
|
||||||
|
'${queryParameterKey}__isnull', () => _assignmentStatus!.toString());
|
||||||
}
|
}
|
||||||
if (isSet) {
|
if (isSet) {
|
||||||
return "&${queryParameterKey}__id=$id";
|
params.putIfAbsent("${queryParameterKey}__id", () => id!.toString());
|
||||||
}
|
}
|
||||||
return "";
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import 'package:equatable/equatable.dart';
|
|||||||
|
|
||||||
abstract class TagsQuery extends Equatable {
|
abstract class TagsQuery extends Equatable {
|
||||||
const TagsQuery();
|
const TagsQuery();
|
||||||
String toQueryParameter();
|
Map<String, String> toQueryParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnlyNotAssignedTagsQuery extends TagsQuery {
|
class OnlyNotAssignedTagsQuery extends TagsQuery {
|
||||||
const OnlyNotAssignedTagsQuery();
|
const OnlyNotAssignedTagsQuery();
|
||||||
@override
|
@override
|
||||||
String toQueryParameter() {
|
Map<String, String> toQueryParameter() {
|
||||||
return '&is_tagged=0';
|
return {'is_tagged': '0'};
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -24,11 +24,11 @@ class AnyAssignedTagsQuery extends TagsQuery {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toQueryParameter() {
|
Map<String, String> toQueryParameter() {
|
||||||
if (tagIds.isEmpty) {
|
if (tagIds.isEmpty) {
|
||||||
return '&is_tagged=1';
|
return {'is_tagged': '1'};
|
||||||
}
|
}
|
||||||
return '&tags__id__in=${tagIds.join(',')}';
|
return {'tags__id__in': tagIds.join(',')};
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -89,15 +89,15 @@ class IdsTagsQuery extends TagsQuery {
|
|||||||
Iterable<int> get ids => [...includedIds, ...excludedIds];
|
Iterable<int> get ids => [...includedIds, ...excludedIds];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toQueryParameter() {
|
Map<String, String> toQueryParameter() {
|
||||||
final StringBuffer sb = StringBuffer("");
|
final Map<String, String> params = {};
|
||||||
if (includedIds.isNotEmpty) {
|
if (includedIds.isNotEmpty) {
|
||||||
sb.write('&tags__id__all=${includedIds.join(',')}');
|
params.putIfAbsent('tags__id__all', () => includedIds.join(','));
|
||||||
}
|
}
|
||||||
if (excludedIds.isNotEmpty) {
|
if (excludedIds.isNotEmpty) {
|
||||||
sb.write('&tags__id__none=${excludedIds.join(',')}');
|
params.putIfAbsent('tags__id__none', () => excludedIds.join(','));
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -136,9 +136,12 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PagedSearchResult<DocumentModel>> find(DocumentFilter filter) async {
|
Future<PagedSearchResult<DocumentModel>> find(DocumentFilter filter) async {
|
||||||
final filterParams = filter.toQueryString();
|
final filterParams = filter.toQueryParameters();
|
||||||
final response = await baseClient.get(
|
final response = await baseClient.get(
|
||||||
Uri.parse("/api/documents/?$filterParams"),
|
Uri(
|
||||||
|
path: "/api/documents/?$filterParams",
|
||||||
|
queryParameters: filterParams,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return compute(
|
return compute(
|
||||||
|
|||||||
Reference in New Issue
Block a user