mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -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">
|
||||
@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-text" i18n>Page</div>
|
||||
<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) {
|
||||
<div [formGroup]="customFieldFormFields.controls[i]">
|
||||
@switch (getCustomFieldFromInstance(fieldInstance)?.data_type) {
|
||||
@case (PaperlessCustomFieldDataType.String) {
|
||||
@case (CustomFieldDataType.String) {
|
||||
<pngx-input-text formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
@ -114,7 +114,7 @@
|
||||
[horizontal]="true"
|
||||
[error]="getCustomFieldError(i)"></pngx-input-text>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.Date) {
|
||||
@case (CustomFieldDataType.Date) {
|
||||
<pngx-input-date formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
@ -122,7 +122,7 @@
|
||||
[horizontal]="true"
|
||||
[error]="getCustomFieldError(i)"></pngx-input-date>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.Integer) {
|
||||
@case (CustomFieldDataType.Integer) {
|
||||
<pngx-input-number formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
@ -131,7 +131,7 @@
|
||||
[showAdd]="false"
|
||||
[error]="getCustomFieldError(i)"></pngx-input-number>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.Float) {
|
||||
@case (CustomFieldDataType.Float) {
|
||||
<pngx-input-number formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
@ -141,7 +141,7 @@
|
||||
[step]=".1"
|
||||
[error]="getCustomFieldError(i)"></pngx-input-number>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.Monetary) {
|
||||
@case (CustomFieldDataType.Monetary) {
|
||||
<pngx-input-number formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
@ -151,14 +151,14 @@
|
||||
[step]=".01"
|
||||
[error]="getCustomFieldError(i)"></pngx-input-number>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.Boolean) {
|
||||
@case (CustomFieldDataType.Boolean) {
|
||||
<pngx-input-check formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
(removed)="removeField(fieldInstance)"
|
||||
[horizontal]="true"></pngx-input-check>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.Url) {
|
||||
@case (CustomFieldDataType.Url) {
|
||||
<pngx-input-url formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[removable]="userIsOwner"
|
||||
@ -166,7 +166,7 @@
|
||||
[horizontal]="true"
|
||||
[error]="getCustomFieldError(i)"></pngx-input-url>
|
||||
}
|
||||
@case (PaperlessCustomFieldDataType.DocumentLink) {
|
||||
@case (CustomFieldDataType.DocumentLink) {
|
||||
<pngx-input-document-link formControlName="value"
|
||||
[title]="getCustomFieldFromInstance(fieldInstance)?.name"
|
||||
[parentDocumentID]="documentId"
|
||||
@ -260,7 +260,9 @@
|
||||
<a ngbNavLink i18n>Preview</a>
|
||||
@if (!pdfPreview.offsetParent) {
|
||||
<ng-template ngbNavContent>
|
||||
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
||||
<div class="position-relative">
|
||||
<ng-container *ngTemplateOutlet="previewContent"></ng-container>
|
||||
</div>
|
||||
</ng-template>
|
||||
}
|
||||
</li>
|
||||
@ -295,16 +297,6 @@
|
||||
|
||||
<div class="col-md-6 col-xl-8 mb-3 d-none d-md-block position-relative" #pdfPreview>
|
||||
<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>
|
||||
@ -333,29 +325,39 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (getContentType() === 'application/pdf') {
|
||||
@if (!useNativePdfViewer ) {
|
||||
<div class="preview-sticky pdf-viewer-container">
|
||||
<pngx-pdf-viewer
|
||||
[src]="{ url: previewUrl, password: password }"
|
||||
[original-size]="false"
|
||||
[show-borders]="true"
|
||||
[show-all]="true"
|
||||
[(page)]="previewCurrentPage"
|
||||
[zoom-scale]="previewZoomScale"
|
||||
[zoom]="previewZoomSetting"
|
||||
(error)="onError($event)"
|
||||
(after-load-complete)="pdfPreviewLoaded($event)">
|
||||
</pngx-pdf-viewer>
|
||||
@switch (contentRenderType) {
|
||||
@case (ContentRenderType.PDF) {
|
||||
@if (!useNativePdfViewer) {
|
||||
<div class="preview-sticky pdf-viewer-container">
|
||||
<pngx-pdf-viewer
|
||||
[src]="{ url: previewUrl, password: password }"
|
||||
[original-size]="false"
|
||||
[show-borders]="true"
|
||||
[show-all]="true"
|
||||
[(page)]="previewCurrentPage"
|
||||
[zoom-scale]="previewZoomScale"
|
||||
[zoom]="previewZoomSetting"
|
||||
(error)="onError($event)"
|
||||
(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>
|
||||
} @else {
|
||||
}
|
||||
@case (ContentRenderType.Other) {
|
||||
<object [data]="previewUrl | safeUrl" class="preview-sticky" width="100%"></object>
|
||||
}
|
||||
}
|
||||
@if (renderAsPlainText) {
|
||||
<div [innerText]="previewText" class="preview-sticky bg-light p-3 overflow-auto" width="100%"></div>
|
||||
}
|
||||
@if (showPasswordField) {
|
||||
@if (requiresPassword) {
|
||||
<div class="password-prompt">
|
||||
<form>
|
||||
<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-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()
|
||||
})
|
||||
|
||||
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() {
|
||||
jest
|
||||
.spyOn(activatedRoute, 'paramMap', 'get')
|
||||
|
@ -77,6 +77,13 @@ enum DocumentDetailNavIDs {
|
||||
Permissions = 6,
|
||||
}
|
||||
|
||||
enum ContentRenderType {
|
||||
PDF = 'pdf',
|
||||
Image = 'image',
|
||||
Text = 'text',
|
||||
Other = 'other',
|
||||
}
|
||||
|
||||
enum ZoomSetting {
|
||||
PageFit = 'page-fit',
|
||||
PageWidth = 'page-width',
|
||||
@ -154,7 +161,9 @@ export class DocumentDetailComponent
|
||||
ogDate: Date
|
||||
|
||||
customFields: CustomField[]
|
||||
public readonly PaperlessCustomFieldDataType = CustomFieldDataType
|
||||
public readonly CustomFieldDataType = CustomFieldDataType
|
||||
|
||||
public readonly ContentRenderType = ContentRenderType
|
||||
|
||||
@ViewChild('nav') nav: NgbNav
|
||||
@ViewChild('pdfPreview') set pdfPreview(element) {
|
||||
@ -201,16 +210,21 @@ export class DocumentDetailComponent
|
||||
return this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)
|
||||
}
|
||||
|
||||
getContentType() {
|
||||
return this.metadata?.has_archive_version
|
||||
get contentRenderType(): ContentRenderType {
|
||||
const contentType = this.metadata?.has_archive_version
|
||||
? 'application/pdf'
|
||||
: this.metadata?.original_mime_type
|
||||
}
|
||||
|
||||
get renderAsPlainText(): boolean {
|
||||
return ['text/plain', 'application/csv', 'text/csv'].includes(
|
||||
this.getContentType()
|
||||
)
|
||||
if (contentType === 'application/pdf') {
|
||||
return ContentRenderType.PDF
|
||||
} 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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user