diff --git a/src-ui/cypress/e2e/settings/settings.cy.ts b/src-ui/cypress/e2e/settings/settings.cy.ts index 157796a11..0480e39ce 100644 --- a/src-ui/cypress/e2e/settings/settings.cy.ts +++ b/src-ui/cypress/e2e/settings/settings.cy.ts @@ -46,7 +46,7 @@ describe('settings', () => { }) }) - cy.viewport(1024, 1280) + cy.viewport(1024, 1600) cy.visit('/settings') cy.wait('@savedViews') }) 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 8f94f80aa..7d003225d 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 @@ -4,11 +4,11 @@ (click)="isMenuCollapsed = !isMenuCollapsed"> <span class="navbar-toggler-icon"></span> </button> - <a class="navbar-brand col-auto col-md-3 col-lg-2 me-0 px-3 py-3 order-sm-0" routerLink="/dashboard"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.43 238.91" width="1em" class="me-2" fill="currentColor"> + <a class="navbar-brand me-0 px-3 py-3 order-sm-0" [ngClass]="slimSidebarEnabled ? 'slim' : 'col-auto col-md-3 col-lg-2'" routerLink="/dashboard"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.43 238.91" width="1em" fill="currentColor"> <path d="M194.7,0C164.22,70.94,17.64,79.74,64.55,194.06c.58,1.47-10.85,17-18.47,29.9-1.76-6.45-3.81-13.48-3.52-14.07,38.11-45.14-27.26-70.65-30.78-107.58C-4.64,131.62-10.5,182.92,39,212.53c.3,0,2.64,11.14,3.81,16.71a58.55,58.55,0,0,0-2.93,6.45c-1.17,2.93,7.62,2.64,7.62,3.22.88-.29,21.7-36.93,22.28-37.23C187.67,174.72,208.48,68.6,194.7,0ZM134.61,74.75C79.5,124,70.12,160.64,71.88,178.53,53.41,134.85,107.64,86.77,134.61,74.75ZM28.2,145.11c10.55,9.67,28.14,39.28,13.19,56.57C44.91,193.77,46.08,175.89,28.2,145.11Z" transform="translate(0 0)"/> </svg> - <ng-container i18n="app title">Paperless-ngx</ng-container> + <span class="ms-2" [class.visually-hidden]="slimSidebarEnabled" i18n="app title">Paperless-ngx</span> </a> <div class="search-form-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 ps-md-4 me-sm-auto order-3 order-sm-1"> <form (ngSubmit)="search()" class="form-inline flex-grow-1"> @@ -51,48 +51,54 @@ <div class="container-fluid"> <div class="row"> - <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse" [ngbCollapse]="isMenuCollapsed"> + <nav id="sidebarMenu" class="d-md-block bg-light sidebar collapse" [ngClass]="slimSidebarEnabled ? 'slim' : 'col-md-3 col-lg-2'" [class.animating]="slimSidebarAnimating" [ngbCollapse]="isMenuCollapsed"> + <button class="btn btn-sm btn-dark sidebar-slim-toggler" (click)="toggleSlimSidebar()"> + <svg class="sidebaricon-sm" fill="currentColor"> + <use *ngIf="slimSidebarEnabled" xlink:href="assets/bootstrap-icons.svg#chevron-double-right"/> + <use *ngIf="!slimSidebarEnabled" xlink:href="assets/bootstrap-icons.svg#chevron-double-left"/> + </svg> + </button> <div class="sidebar-sticky pt-3 d-flex flex-column justify-space-around"> <ul class="nav flex-column"> <li class="nav-item"> - <a class="nav-link" routerLink="dashboard" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="dashboard" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Dashboard" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#house"/> - </svg> <ng-container i18n>Dashboard</ng-container> + </svg><span> <ng-container i18n>Dashboard</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="documents" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="documents" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Documents" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#files"/> - </svg> <ng-container i18n>Documents</ng-container> + </svg><span> <ng-container i18n>Documents</ng-container></span> </a> </li> </ul> <h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted" *ngIf='savedViewService.loading || savedViewService.sidebarViews.length > 0'> - <ng-container i18n>Saved views</ng-container> + <span i18n>Saved views</span> <div *ngIf="savedViewService.loading" class="spinner-border spinner-border-sm fw-normal ms-2" role="status"></div> </h6> <ul class="nav flex-column mb-2"> <li class="nav-item w-100" *ngFor="let view of savedViewService.sidebarViews"> - <a class="nav-link text-truncate" routerLink="view/{{view.id}}" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" [class.text-truncate]="!slimSidebarEnabled" routerLink="view/{{view.id}}" routerLinkActive="active" (click)="closeMenu()" [ngbPopover]="view.name" [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#funnel"/> - </svg> {{view.name}} + </svg><span> {{view.name}}</span> </a> </li> </ul> <h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted" *ngIf='openDocuments.length > 0'> - <ng-container i18n>Open documents</ng-container> + <span i18n>Open documents</span> </h6> <ul class="nav flex-column mb-2"> <li class="nav-item w-100" *ngFor='let d of openDocuments'> - <a class="nav-link text-truncate" routerLink="documents/{{d.id}}" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" [class.text-truncate]="!slimSidebarEnabled" routerLink="documents/{{d.id}}" routerLinkActive="active" (click)="closeMenu()" [ngbPopover]="d.title | documentTitle" [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#file-text"/> - </svg> {{d.title | documentTitle}} + </svg><span> {{d.title | documentTitle}}</span> <span class="close" (click)="closeDocument(d); $event.preventDefault()"> <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16"> <use xlink:href="assets/bootstrap-icons.svg#x"/> @@ -101,95 +107,96 @@ </a> </li> <li class="nav-item w-100" *ngIf="openDocuments.length >= 1"> - <a class="nav-link text-truncate" [routerLink]="[]" (click)="closeAll()"> + <a class="nav-link" [class.text-truncate]="!slimSidebarEnabled" [routerLink]="[]" (click)="closeAll()" ngbPopover="Close all" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#x"/> - </svg> <ng-container i18n>Close all</ng-container> + </svg><span> <ng-container i18n>Close all</ng-container></span> </a> </li> </ul> <h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted"> - <ng-container i18n>Manage</ng-container> + <span i18n>Manage</span> </h6> <ul class="nav flex-column mb-2"> <li class="nav-item"> - <a class="nav-link" routerLink="correspondents" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="correspondents" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Correspondents" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#person"/> - </svg> <ng-container i18n>Correspondents</ng-container> + </svg><span> <ng-container i18n>Correspondents</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="tags" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="tags" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Tags" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#tags"/> - </svg> <ng-container i18n>Tags</ng-container> + </svg><span> <ng-container i18n>Tags</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="documenttypes" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="documenttypes" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Document types" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#hash"/> - </svg> <ng-container i18n>Document types</ng-container> + </svg><span> <ng-container i18n>Document types</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="storagepaths" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="storagepaths" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Storage paths" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#folder"/> - </svg> <ng-container i18n>Storage paths</ng-container> + </svg><span> <ng-container i18n>Storage paths</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="tasks" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="tasks" routerLinkActive="active" (click)="closeMenu()" ngbPopover="File Tasks" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> + <span *ngIf="tasksService.failedFileTasks.length > 0 && slimSidebarEnabled" class="badge bg-danger position-absolute top-0 end-0">{{tasksService.failedFileTasks.length}}</span> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#list-task"/> - </svg> <ng-container i18n>File Tasks<ng-container *ngIf="tasksService.failedFileTasks.length > 0"><span class="badge bg-danger ms-2">{{tasksService.failedFileTasks.length}}</span></ng-container></ng-container> + </svg><span> <ng-container i18n>File Tasks<span *ngIf="tasksService.failedFileTasks.length > 0"><span class="badge bg-danger ms-2">{{tasksService.failedFileTasks.length}}</span></span></ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="logs" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="logs" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Logs" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#text-left"/> - </svg> <ng-container i18n>Logs</ng-container> + </svg><span> <ng-container i18n>Logs</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" routerLink="settings" routerLinkActive="active" (click)="closeMenu()"> + <a class="nav-link" routerLink="settings" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Settings" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#gear"/> - </svg> <ng-container i18n>Settings</ng-container> + </svg><span> <ng-container i18n>Settings</ng-container></span> </a> </li> <li class="nav-item"> - <a class="nav-link" href="admin/"> + <a class="nav-link" href="admin/" ngbPopover="Admin" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#toggles"/> - </svg> <ng-container i18n>Admin</ng-container> + </svg><span> <ng-container i18n>Admin</ng-container></span> </a> </li> </ul> <h6 class="sidebar-heading px-3 mt-auto pt-4 mb-1 text-muted"> - <ng-container i18n>Info</ng-container> + <span i18n>Info</span> </h6> <ul class="nav flex-column mb-2"> <li class="nav-item"> - <a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://paperless-ngx.readthedocs.io/en/latest/"> + <a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://paperless-ngx.readthedocs.io/en/latest/" ngbPopover="Documentation" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg class="sidebaricon" fill="currentColor"> <use xlink:href="assets/bootstrap-icons.svg#question-circle"/> - </svg> <ng-container i18n>Documentation</ng-container> + </svg><span> <ng-container i18n>Documentation</ng-container></span> </a> </li> <li class="nav-item"> <div class="d-flex w-100 flex-wrap"> - <a class="nav-link pe-2 pb-1" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx"> + <a class="nav-link pe-2 pb-1" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx" ngbPopover="GitHub" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon" viewBox="0 0 16 16"> <use xlink:href="assets/bootstrap-icons.svg#github" /> - </svg> <ng-container i18n>GitHub</ng-container> + </svg><span> <ng-container i18n>GitHub</ng-container></span> </a> - <a class="nav-link-additional small text-muted ms-3" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests" title="Suggest an idea" i18n-title> + <a class="nav-link-additional small text-muted ms-3" [class.visually-hidden]="slimSidebarEnabled" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests" title="Suggest an idea" i18n-title> <svg xmlns="http://www.w3.org/2000/svg" width="1.1em" height="1.1em" fill="currentColor" class="me-1" viewBox="0 0 16 16"> <use xlink:href="assets/bootstrap-icons.svg#lightbulb" /> </svg> @@ -197,7 +204,7 @@ </a> </div> </li> - <li class="nav-item mt-2"> + <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="!settingsService.updateCheckingIsSet || appRemoteVersion" class="version-check"> @@ -242,7 +249,7 @@ </div> </nav> - <main role="main" class="col-md-9 ms-sm-auto col-lg-10 px-md-4"> + <main role="main" class="ms-sm-auto px-md-4" [ngClass]="slimSidebarEnabled ? 'col-slim' : 'col-md-9 col-lg-10'"> <router-outlet></router-outlet> </main> </div> diff --git a/src-ui/src/app/components/app-frame/app-frame.component.scss b/src-ui/src/app/components/app-frame/app-frame.component.scss index 296df26c3..95d7ed7ef 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.scss +++ b/src-ui/src/app/components/app-frame/app-frame.component.scss @@ -1,3 +1,6 @@ +@import "node_modules/bootstrap/scss/functions"; +@import "node_modules/bootstrap/scss/variables"; + /* * Sidebar */ @@ -14,6 +17,17 @@ width: 0.8em; height: 0.8em; } + + // These come from the col-md-3 col-lg-2 classes for regular sidebar, needed for animation + @media (min-width: 768px) { + max-width: 25%; + } + + @media (min-width: 992px) { + max-width: 16.66666667%; + } + + transition: all .2s ease; } @media (max-width: 767.98px) { .sidebar { @@ -21,6 +35,90 @@ } } +main { + transition: all .2s ease; +} + +.sidebar-slim-toggler { + display: none; // hide on mobile +} + +.sidebar li.nav-item span, +.sidebar .sidebar-heading span { + transition: all .1s ease; +} + +@media(min-width: 768px) { + .sidebar.slim { + max-width: 50px; + + li.nav-item span.badge { + display: inline-block; + margin-right: 2px; + } + } + + .sidebar.slim:not(.animating) { + li.nav-item span, + .sidebar-heading span { + display: none; + } + } + + .sidebar.animating { + li.nav-item span, + .sidebar-heading span { + display: unset; + position: absolute; + opacity: 0; + overflow: hidden; + } + } + + .sidebar:not(.slim):not(.animating) { + li.nav-item span, + .sidebar-heading span { + position: unset; + opacity: 1; + overflow: auto; + } + } + + .sidebar.slim, + .sidebar.animating { + .text-truncate { + text-overflow: unset !important; + word-wrap: break-word !important; + } + } + + .sidebar.slim { + li.nav-item span.badge { + display: inline-block; + margin-right: 2px; + } + } + + .col-slim { + padding-left: calc(50px + $grid-gutter-width) !important; + } + + .sidebar-slim-toggler { + display: block; + position: absolute; + right: -12px; + top: 60px; + z-index: 996; + --bs-btn-padding-x: 0.35rem; + --bs-btn-padding-y: 0.125rem; + } +} + +::ng-deep .popover-slim .popover-body { + --bs-popover-body-padding-x: .5rem; + --bs-popover-body-padding-y: .5rem; +} + .sidebar-sticky { position: relative; top: 0; 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 ee8deb5f8..b189409a8 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 @@ -58,6 +58,35 @@ export class AppFrameComponent implements OnInit, ComponentCanDeactivate { isMenuCollapsed: boolean = true + slimSidebarAnimating: boolean = false + + toggleSlimSidebar(): void { + this.slimSidebarAnimating = true + this.slimSidebarEnabled = !this.slimSidebarEnabled + setTimeout(() => { + this.slimSidebarAnimating = false + }, 200) // slightly longer than css animation for slim sidebar + } + + get slimSidebarEnabled(): boolean { + return this.settingsService.get(SETTINGS_KEYS.SLIM_SIDEBAR) + } + + set slimSidebarEnabled(enabled: boolean) { + this.settingsService.set(SETTINGS_KEYS.SLIM_SIDEBAR, enabled) + this.settingsService + .storeSettings() + .pipe(first()) + .subscribe({ + error: (error) => { + this.toastService.showError( + $localize`An error occurred while saving settings.` + ) + console.log(error) + }, + }) + } + closeMenu() { this.isMenuCollapsed = true } diff --git a/src-ui/src/app/components/document-list/document-list.component.scss b/src-ui/src/app/components/document-list/document-list.component.scss index b2d138d7f..3361d7c3a 100644 --- a/src-ui/src/app/components/document-list/document-list.component.scss +++ b/src-ui/src/app/components/document-list/document-list.component.scss @@ -11,7 +11,7 @@ tr { } $paperless-card-breakpoints: ( - 0: 2, // xs + // 0: 2, // xs is manual for slim-sidebar 768px: 3, //md 992px: 4, //lg 1200px: 5, //xl @@ -22,6 +22,12 @@ $paperless-card-breakpoints: ( ); .row-cols-paperless-cards { + // xs, we dont want in .col-slim block + > * { + flex: 0 0 auto; + width: calc(100% / 2); + } + @each $width, $n_cols in $paperless-card-breakpoints { @media(min-width: $width) { > * { @@ -32,6 +38,17 @@ $paperless-card-breakpoints: ( } } +::ng-deep .col-slim .row-cols-paperless-cards { + @each $width, $n_cols in $paperless-card-breakpoints { + @media(min-width: $width) { + > * { + flex: 0 0 auto; + width: calc(100% / ($n-cols + 1)) !important; + } + } + } +} + .dropdown-menu-right { right: 0 !important; left: auto !important; diff --git a/src-ui/src/app/components/manage/settings/settings.component.html b/src-ui/src/app/components/manage/settings/settings.component.html index e2afd76ea..ab4cbc4c4 100644 --- a/src-ui/src/app/components/manage/settings/settings.component.html +++ b/src-ui/src/app/components/manage/settings/settings.component.html @@ -89,6 +89,17 @@ </div> </div> + <div class="row mb-3"> + <div class="col-md-3 col-form-label"> + <span i18n>Sidebar</span> + </div> + <div class="col"> + + <app-input-check i18n-title title="Use 'slim' sidebar (icons only)" formControlName="slimSidebarEnabled"></app-input-check> + + </div> + </div> + <div class="row mb-3"> <div class="col-md-3 col-form-label"> <span i18n>Dark mode</span> diff --git a/src-ui/src/app/components/manage/settings/settings.component.ts b/src-ui/src/app/components/manage/settings/settings.component.ts index 0cf336a01..7a1f31820 100644 --- a/src-ui/src/app/components/manage/settings/settings.component.ts +++ b/src-ui/src/app/components/manage/settings/settings.component.ts @@ -28,6 +28,7 @@ import { 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({ selector: 'app-settings', @@ -43,6 +44,7 @@ export class SettingsComponent bulkEditConfirmationDialogs: new FormControl(null), bulkEditApplyOnClose: new FormControl(null), documentListItemPerPage: new FormControl(null), + slimSidebarEnabled: new FormControl(null), darkModeUseSystem: new FormControl(null), darkModeEnabled: new FormControl(null), darkModeInvertThumbs: new FormControl(null), @@ -99,17 +101,8 @@ export class SettingsComponent } } - ngOnInit() { - this.savedViewService.listAll().subscribe((r) => { - this.savedViews = r.results - this.initialize() - }) - } - - initialize() { - this.unsubscribeNotifier.next(true) - - let storeData = { + private getCurrentSettings() { + return { bulkEditConfirmationDialogs: this.settings.get( SETTINGS_KEYS.BULK_EDIT_CONFIRMATION_DIALOGS ), @@ -119,6 +112,7 @@ export class SettingsComponent 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( @@ -149,6 +143,19 @@ export class SettingsComponent SETTINGS_KEYS.UPDATE_CHECKING_ENABLED ), } + } + + ngOnInit() { + this.savedViewService.listAll().subscribe((r) => { + this.savedViews = r.results + this.initialize() + }) + } + + initialize() { + this.unsubscribeNotifier.next(true) + + let storeData = this.getCurrentSettings() for (let view of this.savedViews) { storeData.savedViews[view.id.toString()] = { @@ -232,6 +239,10 @@ export class SettingsComponent SETTINGS_KEYS.DOCUMENT_LIST_SIZE, this.settingsForm.value.documentListItemPerPage ) + this.settings.set( + SETTINGS_KEYS.SLIM_SIDEBAR, + this.settingsForm.value.slimSidebarEnabled + ) this.settings.set( SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem diff --git a/src-ui/src/app/data/paperless-uisettings.ts b/src-ui/src/app/data/paperless-uisettings.ts index b32315e62..403d11f08 100644 --- a/src-ui/src/app/data/paperless-uisettings.ts +++ b/src-ui/src/app/data/paperless-uisettings.ts @@ -37,6 +37,7 @@ export const SETTINGS_KEYS = { NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD: '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', @@ -58,6 +59,11 @@ export const SETTINGS: PaperlessUiSetting[] = [ type: 'boolean', default: false, }, + { + key: SETTINGS_KEYS.SLIM_SIDEBAR, + type: 'boolean', + default: false, + }, { key: SETTINGS_KEYS.DOCUMENT_LIST_SIZE, type: 'number', diff --git a/src-ui/src/styles.scss b/src-ui/src/styles.scss index d85fb7dc7..b66710dcd 100644 --- a/src-ui/src/styles.scss +++ b/src-ui/src/styles.scss @@ -1,9 +1,9 @@ // bs options $enable-negative-margins: true; +@import "theme"; @import "node_modules/bootstrap/scss/bootstrap"; @import "~@ng-select/ng-select/themes/default.theme.css"; -@import "theme"; @import "print"; // Paperless-ngx styles @@ -84,6 +84,15 @@ svg.logo { } } +.btn-dark { + --bs-btn-color: var(--bs-gray-600); + --bs-btn-bg: var(--bs-gray-200); + --bs-btn-border-color: var(--bs-gray-200); + --bs-btn-hover-bg: var(--bs-gray-400); + --bs-btn-hover-border-color: var(--bs-gray-500); + --bs-btn-active-bg: var(--bs-gray-200); +} + .text-primary { color: var(--bs-primary) !important; } @@ -405,6 +414,11 @@ textarea, vertical-align: text-bottom; } +.sidebaricon-sm { + width: 12px; + height: 12px; +} + table.table { color: var(--bs-body-color); diff --git a/src-ui/src/theme.scss b/src-ui/src/theme.scss index bf9be6662..99dcb8bab 100644 --- a/src-ui/src/theme.scss +++ b/src-ui/src/theme.scss @@ -79,6 +79,15 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,<svg xmlns='htt } } + .btn-dark { + --bs-btn-color: $text-color-dark-bg; + --bs-btn-bg: var(--pngx-bg-alt); + --bs-btn-border-color: var(--pngx-bg-alt); + --bs-btn-hover-bg: var(--bs-light); + --bs-btn-hover-border-color: var(--pngx-bg-darker); + --bs-btn-active-bg: var(--pngx-bg-alt); + } + .btn-outline-primary { &:hover, &:focus, &.active, &:active { color: var(--bs-light) !important;