diff --git a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.html b/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.html deleted file mode 100644 index 01bf5d3fd..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - -
- -
-
diff --git a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.scss b/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.scss deleted file mode 100644 index 4ddd79bfa..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.scss +++ /dev/null @@ -1,28 +0,0 @@ -.pdf-viewer-container { - background-color: gray; - height: 550px; - - pdf-viewer { - width: 100%; - height: 100%; - } -} - -.mw-60 { - max-width: 60px; -} - -div.position-absolute:has(.form-check-input:checked) { - background-color: rgba(var(--bs-dark-rgb), 0.4); -} - -.form-check-input { - &:checked { - background-color: var(--bs-danger); - border-color: var(--bs-danger); - } - &:focus { - box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), var(--pngx-focus-alpha)); - border-color: var(--bs-danger); - } -} diff --git a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.spec.ts b/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.spec.ts deleted file mode 100644 index 964cc05a7..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.spec.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' -import { provideHttpClientTesting } from '@angular/common/http/testing' -import { ComponentFixture, TestBed } from '@angular/core/testing' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' -import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe' -import { DeletePagesConfirmDialogComponent } from './delete-pages-confirm-dialog.component' - -describe('DeletePagesConfirmDialogComponent', () => { - let component: DeletePagesConfirmDialogComponent - let fixture: ComponentFixture - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [], - imports: [ - NgxBootstrapIconsModule.pick(allIcons), - FormsModule, - ReactiveFormsModule, - DeletePagesConfirmDialogComponent, - ], - providers: [ - NgbActiveModal, - SafeHtmlPipe, - provideHttpClient(withInterceptorsFromDi()), - provideHttpClientTesting(), - ], - }).compileComponents() - fixture = TestBed.createComponent(DeletePagesConfirmDialogComponent) - component = fixture.componentInstance - fixture.detectChanges() - }) - - it('should return a string with comma-separated pages', () => { - component.pages = [1, 2, 3, 4] - expect(component.pagesString).toEqual('1, 2, 3, 4') - }) - - it('should update totalPages when pdf is loaded', () => { - component.pdfPreviewLoaded({ numPages: 5 } as any) - expect(component.totalPages).toEqual(5) - }) - - it('should update checks when page is rendered', () => { - const event = { - target: document.createElement('div'), - detail: { pageNumber: 1 }, - } as any - component.pageRendered(event) - expect(component['checks'].length).toEqual(1) - }) - - it('should update pages when page check is changed', () => { - component.pageCheckChanged(1) - expect(component.pages).toEqual([1]) - component.pageCheckChanged(1) - expect(component.pages).toEqual([]) - }) -}) diff --git a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.ts b/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.ts deleted file mode 100644 index 6d49a110e..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Component, TemplateRef, ViewChild, inject } from '@angular/core' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { - PDFDocumentProxy, - PdfViewerComponent, - PdfViewerModule, -} from 'ng2-pdf-viewer' -import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe' -import { DocumentService } from 'src/app/services/rest/document.service' -import { ConfirmDialogComponent } from '../confirm-dialog.component' - -@Component({ - selector: 'pngx-delete-pages-confirm-dialog', - templateUrl: './delete-pages-confirm-dialog.component.html', - styleUrl: './delete-pages-confirm-dialog.component.scss', - imports: [PdfViewerModule, FormsModule, ReactiveFormsModule, SafeHtmlPipe], -}) -export class DeletePagesConfirmDialogComponent extends ConfirmDialogComponent { - private documentService = inject(DocumentService) - - public documentID: number - public pages: number[] = [] - public currentPage: number = 1 - public totalPages: number - - @ViewChild('pdfViewer') pdfViewer: PdfViewerComponent - @ViewChild('pageCheckOverlay') pageCheckOverlay!: TemplateRef - private checks: HTMLElement[] = [] - - public get pagesString(): string { - return this.pages.join(', ') - } - - public get pdfSrc(): string { - return this.documentService.getPreviewUrl(this.documentID) - } - - constructor() { - super() - } - - public pdfPreviewLoaded(pdf: PDFDocumentProxy) { - this.totalPages = pdf.numPages - } - - pageRendered(event: CustomEvent) { - const pageDiv = event.target as HTMLDivElement - const check = this.pageCheckOverlay.createEmbeddedView({ - page: event.detail.pageNumber, - }) - this.checks[event.detail.pageNumber - 1] = check.rootNodes[0] - pageDiv?.insertBefore(check.rootNodes[0], pageDiv.firstChild) - this.updateChecks() - } - - pageCheckChanged(pageNumber: number) { - if (!this.pages.includes(pageNumber)) this.pages.push(pageNumber) - else if (this.pages.includes(pageNumber)) - this.pages.splice(this.pages.indexOf(pageNumber), 1) - this.updateChecks() - } - - private updateChecks() { - this.checks.forEach((check, i) => { - const input = check.getElementsByTagName('input')[0] - input.checked = this.pages.includes(i + 1) - }) - } -} diff --git a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.html b/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.html deleted file mode 100644 index 47e4c137c..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.html +++ /dev/null @@ -1,59 +0,0 @@ - - - diff --git a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.scss b/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.scss deleted file mode 100644 index 9b8df66c5..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.scss +++ /dev/null @@ -1,9 +0,0 @@ -.pdf-viewer-container { - background-color: gray; - height: 500px; - - pdf-viewer { - width: 100%; - height: 100%; - } - } diff --git a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.spec.ts b/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.spec.ts deleted file mode 100644 index b47101f6e..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.spec.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing' - -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' -import { provideHttpClientTesting } from '@angular/common/http/testing' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { PdfViewerModule } from 'ng2-pdf-viewer' -import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons' -import { of } from 'rxjs' -import { DocumentService } from 'src/app/services/rest/document.service' -import { SplitConfirmDialogComponent } from './split-confirm-dialog.component' - -describe('SplitConfirmDialogComponent', () => { - let component: SplitConfirmDialogComponent - let fixture: ComponentFixture - let documentService: DocumentService - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - NgxBootstrapIconsModule.pick(allIcons), - ReactiveFormsModule, - FormsModule, - PdfViewerModule, - SplitConfirmDialogComponent, - ], - providers: [ - NgbActiveModal, - provideHttpClient(withInterceptorsFromDi()), - provideHttpClientTesting(), - ], - }).compileComponents() - - fixture = TestBed.createComponent(SplitConfirmDialogComponent) - documentService = TestBed.inject(DocumentService) - component = fixture.componentInstance - fixture.detectChanges() - }) - - it('should load document on init', () => { - const getSpy = jest.spyOn(documentService, 'get') - component.documentID = 1 - getSpy.mockReturnValue(of({ id: 1 } as any)) - component.ngOnInit() - expect(documentService.get).toHaveBeenCalledWith(1) - }) - - it('should update pagesString when pages are added', () => { - component.totalPages = 5 - component.page = 2 - component.addSplit() - expect(component.pagesString).toEqual('1-2,3-5') - component.page = 4 - component.addSplit() - expect(component.pagesString).toEqual('1-2,3-4,5') - }) - - it('should update pagesString when pages are removed', () => { - component.totalPages = 5 - component.page = 2 - component.addSplit() - component.page = 4 - component.addSplit() - expect(component.pagesString).toEqual('1-2,3-4,5') - component.removeSplit(0) - expect(component.pagesString).toEqual('1-4,5') - }) - - it('should enable confirm button when pages are added', () => { - component.totalPages = 5 - component.page = 2 - component.addSplit() - expect(component.confirmButtonEnabled).toBeTruthy() - }) - - it('should disable confirm button when all pages are removed', () => { - component.totalPages = 5 - component.page = 2 - component.addSplit() - component.removeSplit(0) - expect(component.confirmButtonEnabled).toBeFalsy() - }) - - it('should not add split if page is the last page', () => { - component.totalPages = 5 - component.page = 5 - component.addSplit() - expect(component.pagesString).toEqual('1-5') - }) - - it('should update totalPages when pdf is loaded', () => { - component.pdfPreviewLoaded({ numPages: 5 } as any) - expect(component.totalPages).toEqual(5) - }) - - it('should correctly disable split button', () => { - component.totalPages = 5 - component.page = 1 - expect(component.canSplit).toBeTruthy() - component.page = 5 - expect(component.canSplit).toBeFalsy() - component.page = 4 - expect(component.canSplit).toBeTruthy() - component['pages'] = new Set([1, 2, 3, 4]) - expect(component.canSplit).toBeFalsy() - }) -}) diff --git a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.ts b/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.ts deleted file mode 100644 index 656666be6..000000000 --- a/src-ui/src/app/components/common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { Component, OnInit, inject } from '@angular/core' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { PDFDocumentProxy, PdfViewerModule } from 'ng2-pdf-viewer' -import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' -import { Document } from 'src/app/data/document' -import { PermissionsService } from 'src/app/services/permissions.service' -import { DocumentService } from 'src/app/services/rest/document.service' -import { ConfirmDialogComponent } from '../confirm-dialog.component' - -@Component({ - selector: 'pngx-split-confirm-dialog', - templateUrl: './split-confirm-dialog.component.html', - styleUrl: './split-confirm-dialog.component.scss', - imports: [ - FormsModule, - ReactiveFormsModule, - NgxBootstrapIconsModule, - PdfViewerModule, - ], -}) -export class SplitConfirmDialogComponent - extends ConfirmDialogComponent - implements OnInit -{ - private documentService = inject(DocumentService) - private permissionService = inject(PermissionsService) - - public get pagesString(): string { - let pagesStr = '' - - let lastPage = 1 - for (let i = 1; i <= this.totalPages; i++) { - if (this.pages.has(i) || i === this.totalPages) { - if (lastPage === i) { - pagesStr += `${i},` - lastPage = Math.min(i + 1, this.totalPages) - } else { - pagesStr += `${lastPage}-${i},` - lastPage = Math.min(i + 1, this.totalPages) - } - } - } - - return pagesStr.replace(/,$/, '') - } - - private pages: Set = new Set() - - public documentID: number - private document: Document - public page: number = 1 - public totalPages: number - public deleteOriginal: boolean = false - - public get canSplit(): boolean { - return ( - this.page < this.totalPages && - this.pages.size < this.totalPages - 1 && - !this.pages.has(this.page) - ) - } - - public get pdfSrc(): string { - return this.documentService.getPreviewUrl(this.documentID) - } - - constructor() { - super() - this.confirmButtonEnabled = this.pages.size > 0 - } - - ngOnInit(): void { - this.documentService.get(this.documentID).subscribe((r) => { - this.document = r - }) - } - - pdfPreviewLoaded(pdf: PDFDocumentProxy) { - this.totalPages = pdf.numPages - } - - addSplit() { - if (this.page === this.totalPages) return - this.pages.add(this.page) - this.pages = new Set(Array.from(this.pages).sort((a, b) => a - b)) - this.confirmButtonEnabled = this.pages.size > 0 - } - - removeSplit(i: number) { - let page = Array.from(this.pages)[Math.min(i, this.pages.size - 1)] - this.pages.delete(page) - this.confirmButtonEnabled = this.pages.size > 0 - } - - get userOwnsDocument(): boolean { - return this.permissionService.currentUserOwnsObject(this.document) - } -} diff --git a/src-ui/src/app/components/document-detail/document-detail.component.html b/src-ui/src/app/components/document-detail/document-detail.component.html index 5ae7ee677..7c09ba0aa 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.html +++ b/src-ui/src/app/components/document-detail/document-detail.component.html @@ -58,21 +58,9 @@  More like this - - - - - - diff --git a/src-ui/src/app/components/document-detail/document-detail.component.spec.ts b/src-ui/src/app/components/document-detail/document-detail.component.spec.ts index 360e4bedc..aae1024e0 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.spec.ts +++ b/src-ui/src/app/components/document-detail/document-detail.component.spec.ts @@ -1142,83 +1142,6 @@ describe('DocumentDetailComponent', () => { ).not.toBeUndefined() }) - it('should support split', () => { - let modal: NgbModalRef - modalService.activeInstances.subscribe((m) => (modal = m[0])) - initNormally() - component.splitDocument() - expect(modal).not.toBeUndefined() - modal.componentInstance.documentID = doc.id - modal.componentInstance.totalPages = 5 - modal.componentInstance.page = 2 - modal.componentInstance.addSplit() - modal.componentInstance.confirm() - let req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/bulk_edit/` - ) - expect(req.request.body).toEqual({ - documents: [doc.id], - method: 'split', - parameters: { pages: '1-2,3-5', delete_originals: false }, - }) - req.error(new ProgressEvent('failed')) - modal.componentInstance.confirm() - req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/bulk_edit/` - ) - req.flush(true) - }) - - it('should support rotate', () => { - let modal: NgbModalRef - modalService.activeInstances.subscribe((m) => (modal = m[0])) - initNormally() - component.rotateDocument() - expect(modal).not.toBeUndefined() - modal.componentInstance.documentID = doc.id - modal.componentInstance.rotate() - modal.componentInstance.confirm() - let req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/bulk_edit/` - ) - expect(req.request.body).toEqual({ - documents: [doc.id], - method: 'rotate', - parameters: { degrees: 90 }, - }) - req.error(new ProgressEvent('failed')) - modal.componentInstance.confirm() - req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/bulk_edit/` - ) - req.flush(true) - }) - - it('should support delete pages', () => { - let modal: NgbModalRef - modalService.activeInstances.subscribe((m) => (modal = m[0])) - initNormally() - component.deletePages() - expect(modal).not.toBeUndefined() - modal.componentInstance.documentID = doc.id - modal.componentInstance.pages = [1, 2] - modal.componentInstance.confirm() - let req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/bulk_edit/` - ) - expect(req.request.body).toEqual({ - documents: [doc.id], - method: 'delete_pages', - parameters: { pages: [1, 2] }, - }) - req.error(new ProgressEvent('failed')) - modal.componentInstance.confirm() - req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/bulk_edit/` - ) - req.flush(true) - }) - it('should support pdf editor', () => { let modal: NgbModalRef modalService.activeInstances.subscribe((m) => (modal = m[0])) diff --git a/src-ui/src/app/components/document-detail/document-detail.component.ts b/src-ui/src/app/components/document-detail/document-detail.component.ts index 6704806c2..4089d7e33 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.ts +++ b/src-ui/src/app/components/document-detail/document-detail.component.ts @@ -81,9 +81,6 @@ import { getFilenameFromContentDisposition } from 'src/app/utils/http' import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter' import * as UTIF from 'utif' import { ConfirmDialogComponent } from '../common/confirm-dialog/confirm-dialog.component' -import { DeletePagesConfirmDialogComponent } from '../common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component' -import { RotateConfirmDialogComponent } from '../common/confirm-dialog/rotate-confirm-dialog/rotate-confirm-dialog.component' -import { SplitConfirmDialogComponent } from '../common/confirm-dialog/split-confirm-dialog/split-confirm-dialog.component' import { CustomFieldsDropdownComponent } from '../common/custom-fields-dropdown/custom-fields-dropdown.component' import { CorrespondentEditDialogComponent } from '../common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component' import { DocumentTypeEditDialogComponent } from '../common/edit-dialog/document-type-edit-dialog/document-type-edit-dialog.component' @@ -1337,87 +1334,6 @@ export class DocumentDetailComponent this.documentForm.updateValueAndValidity() } - splitDocument() { - let modal = this.modalService.open(SplitConfirmDialogComponent, { - backdrop: 'static', - size: 'lg', - }) - modal.componentInstance.title = $localize`Split confirm` - modal.componentInstance.messageBold = $localize`This operation will split the selected document(s) into new documents.` - modal.componentInstance.btnCaption = $localize`Proceed` - modal.componentInstance.documentID = this.document.id - modal.componentInstance.confirmClicked - .pipe(takeUntil(this.unsubscribeNotifier)) - .subscribe(() => { - modal.componentInstance.buttonsEnabled = false - this.documentsService - .bulkEdit([this.document.id], 'split', { - pages: modal.componentInstance.pagesString, - delete_originals: modal.componentInstance.deleteOriginal, - }) - .pipe(first(), takeUntil(this.unsubscribeNotifier)) - .subscribe({ - next: () => { - this.toastService.showInfo( - $localize`Split operation for "${this.document.title}" will begin in the background.` - ) - modal.close() - }, - error: (error) => { - if (modal) { - modal.componentInstance.buttonsEnabled = true - } - this.toastService.showError( - $localize`Error executing split operation`, - error - ) - }, - }) - }) - } - - rotateDocument() { - let modal = this.modalService.open(RotateConfirmDialogComponent, { - backdrop: 'static', - size: 'lg', - }) - modal.componentInstance.title = $localize`Rotate confirm` - modal.componentInstance.messageBold = $localize`This operation will permanently rotate the original version of the current document.` - modal.componentInstance.btnCaption = $localize`Proceed` - modal.componentInstance.documentID = this.document.id - modal.componentInstance.showPDFNote = false - modal.componentInstance.confirmClicked - .pipe(takeUntil(this.unsubscribeNotifier)) - .subscribe(() => { - modal.componentInstance.buttonsEnabled = false - this.documentsService - .bulkEdit([this.document.id], 'rotate', { - degrees: modal.componentInstance.degrees, - }) - .pipe(first(), takeUntil(this.unsubscribeNotifier)) - .subscribe({ - next: () => { - this.toastService.show({ - content: $localize`Rotation of "${this.document.title}" will begin in the background. Close and re-open the document after the operation has completed to see the changes.`, - delay: 8000, - action: this.close.bind(this), - actionName: $localize`Close`, - }) - modal.close() - }, - error: (error) => { - if (modal) { - modal.componentInstance.buttonsEnabled = true - } - this.toastService.showError( - $localize`Error executing rotate operation`, - error - ) - }, - }) - }) - } - editPdf() { let modal = this.modalService.open(PDFEditorComponent, { backdrop: 'static', @@ -1457,43 +1373,6 @@ export class DocumentDetailComponent }) } - deletePages() { - let modal = this.modalService.open(DeletePagesConfirmDialogComponent, { - backdrop: 'static', - }) - modal.componentInstance.title = $localize`Delete pages confirm` - modal.componentInstance.messageBold = $localize`This operation will permanently delete the selected pages from the original document.` - modal.componentInstance.btnCaption = $localize`Proceed` - modal.componentInstance.documentID = this.document.id - modal.componentInstance.confirmClicked - .pipe(takeUntil(this.unsubscribeNotifier)) - .subscribe(() => { - modal.componentInstance.buttonsEnabled = false - this.documentsService - .bulkEdit([this.document.id], 'delete_pages', { - pages: modal.componentInstance.pages, - }) - .pipe(first(), takeUntil(this.unsubscribeNotifier)) - .subscribe({ - next: () => { - this.toastService.showInfo( - $localize`Delete pages operation for "${this.document.title}" will begin in the background. Close and re-open or reload this document after the operation has completed to see the changes.` - ) - modal.close() - }, - error: (error) => { - if (modal) { - modal.componentInstance.buttonsEnabled = true - } - this.toastService.showError( - $localize`Error executing delete pages operation`, - error - ) - }, - }) - }) - } - public openShareLinks() { const modal = this.modalService.open(ShareLinksDialogComponent) modal.componentInstance.documentId = this.document.id