mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-08-26 01:16:16 +00:00
Compare commits
9 Commits
v2.18.2
...
fix-refact
Author | SHA1 | Date | |
---|---|---|---|
![]() |
87f37416a9 | ||
![]() |
6a0311bd45 | ||
![]() |
297e9558cc | ||
![]() |
3f84d581b1 | ||
![]() |
22064ed004 | ||
![]() |
23daa0b974 | ||
![]() |
7b63f5a98c | ||
![]() |
7c76377477 | ||
![]() |
56c70bf177 |
@@ -1,5 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
## paperless-ngx 2.18.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: prevent loss of changes when switching between open docs [@shamoon](https://github.com/shamoon) ([#10659](https://github.com/paperless-ngx/paperless-ngx/pull/10659))
|
||||
- Fix: ignore incomplete tasks for system status 'last run' [@shamoon](https://github.com/shamoon) ([#10641](https://github.com/paperless-ngx/paperless-ngx/pull/10641))
|
||||
- Fix: increase legibility of date filter clear button in light mode [@shamoon](https://github.com/shamoon) ([#10649](https://github.com/paperless-ngx/paperless-ngx/pull/10649))
|
||||
- Fix: ensure saved view count is visible with long names [@shamoon](https://github.com/shamoon) ([#10616](https://github.com/paperless-ngx/paperless-ngx/pull/10616))
|
||||
- Tweak: improve dateparser auto-detection messages [@shamoon](https://github.com/shamoon) ([#10640](https://github.com/paperless-ngx/paperless-ngx/pull/10640))
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Chore(deps): Bump the development group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#10578](https://github.com/paperless-ngx/paperless-ngx/pull/10578))
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>6 changes</summary>
|
||||
|
||||
- Fix: prevent loss of changes when switching between open docs [@shamoon](https://github.com/shamoon) ([#10659](https://github.com/paperless-ngx/paperless-ngx/pull/10659))
|
||||
- Fix: ignore incomplete tasks for system status 'last run' [@shamoon](https://github.com/shamoon) ([#10641](https://github.com/paperless-ngx/paperless-ngx/pull/10641))
|
||||
- Tweak: improve dateparser auto-detection messages [@shamoon](https://github.com/shamoon) ([#10640](https://github.com/paperless-ngx/paperless-ngx/pull/10640))
|
||||
- Fix: increase legibility of date filter clear button in light mode [@shamoon](https://github.com/shamoon) ([#10649](https://github.com/paperless-ngx/paperless-ngx/pull/10649))
|
||||
- Fix: ensure saved view count is visible with long names [@shamoon](https://github.com/shamoon) ([#10616](https://github.com/paperless-ngx/paperless-ngx/pull/10616))
|
||||
- Chore(deps): Bump the development group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#10578](https://github.com/paperless-ngx/paperless-ngx/pull/10578))
|
||||
</details>
|
||||
|
||||
## paperless-ngx 2.18.1
|
||||
|
||||
### Features / Enhancements
|
||||
|
@@ -147,7 +147,7 @@
|
||||
[disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave"
|
||||
popoverClass="popover-slim">
|
||||
<i-bs class="me-1" name="file-text"></i-bs><span> {{d.title | documentTitle}}</span>
|
||||
<span class="close" (click)="closeDocument(d); $event.preventDefault()">
|
||||
<span class="close flex-column justify-content-center" (click)="closeDocument(d); $event.preventDefault()">
|
||||
<i-bs name="x"></i-bs>
|
||||
</span>
|
||||
</a>
|
||||
|
@@ -191,7 +191,7 @@ main {
|
||||
list-style-type: none;
|
||||
|
||||
&:hover .close {
|
||||
display: block;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.close {
|
||||
|
@@ -452,6 +452,18 @@ describe('DocumentDetailComponent', () => {
|
||||
expect(navigateSpy).toHaveBeenCalledWith(['404'], { replaceUrl: true })
|
||||
})
|
||||
|
||||
it('should navigate to 404 if error on load', () => {
|
||||
jest
|
||||
.spyOn(activatedRoute, 'paramMap', 'get')
|
||||
.mockReturnValue(of(convertToParamMap({ id: 3, section: 'details' })))
|
||||
const navigateSpy = jest.spyOn(router, 'navigate')
|
||||
jest
|
||||
.spyOn(documentService, 'get')
|
||||
.mockReturnValue(throwError(() => new Error('not found')))
|
||||
fixture.detectChanges()
|
||||
expect(navigateSpy).toHaveBeenCalledWith(['404'], { replaceUrl: true })
|
||||
})
|
||||
|
||||
it('should support save, close and show success toast', () => {
|
||||
initNormally()
|
||||
component.title = 'Foo Bar'
|
||||
@@ -1388,4 +1400,19 @@ describe('DocumentDetailComponent', () => {
|
||||
component.openEmailDocument()
|
||||
expect(modalSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should set previewText', () => {
|
||||
initNormally()
|
||||
const previewText = 'Hello world, this is a test'
|
||||
httpTestingController.expectOne(component.previewUrl).flush(previewText)
|
||||
expect(component.previewText).toEqual(previewText)
|
||||
})
|
||||
|
||||
it('should set previewText to error message if preview fails', () => {
|
||||
initNormally()
|
||||
httpTestingController
|
||||
.expectOne(component.previewUrl)
|
||||
.flush('fail', { status: 500, statusText: 'Server Error' })
|
||||
expect(component.previewText).toContain('An error occurred loading content')
|
||||
})
|
||||
})
|
||||
|
@@ -21,8 +21,9 @@ import { dirtyCheck, DirtyComponent } from '@ngneat/dirty-check-forms'
|
||||
import { PDFDocumentProxy, PdfViewerModule } from 'ng2-pdf-viewer'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { DeviceDetectorService } from 'ngx-device-detector'
|
||||
import { BehaviorSubject, Observable, Subject } from 'rxjs'
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs'
|
||||
import {
|
||||
catchError,
|
||||
debounceTime,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
@@ -327,19 +328,163 @@ export class DocumentDetailComponent
|
||||
}
|
||||
}
|
||||
|
||||
private mapDocToForm(doc: Document): any {
|
||||
return {
|
||||
...doc,
|
||||
permissions_form: { owner: doc.owner, set_permissions: doc.permissions },
|
||||
}
|
||||
}
|
||||
|
||||
private mapFormToDoc(value: any): any {
|
||||
const docValues = { ...value }
|
||||
docValues['owner'] = value['permissions_form']?.owner
|
||||
docValues['set_permissions'] = value['permissions_form']?.set_permissions
|
||||
delete docValues['permissions_form']
|
||||
return docValues
|
||||
}
|
||||
|
||||
private prepareForm(doc: Document): void {
|
||||
this.documentForm.reset(this.mapDocToForm(doc), { emitEvent: false })
|
||||
if (!this.userCanEditDoc(doc)) {
|
||||
this.documentForm.disable({ emitEvent: false })
|
||||
} else {
|
||||
this.documentForm.enable({ emitEvent: false })
|
||||
}
|
||||
if (doc.__changedFields) {
|
||||
doc.__changedFields.forEach((field) => {
|
||||
if (field === 'owner' || field === 'set_permissions') {
|
||||
this.documentForm.get('permissions_form')?.markAsDirty()
|
||||
} else {
|
||||
this.documentForm.get(field)?.markAsDirty()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private setupDirtyTracking(
|
||||
currentDocument: Document,
|
||||
originalDocument: Document
|
||||
): void {
|
||||
this.store = new BehaviorSubject({
|
||||
title: originalDocument.title,
|
||||
content: originalDocument.content,
|
||||
created: originalDocument.created,
|
||||
correspondent: originalDocument.correspondent,
|
||||
document_type: originalDocument.document_type,
|
||||
storage_path: originalDocument.storage_path,
|
||||
archive_serial_number: originalDocument.archive_serial_number,
|
||||
tags: [...originalDocument.tags],
|
||||
permissions_form: {
|
||||
owner: originalDocument.owner,
|
||||
set_permissions: originalDocument.permissions,
|
||||
},
|
||||
custom_fields: [...originalDocument.custom_fields],
|
||||
})
|
||||
this.isDirty$ = dirtyCheck(this.documentForm, this.store.asObservable())
|
||||
this.isDirty$
|
||||
.pipe(
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
takeUntil(this.docChangeNotifier)
|
||||
)
|
||||
.subscribe((dirty) =>
|
||||
this.openDocumentService.setDirty(
|
||||
currentDocument,
|
||||
dirty,
|
||||
this.getChangedFields()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private loadDocument(documentId: number): void {
|
||||
this.previewUrl = this.documentsService.getPreviewUrl(documentId)
|
||||
this.http
|
||||
.get(this.previewUrl, { responseType: 'text' })
|
||||
.pipe(
|
||||
first(),
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
takeUntil(this.docChangeNotifier)
|
||||
)
|
||||
.subscribe({
|
||||
next: (res) => (this.previewText = res.toString()),
|
||||
error: (err) =>
|
||||
(this.previewText = $localize`An error occurred loading content: ${
|
||||
err.message ?? err.toString()
|
||||
}`),
|
||||
})
|
||||
this.thumbUrl = this.documentsService.getThumbUrl(documentId)
|
||||
this.documentsService
|
||||
.get(documentId)
|
||||
.pipe(
|
||||
catchError(() => {
|
||||
// 404 is handled in the subscribe below
|
||||
return of(null)
|
||||
}),
|
||||
first(),
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
takeUntil(this.docChangeNotifier)
|
||||
)
|
||||
.subscribe({
|
||||
next: (doc) => {
|
||||
if (!doc) {
|
||||
this.router.navigate(['404'], { replaceUrl: true })
|
||||
return
|
||||
}
|
||||
this.documentId = doc.id
|
||||
this.suggestions = null
|
||||
const openDocument = this.openDocumentService.getOpenDocument(
|
||||
this.documentId
|
||||
)
|
||||
const useDoc = openDocument || doc
|
||||
if (openDocument) {
|
||||
if (
|
||||
new Date(doc.modified) > new Date(openDocument.modified) &&
|
||||
!this.modalService.hasOpenModals()
|
||||
) {
|
||||
const modal = this.modalService.open(ConfirmDialogComponent)
|
||||
modal.componentInstance.title = $localize`Document changes detected`
|
||||
modal.componentInstance.messageBold = $localize`The version of this document in your browser session appears older than the existing version.`
|
||||
modal.componentInstance.message = $localize`Saving the document here may overwrite other changes that were made. To restore the existing version, discard your changes or close the document.`
|
||||
modal.componentInstance.cancelBtnClass = 'visually-hidden'
|
||||
modal.componentInstance.btnCaption = $localize`Ok`
|
||||
modal.componentInstance.confirmClicked.subscribe(() =>
|
||||
modal.close()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
this.openDocumentService
|
||||
.openDocument(doc)
|
||||
.pipe(
|
||||
first(),
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
takeUntil(this.docChangeNotifier)
|
||||
)
|
||||
.subscribe()
|
||||
}
|
||||
this.updateComponent(useDoc)
|
||||
this.titleSubject
|
||||
.pipe(
|
||||
debounceTime(1000),
|
||||
distinctUntilChanged(),
|
||||
takeUntil(this.docChangeNotifier),
|
||||
takeUntil(this.unsubscribeNotifier)
|
||||
)
|
||||
.subscribe((titleValue) => {
|
||||
if (titleValue !== this.titleInput.value) return
|
||||
this.title = titleValue
|
||||
this.documentForm.patchValue({ title: titleValue })
|
||||
})
|
||||
this.setupDirtyTracking(useDoc, doc)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.setZoom(this.settings.get(SETTINGS_KEYS.PDF_VIEWER_ZOOM_SETTING))
|
||||
this.documentForm.valueChanges
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe(() => {
|
||||
.subscribe((values) => {
|
||||
this.error = null
|
||||
const docValues = Object.assign({}, this.documentForm.value)
|
||||
docValues['owner'] =
|
||||
this.documentForm.get('permissions_form').value['owner']
|
||||
docValues['set_permissions'] =
|
||||
this.documentForm.get('permissions_form').value['set_permissions']
|
||||
delete docValues['permissions_form']
|
||||
Object.assign(this.document, docValues)
|
||||
Object.assign(this.document, this.mapFormToDoc(values))
|
||||
})
|
||||
|
||||
if (
|
||||
@@ -391,171 +536,36 @@ export class DocumentDetailComponent
|
||||
|
||||
this.route.paramMap
|
||||
.pipe(
|
||||
filter((paramMap) => {
|
||||
// only init when changing docs & section is set
|
||||
return (
|
||||
filter(
|
||||
(paramMap) =>
|
||||
+paramMap.get('id') !== this.documentId &&
|
||||
paramMap.get('section')?.length > 0
|
||||
)
|
||||
}),
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
switchMap((paramMap) => {
|
||||
const documentId = +paramMap.get('id')
|
||||
this.docChangeNotifier.next(documentId)
|
||||
// Dont wait to get the preview
|
||||
this.previewUrl = this.documentsService.getPreviewUrl(documentId)
|
||||
this.http.get(this.previewUrl, { responseType: 'text' }).subscribe({
|
||||
next: (res) => {
|
||||
this.previewText = res.toString()
|
||||
},
|
||||
error: (err) => {
|
||||
this.previewText = $localize`An error occurred loading content: ${
|
||||
err.message ?? err.toString()
|
||||
}`
|
||||
},
|
||||
})
|
||||
this.thumbUrl = this.documentsService.getThumbUrl(documentId)
|
||||
return this.documentsService.get(documentId)
|
||||
})
|
||||
),
|
||||
takeUntil(this.unsubscribeNotifier)
|
||||
)
|
||||
.pipe(
|
||||
switchMap((doc) => {
|
||||
this.documentId = doc.id
|
||||
this.suggestions = null
|
||||
const openDocument = this.openDocumentService.getOpenDocument(
|
||||
this.documentId
|
||||
)
|
||||
|
||||
if (openDocument) {
|
||||
if (
|
||||
new Date(doc.modified) > new Date(openDocument.modified) &&
|
||||
!this.modalService.hasOpenModals()
|
||||
) {
|
||||
let modal = this.modalService.open(ConfirmDialogComponent)
|
||||
modal.componentInstance.title = $localize`Document changes detected`
|
||||
modal.componentInstance.messageBold = $localize`The version of this document in your browser session appears older than the existing version.`
|
||||
modal.componentInstance.message = $localize`Saving the document here may overwrite other changes that were made. To restore the existing version, discard your changes or close the document.`
|
||||
modal.componentInstance.cancelBtnClass = 'visually-hidden'
|
||||
modal.componentInstance.btnCaption = $localize`Ok`
|
||||
modal.componentInstance.confirmClicked.subscribe(() =>
|
||||
modal.close()
|
||||
)
|
||||
}
|
||||
|
||||
// Prevent mutating stale form values into the next document: only sync if it still matches the active document.
|
||||
if (
|
||||
this.documentForm.dirty &&
|
||||
(this.document?.id === openDocument.id || !this.document)
|
||||
) {
|
||||
Object.assign(openDocument, this.documentForm.value)
|
||||
openDocument['owner'] =
|
||||
this.documentForm.get('permissions_form').value['owner']
|
||||
openDocument['permissions'] =
|
||||
this.documentForm.get('permissions_form').value[
|
||||
'set_permissions'
|
||||
]
|
||||
delete openDocument['permissions_form']
|
||||
}
|
||||
if (openDocument.__changedFields) {
|
||||
openDocument.__changedFields.forEach((field) => {
|
||||
if (field === 'owner' || field === 'set_permissions') {
|
||||
this.documentForm.get('permissions_form').markAsDirty()
|
||||
} else {
|
||||
this.documentForm.get(field)?.markAsDirty()
|
||||
}
|
||||
})
|
||||
}
|
||||
this.updateComponent(openDocument)
|
||||
} else {
|
||||
this.openDocumentService.openDocument(doc)
|
||||
this.updateComponent(doc)
|
||||
}
|
||||
|
||||
this.titleSubject
|
||||
.pipe(
|
||||
debounceTime(1000),
|
||||
distinctUntilChanged(),
|
||||
takeUntil(this.docChangeNotifier),
|
||||
takeUntil(this.unsubscribeNotifier)
|
||||
)
|
||||
.subscribe({
|
||||
next: (titleValue) => {
|
||||
// In the rare case when the field changed just after debounced event was fired.
|
||||
// We dont want to overwrite what's actually in the text field, so just return
|
||||
if (titleValue !== this.titleInput.value) return
|
||||
|
||||
this.title = titleValue
|
||||
this.documentForm.patchValue({ title: titleValue })
|
||||
},
|
||||
complete: () => {
|
||||
// doc changed so we manually check dirty in case title was changed
|
||||
if (
|
||||
this.store.getValue().title !==
|
||||
this.documentForm.get('title').value
|
||||
) {
|
||||
this.openDocumentService.setDirty(
|
||||
doc,
|
||||
true,
|
||||
this.getChangedFields()
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
// Initialize dirtyCheck
|
||||
this.store = new BehaviorSubject({
|
||||
title: doc.title,
|
||||
content: doc.content,
|
||||
created: doc.created,
|
||||
correspondent: doc.correspondent,
|
||||
document_type: doc.document_type,
|
||||
storage_path: doc.storage_path,
|
||||
archive_serial_number: doc.archive_serial_number,
|
||||
tags: [...doc.tags],
|
||||
permissions_form: {
|
||||
owner: doc.owner,
|
||||
set_permissions: doc.permissions,
|
||||
},
|
||||
custom_fields: [...doc.custom_fields],
|
||||
})
|
||||
|
||||
this.isDirty$ = dirtyCheck(
|
||||
this.documentForm,
|
||||
this.store.asObservable()
|
||||
)
|
||||
|
||||
return this.isDirty$.pipe(
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
map((dirty) => ({ doc, dirty }))
|
||||
)
|
||||
})
|
||||
)
|
||||
.subscribe({
|
||||
next: ({ doc, dirty }) => {
|
||||
this.openDocumentService.setDirty(doc, dirty, this.getChangedFields())
|
||||
},
|
||||
error: (error) => {
|
||||
this.router.navigate(['404'], {
|
||||
replaceUrl: true,
|
||||
})
|
||||
},
|
||||
.subscribe((paramMap) => {
|
||||
const documentId = +paramMap.get('id')
|
||||
this.docChangeNotifier.next(documentId)
|
||||
this.loadDocument(documentId)
|
||||
})
|
||||
|
||||
this.route.paramMap.subscribe((paramMap) => {
|
||||
const section = paramMap.get('section')
|
||||
if (section) {
|
||||
const navIDKey: string = Object.keys(DocumentDetailNavIDs).find(
|
||||
(navID) => navID.toLowerCase() == section
|
||||
)
|
||||
if (navIDKey) {
|
||||
this.activeNavID = DocumentDetailNavIDs[navIDKey]
|
||||
this.route.paramMap
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe((paramMap) => {
|
||||
const section = paramMap.get('section')
|
||||
if (section) {
|
||||
const navIDKey: string = Object.keys(DocumentDetailNavIDs).find(
|
||||
(navID) => navID.toLowerCase() == section
|
||||
)
|
||||
if (navIDKey) {
|
||||
this.activeNavID = DocumentDetailNavIDs[navIDKey]
|
||||
}
|
||||
} else if (paramMap.get('id')) {
|
||||
this.router.navigate(['documents', +paramMap.get('id'), 'details'], {
|
||||
replaceUrl: true,
|
||||
})
|
||||
}
|
||||
} else if (paramMap.get('id')) {
|
||||
this.router.navigate(['documents', +paramMap.get('id'), 'details'], {
|
||||
replaceUrl: true,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.hotKeyService
|
||||
.addShortcut({
|
||||
@@ -682,19 +692,7 @@ export class DocumentDetailComponent
|
||||
})
|
||||
}
|
||||
this.title = this.documentTitlePipe.transform(doc.title)
|
||||
const docFormValues = Object.assign({}, doc)
|
||||
docFormValues['permissions_form'] = {
|
||||
owner: doc.owner,
|
||||
set_permissions: doc.permissions,
|
||||
}
|
||||
|
||||
this.documentForm.patchValue(docFormValues, { emitEvent: false })
|
||||
if (!this.userCanEdit) this.documentForm.disable()
|
||||
setTimeout(() => {
|
||||
// check again after a tick in case form was dirty
|
||||
if (!this.userCanEdit) this.documentForm.disable()
|
||||
else this.documentForm.enable()
|
||||
}, 10)
|
||||
this.prepareForm(doc)
|
||||
}
|
||||
|
||||
get customFieldFormFields(): FormArray {
|
||||
@@ -797,7 +795,11 @@ export class DocumentDetailComponent
|
||||
discard() {
|
||||
this.documentsService
|
||||
.get(this.documentId)
|
||||
.pipe(first())
|
||||
.pipe(
|
||||
first(),
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
takeUntil(this.docChangeNotifier)
|
||||
)
|
||||
.subscribe({
|
||||
next: (doc) => {
|
||||
Object.assign(this.document, doc)
|
||||
@@ -900,9 +902,10 @@ export class DocumentDetailComponent
|
||||
.patch(this.getChangedFields())
|
||||
.pipe(
|
||||
switchMap((updateResult) => {
|
||||
return this.documentListViewService
|
||||
.getNext(this.documentId)
|
||||
.pipe(map((nextDocId) => ({ nextDocId, updateResult })))
|
||||
return this.documentListViewService.getNext(this.documentId).pipe(
|
||||
map((nextDocId) => ({ nextDocId, updateResult })),
|
||||
takeUntil(this.unsubscribeNotifier)
|
||||
)
|
||||
})
|
||||
)
|
||||
.pipe(
|
||||
@@ -912,7 +915,10 @@ export class DocumentDetailComponent
|
||||
return this.openDocumentService
|
||||
.closeDocument(this.document)
|
||||
.pipe(
|
||||
map((closeResult) => ({ updateResult, nextDocId, closeResult }))
|
||||
map(
|
||||
(closeResult) => ({ updateResult, nextDocId, closeResult }),
|
||||
takeUntil(this.unsubscribeNotifier)
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1238,16 +1244,19 @@ export class DocumentDetailComponent
|
||||
) {
|
||||
doc.owner = this.store.value.permissions_form.owner
|
||||
}
|
||||
return !this.document || this.userCanEditDoc(doc)
|
||||
}
|
||||
|
||||
private userCanEditDoc(doc: Document): boolean {
|
||||
return (
|
||||
!this.document ||
|
||||
(this.permissionsService.currentUserCan(
|
||||
this.permissionsService.currentUserCan(
|
||||
PermissionAction.Change,
|
||||
PermissionType.Document
|
||||
) &&
|
||||
this.permissionsService.currentUserHasObjectPermissions(
|
||||
PermissionAction.Change,
|
||||
doc
|
||||
))
|
||||
this.permissionsService.currentUserHasObjectPermissions(
|
||||
PermissionAction.Change,
|
||||
doc
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1429,43 +1438,50 @@ export class DocumentDetailComponent
|
||||
}
|
||||
|
||||
private tryRenderTiff() {
|
||||
this.http.get(this.previewUrl, { responseType: 'arraybuffer' }).subscribe({
|
||||
next: (res) => {
|
||||
/* istanbul ignore next */
|
||||
try {
|
||||
// See UTIF.js > _imgLoaded
|
||||
const tiffIfds: any[] = UTIF.decode(res)
|
||||
var vsns = tiffIfds,
|
||||
ma = 0,
|
||||
page = vsns[0]
|
||||
if (tiffIfds[0].subIFD) vsns = vsns.concat(tiffIfds[0].subIFD)
|
||||
for (var i = 0; i < vsns.length; i++) {
|
||||
var img = vsns[i]
|
||||
if (img['t258'] == null || img['t258'].length < 3) continue
|
||||
var ar = img['t256'] * img['t257']
|
||||
if (ar > ma) {
|
||||
ma = ar
|
||||
page = img
|
||||
this.http
|
||||
.get(this.previewUrl, { responseType: 'arraybuffer' })
|
||||
.pipe(
|
||||
first(),
|
||||
takeUntil(this.unsubscribeNotifier),
|
||||
takeUntil(this.docChangeNotifier)
|
||||
)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
/* istanbul ignore next */
|
||||
try {
|
||||
// See UTIF.js > _imgLoaded
|
||||
const tiffIfds: any[] = UTIF.decode(res)
|
||||
var vsns = tiffIfds,
|
||||
ma = 0,
|
||||
page = vsns[0]
|
||||
if (tiffIfds[0].subIFD) vsns = vsns.concat(tiffIfds[0].subIFD)
|
||||
for (var i = 0; i < vsns.length; i++) {
|
||||
var img = vsns[i]
|
||||
if (img['t258'] == null || img['t258'].length < 3) continue
|
||||
var ar = img['t256'] * img['t257']
|
||||
if (ar > ma) {
|
||||
ma = ar
|
||||
page = img
|
||||
}
|
||||
}
|
||||
UTIF.decodeImage(res, page, tiffIfds)
|
||||
const rgba = UTIF.toRGBA8(page)
|
||||
const { width: w, height: h } = page
|
||||
var cnv = document.createElement('canvas')
|
||||
cnv.width = w
|
||||
cnv.height = h
|
||||
var ctx = cnv.getContext('2d'),
|
||||
imgd = ctx.createImageData(w, h)
|
||||
for (var i = 0; i < rgba.length; i++) imgd.data[i] = rgba[i]
|
||||
ctx.putImageData(imgd, 0, 0)
|
||||
this.tiffURL = cnv.toDataURL()
|
||||
} catch (err) {
|
||||
this.tiffError = $localize`An error occurred loading tiff: ${err.toString()}`
|
||||
}
|
||||
UTIF.decodeImage(res, page, tiffIfds)
|
||||
const rgba = UTIF.toRGBA8(page)
|
||||
const { width: w, height: h } = page
|
||||
var cnv = document.createElement('canvas')
|
||||
cnv.width = w
|
||||
cnv.height = h
|
||||
var ctx = cnv.getContext('2d'),
|
||||
imgd = ctx.createImageData(w, h)
|
||||
for (var i = 0; i < rgba.length; i++) imgd.data[i] = rgba[i]
|
||||
ctx.putImageData(imgd, 0, 0)
|
||||
this.tiffURL = cnv.toDataURL()
|
||||
} catch (err) {
|
||||
},
|
||||
error: (err) => {
|
||||
this.tiffError = $localize`An error occurred loading tiff: ${err.toString()}`
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
this.tiffError = $localize`An error occurred loading tiff: ${err.toString()}`
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user