Fixed bugs, added serialization for documents state

This commit is contained in:
Anton Stubenbord
2023-01-06 18:22:43 +01:00
parent 738ef99bc5
commit 23bcb355b1
76 changed files with 1333 additions and 595 deletions

View File

@@ -2,3 +2,4 @@ library paperless_api;
export 'src/models/models.dart';
export 'src/modules/modules.dart';
export 'src/converters/converters.dart';

View File

@@ -0,0 +1,3 @@
export 'document_model_json_converter.dart';
export 'similar_document_model_json_converter.dart';
export 'date_range_query_json_converter.dart';

View File

@@ -0,0 +1,32 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/models/models.dart';
import 'package:paperless_api/src/models/query_parameters/date_range_queries/absolute_date_range_query.dart';
import 'package:paperless_api/src/models/query_parameters/date_range_queries/relative_date_range_query.dart';
class DateRangeQueryJsonConverter
extends JsonConverter<DateRangeQuery, Map<String, dynamic>> {
const DateRangeQueryJsonConverter();
@override
DateRangeQuery fromJson(Map<String, dynamic> json) {
final type = json['type'];
final data = json['data'];
switch (json['type'] as String) {
case 'UnsetDateRangeQuery':
return const UnsetDateRangeQuery();
case 'AbsoluteDateRangeQuery':
return AbsoluteDateRangeQuery.fromJson(data);
case 'RelativeDateRangeQuery':
return RelativeDateRangeQuery.fromJson(data);
default:
throw Exception('Error parsing DateRangeQuery: Unknown type $type');
}
}
@override
Map<String, dynamic> toJson(DateRangeQuery object) {
return {
'type': object.runtimeType.toString(),
'data': object.toJson(),
};
}
}

View File

@@ -0,0 +1,15 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/models/document_model.dart';
class DocumentModelJsonConverter
extends JsonConverter<DocumentModel, Map<String, dynamic>> {
@override
DocumentModel fromJson(Map<String, dynamic> json) {
return DocumentModel.fromJson(json);
}
@override
Map<String, dynamic> toJson(DocumentModel object) {
return object.toJson();
}
}

View File

@@ -1,21 +0,0 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/models/models.dart';
class IdQueryParameterJsonConverter
extends JsonConverter<IdQueryParameter, Map<String, dynamic>> {
const IdQueryParameterJsonConverter();
static const _idKey = "id";
static const _assignmentStatusKey = 'assignmentStatus';
@override
IdQueryParameter fromJson(Map<String, dynamic> json) {
return IdQueryParameter(json[_assignmentStatusKey], json[_idKey]);
}
@override
Map<String, dynamic> toJson(IdQueryParameter object) {
return {
_idKey: object.id,
_assignmentStatusKey: object.assignmentStatus,
};
}
}

View File

@@ -0,0 +1,15 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/paperless_api.dart';
class SimilarDocumentModelJsonConverter
extends JsonConverter<SimilarDocumentModel, Map<String, dynamic>> {
@override
SimilarDocumentModel fromJson(Map<String, dynamic> json) {
return SimilarDocumentModel.fromJson(json);
}
@override
Map<String, dynamic> toJson(SimilarDocumentModel object) {
return object.toJson();
}
}

View File

@@ -0,0 +1,34 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/models/query_parameters/tags_query/any_assigned_tags_query.dart';
import 'package:paperless_api/src/models/query_parameters/tags_query/ids_tags_query.dart';
import 'package:paperless_api/src/models/query_parameters/tags_query/only_not_assigned_tags_query.dart';
import '../models/query_parameters/tags_query/tags_query.dart';
class TagsQueryJsonConverter
extends JsonConverter<TagsQuery, Map<String, dynamic>> {
const TagsQueryJsonConverter();
@override
TagsQuery fromJson(Map<String, dynamic> json) {
final type = json['type'] as String;
final data = json['data'] as Map<String, dynamic>;
switch (type) {
case 'OnlyNotAssignedTagsQuery':
return const OnlyNotAssignedTagsQuery();
case 'AnyAssignedTagsQuery':
return AnyAssignedTagsQuery.fromJson(data);
case 'IdsTagsQuery':
return IdsTagsQuery.fromJson(data);
default:
throw Exception('Error parsing TagsQuery: Unknown type $type');
}
}
@override
Map<String, dynamic> toJson(TagsQuery object) {
return {
'type': object.runtimeType.toString(),
'data': object.toJson(),
};
}
}

