1.0.0 #253
| @@ -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) }, | ||||
|   | ||||
| @@ -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' }, | ||||
|         ] | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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]); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -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<Server>(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(); | ||||
|     }); | ||||
|   } | ||||
|   | ||||
							
								
								
									
										16
									
								
								kdb-web/src/app/services/sidebar/sidebar.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								kdb-web/src/app/services/sidebar/sidebar.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -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(); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										73
									
								
								kdb-web/src/app/services/sidebar/sidebar.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								kdb-web/src/app/services/sidebar/sidebar.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -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<MenuItem[]> = new BehaviorSubject(new Array<MenuItem>()); | ||||
|   serverName$: BehaviorSubject<string> = 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); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user