From b1cb41438dfe4c47e72f465ff091354a9c21b56f Mon Sep 17 00:00:00 2001
From: shamoon <4887959+shamoon@users.noreply.github.com>
Date: Tue, 8 Sep 2026 11:52:11 -0700
Subject: [PATCH] A little more machinery here
---
.../admin/settings/settings.component.html | 16 ++++++++
.../admin/settings/settings.component.spec.ts | 25 ++++++++++-
.../admin/settings/settings.component.ts | 41 ++++++++++++++++++-
.../src/app/services/settings.service.spec.ts | 12 ++----
src-ui/src/app/services/settings.service.ts | 15 -------
5 files changed, 83 insertions(+), 26 deletions(-)
diff --git a/src-ui/src/app/components/admin/settings/settings.component.html b/src-ui/src/app/components/admin/settings/settings.component.html
index 305bb8a96..b520e8218 100644
--- a/src-ui/src/app/components/admin/settings/settings.component.html
+++ b/src-ui/src/app/components/admin/settings/settings.component.html
@@ -112,6 +112,22 @@
+
Sidebar items to show:
+ @for (option of sidebarItemOptions; track option.id) {
+
+
+
+
+ }
+
diff --git a/src-ui/src/app/components/admin/settings/settings.component.spec.ts b/src-ui/src/app/components/admin/settings/settings.component.spec.ts
index 7b65281d0..08ff5c445 100644
--- a/src-ui/src/app/components/admin/settings/settings.component.spec.ts
+++ b/src-ui/src/app/components/admin/settings/settings.component.spec.ts
@@ -24,7 +24,7 @@ import {
SystemStatus,
SystemStatusItemStatus,
} from 'src/app/data/system-status'
-import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
+import { HideableSidebarItemID, SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { IfOwnerDirective } from 'src/app/directives/if-owner.directive'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
@@ -209,6 +209,23 @@ describe('SettingsComponent', () => {
fixture.detectChanges()
}
+ it('supports configuring sidebar items and canceling changes', () => {
+ completeSetup()
+
+ component.toggleSidebarItem(HideableSidebarItemID.Workflows, false)
+ fixture.detectChanges()
+
+ expect(component.settingsForm.value.sidebarHiddenItems).toContain(
+ HideableSidebarItemID.Workflows
+ )
+
+ component.reset()
+
+ expect(component.settingsForm.value.sidebarHiddenItems).not.toContain(
+ HideableSidebarItemID.Workflows
+ )
+ })
+
it('should support tabbed settings & change URL, prevent navigation if dirty confirmation rejected', async () => {
completeSetup()
const navigateSpy = jest.spyOn(router, 'navigate')
@@ -249,6 +266,7 @@ describe('SettingsComponent', () => {
it('should support save local settings updating appearance settings and calling API, show error', () => {
completeSetup()
+ component.toggleSidebarItem(HideableSidebarItemID.Workflows, false)
const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastSpy = jest.spyOn(toastService, 'show')
const storeSpy = jest.spyOn(settingsService, 'storeSettings')
@@ -267,7 +285,10 @@ describe('SettingsComponent', () => {
expect(toastErrorSpy).toHaveBeenCalled()
expect(storeSpy).toHaveBeenCalled()
expect(appearanceSettingsSpy).not.toHaveBeenCalled()
- expect(setSpy).toHaveBeenCalledTimes(33)
+ expect(setSpy).toHaveBeenCalledTimes(34)
+ expect(setSpy).toHaveBeenCalledWith(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS, [
+ HideableSidebarItemID.Workflows,
+ ])
// succeed
storeSpy.mockReturnValueOnce(of(true))
diff --git a/src-ui/src/app/components/admin/settings/settings.component.ts b/src-ui/src/app/components/admin/settings/settings.component.ts
index 218f6683c..583b10c38 100644
--- a/src-ui/src/app/components/admin/settings/settings.component.ts
+++ b/src-ui/src/app/components/admin/settings/settings.component.ts
@@ -39,7 +39,12 @@ import {
SystemStatus,
SystemStatusItemStatus,
} from 'src/app/data/system-status'
-import { GlobalSearchType, SETTINGS_KEYS } from 'src/app/data/ui-settings'
+import {
+ GlobalSearchType,
+ HIDEABLE_SIDEBAR_ITEM_IDS,
+ HideableSidebarItemID,
+ SETTINGS_KEYS,
+} from 'src/app/data/ui-settings'
import { User } from 'src/app/data/user'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
@@ -102,6 +107,14 @@ const documentDetailFieldOptions = [
{ id: DocumentDetailFieldID.Tags, label: $localize`Tags` },
]
+const sidebarItemLabels: Record = {
+ [HideableSidebarItemID.Dashboard]: $localize`Dashboard`,
+ [HideableSidebarItemID.SavedViews]: $localize`Saved Views`,
+ [HideableSidebarItemID.Workflows]: $localize`Workflows`,
+ [HideableSidebarItemID.Mail]: $localize`Mail`,
+ [HideableSidebarItemID.Documentation]: $localize`Documentation`,
+}
+
@Component({
selector: 'pngx-settings',
templateUrl: './settings.component.html',
@@ -149,6 +162,7 @@ export class SettingsComponent
bulkEditApplyOnClose: new FormControl(null),
documentListItemPerPage: new FormControl(null),
slimSidebarEnabled: new FormControl(null),
+ sidebarHiddenItems: new FormControl([]),
darkModeUseSystem: new FormControl(null),
darkModeEnabled: new FormControl(null),
darkModeInvertThumbs: new FormControl(null),
@@ -203,6 +217,10 @@ export class SettingsComponent
public readonly PdfEditorEditMode = PdfEditorEditMode
public readonly documentDetailFieldOptions = documentDetailFieldOptions
+ public readonly sidebarItemOptions = HIDEABLE_SIDEBAR_ITEM_IDS.map((id) => ({
+ id,
+ label: sidebarItemLabels[id],
+ }))
get systemStatusHasErrors(): boolean {
const status = this.systemStatus()
@@ -310,6 +328,7 @@ export class SettingsComponent
SETTINGS_KEYS.DOCUMENT_LIST_SIZE
),
slimSidebarEnabled: this.settings.get(SETTINGS_KEYS.SLIM_SIDEBAR),
+ sidebarHiddenItems: this.settings.get(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS),
darkModeUseSystem: this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM),
darkModeEnabled: this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED),
darkModeInvertThumbs: this.settings.get(
@@ -448,6 +467,22 @@ export class SettingsComponent
this.storeSub && this.storeSub.unsubscribe()
}
+ isSidebarItemShown(item: HideableSidebarItemID): boolean {
+ return !(this.settingsForm.value.sidebarHiddenItems || []).includes(item)
+ }
+
+ toggleSidebarItem(item: HideableSidebarItemID, checked: boolean): void {
+ const hiddenItems = new Set(
+ this.settingsForm.value.sidebarHiddenItems || []
+ )
+ if (checked) {
+ hiddenItems.delete(item)
+ } else {
+ hiddenItems.add(item)
+ }
+ this.settingsForm.controls.sidebarHiddenItems.setValue([...hiddenItems])
+ }
+
public saveSettings() {
this.savePending = true
const reloadRequired =
@@ -473,6 +508,10 @@ export class SettingsComponent
SETTINGS_KEYS.SLIM_SIDEBAR,
this.settingsForm.value.slimSidebarEnabled
)
+ this.settings.set(
+ SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS,
+ this.settingsForm.value.sidebarHiddenItems
+ )
this.settings.set(
SETTINGS_KEYS.DARK_MODE_USE_SYSTEM,
this.settingsForm.value.darkModeUseSystem
diff --git a/src-ui/src/app/services/settings.service.spec.ts b/src-ui/src/app/services/settings.service.spec.ts
index be8e393c9..4167858e2 100644
--- a/src-ui/src/app/services/settings.service.spec.ts
+++ b/src-ui/src/app/services/settings.service.spec.ts
@@ -234,7 +234,7 @@ describe('SettingsService', () => {
expect(notesEnabled()).toBeFalsy()
})
- it('updates sidebar item visibility', () => {
+ it('reports whether a sidebar item is hidden', () => {
httpTestingController
.expectOne(`${environment.apiBaseUrl}ui_settings/`)
.flush(ui_settings)
@@ -243,19 +243,15 @@ describe('SettingsService', () => {
settingsService.sidebarItemIsHidden(HideableSidebarItemID.Workflows)
).toBe(false)
- settingsService.updateSidebarItemVisibility(
+ settingsService.set(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS, [
HideableSidebarItemID.Workflows,
- false
- )
+ ])
expect(
settingsService.sidebarItemIsHidden(HideableSidebarItemID.Workflows)
).toBe(true)
- settingsService.updateSidebarItemVisibility(
- HideableSidebarItemID.Workflows,
- true
- )
+ settingsService.set(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS, [])
expect(
settingsService.sidebarItemIsHidden(HideableSidebarItemID.Workflows)
diff --git a/src-ui/src/app/services/settings.service.ts b/src-ui/src/app/services/settings.service.ts
index f012b56de..9b1b47e09 100644
--- a/src-ui/src/app/services/settings.service.ts
+++ b/src-ui/src/app/services/settings.service.ts
@@ -314,7 +314,6 @@ export class SettingsService {
readonly globalDropzoneEnabled = signal(true)
readonly globalDropzoneActive = signal(false)
readonly organizingSidebarSavedViews = signal(false)
- readonly organizingSidebarItems = signal(false)
readonly hiddenSidebarItems = this.getSignal(
SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS
)
@@ -758,20 +757,6 @@ export class SettingsService {
return this.hiddenSidebarItems().includes(item)
}
- updateSidebarItemVisibility(
- item: HideableSidebarItemID,
- visible: boolean
- ): Observable {
- const hiddenItems = new Set(this.hiddenSidebarItems())
- if (visible) {
- hiddenItems.delete(item)
- } else {
- hiddenItems.add(item)
- }
- this.set(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS, [...hiddenItems])
- return this.storeSettings()
- }
-
updateSavedViewsVisibility(
dashboardVisibleViewIds: number[],
sidebarVisibleViewIds: number[]