Enhancement: directly render plaintext in previews

This commit is contained in:
shamoon 2024-10-14 13:27:02 -07:00
parent 82fd706dca
commit 0abdb96103
5 changed files with 67 additions and 10 deletions

View File

@ -5,7 +5,11 @@
</div> </div>
} @else { } @else {
@if (renderAsObject) { @if (renderAsObject) {
<object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf" [class.pdf]="isPdf"></object> @if (previewText) {
<div class="preview-sticky bg-light p-3 overflow-auto whitespace-preserve" width="100%">{{previewText}}</div>
} @else {
<object [data]="previewURL | safeUrl" width="100%" class="bg-light" [class.p-2]="!isPdf"></object>
}
} @else { } @else {
@if (requiresPassword) { @if (requiresPassword) {
<div class="w-100 h-100 position-relative"> <div class="w-100 h-100 position-relative">

View File

@ -9,7 +9,12 @@ import { provideHttpClientTesting } from '@angular/common/http/testing'
import { DocumentService } from 'src/app/services/rest/document.service' import { DocumentService } from 'src/app/services/rest/document.service'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { PdfViewerModule } from 'ng2-pdf-viewer' import { PdfViewerModule } from 'ng2-pdf-viewer'
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' import {
HttpClient,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http'
import { of, throwError } from 'rxjs'
const doc = { const doc = {
id: 10, id: 10,
@ -23,6 +28,7 @@ describe('PreviewPopupComponent', () => {
let fixture: ComponentFixture<PreviewPopupComponent> let fixture: ComponentFixture<PreviewPopupComponent>
let settingsService: SettingsService let settingsService: SettingsService
let documentService: DocumentService let documentService: DocumentService
let http: HttpClient
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -35,6 +41,7 @@ describe('PreviewPopupComponent', () => {
}) })
settingsService = TestBed.inject(SettingsService) settingsService = TestBed.inject(SettingsService)
documentService = TestBed.inject(DocumentService) documentService = TestBed.inject(DocumentService)
http = TestBed.inject(HttpClient)
jest jest
.spyOn(documentService, 'getPreviewUrl') .spyOn(documentService, 'getPreviewUrl')
.mockImplementation((id) => doc.original_file_name) .mockImplementation((id) => doc.original_file_name)
@ -95,4 +102,17 @@ describe('PreviewPopupComponent', () => {
'Error loading preview' 'Error loading preview'
) )
}) })
it('should get text content from http if appropriate', () => {
const httpSpy = jest.spyOn(http, 'get')
httpSpy.mockReturnValueOnce(
throwError(() => new Error('Error getting preview'))
)
component.init()
expect(httpSpy).toHaveBeenCalled()
expect(component.error).toBeTruthy()
httpSpy.mockReturnValueOnce(of('Preview text'))
component.init()
expect(component.previewText).toEqual('Preview text')
})
}) })

View File

@ -1,4 +1,6 @@
import { Component, Input } from '@angular/core' import { HttpClient } from '@angular/common/http'
import { Component, Input, OnDestroy } from '@angular/core'
import { first, Subject, takeUntil } from 'rxjs'
import { Document } from 'src/app/data/document' import { Document } from 'src/app/data/document'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { DocumentService } from 'src/app/services/rest/document.service' import { DocumentService } from 'src/app/services/rest/document.service'
@ -9,14 +11,26 @@ import { SettingsService } from 'src/app/services/settings.service'
templateUrl: './preview-popup.component.html', templateUrl: './preview-popup.component.html',
styleUrls: ['./preview-popup.component.scss'], styleUrls: ['./preview-popup.component.scss'],
}) })
export class PreviewPopupComponent { export class PreviewPopupComponent implements OnDestroy {
private _document: Document
@Input() @Input()
document: Document set document(document: Document) {
this._document = document
this.init()
}
get document(): Document {
return this._document
}
unsubscribeNotifier: Subject<any> = new Subject()
error = false error = false
requiresPassword: boolean = false requiresPassword: boolean = false
previewText: string
get renderAsObject(): boolean { get renderAsObject(): boolean {
return (this.isPdf && this.useNativePdfViewer) || !this.isPdf return (this.isPdf && this.useNativePdfViewer) || !this.isPdf
} }
@ -39,9 +53,28 @@ export class PreviewPopupComponent {
constructor( constructor(
private settingsService: SettingsService, private settingsService: SettingsService,
private documentService: DocumentService private documentService: DocumentService,
private http: HttpClient
) {} ) {}
ngOnDestroy(): void {
this.unsubscribeNotifier.next(this)
}
init() {
this.http
.get(this.previewURL, { responseType: 'text' })
.pipe(first(), takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (res) => {
this.previewText = res.toString()
},
error: (err) => {
this.error = err
},
})
}
onError(event: any) { onError(event: any) {
if (event.name == 'PasswordException') { if (event.name == 'PasswordException') {
this.requiresPassword = true this.requiresPassword = true

View File

@ -62,7 +62,3 @@ textarea.rtl {
height: 100%; height: 100%;
object-fit: contain; object-fit: contain;
} }
.whitespace-preserve {
white-space: preserve;
}

View File

@ -680,6 +680,10 @@ code {
opacity: .5; opacity: .5;
} }
.whitespace-preserve {
white-space: preserve;
}
/* Animate items as they're being sorted. */ /* Animate items as they're being sorted. */
.cdk-drop-list-dragging .cdk-drag { .cdk-drop-list-dragging .cdk-drag {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);