Fully dynamic config form
This commit is contained in:
parent
cf0dc73eb3
commit
d7067dc355
@ -29,6 +29,7 @@
|
||||
@case (ConfigOptionType.Number) { <pngx-input-number [formControlName]="option.key" [error]="errors[option.key]" [showAdd]="false"></pngx-input-number> }
|
||||
@case (ConfigOptionType.Boolean) { <pngx-input-switch [formControlName]="option.key" [error]="errors[option.key]" title="Enable" i18n-title></pngx-input-switch> }
|
||||
@case (ConfigOptionType.String) { <pngx-input-text [formControlName]="option.key" [error]="errors[option.key]"></pngx-input-text> }
|
||||
@case (ConfigOptionType.JSON) { <pngx-input-text [formControlName]="option.key" [error]="errors[option.key]"></pngx-input-text> }
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,7 +87,7 @@ describe('ConfigComponent', () => {
|
||||
|
||||
it('should support discard changes', () => {
|
||||
component.initialConfig = { output_type: OutputTypeConfig.PDF_A2 } as any
|
||||
component.configForm.get('output_type').patchValue(OutputTypeConfig.PDF_A)
|
||||
component.configForm.patchValue({ output_type: OutputTypeConfig.PDF_A })
|
||||
component.discardChanges()
|
||||
expect(component.configForm.get('output_type').value).toEqual(
|
||||
OutputTypeConfig.PDF_A2
|
||||
@ -95,9 +95,9 @@ describe('ConfigComponent', () => {
|
||||
})
|
||||
|
||||
it('should support JSON validation for e.g. user_args', () => {
|
||||
component.configForm.get('user_args').patchValue('{ foo bar }')
|
||||
component.configForm.patchValue({ user_args: '{ foo bar }' })
|
||||
expect(component.errors).toEqual({ user_args: 'Invalid JSON' })
|
||||
component.configForm.get('user_args').patchValue('{ "foo": "bar" }')
|
||||
component.configForm.patchValue({ user_args: '{ "foo": "bar" }' })
|
||||
expect(component.errors).toEqual({ user_args: null })
|
||||
})
|
||||
})
|
||||
|
@ -31,22 +31,8 @@ export class ConfigComponent
|
||||
{
|
||||
public readonly ConfigOptionType = ConfigOptionType
|
||||
|
||||
public configForm = new FormGroup({
|
||||
id: new FormControl(),
|
||||
output_type: new FormControl(),
|
||||
pages: new FormControl(),
|
||||
language: new FormControl(),
|
||||
mode: new FormControl(),
|
||||
skip_archive_file: new FormControl(),
|
||||
image_dpi: new FormControl(),
|
||||
unpaper_clean: new FormControl(),
|
||||
deskew: new FormControl(),
|
||||
rotate_pages: new FormControl(),
|
||||
rotate_pages_threshold: new FormControl(),
|
||||
max_image_pixels: new FormControl(),
|
||||
color_conversion_strategy: new FormControl(),
|
||||
user_args: new FormControl(),
|
||||
})
|
||||
// generated dynamically
|
||||
public configForm = new FormGroup({})
|
||||
|
||||
public errors = {}
|
||||
|
||||
@ -72,6 +58,10 @@ export class ConfigComponent
|
||||
private toastService: ToastService
|
||||
) {
|
||||
super()
|
||||
this.configForm.addControl('id', new FormControl())
|
||||
PaperlessConfigOptions.forEach((option) => {
|
||||
this.configForm.addControl(option.key, new FormControl())
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -90,27 +80,32 @@ export class ConfigComponent
|
||||
},
|
||||
})
|
||||
|
||||
// validate JSON input for user_args
|
||||
this.configForm
|
||||
.get('user_args')
|
||||
.addValidators((control: AbstractControl) => {
|
||||
if (!control.value || control.value.toString().length === 0) return null
|
||||
try {
|
||||
JSON.parse(control.value)
|
||||
} catch (e) {
|
||||
return [
|
||||
{
|
||||
user_args: e,
|
||||
},
|
||||
]
|
||||
}
|
||||
return null
|
||||
// validate JSON inputs
|
||||
PaperlessConfigOptions.filter(
|
||||
(o) => o.type === ConfigOptionType.JSON
|
||||
).forEach((option) => {
|
||||
this.configForm
|
||||
.get(option.key)
|
||||
.addValidators((control: AbstractControl) => {
|
||||
if (!control.value || control.value.toString().length === 0)
|
||||
return null
|
||||
try {
|
||||
JSON.parse(control.value)
|
||||
} catch (e) {
|
||||
return [
|
||||
{
|
||||
user_args: e,
|
||||
},
|
||||
]
|
||||
}
|
||||
return null
|
||||
})
|
||||
this.configForm.get(option.key).statusChanges.subscribe((status) => {
|
||||
this.errors[option.key] =
|
||||
status === 'INVALID' ? $localize`Invalid JSON` : null
|
||||
})
|
||||
this.configForm.get('user_args').statusChanges.subscribe((status) => {
|
||||
this.errors['user_args'] =
|
||||
status === 'INVALID' ? $localize`Invalid JSON` : null
|
||||
this.configForm.get(option.key).updateValueAndValidity()
|
||||
})
|
||||
this.configForm.get('user_args').updateValueAndValidity()
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@ -131,7 +126,6 @@ export class ConfigComponent
|
||||
|
||||
this.isDirty$ = dirtyCheck(this.configForm, this.store.asObservable())
|
||||
}
|
||||
|
||||
this.configForm.patchValue(config)
|
||||
|
||||
this.initialConfig = config
|
||||
|
@ -42,6 +42,7 @@ export enum ConfigOptionType {
|
||||
Number = 'number',
|
||||
Select = 'select',
|
||||
Boolean = 'boolean',
|
||||
JSON = 'json',
|
||||
}
|
||||
|
||||
export const ConfigCategory = {
|
||||
@ -52,12 +53,12 @@ export interface ConfigOption {
|
||||
key: string
|
||||
title: string
|
||||
type: ConfigOptionType
|
||||
choices?: Array<string>
|
||||
choices?: Array<{ id: string; name: string }>
|
||||
config_key?: string
|
||||
category: string
|
||||
}
|
||||
|
||||
function mapToFlatChoices(enumObj: Object): Array<any> {
|
||||
function mapToItems(enumObj: Object): Array<{ id: string; name: string }> {
|
||||
return Object.keys(enumObj).map((key) => {
|
||||
return {
|
||||
id: enumObj[key],
|
||||
@ -71,10 +72,17 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
key: 'output_type',
|
||||
title: $localize`Output Type`,
|
||||
type: ConfigOptionType.Select,
|
||||
choices: mapToFlatChoices(OutputTypeConfig),
|
||||
choices: mapToItems(OutputTypeConfig),
|
||||
config_key: 'PAPERLESS_OCR_OUTPUT_TYPE',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
{
|
||||
key: 'language',
|
||||
title: $localize`Language`,
|
||||
type: ConfigOptionType.String,
|
||||
config_key: 'PAPERLESS_OCR_LANGUAGE',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
{
|
||||
key: 'pages',
|
||||
title: $localize`Pages`,
|
||||
@ -86,7 +94,7 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
key: 'mode',
|
||||
title: $localize`Mode`,
|
||||
type: ConfigOptionType.Select,
|
||||
choices: mapToFlatChoices(ModeConfig),
|
||||
choices: mapToItems(ModeConfig),
|
||||
config_key: 'PAPERLESS_OCR_MODE',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
@ -94,7 +102,7 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
key: 'skip_archive_file',
|
||||
title: $localize`Skip Archive File`,
|
||||
type: ConfigOptionType.Select,
|
||||
choices: mapToFlatChoices(ArchiveFileConfig),
|
||||
choices: mapToItems(ArchiveFileConfig),
|
||||
config_key: 'PAPERLESS_OCR_SKIP_ARCHIVE_FILE',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
@ -109,7 +117,7 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
key: 'unpaper_clean',
|
||||
title: $localize`Clean`,
|
||||
type: ConfigOptionType.Select,
|
||||
choices: mapToFlatChoices(CleanConfig),
|
||||
choices: mapToItems(CleanConfig),
|
||||
config_key: 'PAPERLESS_OCR_CLEAN',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
@ -145,14 +153,14 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
key: 'color_conversion_strategy',
|
||||
title: $localize`Color Conversion Strategy`,
|
||||
type: ConfigOptionType.Select,
|
||||
choices: mapToFlatChoices(ColorConvertConfig),
|
||||
choices: mapToItems(ColorConvertConfig),
|
||||
config_key: 'PAPERLESS_OCR_COLOR_CONVERSION_STRATEGY',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
{
|
||||
key: 'user_args',
|
||||
title: $localize`OCR Arguments`,
|
||||
type: ConfigOptionType.String,
|
||||
type: ConfigOptionType.JSON,
|
||||
config_key: 'PAPERLESS_OCR_USER_ARGS',
|
||||
category: ConfigCategory.OCR,
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user