mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Merge branch 'dev' into feature/slim-sidebar
This commit is contained in:
@@ -207,14 +207,25 @@
|
||||
<li class="nav-item mt-2" [class.visually-hidden]="slimSidebarEnabled">
|
||||
<div class="px-3 py-2 text-muted small d-flex align-items-center flex-wrap">
|
||||
<div class="me-3">{{ versionString }}</div>
|
||||
<div *ngIf="appRemoteVersion" class="version-check">
|
||||
<div *ngIf="!settingsService.updateCheckingIsSet || appRemoteVersion" class="version-check">
|
||||
<ng-template #updateAvailablePopContent>
|
||||
<span class="small">Paperless-ngx {{ appRemoteVersion.version }} <ng-container i18n>is available.</ng-container><br/><ng-container i18n>Click to view.</ng-container></span>
|
||||
</ng-template>
|
||||
<ng-template #updateCheckingNotEnabledPopContent>
|
||||
<span class="small"><ng-container i18n>Checking for updates is disabled.</ng-container><br/><ng-container i18n>Click for more information.</ng-container></span>
|
||||
<p class="small mb-2">
|
||||
<ng-container i18n>Paperless-ngx can automatically check for updates</ng-container>
|
||||
</p>
|
||||
<div class="btn-group btn-group-xs flex-fill w-100">
|
||||
<button class="btn btn-outline-primary" (click)="setUpdateChecking(true)">Enable</button>
|
||||
<button class="btn btn-outline-secondary" (click)="setUpdateChecking(false)">Disable</button>
|
||||
</div>
|
||||
<p class="small mb-0 mt-2">
|
||||
<a class="small text-decoration-none fst-italic" routerLink="/settings" fragment="update-checking" i18n>
|
||||
How does this work?
|
||||
</a>
|
||||
</p>
|
||||
</ng-template>
|
||||
<ng-container *ngIf="appRemoteVersion.feature_is_set; else updateCheckNotSet">
|
||||
<ng-container *ngIf="settingsService.updateCheckingIsSet; else updateCheckNotSet">
|
||||
<a *ngIf="appRemoteVersion.update_available" class="small text-decoration-none" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/releases"
|
||||
[ngbPopover]="updateAvailablePopContent" popoverClass="shadow" triggers="mouseenter:mouseleave" container="body">
|
||||
<svg fill="currentColor" class="me-1" width="1.2em" height="1.2em" style="vertical-align: text-top;" viewBox="0 0 16 16">
|
||||
@@ -224,8 +235,8 @@
|
||||
</a>
|
||||
</ng-container>
|
||||
<ng-template #updateCheckNotSet>
|
||||
<a class="small text-decoration-none" target="_blank" rel="noopener noreferrer" href="https://paperless-ngx.readthedocs.io/en/latest/configuration.html#update-checking"
|
||||
[ngbPopover]="updateCheckingNotEnabledPopContent" popoverClass="shadow" triggers="mouseenter:mouseleave" container="body">
|
||||
<a class="small text-decoration-none" routerLink="/settings" fragment="update-checking"
|
||||
[ngbPopover]="updateCheckingNotEnabledPopContent" popoverClass="shadow" triggers="mouseenter" container="body">
|
||||
<svg fill="currentColor" class="me-1" width="1.2em" height="1.2em" style="vertical-align: text-top;" viewBox="0 0 16 16">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#info-circle" />
|
||||
</svg>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Component, HostListener } from '@angular/core'
|
||||
import { Component, HostListener, OnInit } from '@angular/core'
|
||||
import { FormControl } from '@angular/forms'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
import { from, Observable } from 'rxjs'
|
||||
@@ -32,7 +32,7 @@ import { ToastService } from 'src/app/services/toast.service'
|
||||
templateUrl: './app-frame.component.html',
|
||||
styleUrls: ['./app-frame.component.scss'],
|
||||
})
|
||||
export class AppFrameComponent implements ComponentCanDeactivate {
|
||||
export class AppFrameComponent implements OnInit, ComponentCanDeactivate {
|
||||
constructor(
|
||||
public router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
@@ -43,14 +43,14 @@ export class AppFrameComponent implements ComponentCanDeactivate {
|
||||
private list: DocumentListViewService,
|
||||
public settingsService: SettingsService,
|
||||
public tasksService: TasksService,
|
||||
private toastService: ToastService
|
||||
) {
|
||||
this.remoteVersionService
|
||||
.checkForUpdates()
|
||||
.subscribe((appRemoteVersion: AppRemoteVersion) => {
|
||||
this.appRemoteVersion = appRemoteVersion
|
||||
})
|
||||
tasksService.reload()
|
||||
private readonly toastService: ToastService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.settingsService.get(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED)) {
|
||||
this.checkForUpdates()
|
||||
}
|
||||
this.tasksService.reload()
|
||||
}
|
||||
|
||||
versionString = `${environment.appTitle} ${environment.version}`
|
||||
@@ -182,4 +182,30 @@ export class AppFrameComponent implements ComponentCanDeactivate {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private checkForUpdates() {
|
||||
this.remoteVersionService
|
||||
.checkForUpdates()
|
||||
.subscribe((appRemoteVersion: AppRemoteVersion) => {
|
||||
this.appRemoteVersion = appRemoteVersion
|
||||
})
|
||||
}
|
||||
|
||||
setUpdateChecking(enable: boolean) {
|
||||
this.settingsService.set(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED, enable)
|
||||
this.settingsService
|
||||
.storeSettings()
|
||||
.pipe(first())
|
||||
.subscribe({
|
||||
error: (error) => {
|
||||
this.toastService.showError(
|
||||
$localize`An error occurred while saving update checking settings.`
|
||||
)
|
||||
console.log(error)
|
||||
},
|
||||
})
|
||||
if (enable) {
|
||||
this.checkForUpdates()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
|
||||
import { FormControl, FormGroup } from '@angular/forms'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
|
||||
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
|
||||
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'
|
||||
import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
@@ -31,7 +32,7 @@ export class CorrespondentEditDialogComponent extends EditDialogComponent<Paperl
|
||||
getForm(): FormGroup {
|
||||
return new FormGroup({
|
||||
name: new FormControl(''),
|
||||
matching_algorithm: new FormControl(1),
|
||||
matching_algorithm: new FormControl(DEFAULT_MATCHING_ALGORITHM),
|
||||
match: new FormControl(''),
|
||||
is_insensitive: new FormControl(true),
|
||||
})
|
||||
|
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
|
||||
import { FormControl, FormGroup } from '@angular/forms'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
|
||||
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
|
||||
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'
|
||||
import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
@@ -31,7 +32,7 @@ export class DocumentTypeEditDialogComponent extends EditDialogComponent<Paperle
|
||||
getForm(): FormGroup {
|
||||
return new FormGroup({
|
||||
name: new FormControl(''),
|
||||
matching_algorithm: new FormControl(1),
|
||||
matching_algorithm: new FormControl(DEFAULT_MATCHING_ALGORITHM),
|
||||
match: new FormControl(''),
|
||||
is_insensitive: new FormControl(true),
|
||||
})
|
||||
|
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
|
||||
import { FormControl, FormGroup } from '@angular/forms'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
|
||||
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
|
||||
import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path'
|
||||
import { StoragePathService } from 'src/app/services/rest/storage-path.service'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
@@ -42,7 +43,7 @@ export class StoragePathEditDialogComponent extends EditDialogComponent<Paperles
|
||||
return new FormGroup({
|
||||
name: new FormControl(''),
|
||||
path: new FormControl(''),
|
||||
matching_algorithm: new FormControl(1),
|
||||
matching_algorithm: new FormControl(DEFAULT_MATCHING_ALGORITHM),
|
||||
match: new FormControl(''),
|
||||
is_insensitive: new FormControl(true),
|
||||
})
|
||||
|
@@ -6,6 +6,7 @@ import { PaperlessTag } from 'src/app/data/paperless-tag'
|
||||
import { TagService } from 'src/app/services/rest/tag.service'
|
||||
import { ToastService } from 'src/app/services/toast.service'
|
||||
import { randomColor } from 'src/app/utils/color'
|
||||
import { DEFAULT_MATCHING_ALGORITHM } from 'src/app/data/matching-model'
|
||||
|
||||
@Component({
|
||||
selector: 'app-tag-edit-dialog',
|
||||
@@ -34,7 +35,7 @@ export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {
|
||||
name: new FormControl(''),
|
||||
color: new FormControl(randomColor()),
|
||||
is_inbox_tag: new FormControl(false),
|
||||
matching_algorithm: new FormControl(1),
|
||||
matching_algorithm: new FormControl(DEFAULT_MATCHING_ALGORITHM),
|
||||
match: new FormControl(''),
|
||||
is_insensitive: new FormControl(true),
|
||||
})
|
||||
|
@@ -17,25 +17,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group-xs {
|
||||
> .btn {
|
||||
padding: 0.2rem 0.25rem;
|
||||
font-size: 0.675rem;
|
||||
line-height: 1.2;
|
||||
border-radius: 0.15rem;
|
||||
}
|
||||
|
||||
> .btn:not(:first-child) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
> .btn:not(:last-child) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group > label.disabled {
|
||||
filter: brightness(0.5);
|
||||
|
||||
|
@@ -64,9 +64,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100 d-xxl-none"></div>
|
||||
<div class="col col-xl-auto ps-0">
|
||||
<div class="col col-xl-auto ps-xxl-0">
|
||||
<button class="btn btn-link btn-sm px-0" [disabled]="!rulesModified" (click)="resetSelected()">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1 ms-n1" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
||||
</svg><ng-container i18n>Reset filters</ng-container>
|
||||
</button>
|
||||
|
@@ -127,6 +127,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-4" id="update-checking" i18n>Update checking</h4>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="offset-md-3 col">
|
||||
<p i18n>
|
||||
Update checking works by pinging the the public <a href="https://api.github.com/repos/paperless-ngx/paperless-ngx/releases/latest" target="_blank" rel="noopener noreferrer">Github API</a> for the latest release to determine whether a new version is available.<br/>
|
||||
Actual updating of the app must still be performed manually.
|
||||
</p>
|
||||
<p i18n>
|
||||
<em>No tracking data is collected by the app in any way.</em>
|
||||
</p>
|
||||
<app-input-check i18n-title title="Enable update checking" formControlName="updateCheckingEnabled" i18n-hint hint="Note that for users of thirdy-party containers e.g. linuxserver.io this notification may be 'ahead' of the current third-party release."></app-input-check>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-4" i18n>Bulk editing</h4>
|
||||
|
||||
<div class="row mb-3">
|
||||
@@ -205,5 +220,5 @@
|
||||
|
||||
<div [ngbNavOutlet]="nav" class="border-start border-end border-bottom p-3 mb-3 shadow-sm"></div>
|
||||
|
||||
<button type="submit" class="btn btn-primary" [disabled]="!(isDirty$ | async)" i18n>Save</button>
|
||||
<button type="submit" class="btn btn-primary mb-2" [disabled]="!(isDirty$ | async)" i18n>Save</button>
|
||||
</form>
|
||||
|
@@ -1,4 +1,11 @@
|
||||
import { Component, Inject, LOCALE_ID, OnInit, OnDestroy } from '@angular/core'
|
||||
import {
|
||||
Component,
|
||||
Inject,
|
||||
LOCALE_ID,
|
||||
OnInit,
|
||||
OnDestroy,
|
||||
AfterViewInit,
|
||||
} from '@angular/core'
|
||||
import { FormControl, FormGroup } from '@angular/forms'
|
||||
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||
@@ -9,8 +16,18 @@ import {
|
||||
} from 'src/app/services/settings.service'
|
||||
import { Toast, ToastService } from 'src/app/services/toast.service'
|
||||
import { dirtyCheck, DirtyComponent } from '@ngneat/dirty-check-forms'
|
||||
import { Observable, Subscription, BehaviorSubject, first } from 'rxjs'
|
||||
import {
|
||||
Observable,
|
||||
Subscription,
|
||||
BehaviorSubject,
|
||||
first,
|
||||
tap,
|
||||
takeUntil,
|
||||
Subject,
|
||||
} from 'rxjs'
|
||||
import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings'
|
||||
import { ActivatedRoute } from '@angular/router'
|
||||
import { ViewportScroller } from '@angular/common'
|
||||
import { ForwardRefHandling } from '@angular/compiler'
|
||||
|
||||
@Component({
|
||||
@@ -18,7 +35,9 @@ import { ForwardRefHandling } from '@angular/compiler'
|
||||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['./settings.component.scss'],
|
||||
})
|
||||
export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
export class SettingsComponent
|
||||
implements OnInit, AfterViewInit, OnDestroy, DirtyComponent
|
||||
{
|
||||
savedViewGroup = new FormGroup({})
|
||||
|
||||
settingsForm = new FormGroup({
|
||||
@@ -40,6 +59,7 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
notificationsConsumerFailed: new FormControl(null),
|
||||
notificationsConsumerSuppressOnDashboard: new FormControl(null),
|
||||
commentsEnabled: new FormControl(null),
|
||||
updateCheckingEnabled: new FormControl(null),
|
||||
})
|
||||
|
||||
savedViews: PaperlessSavedView[]
|
||||
@@ -47,7 +67,9 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
store: BehaviorSubject<any>
|
||||
storeSub: Subscription
|
||||
isDirty$: Observable<boolean>
|
||||
isDirty: Boolean = false
|
||||
isDirty: boolean = false
|
||||
unsubscribeNotifier: Subject<any> = new Subject()
|
||||
savePending: boolean = false
|
||||
|
||||
get computedDateLocale(): string {
|
||||
return (
|
||||
@@ -57,29 +79,28 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
)
|
||||
}
|
||||
|
||||
get displayLanguageIsDirty(): boolean {
|
||||
return (
|
||||
this.settingsForm.get('displayLanguage').value !=
|
||||
this.store?.getValue()['displayLanguage']
|
||||
)
|
||||
}
|
||||
|
||||
constructor(
|
||||
public savedViewService: SavedViewService,
|
||||
private documentListViewService: DocumentListViewService,
|
||||
private toastService: ToastService,
|
||||
private settings: SettingsService,
|
||||
@Inject(LOCALE_ID) public currentLocale: string
|
||||
@Inject(LOCALE_ID) public currentLocale: string,
|
||||
private viewportScroller: ViewportScroller,
|
||||
private activatedRoute: ActivatedRoute
|
||||
) {
|
||||
this.settings.changed.subscribe({
|
||||
next: () => {
|
||||
this.settingsForm.patchValue(this.getCurrentSettings(), {
|
||||
emitEvent: false,
|
||||
})
|
||||
},
|
||||
this.settings.settingsSaved.subscribe(() => {
|
||||
if (!this.savePending) this.initialize()
|
||||
})
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
if (this.activatedRoute.snapshot.fragment) {
|
||||
this.viewportScroller.scrollToAnchor(
|
||||
this.activatedRoute.snapshot.fragment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private getCurrentSettings() {
|
||||
return {
|
||||
bulkEditConfirmationDialogs: this.settings.get(
|
||||
@@ -91,7 +112,6 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
documentListItemPerPage: this.settings.get(
|
||||
SETTINGS_KEYS.DOCUMENT_LIST_SIZE
|
||||
),
|
||||
slimSidebarEnabled: this.settings.get(SETTINGS_KEYS.SLIM_SIDEBAR),
|
||||
darkModeUseSystem: this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM),
|
||||
darkModeEnabled: this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED),
|
||||
darkModeInvertThumbs: this.settings.get(
|
||||
@@ -118,55 +138,68 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD
|
||||
),
|
||||
commentsEnabled: this.settings.get(SETTINGS_KEYS.COMMENTS_ENABLED),
|
||||
updateCheckingEnabled: this.settings.get(
|
||||
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.savedViewService.listAll().subscribe((r) => {
|
||||
this.savedViews = r.results
|
||||
let storeData = this.getCurrentSettings()
|
||||
this.initialize()
|
||||
})
|
||||
}
|
||||
|
||||
for (let view of this.savedViews) {
|
||||
storeData.savedViews[view.id.toString()] = {
|
||||
id: view.id,
|
||||
name: view.name,
|
||||
show_on_dashboard: view.show_on_dashboard,
|
||||
show_in_sidebar: view.show_in_sidebar,
|
||||
}
|
||||
this.savedViewGroup.addControl(
|
||||
view.id.toString(),
|
||||
new FormGroup({
|
||||
id: new FormControl(null),
|
||||
name: new FormControl(null),
|
||||
show_on_dashboard: new FormControl(null),
|
||||
show_in_sidebar: new FormControl(null),
|
||||
})
|
||||
)
|
||||
initialize() {
|
||||
this.unsubscribeNotifier.next(true)
|
||||
|
||||
let storeData = this.getCurrentSettings()
|
||||
|
||||
for (let view of this.savedViews) {
|
||||
storeData.savedViews[view.id.toString()] = {
|
||||
id: view.id,
|
||||
name: view.name,
|
||||
show_on_dashboard: view.show_on_dashboard,
|
||||
show_in_sidebar: view.show_in_sidebar,
|
||||
}
|
||||
this.savedViewGroup.addControl(
|
||||
view.id.toString(),
|
||||
new FormGroup({
|
||||
id: new FormControl(null),
|
||||
name: new FormControl(null),
|
||||
show_on_dashboard: new FormControl(null),
|
||||
show_in_sidebar: new FormControl(null),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
this.store = new BehaviorSubject(storeData)
|
||||
this.store = new BehaviorSubject(storeData)
|
||||
|
||||
this.storeSub = this.store.asObservable().subscribe((state) => {
|
||||
this.settingsForm.patchValue(state, { emitEvent: false })
|
||||
})
|
||||
this.storeSub = this.store.asObservable().subscribe((state) => {
|
||||
this.settingsForm.patchValue(state, { emitEvent: false })
|
||||
})
|
||||
|
||||
// Initialize dirtyCheck
|
||||
this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable())
|
||||
// Initialize dirtyCheck
|
||||
this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable())
|
||||
|
||||
// Record dirty in case we need to 'undo' appearance settings if not saved on close
|
||||
this.isDirty$.subscribe((dirty) => {
|
||||
// Record dirty in case we need to 'undo' appearance settings if not saved on close
|
||||
this.isDirty$
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe((dirty) => {
|
||||
this.isDirty = dirty
|
||||
})
|
||||
|
||||
// "Live" visual changes prior to save
|
||||
this.settingsForm.valueChanges.subscribe(() => {
|
||||
// "Live" visual changes prior to save
|
||||
this.settingsForm.valueChanges
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
.subscribe(() => {
|
||||
this.settings.updateAppearanceSettings(
|
||||
this.settingsForm.get('darkModeUseSystem').value,
|
||||
this.settingsForm.get('darkModeEnabled').value,
|
||||
this.settingsForm.get('themeColor').value
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@@ -185,7 +218,14 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
}
|
||||
|
||||
private saveLocalSettings() {
|
||||
const reloadRequired = this.displayLanguageIsDirty // just this one, for now
|
||||
this.savePending = true
|
||||
const reloadRequired =
|
||||
this.settingsForm.value.displayLanguage !=
|
||||
this.store?.getValue()['displayLanguage'] || // displayLanguage is dirty
|
||||
(this.settingsForm.value.updateCheckingEnabled !=
|
||||
this.store?.getValue()['updateCheckingEnabled'] &&
|
||||
this.settingsForm.value.updateCheckingEnabled) // update checking was turned on
|
||||
|
||||
this.settings.set(
|
||||
SETTINGS_KEYS.BULK_EDIT_APPLY_ON_CLOSE,
|
||||
this.settingsForm.value.bulkEditApplyOnClose
|
||||
@@ -250,10 +290,15 @@ export class SettingsComponent implements OnInit, OnDestroy, DirtyComponent {
|
||||
SETTINGS_KEYS.COMMENTS_ENABLED,
|
||||
this.settingsForm.value.commentsEnabled
|
||||
)
|
||||
this.settings.set(
|
||||
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED,
|
||||
this.settingsForm.value.updateCheckingEnabled
|
||||
)
|
||||
this.settings.setLanguage(this.settingsForm.value.displayLanguage)
|
||||
this.settings
|
||||
.storeSettings()
|
||||
.pipe(first())
|
||||
.pipe(tap(() => (this.savePending = false)))
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.store.next(this.settingsForm.value)
|
||||
|
@@ -6,6 +6,7 @@ export const MATCH_LITERAL = 3
|
||||
export const MATCH_REGEX = 4
|
||||
export const MATCH_FUZZY = 5
|
||||
export const MATCH_AUTO = 6
|
||||
export const DEFAULT_MATCHING_ALGORITHM = MATCH_AUTO
|
||||
|
||||
export const MATCHING_ALGORITHMS = [
|
||||
{
|
||||
|
@@ -29,8 +29,6 @@ export interface PaperlessDocument extends ObjectWithId {
|
||||
|
||||
content?: string
|
||||
|
||||
file_type?: string
|
||||
|
||||
tags$?: Observable<PaperlessTag[]>
|
||||
|
||||
tags?: number[]
|
||||
@@ -47,7 +45,7 @@ export interface PaperlessDocument extends ObjectWithId {
|
||||
|
||||
added?: Date
|
||||
|
||||
file_name?: string
|
||||
original_file_name?: string
|
||||
|
||||
download_url?: string
|
||||
|
||||
|
@@ -38,6 +38,9 @@ export const SETTINGS_KEYS = {
|
||||
'general-settings:notifications:consumer-suppress-on-dashboard',
|
||||
COMMENTS_ENABLED: 'general-settings:comments-enabled',
|
||||
SLIM_SIDEBAR: 'general-settings:slim-sidebar',
|
||||
UPDATE_CHECKING_ENABLED: 'general-settings:update-checking:enabled',
|
||||
UPDATE_CHECKING_BACKEND_SETTING:
|
||||
'general-settings:update-checking:backend-setting',
|
||||
}
|
||||
|
||||
export const SETTINGS: PaperlessUiSetting[] = [
|
||||
@@ -126,4 +129,14 @@ export const SETTINGS: PaperlessUiSetting[] = [
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
key: SETTINGS_KEYS.UPDATE_CHECKING_ENABLED,
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: SETTINGS_KEYS.UPDATE_CHECKING_BACKEND_SETTING,
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
]
|
||||
|
@@ -6,7 +6,6 @@ import { environment } from 'src/environments/environment'
|
||||
export interface AppRemoteVersion {
|
||||
version: string
|
||||
update_available: boolean
|
||||
feature_is_set: boolean
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
|
@@ -47,7 +47,7 @@ export class SettingsService {
|
||||
|
||||
public displayName: string
|
||||
|
||||
public changed = new EventEmitter()
|
||||
public settingsSaved: EventEmitter<any> = new EventEmitter()
|
||||
|
||||
constructor(
|
||||
rendererFactory: RendererFactory2,
|
||||
@@ -316,13 +316,7 @@ export class SettingsService {
|
||||
)
|
||||
}
|
||||
|
||||
get(key: string): any {
|
||||
let setting = SETTINGS.find((s) => s.key == key)
|
||||
|
||||
if (!setting) {
|
||||
return null
|
||||
}
|
||||
|
||||
private getSettingRawValue(key: string): any {
|
||||
let value = null
|
||||
// parse key:key:key into nested object
|
||||
const keys = key.replace('general-settings:', '').split(':')
|
||||
@@ -333,6 +327,17 @@ export class SettingsService {
|
||||
if (index == keys.length - 1) value = settingObj[keyPart]
|
||||
else settingObj = settingObj[keyPart]
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
get(key: string): any {
|
||||
let setting = SETTINGS.find((s) => s.key == key)
|
||||
|
||||
if (!setting) {
|
||||
return null
|
||||
}
|
||||
|
||||
let value = this.getSettingRawValue(key)
|
||||
|
||||
if (value != null) {
|
||||
switch (setting.type) {
|
||||
@@ -362,10 +367,19 @@ export class SettingsService {
|
||||
})
|
||||
}
|
||||
|
||||
private settingIsSet(key: string): boolean {
|
||||
let value = this.getSettingRawValue(key)
|
||||
return value != null
|
||||
}
|
||||
|
||||
storeSettings(): Observable<any> {
|
||||
return this.http
|
||||
.post(this.baseUrl, { settings: this.settings })
|
||||
.pipe(tap((result) => this.changed.emit(!!result.success)))
|
||||
return this.http.post(this.baseUrl, { settings: this.settings }).pipe(
|
||||
tap((results) => {
|
||||
if (results.success) {
|
||||
this.settingsSaved.emit()
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
maybeMigrateSettings() {
|
||||
@@ -405,5 +419,31 @@ export class SettingsService {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
!this.settingIsSet(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED) &&
|
||||
this.get(SETTINGS_KEYS.UPDATE_CHECKING_BACKEND_SETTING) != 'default'
|
||||
) {
|
||||
this.set(
|
||||
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED,
|
||||
this.get(SETTINGS_KEYS.UPDATE_CHECKING_BACKEND_SETTING).toString() ===
|
||||
'true'
|
||||
)
|
||||
|
||||
this.storeSettings()
|
||||
.pipe(first())
|
||||
.subscribe({
|
||||
error: (e) => {
|
||||
this.toastService.showError(
|
||||
'Error migrating update checking setting'
|
||||
)
|
||||
console.log(e)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get updateCheckingIsSet(): boolean {
|
||||
return this.settingIsSet(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED)
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ export const environment = {
|
||||
apiBaseUrl: document.baseURI + 'api/',
|
||||
apiVersion: '2',
|
||||
appTitle: 'Paperless-ngx',
|
||||
version: '1.9.0-dev',
|
||||
version: '1.9.2-dev',
|
||||
webSocketHost: window.location.host,
|
||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||
webSocketBaseUrl: base_url.pathname + 'ws/',
|
||||
|
@@ -540,6 +540,25 @@ a.badge {
|
||||
border-color: var(--bs-primary);
|
||||
}
|
||||
|
||||
.btn-group-xs {
|
||||
> .btn {
|
||||
padding: 0.2rem 0.25rem;
|
||||
font-size: 0.675rem;
|
||||
line-height: 1.2;
|
||||
border-radius: 0.15rem;
|
||||
}
|
||||
|
||||
> .btn:not(:first-child) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
> .btn:not(:last-child) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
color: var(--pngx-body-color-accent)
|
||||
}
|
||||
|
Reference in New Issue
Block a user