View File

@@ -1,10 +1,14 @@
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:paperless_api/src/models/query_parameters/text_query.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:collection/collection.dart';
import 'package:paperless_api/src/converters/tags_query_json_converter.dart';
@JsonSerializable()
part 'document_filter.g.dart';
@TagsQueryJsonConverter()
@DateRangeQueryJsonConverter()
@JsonSerializable(explicitToJson: true)
class DocumentFilter extends Equatable {
static const DocumentFilter initial = DocumentFilter();
@@ -73,7 +77,7 @@ class DocumentFilter extends Equatable {
key,
entries.length == 1
? entries.first.value
: entries.map((e) => e.value).toList(),
: entries.map((e) => e.value).join(","),
),
);
return queryParams;
@@ -150,4 +154,9 @@ class DocumentFilter extends Equatable {
modified,
query,
];
factory DocumentFilter.fromJson(Map<String, dynamic> json) =>
_$DocumentFilterFromJson(json);
Map<String, dynamic> toJson() => _$DocumentFilterToJson(this);
}

View File

@@ -0,0 +1,83 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'document_filter.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
DocumentFilter _$DocumentFilterFromJson(Map<String, dynamic> json) =>
DocumentFilter(
documentType: json['documentType'] == null
? const IdQueryParameter.unset()
: IdQueryParameter.fromJson(
json['documentType'] as Map<String, dynamic>),
correspondent: json['correspondent'] == null
? const IdQueryParameter.unset()
: IdQueryParameter.fromJson(
json['correspondent'] as Map<String, dynamic>),
storagePath: json['storagePath'] == null
? const IdQueryParameter.unset()
: IdQueryParameter.fromJson(
json['storagePath'] as Map<String, dynamic>),
asnQuery: json['asnQuery'] == null
? const IdQueryParameter.unset()
: IdQueryParameter.fromJson(json['asnQuery'] as Map<String, dynamic>),
tags: json['tags'] == null
? const IdsTagsQuery()
: const TagsQueryJsonConverter()
.fromJson(json['tags'] as Map<String, dynamic>),
sortField: $enumDecodeNullable(_$SortFieldEnumMap, json['sortField']) ??
SortField.created,
sortOrder: $enumDecodeNullable(_$SortOrderEnumMap, json['sortOrder']) ??
SortOrder.descending,
page: json['page'] as int? ?? 1,
pageSize: json['pageSize'] as int? ?? 25,
query: json['query'] == null
? const TextQuery()
: TextQuery.fromJson(json['query'] as Map<String, dynamic>),
added: json['added'] == null
? const UnsetDateRangeQuery()
: const DateRangeQueryJsonConverter()
.fromJson(json['added'] as Map<String, dynamic>),
created: json['created'] == null
? const UnsetDateRangeQuery()
: const DateRangeQueryJsonConverter()
.fromJson(json['created'] as Map<String, dynamic>),
modified: json['modified'] == null
? const UnsetDateRangeQuery()
: const DateRangeQueryJsonConverter()
.fromJson(json['modified'] as Map<String, dynamic>),
);
Map<String, dynamic> _$DocumentFilterToJson(DocumentFilter instance) =>
<String, dynamic>{
'pageSize': instance.pageSize,
'page': instance.page,
'documentType': instance.documentType.toJson(),
'correspondent': instance.correspondent.toJson(),
'storagePath': instance.storagePath.toJson(),
'asnQuery': instance.asnQuery.toJson(),
'tags': const TagsQueryJsonConverter().toJson(instance.tags),
'sortField': _$SortFieldEnumMap[instance.sortField]!,
'sortOrder': _$SortOrderEnumMap[instance.sortOrder]!,
'created': const DateRangeQueryJsonConverter().toJson(instance.created),
'added': const DateRangeQueryJsonConverter().toJson(instance.added),
'modified': const DateRangeQueryJsonConverter().toJson(instance.modified),
'query': instance.query.toJson(),
};
const _$SortFieldEnumMap = {
SortField.archiveSerialNumber: 'archiveSerialNumber',
SortField.correspondentName: 'correspondentName',
SortField.title: 'title',
SortField.documentType: 'documentType',
SortField.created: 'created',
SortField.added: 'added',
SortField.modified: 'modified',
};
const _$SortOrderEnumMap = {
SortOrder.ascending: 'ascending',
SortOrder.descending: 'descending',
};

