diff --git a/kdb-web/src/app/app-routing.module.ts b/kdb-web/src/app/app-routing.module.ts index e7993348..1ae6ad4b 100644 --- a/kdb-web/src/app/app-routing.module.ts +++ b/kdb-web/src/app/app-routing.module.ts @@ -7,7 +7,7 @@ import { AuthGuard } from './modules/shared/guards/auth/auth.guard'; const routes: Routes = [ { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, { path: 'dashboard', loadChildren: () => import('./modules/view/dashboard/dashboard.module').then(m => m.DashboardModule), canActivate: [AuthGuard] }, - { path: 'server/:id', loadChildren: () => import('./modules/view/server/server.module').then(m => m.ServerModule), canActivate: [AuthGuard] }, + { path: 'server/:serverId', loadChildren: () => import('./modules/view/server/server.module').then(m => m.ServerModule), canActivate: [AuthGuard] }, { path: 'change-password', loadChildren: () => import('./modules/view/change-password/change-password.module').then(m => m.ChangePasswordModule), canActivate: [AuthGuard] }, { path: 'user-settings', loadChildren: () => import('./modules/view/user-settings/user-settings.module').then(m => m.UserSettingsModule), canActivate: [AuthGuard] }, { path: 'auth', loadChildren: () => import('./modules/auth/auth.module').then(m => m.AuthModule) }, diff --git a/kdb-web/src/app/components/sidebar/sidebar.component.ts b/kdb-web/src/app/components/sidebar/sidebar.component.ts index ad7a3df0..09eb593b 100644 --- a/kdb-web/src/app/components/sidebar/sidebar.component.ts +++ b/kdb-web/src/app/components/sidebar/sidebar.component.ts @@ -1,90 +1,42 @@ import { Component, OnInit } from "@angular/core"; -import { ActivatedRoute } from "@angular/router"; import { LangChangeEvent, TranslateService } from "@ngx-translate/core"; import { MenuItem } from "primeng/api"; -import { AuthRoles } from "src/app/models/auth/auth-roles.enum"; import { AuthService } from "src/app/services/auth/auth.service"; import { ThemeService } from "src/app/services/theme/theme.service"; +import { SidebarService } from "../../services/sidebar/sidebar.service"; @Component({ - selector: 'app-sidebar', - templateUrl: './sidebar.component.html', - styleUrls: ['./sidebar.component.scss'] + selector: "app-sidebar", + templateUrl: "./sidebar.component.html", + styleUrls: ["./sidebar.component.scss"] }) export class SidebarComponent implements OnInit { - isSidebarOpen: boolean = true; + isSidebarOpen!: boolean; menuItems!: MenuItem[]; - private serverId?: number; - constructor( private authService: AuthService, private translateService: TranslateService, private themeService: ThemeService, - private route: ActivatedRoute, + private sidebar: SidebarService ) { + this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { + this.sidebar.setMenu(); + }); + this.themeService.isSidebarOpen$.subscribe(value => { this.isSidebarOpen = value; - this.setMenu(); + this.sidebar.setMenu(); }); - this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { - this.setMenu(); + this.sidebar.menuItems$.subscribe(value => { + this.menuItems = value; }); - - // this.serverService.server$.subscribe(server => { - // if (!server) { - // return; - // } - // - // this.serverId = server.id; - // this.setMenu(); - // }); } ngOnInit(): void { this.themeService.loadMenu(); } - setMenu() { - this.authService.hasUserPermission(AuthRoles.Admin).then(hasPermission => { - this.menuItems = []; - this.menuItems = [ - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.dashboard') : '', icon: 'pi pi-th-large', routerLink: 'dashboard' } - ]; - - // if (this.serverId) { - // this.addServerMenu(); - // } - - if (hasPermission) { - this.addAdminMenu(); - } - this.menuItems = this.menuItems.slice(); - }); - } - - addServerMenu() { - this.menuItems.push( - { - label: this.isSidebarOpen ? this.translateService.instant('sidebar.server') : '', icon: 'pi pi-server', items: [ - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.settings') : '', icon: 'pi pi-cog', routerLink: 'server/settings' }, - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.members') : '', icon: 'pi pi-users', routerLink: 'server/members' }, - ] - } - ); - } - - addAdminMenu() { - this.menuItems.push( - { - label: this.isSidebarOpen ? this.translateService.instant('sidebar.administration') : '', icon: 'pi pi-cog', items: [ - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.config') : '', icon: 'pi pi-cog', routerLink: '/admin/settings' }, - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.auth_user_list') : '', icon: 'pi pi-user-edit', routerLink: '/admin/users' }, - ] - }, - ); - } - } diff --git a/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts b/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts index 4efb1940..685eaf9c 100644 --- a/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts +++ b/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts @@ -14,6 +14,7 @@ import { Queries } from "../../../../../models/graphql/queries.model"; import { Page } from "../../../../../models/graphql/filter/page.model"; import { Sort } from "../../../../../models/graphql/filter/sort.model"; import { Query } from "../../../../../models/graphql/query.model"; +import { SidebarService } from "../../../../../services/sidebar/sidebar.service"; @Component({ selector: "app-dashboard", @@ -49,7 +50,7 @@ export class DashboardComponent implements OnInit { private fb: FormBuilder, private translate: TranslateService, private router: Router, - // private serverService: ServerService + private sidebar: SidebarService, ) { } @@ -121,7 +122,7 @@ export class DashboardComponent implements OnInit { } selectServer(server: Server) { - // this.serverService.server$.next(server); + this.sidebar.serverName$.next(server.name ?? ""); this.router.navigate(["/server", server.id]); } diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts index 06b9eb23..28f87e1a 100644 --- a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts +++ b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts @@ -5,6 +5,7 @@ import { DataService } from "src/app/services/data/data.service"; import { SpinnerService } from "src/app/services/spinner/spinner.service"; import { Queries } from "../../../../models/graphql/queries.model"; import { Query } from "../../../../models/graphql/query.model"; +import { SidebarService } from "../../../../services/sidebar/sidebar.service"; @Component({ selector: "app-server-dashboard", @@ -20,20 +21,28 @@ export class ServerDashboardComponent implements OnInit { private route: ActivatedRoute, private router: Router, private data: DataService, - private spinner: SpinnerService + private spinner: SpinnerService, + private sidebar: SidebarService ) { } ngOnInit(): void { this.spinner.showSpinner(); + if (!this.route.snapshot.params["serverId"]) { + this.spinner.hideSpinner(); + this.router.navigate(['/dashboard']); + return; + } + this.data.query(Queries.serversQuery, { - filter: { id: this.route.snapshot.params["id"] } + filter: { id: this.route.snapshot.params["serverId"] } }, function(data: Query) { return data.servers.length > 0 ? data.servers[0] : null; } ).subscribe(server => { this.server = server; + this.sidebar.serverName$.next(server.name ?? ""); this.spinner.hideSpinner(); }); } diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.spec.ts b/kdb-web/src/app/services/sidebar/sidebar.service.spec.ts new file mode 100644 index 00000000..63b8b69f --- /dev/null +++ b/kdb-web/src/app/services/sidebar/sidebar.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SidebarService } from './sidebar.service'; + +describe('SidebarService', () => { + let service: SidebarService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SidebarService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts new file mode 100644 index 00000000..ef3f6a95 --- /dev/null +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -0,0 +1,73 @@ +import { Injectable } from "@angular/core"; +import { MenuItem } from "primeng/api"; +import { BehaviorSubject } from "rxjs"; +import { AuthRoles } from "../../models/auth/auth-roles.enum"; +import { AuthService } from "../auth/auth.service"; +import { TranslateService } from "@ngx-translate/core"; +import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; +import { ThemeService } from "../theme/theme.service"; + +@Injectable({ + providedIn: "root" +}) +export class SidebarService { + + isSidebarOpen: boolean = true; + menuItems$: BehaviorSubject = new BehaviorSubject(new Array()); + serverName$: BehaviorSubject = new BehaviorSubject(""); + + constructor( + private themeService: ThemeService, + private authService: AuthService, + private translateService: TranslateService, + private router: Router, + ) { + this.themeService.isSidebarOpen$.subscribe(value => { + this.isSidebarOpen = value; + this.setMenu(); + }); + + + this.serverName$.subscribe(value => { + this.setMenu(); + }); + + this.router.events.subscribe(event => { + if (!(event instanceof NavigationEnd)) { + return; + } + }); + } + + setMenu() { + this.authService.hasUserPermission(AuthRoles.Admin).then(hasPermission => { + let menuItems: MenuItem[] = [ + { label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", icon: "pi pi-th-large", routerLink: "dashboard" } + ]; + + const serverMenu = { + label: this.isSidebarOpen ? this.serverName$.value : "", icon: "pi pi-server", items: [ + { label: this.isSidebarOpen ? this.translateService.instant("sidebar.settings") : "", icon: "pi pi-cog", routerLink: "server/settings" }, + { label: this.isSidebarOpen ? this.translateService.instant("sidebar.members") : "", icon: "pi pi-users", routerLink: "server/members" } + ] + }; + if (this.serverName$.value != "") { + menuItems.push(serverMenu); + } else if (menuItems.find(x => x.icon == "pi pi-server")) { + menuItems.splice(menuItems.indexOf(serverMenu), 1); + } + + if (hasPermission) { + menuItems.push( + { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.administration") : "", icon: "pi pi-cog", items: [ + { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", icon: "pi pi-cog", routerLink: "/admin/settings" }, + { label: this.isSidebarOpen ? this.translateService.instant("sidebar.auth_user_list") : "", icon: "pi pi-user-edit", routerLink: "/admin/users" } + ] + } + ); + } + this.menuItems$.next(menuItems); + }); + } +} diff --git a/kdb-web/src/styles/primeng-fixes.scss b/kdb-web/src/styles/primeng-fixes.scss index c6b246f4..7361d673 100644 --- a/kdb-web/src/styles/primeng-fixes.scss +++ b/kdb-web/src/styles/primeng-fixes.scss @@ -1,102 +1,106 @@ @import "./constants.scss"; .btn { - &:focus { - box-shadow: none !important; - } + &:focus { + box-shadow: none !important; + } } .p-menu, .p-panelmenu { - background: none !important; - border: none !important; - width: auto !important; - border-radius: 0px !important; - padding: 0 !important; + background: none !important; + border: none !important; + width: auto !important; + border-radius: 0px !important; + padding: 0 !important; - .p-menuitem-link, - .p-panelmenu-header > a, - .p-panelmenu-content .p-menuitem .p-menuitem-link { - $distance: 10px; - padding: $distance 0px $distance $distance !important; - margin: 4px 0px 4px 6px !important; - } + .p-menuitem-link, + .p-panelmenu-header > a, + .p-panelmenu-content .p-menuitem .p-menuitem-link { + $distance: 10px; + padding: $distance 0px $distance $distance !important; + margin: 4px 0px 4px 6px !important; + } } header, .app { - .p-menu-overlay { - top: $headerHeight !important; - } + .p-menu-overlay { + top: $headerHeight !important; + } } .p-panelmenu { - .p-panelmenu-icon { - order: 1; // to be the first item on right side. - } - .p-menuitem-text { - flex-grow: 1; // to fill the whole space and push the icon to the end - } + .p-panelmenu-icon { + order: 1; // to be the first item on right side. + } - .p-panelmenu-header > a { - border: none !important; - border-radius: none !important; - font-weight: none !important; - transition: none !important; - } + .p-menuitem-text { + flex-grow: 1; // to fill the whole space and push the icon to the end + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } - .p-panelmenu-content { - border: none !important; - background: none !important; - } + .p-panelmenu-header > a { + border: none !important; + border-radius: none !important; + font-weight: none !important; + transition: none !important; + } - .p-menuitem-text { - line-height: normal !important; - } + .p-panelmenu-content { + border: none !important; + background: none !important; + } + + .p-menuitem-text { + line-height: normal !important; + } } ui-menu .ui-menu-parent .ui-menu-child { - width: 400px; /* exagerated !! */ + width: 400px; /* exagerated !! */ } .p-toast-detail { - white-space: pre-line; + white-space: pre-line; } .p-datatable .p-sortable-column:focus { - box-shadow: none !important; + box-shadow: none !important; } .p-password { - padding: 0px !important; + padding: 0px !important; } .p-paginator { - background-color: transparent !important; - border: none !important; + background-color: transparent !important; + border: none !important; } p-table { - .p-datatable .p-datatable-header { - border: none !important; - } + .p-datatable .p-datatable-header { + border: none !important; + } - .p-datatable .p-datatable-header, - .p-datatable .p-datatable-tbody > tr, - .p-datatable .p-datatable-thead > tr > th { - background-color: transparent !important; - color: inherit !important; - } + .p-datatable .p-datatable-header, + .p-datatable .p-datatable-tbody > tr, + .p-datatable .p-datatable-thead > tr > th { + background-color: transparent !important; + color: inherit !important; + } } .pi-sort-alt:before { - content: "\e915" !important; + content: "\e915" !important; } .pi-sort-amount-up-alt:before { - content: "\e914" !important; + content: "\e914" !important; } .pi-sort-amount-down:before { - content: "\e913" !important; + content: "\e913" !important; }