WIP - Implemented similar documents view

This commit is contained in:
Anton Stubenbord
2023-01-22 01:17:52 +01:00
parent d4978172cf
commit b370fa4164
27 changed files with 476 additions and 381 deletions

View File

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

View File

@@ -1,15 +0,0 @@
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

@@ -33,6 +33,9 @@ class DocumentFilter extends Equatable {
final DateRangeQuery modified;
final TextQuery query;
/// Query documents similar to the document with this id.
final int? moreLike;
const DocumentFilter({
this.documentType = const IdQueryParameter.unset(),
this.correspondent = const IdQueryParameter.unset(),
@@ -47,6 +50,7 @@ class DocumentFilter extends Equatable {
this.added = const UnsetDateRangeQuery(),
this.created = const UnsetDateRangeQuery(),
this.modified = const UnsetDateRangeQuery(),
this.moreLike,
});
bool get forceExtendedQuery {
@@ -77,6 +81,10 @@ class DocumentFilter extends Equatable {
),
);
}
if (moreLike != null) {
params.add(MapEntry('more_like_id', moreLike.toString()));
}
// Reverse ordering can also be encoded using &reverse=1
// Merge query params
final queryParams = groupBy(params, (e) => e.key).map(
@@ -107,7 +115,7 @@ class DocumentFilter extends Equatable {
DateRangeQuery? created,
DateRangeQuery? modified,
TextQuery? query,
int? selectedViewId,
int? Function()? moreLike,
}) {
final newFilter = DocumentFilter(
pageSize: pageSize ?? this.pageSize,
@@ -123,6 +131,7 @@ class DocumentFilter extends Equatable {
added: added ?? this.added,
created: created ?? this.created,
modified: modified ?? this.modified,
moreLike: moreLike != null ? moreLike.call() : this.moreLike,
);
if (query?.queryType != QueryType.extended &&
newFilter.forceExtendedQuery) {

View File

@@ -48,6 +48,7 @@ DocumentFilter _$DocumentFilterFromJson(Map<String, dynamic> json) =>
? const UnsetDateRangeQuery()
: const DateRangeQueryJsonConverter()
.fromJson(json['modified'] as Map<String, dynamic>),
moreLike: json['moreLike'] as int?,
);
Map<String, dynamic> _$DocumentFilterToJson(DocumentFilter instance) =>
@@ -65,6 +66,7 @@ Map<String, dynamic> _$DocumentFilterToJson(DocumentFilter instance) =>
'added': const DateRangeQueryJsonConverter().toJson(instance.added),
'modified': const DateRangeQueryJsonConverter().toJson(instance.modified),
'query': instance.query.toJson(),
'moreLike': instance.moreLike,
};
const _$SortFieldEnumMap = {

View File

@@ -3,6 +3,7 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/converters/local_date_time_json_converter.dart';
import 'package:paperless_api/src/models/search_hit.dart';
part 'document_model.g.dart';
@@ -37,6 +38,12 @@ class DocumentModel extends Equatable {
final String originalFileName;
final String? archivedFileName;
@JsonKey(
name: '__search_hit__',
includeIfNull: false,
)
final SearchHit? searchHit;
const DocumentModel({
required this.id,
required this.title,
@@ -51,6 +58,7 @@ class DocumentModel extends Equatable {
required this.originalFileName,
this.archivedFileName,
this.storagePath,
this.searchHit,
});
factory DocumentModel.fromJson(Map<String, dynamic> json) =>

View File

@@ -25,21 +25,34 @@ DocumentModel _$DocumentModelFromJson(Map<String, dynamic> json) =>
originalFileName: json['original_file_name'] as String,
archivedFileName: json['archived_file_name'] as String?,
storagePath: json['storage_path'] as int?,
searchHit: json['__search_hit__'] == null
? null
: SearchHit.fromJson(json['__search_hit__'] as Map<String, dynamic>),
);
Map<String, dynamic> _$DocumentModelToJson(DocumentModel instance) =>
<String, dynamic>{
'id': instance.id,
'title': instance.title,
'content': instance.content,
'tags': instance.tags.toList(),
'document_type': instance.documentType,
'correspondent': instance.correspondent,
'storage_path': instance.storagePath,
'created': const LocalDateTimeJsonConverter().toJson(instance.created),
'modified': const LocalDateTimeJsonConverter().toJson(instance.modified),
'added': const LocalDateTimeJsonConverter().toJson(instance.added),
'archive_serial_number': instance.archiveSerialNumber,
'original_file_name': instance.originalFileName,
'archived_file_name': instance.archivedFileName,
};
Map<String, dynamic> _$DocumentModelToJson(DocumentModel instance) {
final val = <String, dynamic>{
'id': instance.id,
'title': instance.title,
'content': instance.content,
'tags': instance.tags.toList(),
'document_type': instance.documentType,
'correspondent': instance.correspondent,
'storage_path': instance.storagePath,
'created': const LocalDateTimeJsonConverter().toJson(instance.created),
'modified': const LocalDateTimeJsonConverter().toJson(instance.modified),
'added': const LocalDateTimeJsonConverter().toJson(instance.added),
'archive_serial_number': instance.archiveSerialNumber,
'original_file_name': instance.originalFileName,
'archived_file_name': instance.archivedFileName,
};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('__search_hit__', instance.searchHit);
return val;
}

View File

@@ -21,7 +21,6 @@ export 'paperless_server_exception.dart';
export 'paperless_server_information_model.dart';
export 'paperless_server_statistics_model.dart';
export 'saved_view_model.dart';
export 'similar_document_model.dart';
export 'task/task.dart';
export 'task/task_status.dart';
export 'field_suggestions.dart';

View File

@@ -1,36 +0,0 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_api/src/converters/local_date_time_json_converter.dart';
import 'package:paperless_api/src/models/document_model.dart';
import 'package:paperless_api/src/models/search_hit.dart';
part 'similar_document_model.g.dart';
@LocalDateTimeJsonConverter()
@JsonSerializable()
class SimilarDocumentModel extends DocumentModel {
@JsonKey(name: '__search_hit__')
final SearchHit searchHit;
const SimilarDocumentModel({
required super.id,
required super.title,
required super.documentType,
required super.correspondent,
required super.created,
required super.modified,
required super.added,
required super.originalFileName,
required this.searchHit,
super.archiveSerialNumber,
super.archivedFileName,
super.content,
super.storagePath,
super.tags,
});
factory SimilarDocumentModel.fromJson(Map<String, dynamic> json) =>
_$SimilarDocumentModelFromJson(json);
@override
Map<String, dynamic> toJson() => _$SimilarDocumentModelToJson(this);
}

View File

@@ -1,50 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'similar_document_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SimilarDocumentModel _$SimilarDocumentModelFromJson(
Map<String, dynamic> json) =>
SimilarDocumentModel(
id: json['id'] as int,
title: json['title'] as String,
documentType: json['documentType'] as int?,
correspondent: json['correspondent'] as int?,
created: const LocalDateTimeJsonConverter()
.fromJson(json['created'] as String),
modified: const LocalDateTimeJsonConverter()
.fromJson(json['modified'] as String),
added:
const LocalDateTimeJsonConverter().fromJson(json['added'] as String),
originalFileName: json['originalFileName'] as String,
searchHit:
SearchHit.fromJson(json['__search_hit__'] as Map<String, dynamic>),
archiveSerialNumber: json['archiveSerialNumber'] as int?,
archivedFileName: json['archivedFileName'] as String?,
content: json['content'] as String?,
storagePath: json['storagePath'] as int?,
tags: (json['tags'] as List<dynamic>?)?.map((e) => e as int) ??
const <int>[],
);
Map<String, dynamic> _$SimilarDocumentModelToJson(
SimilarDocumentModel instance) =>
<String, dynamic>{
'id': instance.id,
'title': instance.title,
'content': instance.content,
'tags': instance.tags.toList(),
'documentType': instance.documentType,
'correspondent': instance.correspondent,
'storagePath': instance.storagePath,
'created': const LocalDateTimeJsonConverter().toJson(instance.created),
'modified': const LocalDateTimeJsonConverter().toJson(instance.modified),
'added': const LocalDateTimeJsonConverter().toJson(instance.added),
'archiveSerialNumber': instance.archiveSerialNumber,
'originalFileName': instance.originalFileName,
'archivedFileName': instance.archivedFileName,
'__search_hit__': instance.searchHit,
};

View File

@@ -18,7 +18,6 @@ abstract class PaperlessDocumentsApi {
Future<int> findNextAsn();
Future<PagedSearchResult<DocumentModel>> findAll(DocumentFilter filter);
Future<DocumentModel?> find(int id);
Future<List<SimilarDocumentModel>> findSimilar(int docId);
Future<int> delete(DocumentModel doc);
Future<DocumentMetaData> getMetaData(DocumentModel document);
Future<Iterable<int>> bulkAction(BulkAction action);

View File

@@ -241,27 +241,6 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
}
}
@override
Future<List<SimilarDocumentModel>> findSimilar(int docId) async {
try {
final response =
await client.get("/api/documents/?more_like=$docId&pageSize=10");
if (response.statusCode == 200) {
return (await compute(
PagedSearchResult<SimilarDocumentModel>.fromJsonSingleParam,
PagedSearchResultJsonSerializer(
response.data,
SimilarDocumentModelJsonConverter(),
),
))
.results;
}
throw const PaperlessServerException(ErrorCode.similarQueryError);
} on DioError catch (err) {
throw err.error;
}
}
@override
Future<FieldSuggestions> findSuggestions(DocumentModel document) async {
try {