Handle settings live refresh, unsubscribe subscriptions

This commit is contained in:
Michael Shamoon 2022-09-30 15:39:02 -07:00
parent 98ab770437
commit 06a29cd45c
2 changed files with 107 additions and 74 deletions

View File

@ -16,7 +16,15 @@ import {
} from 'src/app/services/settings.service' } from 'src/app/services/settings.service'
import { Toast, ToastService } from 'src/app/services/toast.service' import { Toast, ToastService } from 'src/app/services/toast.service'
import { dirtyCheck, DirtyComponent } from '@ngneat/dirty-check-forms' 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 { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings'
import { ActivatedRoute } from '@angular/router' import { ActivatedRoute } from '@angular/router'
import { ViewportScroller } from '@angular/common' import { ViewportScroller } from '@angular/common'
@ -57,7 +65,9 @@ export class SettingsComponent
store: BehaviorSubject<any> store: BehaviorSubject<any>
storeSub: Subscription storeSub: Subscription
isDirty$: Observable<boolean> isDirty$: Observable<boolean>
isDirty: Boolean = false isDirty: boolean = false
unsubscribeNotifier: Subject<any> = new Subject()
savePending: boolean = false
get computedDateLocale(): string { get computedDateLocale(): string {
return ( return (
@ -75,7 +85,11 @@ export class SettingsComponent
@Inject(LOCALE_ID) public currentLocale: string, @Inject(LOCALE_ID) public currentLocale: string,
private viewportScroller: ViewportScroller, private viewportScroller: ViewportScroller,
private activatedRoute: ActivatedRoute private activatedRoute: ActivatedRoute
) {} ) {
this.settings.settingsSaved.subscribe(() => {
if (!this.savePending) this.initialize()
})
}
ngAfterViewInit(): void { ngAfterViewInit(): void {
if (this.activatedRoute.snapshot.fragment) { if (this.activatedRoute.snapshot.fragment) {
@ -88,90 +102,98 @@ export class SettingsComponent
ngOnInit() { ngOnInit() {
this.savedViewService.listAll().subscribe((r) => { this.savedViewService.listAll().subscribe((r) => {
this.savedViews = r.results this.savedViews = r.results
let storeData = { this.initialize()
bulkEditConfirmationDialogs: this.settings.get( })
SETTINGS_KEYS.BULK_EDIT_CONFIRMATION_DIALOGS }
),
bulkEditApplyOnClose: this.settings.get( initialize() {
SETTINGS_KEYS.BULK_EDIT_APPLY_ON_CLOSE this.unsubscribeNotifier.next(true)
),
documentListItemPerPage: this.settings.get( let storeData = {
SETTINGS_KEYS.DOCUMENT_LIST_SIZE bulkEditConfirmationDialogs: this.settings.get(
), SETTINGS_KEYS.BULK_EDIT_CONFIRMATION_DIALOGS
darkModeUseSystem: this.settings.get( ),
SETTINGS_KEYS.DARK_MODE_USE_SYSTEM bulkEditApplyOnClose: this.settings.get(
), SETTINGS_KEYS.BULK_EDIT_APPLY_ON_CLOSE
darkModeEnabled: this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED), ),
darkModeInvertThumbs: this.settings.get( documentListItemPerPage: this.settings.get(
SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED SETTINGS_KEYS.DOCUMENT_LIST_SIZE
), ),
themeColor: this.settings.get(SETTINGS_KEYS.THEME_COLOR), darkModeUseSystem: this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM),
useNativePdfViewer: this.settings.get( darkModeEnabled: this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED),
SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER darkModeInvertThumbs: this.settings.get(
), SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED
savedViews: {}, ),
displayLanguage: this.settings.getLanguage(), themeColor: this.settings.get(SETTINGS_KEYS.THEME_COLOR),
dateLocale: this.settings.get(SETTINGS_KEYS.DATE_LOCALE), useNativePdfViewer: this.settings.get(
dateFormat: this.settings.get(SETTINGS_KEYS.DATE_FORMAT), SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER
notificationsConsumerNewDocument: this.settings.get( ),
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT savedViews: {},
), displayLanguage: this.settings.getLanguage(),
notificationsConsumerSuccess: this.settings.get( dateLocale: this.settings.get(SETTINGS_KEYS.DATE_LOCALE),
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS dateFormat: this.settings.get(SETTINGS_KEYS.DATE_FORMAT),
), notificationsConsumerNewDocument: this.settings.get(
notificationsConsumerFailed: this.settings.get( SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED ),
), notificationsConsumerSuccess: this.settings.get(
notificationsConsumerSuppressOnDashboard: this.settings.get( SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS
SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD ),
), notificationsConsumerFailed: this.settings.get(
commentsEnabled: this.settings.get(SETTINGS_KEYS.COMMENTS_ENABLED), SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED
updateCheckingEnabled: this.settings.get( ),
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED notificationsConsumerSuppressOnDashboard: this.settings.get(
), SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD
),
commentsEnabled: this.settings.get(SETTINGS_KEYS.COMMENTS_ENABLED),
updateCheckingEnabled: this.settings.get(
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED
),
}
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),
})
)
}
for (let view of this.savedViews) { this.store = new BehaviorSubject(storeData)
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.storeSub = this.store.asObservable().subscribe((state) => {
this.settingsForm.patchValue(state, { emitEvent: false })
})
this.storeSub = this.store.asObservable().subscribe((state) => { // Initialize dirtyCheck
this.settingsForm.patchValue(state, { emitEvent: false }) this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable())
})
// Initialize dirtyCheck // Record dirty in case we need to 'undo' appearance settings if not saved on close
this.isDirty$ = dirtyCheck(this.settingsForm, this.store.asObservable()) this.isDirty$
.pipe(takeUntil(this.unsubscribeNotifier))
// Record dirty in case we need to 'undo' appearance settings if not saved on close .subscribe((dirty) => {
this.isDirty$.subscribe((dirty) => {
this.isDirty = dirty this.isDirty = dirty
}) })
// "Live" visual changes prior to save // "Live" visual changes prior to save
this.settingsForm.valueChanges.subscribe(() => { this.settingsForm.valueChanges
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe(() => {
this.settings.updateAppearanceSettings( this.settings.updateAppearanceSettings(
this.settingsForm.get('darkModeUseSystem').value, this.settingsForm.get('darkModeUseSystem').value,
this.settingsForm.get('darkModeEnabled').value, this.settingsForm.get('darkModeEnabled').value,
this.settingsForm.get('themeColor').value this.settingsForm.get('themeColor').value
) )
}) })
})
} }
ngOnDestroy() { ngOnDestroy() {
@ -190,6 +212,7 @@ export class SettingsComponent
} }
private saveLocalSettings() { private saveLocalSettings() {
this.savePending = true
const reloadRequired = const reloadRequired =
this.settingsForm.value.displayLanguage != this.settingsForm.value.displayLanguage !=
this.store?.getValue()['displayLanguage'] || // displayLanguage is dirty this.store?.getValue()['displayLanguage'] || // displayLanguage is dirty
@ -265,6 +288,7 @@ export class SettingsComponent
this.settings this.settings
.storeSettings() .storeSettings()
.pipe(first()) .pipe(first())
.pipe(tap(() => (this.savePending = false)))
.subscribe({ .subscribe({
next: () => { next: () => {
this.store.next(this.settingsForm.value) this.store.next(this.settingsForm.value)

View File

@ -1,6 +1,7 @@
import { DOCUMENT } from '@angular/common' import { DOCUMENT } from '@angular/common'
import { HttpClient } from '@angular/common/http' import { HttpClient } from '@angular/common/http'
import { import {
EventEmitter,
Inject, Inject,
Injectable, Injectable,
LOCALE_ID, LOCALE_ID,
@ -46,6 +47,8 @@ export class SettingsService {
public displayName: string public displayName: string
public settingsSaved: EventEmitter<any> = new EventEmitter()
constructor( constructor(
rendererFactory: RendererFactory2, rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document, @Inject(DOCUMENT) private document,
@ -370,7 +373,13 @@ export class SettingsService {
} }
storeSettings(): Observable<any> { storeSettings(): Observable<any> {
return this.http.post(this.baseUrl, { settings: this.settings }) return this.http.post(this.baseUrl, { settings: this.settings }).pipe(
tap((results) => {
if (results.success) {
this.settingsSaved.emit()
}
})
)
} }
maybeMigrateSettings() { maybeMigrateSettings() {