diff --git a/src-ui/src/app/app-routing.module.ts b/src-ui/src/app/app-routing.module.ts index b3952634c..89ed06e39 100644 --- a/src-ui/src/app/app-routing.module.ts +++ b/src-ui/src/app/app-routing.module.ts @@ -25,6 +25,7 @@ import { ConsumptionTemplatesComponent } from './components/manage/consumption-t import { MailComponent } from './components/manage/mail/mail.component' import { UsersAndGroupsComponent } from './components/admin/users-groups/users-groups.component' import { CustomFieldsComponent } from './components/manage/custom-fields/custom-fields.component' +import { ConfigComponent } from './components/admin/config/config.component' export const routes: Routes = [ { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, @@ -179,6 +180,17 @@ export const routes: Routes = [ }, }, }, + { + path: 'config', + component: ConfigComponent, + canActivate: [PermissionsGuard], + data: { + requiredPermission: { + action: PermissionAction.View, + type: PermissionType.Admin, + }, + }, + }, { path: 'tasks', component: TasksComponent, diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index c3b98549a..dbccec0ca 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -108,6 +108,7 @@ import { ProfileEditDialogComponent } from './components/common/profile-edit-dia import { PdfViewerComponent } from './components/common/pdf-viewer/pdf-viewer.component' import { DocumentLinkComponent } from './components/common/input/document-link/document-link.component' import { PreviewPopupComponent } from './components/common/preview-popup/preview-popup.component' +import { ConfigComponent } from './components/admin/config/config.component' import localeAf from '@angular/common/locales/af' import localeAr from '@angular/common/locales/ar' @@ -263,6 +264,7 @@ function initializeApp(settings: SettingsService) { PdfViewerComponent, DocumentLinkComponent, PreviewPopupComponent, + ConfigComponent, ], imports: [ BrowserModule, diff --git a/src-ui/src/app/components/admin/config/config.component.html b/src-ui/src/app/components/admin/config/config.component.html new file mode 100644 index 000000000..9167dfc34 --- /dev/null +++ b/src-ui/src/app/components/admin/config/config.component.html @@ -0,0 +1,116 @@ + + +
+ +

OCR Settings

+ +
+
+ Output Type +
+
+ +
+
+ +
+
+ Pages +
+
+ +
+
+ +
+
+ Mode +
+
+ +
+
+ +
+
+ Skip Archive File +
+
+ +
+
+ +
+
+ Image DPI +
+
+ +
+
+ +
+
+ Clean +
+
+ +
+
+ +
+
+ Deskew +
+
+ +
+
+ +
+
+ Rotate Pages +
+
+ +
+
+ +
+
+ Rotate Pages Threshold +
+
+ +
+
+ +
+
+ Max Image Pixels +
+
+ +
+
+ +
+
+ Color Conversion Strategy +
+
+ +
+
+ +
+
+ OCR Arguments +
+
+ +
+
+ + +
diff --git a/src-ui/src/app/components/admin/config/config.component.scss b/src-ui/src/app/components/admin/config/config.component.scss new file mode 100644 index 000000000..e69de29bb 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 new file mode 100644 index 000000000..e8de0237b --- /dev/null +++ b/src-ui/src/app/components/admin/config/config.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing' + +import { ConfigComponent } from './config.component' + +describe('ConfigComponent', () => { + let component: ConfigComponent + let fixture: ComponentFixture + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ConfigComponent], + }).compileComponents() + + fixture = TestBed.createComponent(ConfigComponent) + component = fixture.componentInstance + fixture.detectChanges() + }) + + it('should create', () => { + expect(component).toBeTruthy() + }) +}) diff --git a/src-ui/src/app/components/admin/config/config.component.ts b/src-ui/src/app/components/admin/config/config.component.ts new file mode 100644 index 000000000..9dc3d5338 --- /dev/null +++ b/src-ui/src/app/components/admin/config/config.component.ts @@ -0,0 +1,108 @@ +import { Component, OnDestroy, OnInit } from '@angular/core' +import { FormControl, FormGroup } from '@angular/forms' +import { + BehaviorSubject, + Observable, + Subject, + Subscription, + takeUntil, +} from 'rxjs' +import { + ArchiveFileConfig, + CleanConfig, + ColorConvertConfig, + ModeConfig, + OutputTypeConfig, + PaperlessConfig, +} from 'src/app/data/paperless-config' +import { ConfigService } from 'src/app/services/config.service' +import { ToastService } from 'src/app/services/toast.service' +import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' +import { DirtyComponent, dirtyCheck } from '@ngneat/dirty-check-forms' + +@Component({ + selector: 'pngx-config', + templateUrl: './config.component.html', + styleUrl: './config.component.scss', +}) +export class ConfigComponent + extends ComponentWithPermissions + implements OnInit, OnDestroy, DirtyComponent +{ + public ConfigChoices = { + output_type: Object.values(OutputTypeConfig), + mode: Object.values(ModeConfig), + skip_archive_file: Object.values(ArchiveFileConfig), + unpaper_clean: Object.values(CleanConfig), + color_conversion_strategy: Object.values(ColorConvertConfig), + } + + public configForm = new FormGroup({ + output_type: new FormControl(null), + pages: new FormControl(null), + language: new FormControl(null), + mode: new FormControl(null), + skip_archive_file: new FormControl(null), + image_dpi: new FormControl(null), + unpaper_clean: new FormControl(null), + deskew: new FormControl(null), + rotate_pages: new FormControl(null), + rotate_pages_threshold: new FormControl(null), + max_image_pixels: new FormControl(null), + color_conversion_strategy: new FormControl(null), + user_args: new FormControl(null), + }) + + public loading: boolean = false + + store: BehaviorSubject + storeSub: Subscription + isDirty$: Observable + + private unsubscribeNotifier: Subject = new Subject() + + constructor( + private configService: ConfigService, + private toastService: ToastService + ) { + super() + } + + ngOnInit(): void { + this.configService + .getConfig() + .pipe(takeUntil(this.unsubscribeNotifier)) + .subscribe({ + next: (config) => { + this.initialize(config) + }, + error: (e) => { + this.toastService.showError($localize`Error retrieving config`, e) + }, + }) + } + + ngOnDestroy(): void { + this.unsubscribeNotifier.next(true) + this.unsubscribeNotifier.complete() + } + + private initialize(config: PaperlessConfig) { + this.store = new BehaviorSubject(config) + + this.store + .asObservable() + .pipe(takeUntil(this.unsubscribeNotifier)) + .subscribe((state) => { + this.configForm.patchValue(state, { emitEvent: false }) + }) + + this.isDirty$ = dirtyCheck(this.configForm, this.store.asObservable()) + + this.configForm.patchValue(config) + } + + public saveConfig() { + throw Error('Not Implemented') + } +} diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 2ab3fe0ae..234099d60 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -271,6 +271,15 @@  Settings +