diff --git a/src-ui/src/app/components/admin/config/config.component.html b/src-ui/src/app/components/admin/config/config.component.html
index e453a3fae..48cac6bfa 100644
--- a/src-ui/src/app/components/admin/config/config.component.html
+++ b/src-ui/src/app/components/admin/config/config.component.html
@@ -29,6 +29,7 @@
@case (ConfigOptionType.Number) { }
@case (ConfigOptionType.Boolean) { }
@case (ConfigOptionType.String) { }
+ @case (ConfigOptionType.JSON) { }
}
diff --git a/src-ui/src/app/components/admin/config/config.component.spec.ts b/src-ui/src/app/components/admin/config/config.component.spec.ts
index 2e15c4399..5d70881b6 100644
--- a/src-ui/src/app/components/admin/config/config.component.spec.ts
+++ b/src-ui/src/app/components/admin/config/config.component.spec.ts
@@ -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 })
})
})
diff --git a/src-ui/src/app/components/admin/config/config.component.ts b/src-ui/src/app/components/admin/config/config.component.ts
index 56cd027cc..66d7b537f 100644
--- a/src-ui/src/app/components/admin/config/config.component.ts
+++ b/src-ui/src/app/components/admin/config/config.component.ts
@@ -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
diff --git a/src-ui/src/app/data/paperless-config.ts b/src-ui/src/app/data/paperless-config.ts
index 5720235e3..dd9dfdb33 100644
--- a/src-ui/src/app/data/paperless-config.ts
+++ b/src-ui/src/app/data/paperless-config.ts
@@ -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
+ choices?: Array<{ id: string; name: string }>
config_key?: string
category: string
}
-function mapToFlatChoices(enumObj: Object): Array {
+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,
},