From 6e03d9848c8d288779ab60985c10810d86ccaca8 Mon Sep 17 00:00:00 2001
From: shamoon <4887959+shamoon@users.noreply.github.com>
Date: Wed, 20 Dec 2023 00:18:17 -0800
Subject: [PATCH] Saving some work on frontend config
---
src-ui/src/app/app-routing.module.ts | 12 ++
src-ui/src/app/app.module.ts | 2 +
.../admin/config/config.component.html | 116 ++++++++++++++++++
.../admin/config/config.component.scss | 0
.../admin/config/config.component.spec.ts | 22 ++++
.../admin/config/config.component.ts | 108 ++++++++++++++++
.../app-frame/app-frame.component.html | 9 ++
src-ui/src/app/data/paperless-config.ts | 54 ++++++++
.../src/app/services/config.service.spec.ts | 16 +++
src-ui/src/app/services/config.service.ts | 25 ++++
10 files changed, 364 insertions(+)
create mode 100644 src-ui/src/app/components/admin/config/config.component.html
create mode 100644 src-ui/src/app/components/admin/config/config.component.scss
create mode 100644 src-ui/src/app/components/admin/config/config.component.spec.ts
create mode 100644 src-ui/src/app/components/admin/config/config.component.ts
create mode 100644 src-ui/src/app/data/paperless-config.ts
create mode 100644 src-ui/src/app/services/config.service.spec.ts
create mode 100644 src-ui/src/app/services/config.service.ts
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 @@
+
+
+
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
+
+
+ Configuration
+
+
{
+ let service: ConfigService
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({})
+ service = TestBed.inject(ConfigService)
+ })
+
+ it('should be created', () => {
+ expect(service).toBeTruthy()
+ })
+})
diff --git a/src-ui/src/app/services/config.service.ts b/src-ui/src/app/services/config.service.ts
new file mode 100644
index 000000000..8f8b84ac5
--- /dev/null
+++ b/src-ui/src/app/services/config.service.ts
@@ -0,0 +1,25 @@
+import { HttpClient } from '@angular/common/http'
+import { Injectable } from '@angular/core'
+import { Observable, first, map } from 'rxjs'
+import { environment } from 'src/environments/environment'
+import { PaperlessConfig } from '../data/paperless-config'
+
+@Injectable({
+ providedIn: 'root',
+})
+export class ConfigService {
+ protected baseUrl: string = environment.apiBaseUrl + 'config/'
+
+ constructor(protected http: HttpClient) {}
+
+ getConfig(): Observable {
+ return this.http.get<[PaperlessConfig]>(this.baseUrl).pipe(
+ first(),
+ map((configs) => configs[0])
+ )
+ }
+
+ saveConfig(config: PaperlessConfig): Observable {
+ return this.http.patch(this.baseUrl, config).pipe(first())
+ }
+}