mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Fix: render images not converted to pdf, refactor doc detail rendering (#5475)
This commit is contained in:
parent
5781a0d51f
commit
5842944d1e
@ -1,5 +1,5 @@
|
|||||||
<pngx-page-header [(title)]="title">
|
<pngx-page-header [(title)]="title">
|
||||||
@if (getContentType() === 'application/pdf' && !useNativePdfViewer) {
|
@if (contentRenderType === ContentRenderType.PDF && !useNativePdfViewer) {
|
||||||
<div class="input-group input-group-sm me-2 d-none d-md-flex">
|
<div class="input-group input-group-sm me-2 d-none d-md-flex">
|
||||||
<div class="input-group-text" i18n>Page</div>
|
<div class="input-group-text" i18n>Page</div>
|
||||||
<input class="form-control flex-grow-0 w-auto" type="number" min="1" [max]="previewNumPages" [(ngModel)]="previewCurrentPage" />
|
<input class="form-control flex-grow-0 w-auto" type="number" min="1" [max]="previewNumPages" [(ngModel)]="previewCurrentPage" />
|
||||||
@ -106,7 +106,7 @@
|
|||||||
@for (fieldInstance of document?.custom_fields; track fieldInstance; let i = $index) {
|
@for (fieldInstance of document?.custom_fields; track fieldInstance; let i = $index) {
|
||||||
<div [formGroup]="customFieldFormFields.controls[i]">
|
<div [formGroup]="customFieldFormFields.controls[i]">
|
||||||
@switch (getCustomFieldFromInstance(fieldInstance)?.data_type) {
|
@switch (getCustomFieldFromInstance(fieldInstance)?.data_type) {
|
||||||
@case (PaperlessCustomFieldDataType.String) {
|
@case (CustomFieldDataType.String) {
|
||||||
<pngx-input-text formControlName="value"
|
<pngx-input-text formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
@ -114,7 +114,7 @@
|
|||||||
[horizontal]="true"
|
[horizontal]="true"
|
||||||
[error]="getCustomFieldError(i)"></pngx-input-text>
|
[error]="getCustomFieldError(i)"></pngx-input-text>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.Date) {
|
@case (CustomFieldDataType.Date) {
|
||||||
<pngx-input-date formControlName="value"
|
<pngx-input-date formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
@ -122,7 +122,7 @@
|
|||||||
[horizontal]="true"
|
[horizontal]="true"
|
||||||
[error]="getCustomFieldError(i)"></pngx-input-date>
|
[error]="getCustomFieldError(i)"></pngx-input-date>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.Integer) {
|
@case (CustomFieldDataType.Integer) {
|
||||||
<pngx-input-number formControlName="value"
|
<pngx-input-number formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
@ -131,7 +131,7 @@
|
|||||||
[showAdd]="false"
|
[showAdd]="false"
|
||||||
[error]="getCustomFieldError(i)"></pngx-input-number>
|
[error]="getCustomFieldError(i)"></pngx-input-number>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.Float) {
|
@case (CustomFieldDataType.Float) {
|
||||||
<pngx-input-number formControlName="value"
|
<pngx-input-number formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
@ -141,7 +141,7 @@
|
|||||||
[step]=".1"
|
[step]=".1"
|
||||||
[error]="getCustomFieldError(i)"></pngx-input-number>
|
[error]="getCustomFieldError(i)"></pngx-input-number>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.Monetary) {
|
@case (CustomFieldDataType.Monetary) {
|
||||||
<pngx-input-number formControlName="value"
|
<pngx-input-number formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
@ -151,14 +151,14 @@
|
|||||||
[step]=".01"
|
[step]=".01"
|
||||||
[error]="getCustomFieldError(i)"></pngx-input-number>
|
[error]="getCustomFieldError(i)"></pngx-input-number>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.Boolean) {
|
@case (CustomFieldDataType.Boolean) {
|
||||||
<pngx-input-check formControlName="value"
|
<pngx-input-check formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
(removed)="removeField(fieldInstance)"
|
(removed)="removeField(fieldInstance)"
|
||||||
[horizontal]="true"></pngx-input-check>
|
[horizontal]="true"></pngx-input-check>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.Url) {
|
@case (CustomFieldDataType.Url) {
|
||||||
<pngx-input-url formControlName="value"
|
<pngx-input-url formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[removable]="userIsOwner"
|
[removable]="userIsOwner"
|
||||||
@ -166,7 +166,7 @@
|
|||||||
[horizontal]="true"
|
[horizontal]="true"
|
||||||
[error]="getCustomFieldError(i)"></pngx-input-url>
|
[error]="getCustomFieldError(i)"></pngx-input-url>
|
||||||
}
|
}
|
||||||
@case (PaperlessCustomFieldDataType.DocumentLink) {
|
@case (CustomFieldDataType.DocumentLink) {
|
||||||
<pngx-input-document-link formControlName="value"
|
<pngx-input-document-link formControlName="value"
|
||||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||||
[parentDocumentID]="documentId"
|
[parentDocumentID]="documentId"
|
||||||
@ -260,7 +260,9 @@
|
|||||||
<a ngbNavLink i18n>Preview</a>
|
<a ngbNavLink i18n>Preview</a>
|
||||||
@if (!pdfPreview.offsetParent) {
|
@if (!pdfPreview.offsetParent) {
|
||||||
<ng-template ngbNavContent>
|
<ng-template ngbNavContent>
|
||||||
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
<div class="position-relative">
|
||||||
|
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
}
|
}
|
||||||
</li>
|
</li>
|
||||||
@ -295,16 +297,6 @@
|
|||||||
|
|
||||||
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block position-relative" #pdfPreview>
|
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block position-relative" #pdfPreview>
|
||||||
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
||||||
@if (renderAsPlainText) {
|
|
||||||
<div [innerText]="previewText" class="preview-sticky bg-light p-3 overflow-auto" width="100%"></div>
|
|
||||||
}
|
|
||||||
@if (requiresPassword) {
|
|
||||||
<div class="password-prompt">
|
|
||||||
<form>
|
|
||||||
<input autocomplete="" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -333,29 +325,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (getContentType() === 'application/pdf') {
|
@switch (contentRenderType) {
|
||||||
@if (!useNativePdfViewer ) {
|
@case (ContentRenderType.PDF) {
|
||||||
<div class="preview-sticky pdf-viewer-container">
|
@if (!useNativePdfViewer) {
|
||||||
<pngx-pdf-viewer
|
<div class="preview-sticky pdf-viewer-container">
|
||||||
[src]="{ url: previewUrl, password: password }"
|
<pngx-pdf-viewer
|
||||||
[original-size]="false"
|
[src]="{ url: previewUrl, password: password }"
|
||||||
[show-borders]="true"
|
[original-size]="false"
|
||||||
[show-all]="true"
|
[show-borders]="true"
|
||||||
[(page)]="previewCurrentPage"
|
[show-all]="true"
|
||||||
[zoom-scale]="previewZoomScale"
|
[(page)]="previewCurrentPage"
|
||||||
[zoom]="previewZoomSetting"
|
[zoom-scale]="previewZoomScale"
|
||||||
(error)="onError($event)"
|
[zoom]="previewZoomSetting"
|
||||||
(after-load-complete)="pdfPreviewLoaded($event)">
|
(error)="onError($event)"
|
||||||
</pngx-pdf-viewer>
|
(after-load-complete)="pdfPreviewLoaded($event)">
|
||||||
|
</pngx-pdf-viewer>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@case (ContentRenderType.Text) {
|
||||||
|
<div class="preview-sticky bg-light p-3 overflow-auto" width="100%">{{previewText}}</div>
|
||||||
|
}
|
||||||
|
@case (ContentRenderType.Image) {
|
||||||
|
<div class="preview-sticky">
|
||||||
|
<img [src]="previewUrl | safeUrl" width="100%" height="100%" alt="{{title}}" />
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
}
|
||||||
|
@case (ContentRenderType.Other) {
|
||||||
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@if (renderAsPlainText) {
|
@if (requiresPassword) {
|
||||||
<div [innerText]="previewText" class="preview-sticky bg-light p-3 overflow-auto" width="100%"></div>
|
|
||||||
}
|
|
||||||
@if (showPasswordField) {
|
|
||||||
<div class="password-prompt">
|
<div class="password-prompt">
|
||||||
<form>
|
<form>
|
||||||
<input autocomplete="" autofocus="true" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
|
<input autocomplete="" autofocus="true" class="form-control" i18n-placeholder placeholder="Enter Password" type="password" (keyup)="onPasswordKeyUp($event)" />
|
||||||
|
@ -58,3 +58,9 @@ textarea.rtl {
|
|||||||
border-top-right-radius: var(--bs-border-radius-sm);
|
border-top-right-radius: var(--bs-border-radius-sm);
|
||||||
border-bottom-right-radius: var(--bs-border-radius-sm);
|
border-bottom-right-radius: var(--bs-border-radius-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-sticky img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
@ -996,6 +996,53 @@ describe('DocumentDetailComponent', () => {
|
|||||||
expect(closeSpy).toHaveBeenCalled()
|
expect(closeSpy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should change preview element by render type', () => {
|
||||||
|
component.metadata = { has_archive_version: true }
|
||||||
|
initNormally()
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(component.contentRenderType).toEqual(component.ContentRenderType.PDF)
|
||||||
|
expect(
|
||||||
|
fixture.debugElement.query(By.css('pdf-viewer-container'))
|
||||||
|
).not.toBeUndefined()
|
||||||
|
|
||||||
|
component.metadata = {
|
||||||
|
has_archive_version: false,
|
||||||
|
original_mime_type: 'text/plain',
|
||||||
|
}
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(component.contentRenderType).toEqual(
|
||||||
|
component.ContentRenderType.Text
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
fixture.debugElement.query(By.css('div.preview-sticky'))
|
||||||
|
).not.toBeUndefined()
|
||||||
|
|
||||||
|
component.metadata = {
|
||||||
|
has_archive_version: false,
|
||||||
|
original_mime_type: 'image/jpg',
|
||||||
|
}
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(component.contentRenderType).toEqual(
|
||||||
|
component.ContentRenderType.Image
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
fixture.debugElement.query(By.css('.preview-sticky img'))
|
||||||
|
).not.toBeUndefined()
|
||||||
|
|
||||||
|
component.metadata = {
|
||||||
|
has_archive_version: false,
|
||||||
|
original_mime_type:
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
}
|
||||||
|
fixture.detectChanges()
|
||||||
|
expect(component.contentRenderType).toEqual(
|
||||||
|
component.ContentRenderType.Other
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
fixture.debugElement.query(By.css('object.preview-sticky'))
|
||||||
|
).not.toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
function initNormally() {
|
function initNormally() {
|
||||||
jest
|
jest
|
||||||
.spyOn(activatedRoute, 'paramMap', 'get')
|
.spyOn(activatedRoute, 'paramMap', 'get')
|
||||||
|
@ -77,6 +77,13 @@ enum DocumentDetailNavIDs {
|
|||||||
Permissions = 6,
|
Permissions = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ContentRenderType {
|
||||||
|
PDF = 'pdf',
|
||||||
|
Image = 'image',
|
||||||
|
Text = 'text',
|
||||||
|
Other = 'other',
|
||||||
|
}
|
||||||
|
|
||||||
enum ZoomSetting {
|
enum ZoomSetting {
|
||||||
PageFit = 'page-fit',
|
PageFit = 'page-fit',
|
||||||
PageWidth = 'page-width',
|
PageWidth = 'page-width',
|
||||||
@ -154,7 +161,9 @@ export class DocumentDetailComponent
|
|||||||
ogDate: Date
|
ogDate: Date
|
||||||
|
|
||||||
customFields: CustomField[]
|
customFields: CustomField[]
|
||||||
public readonly PaperlessCustomFieldDataType = CustomFieldDataType
|
public readonly CustomFieldDataType = CustomFieldDataType
|
||||||
|
|
||||||
|
public readonly ContentRenderType = ContentRenderType
|
||||||
|
|
||||||
@ViewChild('nav') nav: NgbNav
|
@ViewChild('nav') nav: NgbNav
|
||||||
@ViewChild('pdfPreview') set pdfPreview(element) {
|
@ViewChild('pdfPreview') set pdfPreview(element) {
|
||||||
@ -201,16 +210,21 @@ export class DocumentDetailComponent
|
|||||||
return this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)
|
return this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)
|
||||||
}
|
}
|
||||||
|
|
||||||
getContentType() {
|
get contentRenderType(): ContentRenderType {
|
||||||
return this.metadata?.has_archive_version
|
const contentType = this.metadata?.has_archive_version
|
||||||
? 'application/pdf'
|
? 'application/pdf'
|
||||||
: this.metadata?.original_mime_type
|
: this.metadata?.original_mime_type
|
||||||
}
|
|
||||||
|
|
||||||
get renderAsPlainText(): boolean {
|
if (contentType === 'application/pdf') {
|
||||||
return ['text/plain', 'application/csv', 'text/csv'].includes(
|
return ContentRenderType.PDF
|
||||||
this.getContentType()
|
} else if (
|
||||||
)
|
['text/plain', 'application/csv', 'text/csv'].includes(contentType)
|
||||||
|
) {
|
||||||
|
return ContentRenderType.Text
|
||||||
|
} else if (contentType?.indexOf('image/') === 0) {
|
||||||
|
return ContentRenderType.Image
|
||||||
|
}
|
||||||
|
return ContentRenderType.Other
|
||||||
}
|
}
|
||||||
|
|
||||||
get isRTL() {
|
get isRTL() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user