View File

@@ -1,8 +1,17 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_api/src/constants.dart';
import 'package:paperless_api/src/models/query_parameters/text_query.dart';
import 'query_parameters/tags_query/any_assigned_tags_query.dart';
import 'query_parameters/tags_query/exclude_tag_id_query.dart';
import 'query_parameters/tags_query/ids_tags_query.dart';
import 'query_parameters/tags_query/include_tag_id_query.dart';
import 'query_parameters/tags_query/only_not_assigned_tags_query.dart';
part 'filter_rule_model.g.dart';
@JsonSerializable()
class FilterRule with EquatableMixin {
static const int titleRule = 0;
static const int asnRule = 2;
@@ -35,22 +44,12 @@ class FilterRule with EquatableMixin {
static const String _lastNDateRangeQueryRegex =
r"(?<field>created|added|modified):\[-?(?<n>\d+) (?<unit>day|week|month|year) to now\]";
@JsonKey(name: 'rule_type')
final int ruleType;
final String? value;
FilterRule(this.ruleType, this.value);
FilterRule.fromJson(Map<String, dynamic> json)
: ruleType = json['rule_type'],
value = json['value'];
Map<String, dynamic> toJson() {
return {
'rule_type': ruleType,
'value': value,
};
}
DocumentFilter applyToFilter(final DocumentFilter filter) {
//TODO: Check in profiling mode if this is inefficient enough to cause stutters...
switch (ruleType) {
@@ -368,4 +367,9 @@ class FilterRule with EquatableMixin {
@override
List<Object?> get props => [ruleType, value];
Map<String, dynamic> toJson() => _$FilterRuleToJson(this);
factory FilterRule.fromJson(Map<String, dynamic> json) =>
_$FilterRuleFromJson(json);
}

View File

@@ -0,0 +1,18 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'filter_rule_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
FilterRule _$FilterRuleFromJson(Map<String, dynamic> json) => FilterRule(
json['rule_type'] as int,
json['value'] as String?,
);
Map<String, dynamic> _$FilterRuleToJson(FilterRule instance) =>
<String, dynamic>{
'rule_type': instance.ruleType,
'value': instance.value,
};

View File

@@ -8,8 +8,8 @@ export 'query_parameters/id_query_parameter.dart';
export 'query_parameters/query_type.dart';
export 'query_parameters/sort_field.dart';
export 'query_parameters/sort_order.dart';
export 'query_parameters/tags_query.dart';
export 'query_parameters/date_range_query.dart';
export 'query_parameters/tags_query/tags_queries.dart';
export 'query_parameters/date_range_queries/date_range_queries.dart';
export 'query_parameters/text_query.dart';
export 'bulk_edit_model.dart';
export 'document_filter.dart';

View File

@@ -4,15 +4,13 @@ import 'package:paperless_api/src/models/document_model.dart';
const pageRegex = r".*page=(\d+).*";
//Todo: make this an interface and delegate serialization to implementations
class PagedSearchResultJsonSerializer<T> {
final Map<String, dynamic> json;
final T Function(Map<String, dynamic>) fromJson;
JsonConverter<T, Map<String, dynamic>> converter;
PagedSearchResultJsonSerializer(this.json, this.fromJson);
PagedSearchResultJsonSerializer(this.json, this.converter);
}
@JsonSerializable()
class PagedSearchResult<T> extends Equatable {
/// Total number of available items
final int count;
@@ -54,18 +52,34 @@ class PagedSearchResult<T> extends Equatable {
required this.results,
});
factory PagedSearchResult.fromJson(
PagedSearchResultJsonSerializer<T> serializer) {
factory PagedSearchResult.fromJson(Map<String, dynamic> json,
JsonConverter<T, Map<String, dynamic>> converter) {
return PagedSearchResult(
count: serializer.json['count'],
next: serializer.json['next'],
previous: serializer.json['previous'],
results: List<Map<String, dynamic>>.from(serializer.json['results'])
.map<T>(serializer.fromJson)
count: json['count'],
next: json['next'],
previous: json['previous'],
results: List<Map<String, dynamic>>.from(json['results'])
.map<T>(converter.fromJson)
.toList(),
);
}
Map<String, dynamic> toJson(
JsonConverter<T, Map<String, dynamic>> converter) {
return {
'count': count,
'next': next,
'previous': previous,
'results': results.map((e) => converter.toJson(e)).toList()
};
}
factory PagedSearchResult.fromJsonSingleParam(
PagedSearchResultJsonSerializer<T> serializer,
) {
return PagedSearchResult.fromJson(serializer.json, serializer.converter);
}
PagedSearchResult copyWith({
int? count,
String? next,

View File

@@ -0,0 +1,51 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/constants.dart';
import 'date_range_query.dart';
import 'date_range_query_field.dart';
part 'absolute_date_range_query.g.dart';
@JsonSerializable()
class AbsoluteDateRangeQuery extends DateRangeQuery {
final DateTime? after;
final DateTime? before;
const AbsoluteDateRangeQuery({this.after, this.before});
@override
List<Object?> get props => [after, before];
@override
Map<String, String> toQueryParameter(DateRangeQueryField field) {
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('${field.name}__date__gt',
() => apiDateFormat.format(after!.subtract(const Duration(days: 1))));
}
if (before != null) {
params.putIfAbsent('${field.name}__date__lt',
() => apiDateFormat.format(before!.add(const Duration(days: 1))));
}
return params;
}
AbsoluteDateRangeQuery copyWith({
DateTime? before,
DateTime? after,
}) {
return AbsoluteDateRangeQuery(
before: before ?? this.before,
after: after ?? this.after,
);
}
factory AbsoluteDateRangeQuery.fromJson(json) =>
_$AbsoluteDateRangeQueryFromJson(json);
@override
Map<String, dynamic> toJson() => _$AbsoluteDateRangeQueryToJson(this);
}

View File

@@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'absolute_date_range_query.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
AbsoluteDateRangeQuery _$AbsoluteDateRangeQueryFromJson(
Map<String, dynamic> json) =>
AbsoluteDateRangeQuery(
after: json['after'] == null
? null
: DateTime.parse(json['after'] as String),
before: json['before'] == null
? null
: DateTime.parse(json['before'] as String),
);
Map<String, dynamic> _$AbsoluteDateRangeQueryToJson(
AbsoluteDateRangeQuery instance) =>
<String, dynamic>{
'after': instance.after?.toIso8601String(),
'before': instance.before?.toIso8601String(),
};

View File

@@ -0,0 +1,6 @@
export 'date_range_query.dart';
export 'unset_date_range_query.dart';
export 'absolute_date_range_query.dart';
export 'relative_date_range_query.dart';
export 'date_range_unit.dart';
export 'date_range_query_field.dart';

View File

@@ -0,0 +1,10 @@
import 'package:equatable/equatable.dart';
import 'date_range_query_field.dart';
abstract class DateRangeQuery extends Equatable {
const DateRangeQuery();
Map<String, String> toQueryParameter(DateRangeQueryField field);
Map<String, dynamic> toJson();
}

View File

@@ -0,0 +1,5 @@
enum DateRangeQueryField {
created,
added,
modified;
}

View File

@@ -0,0 +1,6 @@
enum DateRangeUnit {
day,
week,
month,
year;
}

View File

@@ -0,0 +1,43 @@
import 'package:json_annotation/json_annotation.dart';
import 'date_range_query.dart';
import 'date_range_query_field.dart';
import 'date_range_unit.dart';
part 'relative_date_range_query.g.dart';
@JsonSerializable()
class RelativeDateRangeQuery extends DateRangeQuery {
final int offset;
final DateRangeUnit unit;
const RelativeDateRangeQuery([
this.offset = 1,
this.unit = DateRangeUnit.day,
]);
@override
List<Object?> get props => [offset, unit];
@override
Map<String, String> toQueryParameter(DateRangeQueryField field) {
return {
'query': '${field.name}:[-$offset ${unit.name} to now]',
};
}
RelativeDateRangeQuery copyWith({
int? offset,
DateRangeUnit? unit,
}) {
return RelativeDateRangeQuery(
offset ?? this.offset,
unit ?? this.unit,
);
}
@override
Map<String, dynamic> toJson() => _$RelativeDateRangeQueryToJson(this);
factory RelativeDateRangeQuery.fromJson(Map<String, dynamic> json) =>
_$RelativeDateRangeQueryFromJson(json);
}

View File

@@ -0,0 +1,29 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'relative_date_range_query.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
RelativeDateRangeQuery _$RelativeDateRangeQueryFromJson(
Map<String, dynamic> json) =>
RelativeDateRangeQuery(
json['offset'] as int? ?? 1,
$enumDecodeNullable(_$DateRangeUnitEnumMap, json['unit']) ??
DateRangeUnit.day,
);
Map<String, dynamic> _$RelativeDateRangeQueryToJson(
RelativeDateRangeQuery instance) =>
<String, dynamic>{
'offset': instance.offset,
'unit': _$DateRangeUnitEnumMap[instance.unit]!,
};
const _$DateRangeUnitEnumMap = {
DateRangeUnit.day: 'day',
DateRangeUnit.week: 'week',
DateRangeUnit.month: 'month',
DateRangeUnit.year: 'year',
};

View File

@@ -0,0 +1,17 @@
import 'package:paperless_api/src/models/query_parameters/date_range_queries/date_range_query_field.dart';
import 'date_range_query.dart';
class UnsetDateRangeQuery extends DateRangeQuery {
const UnsetDateRangeQuery();
@override
List<Object?> get props => [];
@override
Map<String, String> toQueryParameter(DateRangeQueryField field) => const {};
@override
Map<String, dynamic> toJson() {
return {};
}
}

View File

@@ -1,96 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:paperless_api/src/constants.dart';
abstract class DateRangeQuery extends Equatable {
const DateRangeQuery();
Map<String, String> toQueryParameter(DateRangeQueryField field);
}
class UnsetDateRangeQuery extends DateRangeQuery {
const UnsetDateRangeQuery();
@override
List<Object?> get props => [];
@override
Map<String, String> toQueryParameter(DateRangeQueryField field) => const {};
}
class AbsoluteDateRangeQuery extends DateRangeQuery {
final DateTime? after;
final DateTime? before;
const AbsoluteDateRangeQuery({this.after, this.before});
@override
List<Object?> get props => [after, before];
@override
Map<String, String> toQueryParameter(DateRangeQueryField field) {
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('${field.name}__date__gt',
() => apiDateFormat.format(after!.subtract(const Duration(days: 1))));
}
if (before != null) {
params.putIfAbsent('${field.name}__date__lt',
() => apiDateFormat.format(before!.add(const Duration(days: 1))));
}
return params;
}
AbsoluteDateRangeQuery copyWith({
DateTime? before,
DateTime? after,
}) {
return AbsoluteDateRangeQuery(
before: before ?? this.before,
after: after ?? this.after,
);
}
}
class RelativeDateRangeQuery extends DateRangeQuery {
final int offset;
final DateRangeUnit unit;
const RelativeDateRangeQuery([
this.offset = 1,
this.unit = DateRangeUnit.day,
]);
@override
List<Object?> get props => [offset, unit];
@override
Map<String, String> toQueryParameter(DateRangeQueryField field) {
return {
'query': '${field.name}:[-$offset ${unit.name} to now]',
};
}
RelativeDateRangeQuery copyWith({
int? offset,
DateRangeUnit? unit,
}) {
return RelativeDateRangeQuery(
offset ?? this.offset,
unit ?? this.unit,
);
}
}
enum DateRangeUnit {
day,
week,
month,
year;
}
enum DateRangeQueryField {
created,
added,
modified;
}

View File

@@ -1,49 +1,43 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/converters/id_query_parameter_json_converter.dart';
part 'id_query_parameter.g.dart';
@IdQueryParameterJsonConverter()
@JsonSerializable()
class IdQueryParameter extends Equatable {
final int? _assignmentStatus;
final int? _id;
final int? assignmentStatus;
final int? id;
@Deprecated("Use named constructors, this is only meant for code generation")
const IdQueryParameter(this._assignmentStatus, this._id);
const IdQueryParameter(this.assignmentStatus, this.id);
const IdQueryParameter.notAssigned()
: _assignmentStatus = 1,
_id = null;
: assignmentStatus = 1,
id = null;
const IdQueryParameter.anyAssigned()
: _assignmentStatus = 0,
_id = null;
: assignmentStatus = 0,
id = null;
const IdQueryParameter.fromId(int? id)
: _assignmentStatus = null,
_id = id;
: assignmentStatus = null,
id = id;
const IdQueryParameter.unset() : this.fromId(null);
bool get isUnset => _id == null && _assignmentStatus == null;
bool get isUnset => id == null && assignmentStatus == null;
bool get isSet => _id != null && _assignmentStatus == null;
bool get isSet => id != null && assignmentStatus == null;
bool get onlyNotAssigned => _assignmentStatus == 1;
bool get onlyNotAssigned => assignmentStatus == 1;
bool get onlyAssigned => _assignmentStatus == 0;
int? get id => _id;
@visibleForTesting
int? get assignmentStatus => _assignmentStatus;
bool get onlyAssigned => assignmentStatus == 0;
Map<String, String> toQueryParameter(String field) {
final Map<String, String> params = {};
if (onlyNotAssigned || onlyAssigned) {
params.putIfAbsent(
'${field}__isnull', () => _assignmentStatus!.toString());
'${field}__isnull', () => assignmentStatus!.toString());
}
if (isSet) {
params.putIfAbsent("${field}__id", () => id!.toString());
@@ -52,5 +46,10 @@ class IdQueryParameter extends Equatable {
}
@override
List<Object?> get props => [_assignmentStatus, _id];
List<Object?> get props => [assignmentStatus, id];
Map<String, dynamic> toJson() => _$IdQueryParameterToJson(this);
factory IdQueryParameter.fromJson(Map<String, dynamic> json) =>
_$IdQueryParameterFromJson(json);
}

View File

@@ -0,0 +1,19 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'id_query_parameter.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
IdQueryParameter _$IdQueryParameterFromJson(Map<String, dynamic> json) =>
IdQueryParameter(
json['assignmentStatus'] as int?,
json['id'] as int?,
);
Map<String, dynamic> _$IdQueryParameterToJson(IdQueryParameter instance) =>
<String, dynamic>{
'assignmentStatus': instance.assignmentStatus,
'id': instance.id,
};

View File

@@ -0,0 +1,11 @@
import 'package:json_annotation/json_annotation.dart';
@JsonEnum()
enum TagsQueryType {
notAssigned,
anyAssigned,
ids,
id,
include,
exclude;
}

View File

@@ -1,3 +1,6 @@
import 'package:json_annotation/json_annotation.dart';
@JsonEnum()
enum SortField {
archiveSerialNumber("archive_serial_number"),
correspondentName("correspondent__name"),

View File

@@ -1,3 +1,6 @@
import 'package:json_annotation/json_annotation.dart';
@JsonEnum()
enum SortOrder {
ascending(""),
descending("-");

View File

@@ -0,0 +1,30 @@
import 'package:json_annotation/json_annotation.dart';
import 'tags_query.dart';
part 'any_assigned_tags_query.g.dart';
@JsonSerializable(explicitToJson: true)
class AnyAssignedTagsQuery extends TagsQuery {
final Iterable<int> tagIds;
const AnyAssignedTagsQuery({
this.tagIds = const [],
});
@override
Map<String, String> toQueryParameter() {
if (tagIds.isEmpty) {
return {'is_tagged': '1'};
}
return {'tags__id__in': tagIds.join(',')};
}
@override
List<Object?> get props => [tagIds];
@override
Map<String, dynamic> toJson() => _$AnyAssignedTagsQueryToJson(this);
factory AnyAssignedTagsQuery.fromJson(Map<String, dynamic> json) =>
_$AnyAssignedTagsQueryFromJson(json);
}

View File

@@ -0,0 +1,20 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'any_assigned_tags_query.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
AnyAssignedTagsQuery _$AnyAssignedTagsQueryFromJson(
Map<String, dynamic> json) =>
AnyAssignedTagsQuery(
tagIds:
(json['tagIds'] as List<dynamic>?)?.map((e) => e as int) ?? const [],
);
Map<String, dynamic> _$AnyAssignedTagsQueryToJson(
AnyAssignedTagsQuery instance) =>
<String, dynamic>{
'tagIds': instance.tagIds.toList(),
};

View File

@@ -0,0 +1,15 @@
import 'package:paperless_api/src/models/query_parameters/tags_query/tag_id_query.dart';
import 'include_tag_id_query.dart';
class ExcludeTagIdQuery extends TagIdQuery {
const ExcludeTagIdQuery(super.id);
@override
String get methodName => 'exclude';
@override
TagIdQuery toggle() {
return IncludeTagIdQuery(id);
}
}

View File

@@ -1,40 +1,13 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
abstract class TagsQuery extends Equatable {
const TagsQuery();
Map<String, String> toQueryParameter();
}
import 'exclude_tag_id_query.dart';
import 'include_tag_id_query.dart';
import 'tag_id_query.dart';
import 'tags_query.dart';
class OnlyNotAssignedTagsQuery extends TagsQuery {
const OnlyNotAssignedTagsQuery();
@override
Map<String, String> toQueryParameter() {
return {'is_tagged': '0'};
}
@override
List<Object?> get props => [];
}
class AnyAssignedTagsQuery extends TagsQuery {
final Iterable<int> tagIds;
const AnyAssignedTagsQuery({
this.tagIds = const [],
});
@override
Map<String, String> toQueryParameter() {
if (tagIds.isEmpty) {
return {'is_tagged': '1'};
}
return {'tags__id__in': tagIds.join(',')};
}
@override
List<Object?> get props => [tagIds];
}
part 'ids_tags_query.g.dart';
@JsonSerializable(explicitToJson: true)
class IdsTagsQuery extends TagsQuery {
final Iterable<TagIdQuery> _idQueries;
@@ -102,41 +75,10 @@ class IdsTagsQuery extends TagsQuery {
@override
List<Object?> get props => [_idQueries];
}
abstract class TagIdQuery extends Equatable {
final int id;
const TagIdQuery(this.id);
String get methodName;
@override
List<Object?> get props => [id, methodName];
TagIdQuery toggle();
}
class IncludeTagIdQuery extends TagIdQuery {
const IncludeTagIdQuery(super.id);
@override
String get methodName => 'include';
@override
TagIdQuery toggle() {
return ExcludeTagIdQuery(id);
}
}
class ExcludeTagIdQuery extends TagIdQuery {
const ExcludeTagIdQuery(super.id);
@override
String get methodName => 'exclude';
@override
TagIdQuery toggle() {
return IncludeTagIdQuery(id);
}
@override
Map<String, dynamic> toJson() => _$IdsTagsQueryToJson(this);
factory IdsTagsQuery.fromJson(Map<String, dynamic> json) =>
_$IdsTagsQueryFromJson(json);
}

View File

@@ -0,0 +1,13 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'ids_tags_query.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
IdsTagsQuery _$IdsTagsQueryFromJson(Map<String, dynamic> json) =>
IdsTagsQuery();
Map<String, dynamic> _$IdsTagsQueryToJson(IdsTagsQuery instance) =>
<String, dynamic>{};

View File

@@ -0,0 +1,15 @@
import 'package:paperless_api/src/models/query_parameters/tags_query/tag_id_query.dart';
import 'exclude_tag_id_query.dart';
class IncludeTagIdQuery extends TagIdQuery {
const IncludeTagIdQuery(super.id);
@override
String get methodName => 'include';
@override
TagIdQuery toggle() {
return ExcludeTagIdQuery(id);
}
}

View File

@@ -0,0 +1,17 @@
import 'tags_query.dart';
class OnlyNotAssignedTagsQuery extends TagsQuery {
const OnlyNotAssignedTagsQuery();
@override
Map<String, String> toQueryParameter() {
return {'is_tagged': '0'};
}
@override
List<Object?> get props => [];
@override
Map<String, dynamic> toJson() {
return {};
}
}

View File

@@ -0,0 +1,14 @@
import 'package:equatable/equatable.dart';
abstract class TagIdQuery extends Equatable {
final int id;
const TagIdQuery(this.id);
String get methodName;
@override
List<Object?> get props => [id, methodName];
TagIdQuery toggle();
}

View File

@@ -0,0 +1,7 @@
export 'any_assigned_tags_query.dart';
export 'ids_tags_query.dart';
export 'tags_query.dart';
export 'exclude_tag_id_query.dart';
export 'include_tag_id_query.dart';
export 'only_not_assigned_tags_query.dart';
export 'tag_id_query.dart';

View File

@@ -0,0 +1,7 @@
import 'package:equatable/equatable.dart';
abstract class TagsQuery extends Equatable {
const TagsQuery();
Map<String, String> toQueryParameter();
Map<String, dynamic> toJson();
}

View File

@@ -1,5 +1,10 @@
import 'package:json_annotation/json_annotation.dart';
import 'query_type.dart';
part 'text_query.g.dart';
@JsonSerializable()
class TextQuery {
final QueryType queryType;
final String? queryText;
@@ -51,4 +56,9 @@ class TextQuery {
}
return null;
}
Map<String, dynamic> toJson() => _$TextQueryToJson(this);
factory TextQuery.fromJson(Map<String, dynamic> json) =>
_$TextQueryFromJson(json);
}

View File

@@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'text_query.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
TextQuery _$TextQueryFromJson(Map<String, dynamic> json) => TextQuery(
queryType: $enumDecodeNullable(_$QueryTypeEnumMap, json['queryType']) ??
QueryType.titleAndContent,
queryText: json['queryText'] as String?,
);
Map<String, dynamic> _$TextQueryToJson(TextQuery instance) => <String, dynamic>{
'queryType': _$QueryTypeEnumMap[instance.queryType]!,
'queryText': instance.queryText,
};
const _$QueryTypeEnumMap = {
QueryType.title: 'title',
QueryType.titleAndContent: 'titleAndContent',
QueryType.extended: 'extended',
QueryType.asn: 'asn',
};

View File

@@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:paperless_api/src/models/paperless_server_exception.dart';
import 'package:paperless_api/src/modules/authentication_api/authentication_api.dart';
@@ -24,10 +22,10 @@ class PaperlessAuthenticationApiImpl implements PaperlessAuthenticationApi {
},
);
} on DioError catch (error) {
if (error.error is PaperlessServerException) {
if (error.error is PaperlessServerException ||
error.error is Map<String, String>) {
throw error.error;
} else {
log(error.message);
throw PaperlessServerException(
ErrorCode.authenticationFailed,
details: error.message,

View File

@@ -1,10 +1,11 @@
import 'dart:convert';
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_api/src/constants.dart';
import 'package:paperless_api/src/converters/document_model_json_converter.dart';
import 'package:paperless_api/src/converters/similar_document_model_json_converter.dart';
class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
final Dio client;
@@ -28,9 +29,8 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
'document',
MultipartFile.fromBytes(documentBytes, filename: filename),
),
);
formData.fields.add(MapEntry('title', title));
)
..fields.add(MapEntry('title', title));
if (createdAt != null) {
formData.fields.add(MapEntry('created', apiDateFormat.format(createdAt)));
}
@@ -85,10 +85,10 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
);
if (response.statusCode == 200) {
return compute(
PagedSearchResult.fromJson,
PagedSearchResult.fromJsonSingleParam,
PagedSearchResultJsonSerializer<DocumentModel>(
response.data,
DocumentModel.fromJson,
DocumentModelJsonConverter(),
),
);
} else {
@@ -254,10 +254,10 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
await client.get("/api/documents/?more_like=$docId&pageSize=10");
if (response.statusCode == 200) {
return (await compute(
PagedSearchResult<SimilarDocumentModel>.fromJson,
PagedSearchResult<SimilarDocumentModel>.fromJsonSingleParam,
PagedSearchResultJsonSerializer(
response.data,
SimilarDocumentModel.fromJson,
SimilarDocumentModelJsonConverter(),
),
))
.results;

View File

@@ -18,6 +18,7 @@ dependencies:
json_annotation: ^4.7.0
intl: ^0.17.0
dio: ^4.0.6
collection: ^1.17.0
dev_dependencies:
flutter_test:

View File

@@ -1,5 +1,6 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_api/src/models/query_parameters/tags_query/include_tag_id_query.dart';
import 'package:paperless_api/src/models/query_parameters/text_query.dart';
void main() {