mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-01-18 22:14:22 -06:00
Nice, UX for doc in trash
This commit is contained in:
@@ -385,9 +385,13 @@
|
|||||||
<a
|
<a
|
||||||
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"
|
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"
|
||||||
[routerLink]="['/documents', duplicate.id, 'details']"
|
[routerLink]="['/documents', duplicate.id, 'details']"
|
||||||
|
[class.disabled]="duplicate.deleted_at"
|
||||||
>
|
>
|
||||||
<span class="d-flex align-items-center gap-2">
|
<span class="d-flex align-items-center gap-2">
|
||||||
<span>{{ duplicate.title || ('#' + duplicate.id) }}</span>
|
<span>{{ duplicate.title || ('#' + duplicate.id) }}</span>
|
||||||
|
@if (duplicate.deleted_at) {
|
||||||
|
<span class="badge text-bg-secondary" i18n>In trash</span>
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-secondary">#{{ duplicate.id }}</span>
|
<span class="text-secondary">#{{ duplicate.id }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -456,6 +456,11 @@ export class DocumentDetailComponent
|
|||||||
const openDocument = this.openDocumentService.getOpenDocument(
|
const openDocument = this.openDocumentService.getOpenDocument(
|
||||||
this.documentId
|
this.documentId
|
||||||
)
|
)
|
||||||
|
// update duplicate documents if present
|
||||||
|
if (openDocument && doc?.duplicate_documents) {
|
||||||
|
openDocument.duplicate_documents = doc.duplicate_documents
|
||||||
|
this.openDocumentService.save()
|
||||||
|
}
|
||||||
const useDoc = openDocument || doc
|
const useDoc = openDocument || doc
|
||||||
if (openDocument) {
|
if (openDocument) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -148,13 +148,29 @@ def get_document_count_filter_for_user(user):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_objects_for_user_owner_aware(user, perms, Model) -> QuerySet:
|
def get_objects_for_user_owner_aware(
|
||||||
objects_owned = Model.objects.filter(owner=user)
|
user,
|
||||||
objects_unowned = Model.objects.filter(owner__isnull=True)
|
perms,
|
||||||
|
Model,
|
||||||
|
*,
|
||||||
|
include_deleted=False,
|
||||||
|
) -> QuerySet:
|
||||||
|
"""
|
||||||
|
Returns objects the user owns, are unowned, or has explicit perms.
|
||||||
|
When include_deleted is True, soft-deleted items are also included.
|
||||||
|
"""
|
||||||
|
manager = (
|
||||||
|
Model.global_objects
|
||||||
|
if include_deleted and hasattr(Model, "global_objects")
|
||||||
|
else Model.objects
|
||||||
|
)
|
||||||
|
|
||||||
|
objects_owned = manager.filter(owner=user)
|
||||||
|
objects_unowned = manager.filter(owner__isnull=True)
|
||||||
objects_with_perms = get_objects_for_user(
|
objects_with_perms = get_objects_for_user(
|
||||||
user=user,
|
user=user,
|
||||||
perms=perms,
|
perms=perms,
|
||||||
klass=Model,
|
klass=manager.all(),
|
||||||
accept_global_perms=False,
|
accept_global_perms=False,
|
||||||
)
|
)
|
||||||
return objects_owned | objects_unowned | objects_with_perms
|
return objects_owned | objects_unowned | objects_with_perms
|
||||||
|
|||||||
@@ -1020,23 +1020,17 @@ def _get_viewable_duplicates(document: Document, user: User | None):
|
|||||||
checksums = {document.checksum}
|
checksums = {document.checksum}
|
||||||
if document.archive_checksum:
|
if document.archive_checksum:
|
||||||
checksums.add(document.archive_checksum)
|
checksums.add(document.archive_checksum)
|
||||||
duplicates = (
|
duplicates = Document.global_objects.filter(
|
||||||
Document.global_objects.filter(
|
|
||||||
Q(checksum__in=checksums) | Q(archive_checksum__in=checksums),
|
Q(checksum__in=checksums) | Q(archive_checksum__in=checksums),
|
||||||
deleted_at__isnull=True,
|
).exclude(pk=document.pk)
|
||||||
)
|
duplicates = duplicates.order_by("-created")
|
||||||
.exclude(pk=document.pk)
|
allowed = get_objects_for_user_owner_aware(
|
||||||
.order_by("-created")
|
|
||||||
)
|
|
||||||
if user.is_superuser:
|
|
||||||
return duplicates
|
|
||||||
return duplicates.filter(
|
|
||||||
id__in=get_objects_for_user_owner_aware(
|
|
||||||
user,
|
user,
|
||||||
"documents.view_document",
|
"documents.view_document",
|
||||||
Document,
|
Document,
|
||||||
).values_list("id", flat=True),
|
include_deleted=True,
|
||||||
)
|
)
|
||||||
|
return duplicates.filter(id__in=allowed.values_list("id", flat=True))
|
||||||
|
|
||||||
|
|
||||||
@extend_schema_serializer(
|
@extend_schema_serializer(
|
||||||
@@ -1089,7 +1083,7 @@ class DocumentSerializer(
|
|||||||
request = self.context.get("request")
|
request = self.context.get("request")
|
||||||
user = request.user if request else None
|
user = request.user if request else None
|
||||||
duplicates = _get_viewable_duplicates(obj, user)
|
duplicates = _get_viewable_duplicates(obj, user)
|
||||||
return list(duplicates.values("id", "title"))
|
return list(duplicates.values("id", "title", "deleted_at"))
|
||||||
|
|
||||||
def get_original_file_name(self, obj) -> str | None:
|
def get_original_file_name(self, obj) -> str | None:
|
||||||
return obj.original_filename
|
return obj.original_filename
|
||||||
@@ -2178,7 +2172,7 @@ class TasksViewSerializer(OwnedObjectSerializer):
|
|||||||
request = self.context.get("request")
|
request = self.context.get("request")
|
||||||
user = request.user if request else None
|
user = request.user if request else None
|
||||||
duplicates = _get_viewable_duplicates(document, user)
|
duplicates = _get_viewable_duplicates(document, user)
|
||||||
cache[obj.pk] = list(duplicates.values("id", "title"))
|
cache[obj.pk] = list(duplicates.values("id", "title", "deleted_at"))
|
||||||
return cache[obj.pk]
|
return cache[obj.pk]
|
||||||
|
|
||||||
def get_duplicate_documents(self, obj):
|
def get_duplicate_documents(self, obj):
|
||||||
|
|||||||
Reference in New Issue
Block a user