diff --git a/src-ui/src/app/components/app-frame/app-frame.component.spec.ts b/src-ui/src/app/components/app-frame/app-frame.component.spec.ts
index d9b1acda4..4dd88c84d 100644
--- a/src-ui/src/app/components/app-frame/app-frame.component.spec.ts
+++ b/src-ui/src/app/components/app-frame/app-frame.component.spec.ts
@@ -15,7 +15,7 @@ import { provideUiTour } from 'ngx-ui-tour-ng-bootstrap'
import { of, throwError } from 'rxjs'
import { routes } from 'src/app/app-routing.module'
import { SavedView } from 'src/app/data/saved-view'
-import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
+import { HideableSidebarItemID, SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
import {
@@ -287,6 +287,82 @@ describe('AppFrameComponent', () => {
jest.useRealTimers()
})
+ it('should hide configured sidebar items', () => {
+ settingsService.set(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS, [
+ HideableSidebarItemID.Dashboard,
+ HideableSidebarItemID.Workflows,
+ ])
+ fixture.detectChanges()
+
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="dashboard"]')
+ .parentElement.classList
+ ).toContain('d-none')
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="workflows"]')
+ .parentElement.classList
+ ).toContain('d-none')
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="mail"]').parentElement
+ .classList
+ ).not.toContain('d-none')
+ })
+
+ it('should show hidden items and visibility switches while customizing', () => {
+ settingsService.set(SETTINGS_KEYS.SIDEBAR_HIDDEN_ITEMS, [
+ HideableSidebarItemID.Dashboard,
+ ])
+ settingsService.sidebarHiddenItemsEditing.set([
+ HideableSidebarItemID.Dashboard,
+ ])
+ fixture.detectChanges()
+
+ expect(
+ fixture.nativeElement.querySelectorAll('pngx-input-switch').length
+ ).toBe(5)
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="dashboard"]')
+ .parentElement.classList
+ ).not.toContain('d-none')
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="dashboard"]').classList
+ ).toContain('opacity-50')
+
+ settingsService.set(SETTINGS_KEYS.SLIM_SIDEBAR, true)
+ fixture.detectChanges()
+
+ expect(
+ Array.from(
+ fixture.nativeElement.querySelectorAll('pngx-input-switch')
+ ).every((toggle: HTMLElement) => toggle.classList.contains('d-none'))
+ ).toBe(true)
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="dashboard"]').classList
+ ).not.toContain('pe-5')
+
+ settingsService.set(SETTINGS_KEYS.SLIM_SIDEBAR, false)
+ component.slimSidebarAnimating.set(true)
+ fixture.detectChanges()
+
+ expect(
+ Array.from(
+ fixture.nativeElement.querySelectorAll('pngx-input-switch')
+ ).every((toggle: HTMLElement) => toggle.classList.contains('d-none'))
+ ).toBe(true)
+
+ component.slimSidebarAnimating.set(false)
+ fixture.detectChanges()
+
+ expect(
+ Array.from(
+ fixture.nativeElement.querySelectorAll('pngx-input-switch')
+ ).every((toggle: HTMLElement) => !toggle.classList.contains('d-none'))
+ ).toBe(true)
+ expect(
+ fixture.nativeElement.querySelector('[routerLink="dashboard"]').classList
+ ).toContain('pe-5')
+ })
+
it('should show error on toggle slim sidebar if store settings fails', () => {
jest.spyOn(console, 'warn').mockImplementation(() => {})
const toastSpy = jest.spyOn(toastService, 'showError')
diff --git a/src-ui/src/app/components/app-frame/app-frame.component.ts b/src-ui/src/app/components/app-frame/app-frame.component.ts
index 59a2ba18b..7b4c29d2f 100644
--- a/src-ui/src/app/components/app-frame/app-frame.component.ts
+++ b/src-ui/src/app/components/app-frame/app-frame.component.ts
@@ -7,6 +7,7 @@ import {
} from '@angular/cdk/drag-drop'
import { NgClass } from '@angular/common'
import { Component, HostListener, inject, OnInit, signal } from '@angular/core'
+import { FormsModule } from '@angular/forms'
import { ActivatedRoute, Router, RouterModule } from '@angular/router'
import {
NgbCollapseModule,
@@ -21,7 +22,11 @@ import { Observable } from 'rxjs'
import { first } from 'rxjs/operators'
import { Document } from 'src/app/data/document'
import { SavedView } from 'src/app/data/saved-view'
-import { CollapsibleSection, SETTINGS_KEYS } from 'src/app/data/ui-settings'
+import {
+ CollapsibleSection,
+ HideableSidebarItemID,
+ SETTINGS_KEYS,
+} from 'src/app/data/ui-settings'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { ComponentCanDeactivate } from 'src/app/guards/dirty-doc.guard'
import { DocumentTitlePipe } from 'src/app/pipes/document-title.pipe'
@@ -48,6 +53,7 @@ import { ChatComponent } from '../chat/chat/chat.component'
import { BrandMarkComponent } from '../common/logo/brand-mark/brand-mark.component'
import { LogoComponent } from '../common/logo/logo.component'
import { ProfileEditDialogComponent } from '../common/profile-edit-dialog/profile-edit-dialog.component'
+import { SwitchComponent } from '../common/input/switch/switch.component'
import { DocumentDetailComponent } from '../document-detail/document-detail.component'
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
import { GlobalSearchComponent } from './global-search/global-search.component'
@@ -76,6 +82,8 @@ const SCROLL_THRESHOLD = 16
NgxBootstrapIconsModule,
DragDropModule,
TourNgBootstrap,
+ FormsModule,
+ SwitchComponent,
],
})
export class AppFrameComponent
@@ -98,6 +106,7 @@ export class AppFrameComponent
readonly isMenuCollapsed = signal(true)
readonly slimSidebarAnimating = signal(false)
readonly mobileSearchHidden = signal(false)
+ readonly HideableSidebarItemID = HideableSidebarItemID
private readonly versionSetting = this.settingsService.getSignal
(
SETTINGS_KEYS.VERSION
)
@@ -195,6 +204,10 @@ export class AppFrameComponent
}, 200) // slightly longer than css animation for slim sidebar
}
+ toggleSidebarItem(item: HideableSidebarItemID, visible: boolean): void {
+ this.settingsService.updateSidebarItemVisibility(item, visible)
+ }
+
toggleAttributesSections(event?: Event): void {
event?.preventDefault()
event?.stopPropagation()
diff --git a/src-ui/src/app/components/common/input/switch/switch.component.html b/src-ui/src/app/components/common/input/switch/switch.component.html
index edd831e5c..636356d64 100644
--- a/src-ui/src/app/components/common/input/switch/switch.component.html
+++ b/src-ui/src/app/components/common/input/switch/switch.component.html
@@ -1,6 +1,6 @@
-
-
- @if (!horizontal) {
+
+
+ @if (!horizontal && !compact) {