From 73a0586a757c84babebb9866f21092d69339808e Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 06:00:02 +0000 Subject: [PATCH 1/8] Auto translate strings --- src-ui/messages.xlf | 234 ++++++++++++------------- src/locale/en_US/LC_MESSAGES/django.po | 4 +- 2 files changed, 119 insertions(+), 119 deletions(-) diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 01853f48c..5257aa5e8 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -340,7 +340,7 @@ src/app/components/document-list/document-list.component.ts - 211 + 212 src/app/components/manage/document-attributes/custom-fields/custom-fields.component.html @@ -1077,7 +1077,7 @@ src/app/components/document-list/filter-editor/filter-editor.component.ts - 203 + 205 @@ -3044,7 +3044,7 @@ src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 212 + 210 @@ -3095,15 +3095,15 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 908 + 919 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 944 + 955 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 967 + 978 src/app/components/manage/document-attributes/custom-fields/custom-fields.component.ts @@ -3626,14 +3626,14 @@ Ask a question about this document... src/app/components/chat/chat/chat.component.ts - 42 + 49 Ask a question about a document... src/app/components/chat/chat/chat.component.ts - 43 + 50 @@ -3677,27 +3677,27 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 545 + 556 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 585 + 596 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 623 + 634 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 661 + 672 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 723 + 734 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 856 + 867 @@ -3861,7 +3861,7 @@ Saved field "". src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts - 129 + 132 src/app/components/manage/document-attributes/custom-fields/custom-fields.component.ts @@ -3872,7 +3872,7 @@ Error saving field. src/app/components/common/custom-fields-dropdown/custom-fields-dropdown.component.ts - 138 + 141 src/app/components/manage/document-attributes/custom-fields/custom-fields.component.ts @@ -4931,7 +4931,7 @@ src/app/components/common/input/document-link/document-link.component.ts - 72 + 73 @@ -5713,7 +5713,7 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 860 + 871 @@ -5935,7 +5935,7 @@ Not assigned src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 99 + 100 Filter drop down element to filter for documents with no correspondent/type/tag assigned @@ -5943,7 +5943,7 @@ Open filter src/app/components/common/filterable-dropdown/filterable-dropdown.component.ts - 823 + 824 @@ -6070,7 +6070,7 @@ Search for documents src/app/components/common/input/document-link/document-link.component.ts - 81 + 82 @@ -6602,35 +6602,35 @@ Emails must match src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 146 + 144 Passwords must match src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 173 + 171 Profile updated successfully src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 209 + 207 Error saving profile src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 223 + 221 Error generating auth token src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 241 + 239 @@ -6651,36 +6651,36 @@ TOTP activated successfully src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 306 + 309 Error activating TOTP src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 308 + 311 src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 314 + 317 TOTP deactivated successfully src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 330 + 333 Error deactivating TOTP src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 332 + 335 src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.ts - 337 + 340 @@ -7576,7 +7576,7 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 490 + 501 this string is used to separate processing, failed and added on the file upload widget @@ -7616,7 +7616,7 @@ - Searching document with asn + Searching document with asn src/app/components/document-asn/document-asn.component.html 1 @@ -7760,7 +7760,7 @@ src/app/components/document-list/filter-editor/filter-editor.component.ts - 194 + 196 src/app/data/document.ts @@ -8107,7 +8107,7 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 858 + 869 @@ -8125,7 +8125,7 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 904 + 915 @@ -8322,46 +8322,46 @@ Error deleting version src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 155 + 156 Error updating version label src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 188 + 189 Uploading new version. Processing will happen in the background. src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 210 + 211 Missing task ID. src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 223 + 224 Upload failed. src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 245 + 246 src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 268 + 271 Error uploading new version src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.ts - 270 + 274 @@ -8475,25 +8475,25 @@ Error executing bulk operation src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 319 + 326 "" src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 482 + 493 src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 488 + 499 "" and "" src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 484 + 495 This is for messages like 'modify "tag1" and "tag2"' @@ -8501,7 +8501,7 @@ and "" src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 492,494 + 503,505 this is for messages like 'modify "tag1", "tag2" and "tag3"' @@ -8509,14 +8509,14 @@ Confirm tags assignment src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 509 + 520 This operation will add the tag "" to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 515 + 526 @@ -8525,14 +8525,14 @@ )"/> to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 520,522 + 531,533 This operation will remove the tag "" from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 528 + 539 @@ -8541,7 +8541,7 @@ )"/> from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 533,535 + 544,546 @@ -8552,84 +8552,84 @@ )"/> on selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 537,541 + 548,552 Confirm correspondent assignment src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 578 + 589 This operation will assign the correspondent "" to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 580 + 591 This operation will remove the correspondent from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 582 + 593 Confirm document type assignment src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 616 + 627 This operation will assign the document type "" to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 618 + 629 This operation will remove the document type from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 620 + 631 Confirm storage path assignment src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 654 + 665 This operation will assign the storage path "" to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 656 + 667 This operation will remove the storage path from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 658 + 669 Confirm custom field assignment src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 687 + 698 This operation will assign the custom field "" to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 693 + 704 @@ -8638,14 +8638,14 @@ )"/> to selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 698,700 + 709,711 This operation will remove the custom field "" from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 706 + 717 @@ -8654,7 +8654,7 @@ )"/> from selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 711,713 + 722,724 @@ -8665,91 +8665,91 @@ )"/> on selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 715,719 + 726,730 Move selected document(s) to the trash? src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 857 + 868 This operation will permanently recreate the archive files for selected document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 905 + 916 The archive files will be re-generated with the current settings. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 906 + 917 Rotate confirm src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 941 + 952 This operation will add rotated versions of the document(s). src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 942 + 953 Merge confirm src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 965 + 976 This operation will merge selected documents into a new document. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 966 + 977 Merged document will be queued for consumption. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 989 + 1000 Custom fields updated. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 1013 + 1024 Error updating custom fields. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 1022 + 1033 Share link bundle creation requested. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 1062 + 1073 Share link bundle creation is not available yet. src/app/components/document-list/bulk-editor/bulk-editor.component.ts - 1069 + 1080 @@ -8936,7 +8936,7 @@ src/app/components/document-list/document-list.component.ts - 345 + 346 src/app/components/manage/document-attributes/document-attributes.component.html @@ -8951,7 +8951,7 @@ src/app/components/document-list/document-list.component.ts - 338 + 339 src/app/components/manage/document-attributes/document-attributes.component.html @@ -9066,7 +9066,7 @@ src/app/components/document-list/filter-editor/filter-editor.component.ts - 199 + 201 src/app/data/document.ts @@ -9206,56 +9206,56 @@ Reset filters / selection src/app/components/document-list/document-list.component.ts - 326 + 327 Open first [selected] document src/app/components/document-list/document-list.component.ts - 354 + 355 Previous page src/app/components/document-list/document-list.component.ts - 370 + 371 Next page src/app/components/document-list/document-list.component.ts - 382 + 383 View "" saved successfully. src/app/components/document-list/document-list.component.ts - 416 + 417 Failed to save view "". src/app/components/document-list/document-list.component.ts - 422 + 423 View "" created successfully. src/app/components/document-list/document-list.component.ts - 490 + 491 View "" created successfully, but could not update visibility settings. src/app/components/document-list/document-list.component.ts - 496 + 497 @@ -9269,63 +9269,63 @@ Title & content src/app/components/document-list/filter-editor/filter-editor.component.ts - 197 + 199 File type src/app/components/document-list/filter-editor/filter-editor.component.ts - 200 + 202 Custom fields (Deprecated) src/app/components/document-list/filter-editor/filter-editor.component.ts - 210 + 212 More like src/app/components/document-list/filter-editor/filter-editor.component.ts - 215 + 217 equals src/app/components/document-list/filter-editor/filter-editor.component.ts - 221 + 223 is empty src/app/components/document-list/filter-editor/filter-editor.component.ts - 225 + 227 is not empty src/app/components/document-list/filter-editor/filter-editor.component.ts - 229 + 231 greater than src/app/components/document-list/filter-editor/filter-editor.component.ts - 233 + 235 less than src/app/components/document-list/filter-editor/filter-editor.component.ts - 237 + 239 @@ -9334,14 +9334,14 @@ )?.name"/> src/app/components/document-list/filter-editor/filter-editor.component.ts - 278,282 + 280,284 Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 284 + 286 @@ -9350,14 +9350,14 @@ )?.name"/> src/app/components/document-list/filter-editor/filter-editor.component.ts - 290,294 + 292,296 Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 296 + 298 @@ -9366,77 +9366,77 @@ )?.name"/> src/app/components/document-list/filter-editor/filter-editor.component.ts - 302,306 + 304,308 Without storage path src/app/components/document-list/filter-editor/filter-editor.component.ts - 308 + 310 Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 312,314 + 314,316 Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 318 + 320 Custom fields query src/app/components/document-list/filter-editor/filter-editor.component.ts - 322 + 324 Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 326 + 328 Title & content: src/app/components/document-list/filter-editor/filter-editor.component.ts - 330 + 332 ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 333 + 335 Owner: src/app/components/document-list/filter-editor/filter-editor.component.ts - 336 + 338 Owner not in: src/app/components/document-list/filter-editor/filter-editor.component.ts - 339 + 341 Without an owner src/app/components/document-list/filter-editor/filter-editor.component.ts - 342 + 344 diff --git a/src/locale/en_US/LC_MESSAGES/django.po b/src/locale/en_US/LC_MESSAGES/django.po index dff2d995a..a57157044 100644 --- a/src/locale/en_US/LC_MESSAGES/django.po +++ b/src/locale/en_US/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: paperless-ngx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-15 20:44+0000\n" +"POT-Creation-Date: 2026-07-18 05:59+0000\n" "PO-Revision-Date: 2022-02-17 04:17\n" "Last-Translator: \n" "Language-Team: English\n" @@ -53,7 +53,7 @@ msgstr "" msgid "Maximum nesting depth exceeded." msgstr "" -#: documents/filters.py:1052 +#: documents/filters.py:1059 msgid "Custom field not found" msgstr "" From 99bdfdfe7a8c7cd4ba8552f4c60d0d2919b4fc1c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 19 Jul 2026 07:44:12 -0700 Subject: [PATCH 2/8] Fix: better handle saved view errors in dashboard widgets (#13164) --- .../saved-view-widget.component.html | 4 +- .../saved-view-widget.component.spec.ts | 29 ++++++++++++- .../saved-view-widget.component.ts | 43 ++++++++++++++++--- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html index d53e39bbf..9712a64bb 100644 --- a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html @@ -14,7 +14,9 @@ }
- @if (displayMode() === DisplayMode.TABLE) { + @if (error()) { + + } @else if (displayMode() === DisplayMode.TABLE) { diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts index 39480d373..b985bcb26 100644 --- a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts @@ -1,6 +1,10 @@ import { DragDropModule } from '@angular/cdk/drag-drop' import { DatePipe } from '@angular/common' -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' +import { + HttpErrorResponse, + provideHttpClient, + withInterceptorsFromDi, +} from '@angular/common/http' import { provideHttpClientTesting } from '@angular/common/http/testing' import { ComponentFixture, TestBed } from '@angular/core/testing' import { By } from '@angular/platform-browser' @@ -8,7 +12,7 @@ import { Router } from '@angular/router' import { RouterTestingModule } from '@angular/router/testing' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' -import { Subject, of } from 'rxjs' +import { Subject, of, throwError } from 'rxjs' import { routes } from 'src/app/app-routing.module' import { CustomFieldDisplayComponent } from 'src/app/components/common/custom-field-display/custom-field-display.component' import { PreviewPopupComponent } from 'src/app/components/common/preview-popup/preview-popup.component' @@ -230,6 +234,27 @@ describe('SavedViewWidgetComponent', () => { expect(component.documents()).toEqual(documentResults) }) + it('should show an error if documents fail to load', () => { + jest.spyOn(documentService, 'listFiltered').mockReturnValue( + throwError( + () => + new HttpErrorResponse({ + error: { added__date__lte: ['Enter a valid date.'] }, + status: 400, + }) + ) + ) + + component.reload() + fixture.detectChanges() + + expect(component.loading()).toBe(false) + expect(component.error()).toEqual('Added: Enter a valid date.') + expect(fixture.debugElement.nativeElement.textContent).toContain( + 'Error while loading documents: Added: Enter a valid date.' + ) + }) + it('should reload on document consumption finished', () => { const fileStatusSubject = new Subject() jest diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts index 271ce16bb..6cbf18698 100644 --- a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts @@ -125,6 +125,8 @@ export class SavedViewWidgetComponent readonly count = signal(null) + readonly error = signal(null) + placeholderRows: number[] = [] ngOnInit(): void { @@ -180,6 +182,7 @@ export class SavedViewWidgetComponent reload() { this.loading.set(this.documents().length == 0) + this.error.set(null) this.show.set(true) this.documentService .listFiltered( @@ -191,12 +194,40 @@ export class SavedViewWidgetComponent { truncate_content: true } ) .pipe(takeUntil(this.unsubscribeNotifier)) - .subscribe((result) => { - this.documents.set(result.results) - this.count.set(result.count) - this.savedViewService.setDocumentCount(this.savedView, result.count) - this.loading.set(false) - this.show.set(true) + .subscribe({ + next: (result) => { + this.documents.set(result.results) + this.count.set(result.count) + this.savedViewService.setDocumentCount(this.savedView, result.count) + this.loading.set(false) + this.show.set(true) + }, + error: (error) => { + this.documents.set([]) + this.count.set(null) + let errorMessage + if ( + typeof error.error === 'object' && + Object.keys(error.error).length > 0 + ) { + errorMessage = Object.keys(error.error) + .map((fieldName) => { + const fieldNameBase = fieldName.split('__')[0] + const fieldError: Array = error.error[fieldName] + return `${ + this.documentService.sortFields.find( + (f) => f.field?.split('__')[0] == fieldNameBase + )?.name ?? fieldNameBase + }: ${fieldError[0]}` + }) + .join(', ') + } else { + errorMessage = error.error + } + this.error.set(errorMessage) + this.loading.set(false) + this.show.set(true) + }, }) } From 2180b21c411bd2f06cb3c5a10f0523dba9df5ba1 Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:45:46 +0000 Subject: [PATCH 3/8] Auto translate strings --- src-ui/messages.xlf | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 5257aa5e8..c1ec2aaea 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -260,15 +260,15 @@ src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 60 + 62 src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 63 + 65 src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 66 + 68 src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html @@ -3465,7 +3465,7 @@ src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 120 + 122 src/app/components/document-detail/document-detail.component.html @@ -7381,11 +7381,22 @@ 13 + + Error while loading documents + + src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html + 18 + + + src/app/components/document-list/document-list.component.html + 163 + + Filter by correspondent src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 70 + 72 src/app/components/document-list/document-card-large/document-card-large.component.html @@ -7400,7 +7411,7 @@ Filter by document type src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 80 + 82 src/app/components/document-list/document-card-large/document-card-large.component.html @@ -7415,7 +7426,7 @@ Filter by storage path src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 85 + 87 src/app/components/document-list/document-card-large/document-card-large.component.html @@ -7430,14 +7441,14 @@ Filter by owner src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 90 + 92 Yes src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 100 + 102 src/app/components/document-list/document-list.component.html @@ -7448,7 +7459,7 @@ No src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 100 + 102 src/app/components/document-list/document-list.component.html @@ -7459,7 +7470,7 @@ No documents src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html - 184 + 186 @@ -9044,13 +9055,6 @@ 137 - - Error while loading documents - - src/app/components/document-list/document-list.component.html - 163 - - Sort by ASN From 4f6d9fa93f862a527b8badf20d46409680ffe9ab Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 19 Jul 2026 13:54:58 -0700 Subject: [PATCH 4/8] Fix: dont allow archive version for share links when one doesnt exist (#13163) --- src/documents/tests/test_views.py | 43 +++++++++++++++++++++++++++++++ src/documents/views.py | 3 ++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/documents/tests/test_views.py b/src/documents/tests/test_views.py index 376cb8e93..343f2cc13 100644 --- a/src/documents/tests/test_views.py +++ b/src/documents/tests/test_views.py @@ -177,6 +177,49 @@ class TestViews(DirectoriesMixin, TestCase): self.assertEqual(response.request["PATH_INFO"], "/accounts/login/") self.assertContains(response, b"Share link has expired") + def test_share_link_archive_falls_back_to_original(self) -> None: + """ + GIVEN: + - A document without an archive version + - A share link using the default archive file version + WHEN: + - An unauthenticated request for the share link is made + THEN: + - The original document is returned + """ + _, filename = tempfile.mkstemp(dir=self.dirs.originals_dir) + content = b"This document has no archive" + + with Path(filename).open("wb") as f: + f.write(content) + + doc = Document.objects.create( + title="no archive", + filename=Path(filename).name, + mime_type="text/plain", + ) + + sharelink_permissions = Permission.objects.filter( + codename__contains="sharelink", + ) + self.user.user_permissions.add(*sharelink_permissions) + self.client.force_login(self.user) + + create_response = self.client.post( + "/api/share_links/", + {"document": doc.pk}, + ) + self.assertEqual(create_response.status_code, status.HTTP_201_CREATED) + share_link = ShareLink.objects.get(document=doc) + self.assertEqual(share_link.file_version, ShareLink.FileVersion.ARCHIVE) + + self.client.logout() + + response = self.client.get(f"/share/{share_link.slug}") + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(read_streaming_response(response), content) + def test_list_with_full_permissions(self) -> None: """ GIVEN: diff --git a/src/documents/views.py b/src/documents/views.py index 0a9045126..1591d0b06 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -4534,7 +4534,8 @@ class SharedLinkView(View): return HttpResponseRedirect("/accounts/login/?sharelink_expired=1") return serve_file( doc=share_link.document, - use_archive=share_link.file_version == "archive", + use_archive=share_link.file_version == ShareLink.FileVersion.ARCHIVE + and share_link.document.has_archive_version, disposition="inline", ) From ec8991c2eca7aed8e8ccc346d74a8a60ddf91ade Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 20:56:43 +0000 Subject: [PATCH 5/8] Auto translate strings --- src/locale/en_US/LC_MESSAGES/django.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locale/en_US/LC_MESSAGES/django.po b/src/locale/en_US/LC_MESSAGES/django.po index a57157044..598552327 100644 --- a/src/locale/en_US/LC_MESSAGES/django.po +++ b/src/locale/en_US/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: paperless-ngx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-18 05:59+0000\n" +"POT-Creation-Date: 2026-07-19 20:55+0000\n" "PO-Revision-Date: 2022-02-17 04:17\n" "Last-Translator: \n" "Language-Team: English\n" @@ -1686,11 +1686,11 @@ msgstr "" msgid "Bundle is already being processed." msgstr "" -#: documents/views.py:4554 +#: documents/views.py:4555 msgid "The share link bundle is still being prepared. Please try again later." msgstr "" -#: documents/views.py:4564 +#: documents/views.py:4565 msgid "The share link bundle is unavailable." msgstr "" From b8c424c8e14713eac00ab940e5399f86f0ba9b82 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 19 Jul 2026 15:46:17 -0700 Subject: [PATCH 6/8] Update document-detail.component.html --- .../document-detail/document-detail.component.html | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src-ui/src/app/components/document-detail/document-detail.component.html b/src-ui/src/app/components/document-detail/document-detail.component.html index 42b14528e..83e5b4bfb 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.html +++ b/src-ui/src/app/components/document-detail/document-detail.component.html @@ -482,9 +482,7 @@ } @else { - - Preview is unavailable. - + } } @case (ContentRenderType.Text) { @@ -505,9 +503,7 @@ } } @case (ContentRenderType.Other) { - - Preview is unavailable. - + } } @if (requiresPassword) { From d34ef75786fe806be9d521e9071ef92200fb3494 Mon Sep 17 00:00:00 2001 From: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:48:24 +0000 Subject: [PATCH 7/8] Auto translate strings --- src-ui/messages.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index c1ec2aaea..576986c73 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -7962,7 +7962,7 @@ Enter Password src/app/components/document-detail/document-detail.component.html - 516 + 512 From 80210bd3bf545bc68824e7f8960528df3cd326be Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 19 Jul 2026 18:05:51 -0700 Subject: [PATCH 8/8] Performance: use NgOptimizedImage for thumbnail lazy loading (#13169) --- .../document-card-large/document-card-large.component.html | 2 +- .../document-card-large.component.spec.ts | 6 ++++++ .../document-card-large/document-card-large.component.ts | 3 ++- .../document-card-small/document-card-small.component.html | 2 +- .../document-card-small/document-card-small.component.scss | 6 +++++- .../document-card-small.component.spec.ts | 6 ++++++ .../document-card-small/document-card-small.component.ts | 3 ++- 7 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html index 08d232185..facd0ca27 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html @@ -2,7 +2,7 @@
@if (document()) { - +
diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.spec.ts b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.spec.ts index d50bba65f..421754618 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.spec.ts +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.spec.ts @@ -88,6 +88,12 @@ describe('DocumentCardLargeComponent', () => { expect(fixture.nativeElement.textContent).toContain('8 pages') }) + it('should lazy load the thumbnail', () => { + const thumbnail: HTMLImageElement = + fixture.nativeElement.querySelector('img.doc-img') + expect(thumbnail.getAttribute('loading')).toEqual('lazy') + }) + it('should trim content', () => { expect(component.contentTrimmed).toHaveLength(503) // includes ... }) diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts index 1dac73959..9304d1168 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts @@ -1,4 +1,4 @@ -import { AsyncPipe } from '@angular/common' +import { AsyncPipe, NgOptimizedImage } from '@angular/common' import { AfterViewInit, Component, @@ -46,6 +46,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading TagComponent, CustomFieldDisplayComponent, AsyncPipe, + NgOptimizedImage, UsernamePipe, CorrespondentNamePipe, DocumentTypeNamePipe, diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html index a7a30c790..7a0a507e6 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html @@ -2,7 +2,7 @@
@if (document()) { - +
diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss index 6f2260e47..9dd7ed5cf 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.scss @@ -22,10 +22,14 @@ } } +.doc-img-container { + position: relative; + height: 180px; +} + .doc-img { object-fit: cover; object-position: top left; - height: 180px; } .document-card-check { diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.spec.ts b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.spec.ts index 45b812462..c6127494b 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.spec.ts +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.spec.ts @@ -61,6 +61,12 @@ describe('DocumentCardSmallComponent', () => { expect(fixture.nativeElement.textContent).toContain('12 pages') }) + it('should lazy load the thumbnail', () => { + const thumbnail: HTMLImageElement = + fixture.nativeElement.querySelector('img.doc-img') + expect(thumbnail.getAttribute('loading')).toEqual('lazy') + }) + it('should display a document, limit tags to 5', () => { expect(fixture.nativeElement.textContent).toContain('Document 10') expect( diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts index 1e45b982a..633ad3e2e 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.ts @@ -1,4 +1,4 @@ -import { AsyncPipe } from '@angular/common' +import { AsyncPipe, NgOptimizedImage } from '@angular/common' import { AfterViewInit, Component, @@ -46,6 +46,7 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading TagComponent, CustomFieldDisplayComponent, AsyncPipe, + NgOptimizedImage, UsernamePipe, CorrespondentNamePipe, DocumentTypeNamePipe,