Lots of enum cleanup

This commit is contained in:
shamoon committed 2026-10-20 09:44:37 -07:00
1 parent ea31b6a043
commit b3106e408c
7 files changed
+79 -97

No files matched your search

@@ -1,13 +1,17 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { CustomField } from 'src/app/data/custom-field'
import { OcrTemplateZone } from 'src/app/data/ocr-template'
import {
OcrTemplateZone,
OcrZoneTarget,
OcrZoneTransform,
} from 'src/app/data/ocr-template'
import { OcrTemplateEditorZoneListComponent } from './ocr-template-editor-zone-list.component'
function zone(overrides: Partial<OcrTemplateZone> = {}): OcrTemplateZone {
return {
name: 'Zone 1',
target: 'custom_field',
target: OcrZoneTarget.CustomField,
custom_field: 7,
x: 10,
y: 20,
@@ -15,7 +19,7 @@ function zone(overrides: Partial<OcrTemplateZone> = {}): OcrTemplateZone {
height: 40,
page: 1,
ocr_language: 'eng',
transform: 'strip',
transform: OcrZoneTransform.Strip,
validation_regex: '',
order: 0,
...overrides,
@@ -76,7 +80,7 @@ describe('OcrTemplateEditorZoneListComponent', () => {
it('warns only for zones without a field and clears the warning when assigned', () => {
component.zones = [
zone({ custom_field: null }),
zone({ target: 'title', custom_field: null }),
zone({ target: OcrZoneTarget.Title, custom_field: null }),
zone(),
]
fixture.detectChanges()
@@ -5,6 +5,7 @@ import {
getZoneFieldKey,
OCR_BUILTIN_TARGETS,
OcrTemplateZone,
OcrZoneTarget,
} from 'src/app/data/ocr-template'
import { getZoneColor } from '../zone-geometry'
@@ -35,18 +36,15 @@ export class OcrTemplateEditorZoneListComponent {
}
getZoneTargetName(zone: OcrTemplateZone): string {
const target = zone.target || 'custom_field'
if (target === 'custom_field') {
return zone.custom_field
? this.getCustomFieldName(zone.custom_field)
: $localize`(no field)`
if (zone.target === OcrZoneTarget.CustomField) {
return (
this.customFields.find((field) => field.id === zone.custom_field)
?.name ?? ''
)
}
return OCR_BUILTIN_TARGETS.find((t) => t.id === target)?.name ?? target
}
private getCustomFieldName(id: number): string {
return (
this.customFields.find((field) => field.id === id)?.name ?? `Field #${id}`
OCR_BUILTIN_TARGETS.find((target) => target.id === zone.target)?.name ??
''
)
}
}
@@ -129,7 +129,7 @@
<pngx-input-select [items]="transformOptions" [(ngModel)]="zone.transform" title="Transform" i18n-title></pngx-input-select>
@if (zone.transform === dateTransform) {
@if (zone.transform === OcrZoneTransform.Date) {
<pngx-input-select
[items]="dateFormatItems"
[ngModel]="dateFormatChoice(zone)"
@@ -8,7 +8,9 @@ import { DocumentType } from 'src/app/data/document-type'
import {
OcrTemplate,
OcrTemplateZone,
OcrZoneTarget,
OcrZoneTestResult,
OcrZoneTransform,
} from 'src/app/data/ocr-template'
import { Results } from 'src/app/data/results'
import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
@@ -22,6 +24,7 @@ import { OcrTemplateEditorComponent } from './ocr-template-editor.component'
function zone(): OcrTemplateZone {
return {
name: 'Invoice number',
target: OcrZoneTarget.CustomField,
custom_field: 1,
x: 100,
y: 100,
@@ -29,7 +32,7 @@ function zone(): OcrTemplateZone {
height: 100,
page: 1,
ocr_language: 'eng',
transform: 'strip',
transform: OcrZoneTransform.Strip,
validation_regex: '',
order: 0,
}
@@ -406,13 +409,13 @@ describe('OcrTemplateEditorComponent', () => {
succeeded.next(created)
expect(component.template.zones[0]).toMatchObject({
target: 'custom_field',
target: OcrZoneTarget.CustomField,
custom_field: 5,
})
expect(component.fieldItems().map((item) => item.id)).toEqual([
'title',
'asn',
'created',
OcrZoneTarget.Title,
OcrZoneTarget.Asn,
OcrZoneTarget.Created,
5,
])
})
@@ -470,7 +473,7 @@ describe('OcrTemplateEditorComponent', () => {
const titleZone = {
...zone(),
name: 'First',
target: 'title' as const,
target: OcrZoneTarget.Title,
custom_field: null,
}
component.template.combine_formats = { title: '{First} / {Second}' }
@@ -579,7 +582,7 @@ describe('OcrTemplateEditorComponent', () => {
component.testZone()
expect(component.zoneTestResult?.value).toBe('123')
selected.transform = 'numeric'
selected.transform = OcrZoneTransform.Numeric
expect(component.zoneTestResult).toBeNull()
component.testZone()
selected.width++
@@ -48,18 +48,14 @@ import { DocumentType } from 'src/app/data/document-type'
import {
DATE_FORMAT_OPTIONS,
DEFAULT_OCR_ZONE_LANGUAGE,
DEFAULT_OCR_ZONE_TARGET,
DEFAULT_OCR_ZONE_TRANSFORM,
getZoneFieldKey,
isOcrBuiltinTarget,
OCR_BUILTIN_TARGETS,
OCR_LANGUAGE_OPTIONS,
OCR_SUPPORTED_FIELD_TYPES,
OCR_ZONE_TARGET,
OCR_ZONE_TRANSFORM,
OcrBuiltinTarget,
OcrTemplate,
OcrTemplateZone,
OcrZoneTarget,
OcrZoneTransform,
OcrZoneTestResult,
TRANSFORM_OPTIONS,
ZoneTestRequest,
@@ -91,7 +87,7 @@ import {
} from './zone-geometry'
type ActiveTab = 'settings' | 'zones'
type ZoneFieldSelection = OcrBuiltinTarget | number | null
type ZoneFieldSelection = OcrZoneTarget | number | null
type OverlayInteraction =
| { kind: 'idle' }
| { kind: 'drawing'; pointerId: number; rect: DrawingRect }
@@ -201,7 +197,7 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
readonly documentTypes = signal<DocumentType[]>([])
transformOptions = TRANSFORM_OPTIONS
ocrLanguageOptions = OCR_LANGUAGE_OPTIONS
dateTransform = OCR_ZONE_TRANSFORM.Date
readonly OcrZoneTransform = OcrZoneTransform
noSampleDocumentTitle = $localize`Select a sample document to test this zone`
dateFormatItems = [
...DATE_FORMAT_OPTIONS,
@@ -610,7 +606,7 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
const imageSize = this.imageNaturalSize()
return {
name: `Zone ${this.template.zones.length + 1}`,
target: DEFAULT_OCR_ZONE_TARGET,
target: OcrZoneTarget.CustomField,
custom_field: null,
x: rect.x,
y: rect.y,
@@ -618,7 +614,7 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
height: rect.h,
page: this.previewPageDisplay,
ocr_language: DEFAULT_OCR_ZONE_LANGUAGE,
transform: DEFAULT_OCR_ZONE_TRANSFORM,
transform: OcrZoneTransform.Strip,
date_format: '',
validation_regex: '',
order: this.template.zones.length,
@@ -889,18 +885,20 @@ export class OcrTemplateEditorComponent implements OnInit, OnDestroy {
zone.ocr_language = (langs ?? []).join('+')
}
/** The field select's value: a built-in target, or a custom field id. */
zoneFieldValue(zone: OcrTemplateZone): ZoneFieldSelection {
const target = zone.target || DEFAULT_OCR_ZONE_TARGET
return target === OCR_ZONE_TARGET.CustomField ? zone.custom_field : target
return zone.target === OcrZoneTarget.CustomField
? zone.custom_field
: zone.target
}
setZoneField(zone: OcrTemplateZone, value: ZoneFieldSelection) {
if (isOcrBuiltinTarget(value)) {
if (typeof value === 'string') {
zone.target = value
zone.custom_field = null
} else {
zone.target = OCR_ZONE_TARGET.CustomField
zone.custom_field = typeof value === 'number' ? value : null
zone.target = OcrZoneTarget.CustomField
zone.custom_field = value
}
}
@@ -1,4 +1,8 @@
import { OcrTemplateZone } from 'src/app/data/ocr-template'
import {
OcrTemplateZone,
OcrZoneTarget,
OcrZoneTransform,
} from 'src/app/data/ocr-template'
import {
findHandleAt,
findZoneAt,
@@ -13,7 +17,7 @@ import {
function zone(overrides: Partial<OcrTemplateZone> = {}): OcrTemplateZone {
return {
name: 'Zone',
target: 'custom_field',
target: OcrZoneTarget.CustomField,
custom_field: 1,
x: 100,
y: 200,
@@ -21,7 +25,7 @@ function zone(overrides: Partial<OcrTemplateZone> = {}): OcrTemplateZone {
height: 400,
page: 1,
ocr_language: 'eng',
transform: 'strip',
transform: OcrZoneTransform.Strip,
validation_regex: '',
order: 0,
...overrides,
+32 -57
View File
@@ -1,55 +1,30 @@
import { CustomFieldDataType } from './custom-field'
import { ObjectWithId } from './object-with-id'
export type OcrZoneTarget = 'custom_field' | 'title' | 'asn' | 'created'
export type OcrBuiltinTarget = Exclude<OcrZoneTarget, 'custom_field'>
export type OcrZoneTransform =
| 'none'
| 'strip'
| 'uppercase'
| 'lowercase'
| 'numeric'
| 'strip_punctuation'
| 'date'
| 'qr_code'
export const OCR_ZONE_TARGET = {
CustomField: 'custom_field',
Title: 'title',
Asn: 'asn',
Created: 'created',
} as const satisfies Record<string, OcrZoneTarget>
export const OCR_ZONE_TRANSFORM = {
None: 'none',
Strip: 'strip',
Uppercase: 'uppercase',
Lowercase: 'lowercase',
Numeric: 'numeric',
StripPunctuation: 'strip_punctuation',
Date: 'date',
QrCode: 'qr_code',
} as const satisfies Record<string, OcrZoneTransform>
export const DEFAULT_OCR_ZONE_TARGET = OCR_ZONE_TARGET.CustomField
export const DEFAULT_OCR_ZONE_TRANSFORM = OCR_ZONE_TRANSFORM.Strip
export const DEFAULT_OCR_ZONE_LANGUAGE = 'deu+eng'
export function isOcrBuiltinTarget(value: unknown): value is OcrBuiltinTarget {
return (
value === OCR_ZONE_TARGET.Title ||
value === OCR_ZONE_TARGET.Asn ||
value === OCR_ZONE_TARGET.Created
)
export enum OcrZoneTarget {
CustomField = 'custom_field',
Title = 'title',
Asn = 'asn',
Created = 'created',
}
export enum OcrZoneTransform {
None = 'none',
Strip = 'strip',
Uppercase = 'uppercase',
Lowercase = 'lowercase',
Numeric = 'numeric',
StripPunctuation = 'strip_punctuation',
Date = 'date',
QrCode = 'qr_code',
}
export const DEFAULT_OCR_ZONE_LANGUAGE = 'deu+eng'
/** The field a zone writes to, keyed by OcrTemplate.combine_formats. */
export function getZoneFieldKey(zone: OcrTemplateZone): string | null {
const target = zone.target || DEFAULT_OCR_ZONE_TARGET
if (target !== OCR_ZONE_TARGET.CustomField) return target
return zone.custom_field === null || zone.custom_field === undefined
? null
: String(zone.custom_field)
if (zone.target !== OcrZoneTarget.CustomField) return zone.target
return zone.custom_field === null ? null : String(zone.custom_field)
}
/** Custom field types zone OCR can write to. See models.py OCR_SUPPORTED_FIELD_TYPES. */
@@ -65,15 +40,15 @@ export const OCR_SUPPORTED_FIELD_TYPES: CustomFieldDataType[] = [
]
export const OCR_BUILTIN_TARGETS = [
{ id: OCR_ZONE_TARGET.Title, name: $localize`Title` },
{ id: OCR_ZONE_TARGET.Asn, name: $localize`Archive serial number` },
{ id: OCR_ZONE_TARGET.Created, name: $localize`Date created` },
{ id: OcrZoneTarget.Title, name: $localize`Title` },
{ id: OcrZoneTarget.Asn, name: $localize`Archive serial number` },
{ id: OcrZoneTarget.Created, name: $localize`Date created` },
]
export interface OcrTemplateZone {
id?: number
name: string
target?: OcrZoneTarget
target: OcrZoneTarget
custom_field: number | null
page?: number
x: number
@@ -90,17 +65,17 @@ export interface OcrTemplateZone {
}
export const TRANSFORM_OPTIONS = [
{ id: OCR_ZONE_TRANSFORM.None, name: $localize`None` },
{ id: OCR_ZONE_TRANSFORM.Strip, name: $localize`Strip whitespace` },
{ id: OCR_ZONE_TRANSFORM.Uppercase, name: $localize`Uppercase` },
{ id: OCR_ZONE_TRANSFORM.Lowercase, name: $localize`Lowercase` },
{ id: OCR_ZONE_TRANSFORM.Numeric, name: $localize`Numeric only` },
{ id: OcrZoneTransform.None, name: $localize`None` },
{ id: OcrZoneTransform.Strip, name: $localize`Strip whitespace` },
{ id: OcrZoneTransform.Uppercase, name: $localize`Uppercase` },
{ id: OcrZoneTransform.Lowercase, name: $localize`Lowercase` },
{ id: OcrZoneTransform.Numeric, name: $localize`Numeric only` },
{
id: OCR_ZONE_TRANSFORM.StripPunctuation,
id: OcrZoneTransform.StripPunctuation,
name: $localize`Remove leading/trailing punctuation`,
},
{ id: OCR_ZONE_TRANSFORM.Date, name: $localize`Parse date` },
{ id: OCR_ZONE_TRANSFORM.QrCode, name: $localize`Read QR/barcode` },
{ id: OcrZoneTransform.Date, name: $localize`Parse date` },
{ id: OcrZoneTransform.QrCode, name: $localize`Read QR/barcode` },
]
export const OCR_LANGUAGE_OPTIONS = [