mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-09-01 01:46:16 +00:00
Just save this
[ci skip]
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<pdf-viewer [src]="pdfSrc" [render-text]="false" zoom="0.4" (after-load-complete)="pdfLoaded($event)"></pdf-viewer>
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ title }}</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div cdkDropList (cdkDropListDropped)="drop($event)" cdkDropListOrientation="mixed" class="d-flex flex-wrap row-cols-5">
|
||||
@for (p of pages; track p.page; let i = $index) {
|
||||
<div class="page-item p-2" cdkDrag>
|
||||
<div class="btn-group mb-1">
|
||||
<button class="btn btn-sm btn-secondary" (click)="rotate(i)"><i-bs name="arrow-clockwise"></i-bs></button>
|
||||
<button class="btn btn-sm btn-outline-secondary" (click)="toggleSplit(i)"><i-bs name="scissors"></i-bs></button>
|
||||
<button class="btn btn-sm btn-danger" (click)="remove(i)"><i-bs name="trash"></i-bs></button>
|
||||
</div>
|
||||
<div class="pdf-viewer-container w-100 mt-3">
|
||||
<pdf-viewer [src]="pdfSrc" [page]="p.page" [rotation]="p.rotate" [original-size]="false" [show-all]="false" [render-text]="false"></pdf-viewer>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-check form-switch me-auto">
|
||||
<input class="form-check-input" type="checkbox" id="deleteSwitch" [(ngModel)]="deleteOriginal">
|
||||
<label class="form-check-label" for="deleteSwitch" i18n>Delete original after edit</label>
|
||||
</div>
|
||||
<button type="button" class="btn" [class]="cancelBtnClass" (click)="cancel()" [disabled]="!buttonsEnabled">{{ cancelBtnCaption }}</button>
|
||||
<button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="pages.length === 0">{{ btnCaption }}</button>
|
||||
</div>
|
@@ -0,0 +1,9 @@
|
||||
.pdf-viewer-container {
|
||||
background-color: gray;
|
||||
height: 120px;
|
||||
|
||||
pdf-viewer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||
import { PDFEditorComponent } from './pdf-editor.component'
|
||||
|
||||
describe('PDFEditorComponent', () => {
|
||||
let component: PDFEditorComponent
|
||||
let fixture: ComponentFixture<PDFEditorComponent>
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PDFEditorComponent, NgxBootstrapIconsModule.pick(allIcons)],
|
||||
providers: [
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
provideHttpClientTesting(),
|
||||
{ provide: NgbActiveModal, useValue: {} },
|
||||
],
|
||||
}).compileComponents()
|
||||
fixture = TestBed.createComponent(PDFEditorComponent)
|
||||
component = fixture.componentInstance
|
||||
fixture.detectChanges()
|
||||
})
|
||||
|
||||
it('should rotate and reorder pages', () => {
|
||||
component.pages = [
|
||||
{ page: 1, rotate: 0, splitAfter: false },
|
||||
{ page: 2, rotate: 0, splitAfter: false },
|
||||
]
|
||||
component.rotate(0)
|
||||
expect(component.pages[0].rotate).toBe(90)
|
||||
component.drop({ previousIndex: 0, currentIndex: 1 } as any)
|
||||
expect(component.pages[0].page).toBe(2)
|
||||
})
|
||||
})
|
@@ -0,0 +1,90 @@
|
||||
import {
|
||||
CdkDragDrop,
|
||||
DragDropModule,
|
||||
moveItemInArray,
|
||||
} from '@angular/cdk/drag-drop'
|
||||
import { Component, OnInit, inject } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { PDFDocumentProxy, PdfViewerModule } from 'ng2-pdf-viewer'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { DocumentService } from 'src/app/services/rest/document.service'
|
||||
import { ConfirmDialogComponent } from '../confirm-dialog/confirm-dialog.component'
|
||||
|
||||
interface PageOperation {
|
||||
page: number
|
||||
rotate: number
|
||||
splitAfter: boolean
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-pdf-editor',
|
||||
templateUrl: './pdf-editor.component.html',
|
||||
styleUrl: './pdf-editor.component.scss',
|
||||
imports: [
|
||||
DragDropModule,
|
||||
FormsModule,
|
||||
PdfViewerModule,
|
||||
NgxBootstrapIconsModule,
|
||||
],
|
||||
})
|
||||
export class PDFEditorComponent
|
||||
extends ConfirmDialogComponent
|
||||
implements OnInit
|
||||
{
|
||||
private documentService = inject(DocumentService)
|
||||
activeModal = inject(NgbActiveModal)
|
||||
|
||||
documentID: number
|
||||
pages: PageOperation[] = []
|
||||
totalPages = 0
|
||||
deleteOriginal = false
|
||||
|
||||
get pdfSrc(): string {
|
||||
return this.documentService.getPreviewUrl(this.documentID)
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
pdfLoaded(pdf: PDFDocumentProxy) {
|
||||
this.totalPages = pdf.numPages
|
||||
this.pages = Array.from({ length: this.totalPages }, (_, i) => ({
|
||||
page: i + 1,
|
||||
rotate: 0,
|
||||
splitAfter: false,
|
||||
}))
|
||||
}
|
||||
|
||||
rotate(i: number) {
|
||||
this.pages[i].rotate = (this.pages[i].rotate + 90) % 360
|
||||
}
|
||||
|
||||
remove(i: number) {
|
||||
this.pages.splice(i, 1)
|
||||
}
|
||||
|
||||
toggleSplit(i: number) {
|
||||
this.pages[i].splitAfter = !this.pages[i].splitAfter
|
||||
}
|
||||
|
||||
drop(event: CdkDragDrop<PageOperation[]>) {
|
||||
moveItemInArray(this.pages, event.previousIndex, event.currentIndex)
|
||||
}
|
||||
|
||||
getOperations() {
|
||||
const operations = this.pages.map((p, idx) => ({
|
||||
page: p.page,
|
||||
rotate: p.rotate,
|
||||
doc: this.computeDocIndex(idx),
|
||||
}))
|
||||
return operations
|
||||
}
|
||||
|
||||
private computeDocIndex(index: number): number {
|
||||
let docIndex = 0
|
||||
for (let i = 0; i <= index; i++) {
|
||||
if (this.pages[i].splitAfter && i < index) docIndex++
|
||||
}
|
||||
return docIndex
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user