Fix: render images not converted to pdf, refactor doc detail rendering (#5475)

This commit is contained in:
shamoon 2024-01-20 08:26:24 -08:00 committed by GitHub
parent 5781a0d51f
commit 5842944d1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 116 additions and 47 deletions

View File

@ -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)" />

View File

@ -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;
}

View File

@ -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')

View File

@ -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() {