mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-20 23:08:14 +00:00
dirtycheck
This commit is contained in:
4 files changed
+52
-2
No files matched your search
@@ -292,6 +292,7 @@ export const routes: Routes = [
|
||||
{
|
||||
path: 'ocr-templates/new',
|
||||
component: OcrTemplateEditorComponent,
|
||||
canDeactivate: [DirtyFormGuard],
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
requiredPermission: {
|
||||
@@ -304,6 +305,7 @@ export const routes: Routes = [
|
||||
{
|
||||
path: 'ocr-templates/:id',
|
||||
component: OcrTemplateEditorComponent,
|
||||
canDeactivate: [DirtyFormGuard],
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
requiredPermission: {
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<a routerLink="/ocr-templates" class="btn btn-sm btn-outline-secondary" title="Close" i18n-title aria-label="Close" i18n-aria-label>
|
||||
<i-bs width="1.2em" height="1.2em" name="x"></i-bs><span class="d-none d-lg-inline ps-1" i18n>Close</span>
|
||||
</a>
|
||||
<button type="button" class="btn btn-sm btn-primary" (click)="save()" [disabled]="saving">
|
||||
<button type="button" class="btn btn-sm btn-primary" (click)="save()" [disabled]="saving || !isDirty">
|
||||
@if (saving) {
|
||||
<span class="spinner-border spinner-border-sm me-1" aria-hidden="true"></span>
|
||||
}
|
||||
|
||||
+18
@@ -301,6 +301,24 @@ describe('OcrTemplateEditorComponent', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('tracks unsaved changes against the last loaded or saved state', () => {
|
||||
fixture.detectChanges()
|
||||
expect(component.isDirty$()).toBe(false)
|
||||
|
||||
component.template.combine_formats = { '1': '' }
|
||||
expect(component.isDirty).toBe(false)
|
||||
|
||||
component.template.name = 'Invoices'
|
||||
expect(component.isDirty).toBe(true)
|
||||
|
||||
templates.create.mockReturnValue(of({ ...component.template, id: 3 }))
|
||||
component.save()
|
||||
expect(component.isDirty).toBe(false)
|
||||
|
||||
component.previewDocId = 5
|
||||
expect(component.isDirty).toBe(true)
|
||||
})
|
||||
|
||||
it('hides results when extraction settings or geometry change', () => {
|
||||
const selected = zone()
|
||||
component.template.zones = [selected]
|
||||
|
||||
+31
-1
@@ -19,6 +19,7 @@ import {
|
||||
NgbTypeaheadModule,
|
||||
NgbTypeaheadSelectItemEvent,
|
||||
} from '@ng-bootstrap/ng-bootstrap'
|
||||
import { DirtyComponent } from '@ngneat/dirty-check-forms'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import {
|
||||
catchError,
|
||||
@@ -142,7 +143,9 @@ const RESIZE_CURSOR: Record<ResizeHandle, string> = {
|
||||
templateUrl: './ocr-template-editor.component.html',
|
||||
styleUrls: ['./ocr-template-editor.component.scss'],
|
||||
})
|
||||
export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
|
||||
export class OcrTemplateEditorComponent
|
||||
implements OnInit, OnDestroy, DirtyComponent
|
||||
{
|
||||
private readonly route = inject(ActivatedRoute)
|
||||
private readonly templateService = inject(OcrTemplateService)
|
||||
private readonly customFieldsService = inject(CustomFieldsService)
|
||||
@@ -269,6 +272,30 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
|
||||
: null
|
||||
}
|
||||
|
||||
/** Snapshot of the editor state as last loaded or saved. */
|
||||
private savedState = ''
|
||||
|
||||
get isDirty(): boolean {
|
||||
return this.editorState() !== this.savedState
|
||||
}
|
||||
|
||||
readonly isDirty$ = () => this.isDirty
|
||||
|
||||
private editorState(): string {
|
||||
const formats = Object.entries(this.template.combine_formats ?? {}).filter(
|
||||
([, format]) => format
|
||||
)
|
||||
return JSON.stringify({
|
||||
...this.template,
|
||||
combine_formats: Object.fromEntries(formats),
|
||||
sample_document: this.previewDocId ?? null,
|
||||
})
|
||||
}
|
||||
|
||||
private markSaved() {
|
||||
this.savedState = this.editorState()
|
||||
}
|
||||
|
||||
get pageTitle(): string {
|
||||
return this.isNew
|
||||
? $localize`New OCR Template`
|
||||
@@ -313,6 +340,7 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
|
||||
this.previewDocId = t.sample_document
|
||||
this.loadPreview()
|
||||
}
|
||||
this.markSaved()
|
||||
})
|
||||
} else {
|
||||
const qp = this.route.snapshot.queryParams
|
||||
@@ -325,6 +353,7 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
|
||||
this.previewDocId = docId
|
||||
this.loadPreview()
|
||||
}
|
||||
this.markSaved()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -896,6 +925,7 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
|
||||
this.isNew = false
|
||||
this.selectedZoneIndex = idx
|
||||
this.saving = false
|
||||
this.markSaved()
|
||||
this.toastService.showInfo($localize`OCR template saved.`)
|
||||
this.changeDetector.markForCheck()
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user