From dfcd958965348479a18385c26abbb304cce4e13e Mon Sep 17 00:00:00 2001 From: Jonas Drescher Date: Mon, 20 Feb 2023 20:27:08 +0100 Subject: [PATCH 1/6] WIP: levels table --- .../src/app/models/graphql/queries.model.ts | 2 + .../components/levels/levels.component.html | 215 ++++++++++++++++++ .../components/levels/levels.component.scss | 0 .../levels/levels.component.spec.ts | 23 ++ .../components/levels/levels.component.ts | 127 +++++++++++ .../server/levels/levels-routing.module.ts | 16 ++ .../view/server/levels/levels.module.ts | 18 ++ .../view/server/server-routing.module.ts | 22 +- .../app/services/sidebar/sidebar.service.ts | 25 +- kdb-web/src/assets/i18n/de.json | 22 ++ 10 files changed, 456 insertions(+), 14 deletions(-) create mode 100644 kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html create mode 100644 kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.scss create mode 100644 kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts create mode 100644 kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts create mode 100644 kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts create mode 100644 kdb-web/src/app/modules/view/server/levels/levels.module.ts diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 82bb40af..5911d5f3 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -58,6 +58,8 @@ export class Queries { id name } + createdAt + modifiedAt } } `; diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html new file mode 100644 index 00000000..94888113 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html @@ -0,0 +1,215 @@ +

+ {{'view.server.levels.header' | translate}} +

+
+
+ + + +
+
+ {{levels.length}} {{'view.server.levels.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.levels.levels' | translate}} +
+ +
+ + +
+
+
+ + + + +
+
{{'view.server.levels.headers.id' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.name' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.color' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.min_xp' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.permissions' | translate}}
+ +
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'view.server.members.headers.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + + + + + + + +
+ + + + + + + {{level.id}} + + + {{level.id}} + + + + + + + + {{level.name}} + + + {{level.name}} + + + + + + + + {{level.color}} + + + {{level.color}} + + + + + + + + {{level.minXp}} + + + {{level.minXp}} + + + + + + + + {{level.permissions}} + + + {{level.permissions}} + + + + + + + + {{level.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{level.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{level.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{level.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + + +
+ + + + + +
+ + +
+ + + + + {{'view.server.auto_roles.no_entries_found' | translate}} + + + + + + +
+
+
+ diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.scss b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts new file mode 100644 index 00000000..30dc8eca --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LevelsComponent } from './levels.component'; + +describe('LevelsComponent', () => { + let component: LevelsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LevelsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LevelsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts new file mode 100644 index 00000000..d2b8cdaa --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts @@ -0,0 +1,127 @@ +import {Component} from '@angular/core'; +import {AuthService} from "../../../../../../services/auth/auth.service"; +import {SpinnerService} from "../../../../../../services/spinner/spinner.service"; +import {ToastService} from "../../../../../../services/toast/toast.service"; +import {ConfirmationDialogService} from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import {FormBuilder, FormControl, FormGroup} from "@angular/forms"; +import {TranslateService} from "@ngx-translate/core"; +import {DataService} from "../../../../../../services/data/data.service"; +import {SidebarService} from "../../../../../../services/sidebar/sidebar.service"; +import {ActivatedRoute} from "@angular/router"; +import {Page} from "../../../../../../models/graphql/filter/page.model"; +import {Sort, SortDirection} from "../../../../../../models/graphql/filter/sort.model"; +import {Level, LevelFilter} from "../../../../../../models/data/level.model"; +import {LevelListQuery} from "../../../../../../models/graphql/query.model"; +import {Queries} from "../../../../../../models/graphql/queries.model"; +import {debounceTime} from "rxjs/operators"; +import {LazyLoadEvent} from "primeng/api"; + +@Component({ + selector: 'app-levels', + templateUrl: './levels.component.html', + styleUrls: ['./levels.component.scss'] +}) +export class LevelsComponent { + + levels!: Level[]; + loading = true; + + isEditingNew: boolean = false; + + filterForm!: FormGroup<{ + id: FormControl, + name: FormControl, + color: FormControl, + min_xp: FormControl, + permissions: FormControl, + }>; + + filter: LevelFilter = {}; + page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + totalRecords!: number; + + public constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private sidebar: SidebarService, + private route: ActivatedRoute) { + } + + public ngOnInit(): void { + this.data.getServerFromRoute(this.route); + + this.setFilterForm(); + this.loadNextPage(); + } + + public loadNextPage() { + this.loading = true; + this.data.query(Queries.levelQuery, { + filter: this.filter, page: this.page, sort: this.sort + } + ).subscribe(data => { + this.totalRecords = data.levelCount; + this.levels = data.levels; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + public setFilterForm() { + this.filterForm = this.fb.group({ + id: new FormControl(null), + name: new FormControl(null), + color: new FormControl(null), + min_xp: new FormControl(null), + permissions: new FormControl(null), + }); + + this.filterForm.valueChanges.pipe( + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.name) { + this.filter.name = changes.name; + } else { + this.filter.name = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + public nextPage(event: LazyLoadEvent) { + this.page.pageSize = event.rows ?? 0; + if (event.first != null && event.rows != null) + this.page.pageIndex = event.first / event.rows; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + +} diff --git a/kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts b/kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts new file mode 100644 index 00000000..76c42715 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts @@ -0,0 +1,16 @@ +import {NgModule} from "@angular/core"; +import {RouterModule, Routes} from "@angular/router"; +import {LevelsComponent} from "./components/levels/levels.component"; + +const routes: Routes = [ + + {path: '', component: LevelsComponent}, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class LevelsRoutingModule { + +} diff --git a/kdb-web/src/app/modules/view/server/levels/levels.module.ts b/kdb-web/src/app/modules/view/server/levels/levels.module.ts new file mode 100644 index 00000000..a9d0ba8e --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/levels.module.ts @@ -0,0 +1,18 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {LevelsComponent} from './components/levels/levels.component' +import {SharedModule} from "../../../shared/shared.module"; +import {LevelsRoutingModule} from "./levels-routing.module"; + +@NgModule({ + declarations: [ + LevelsComponent + ], + imports: [ + CommonModule, + LevelsRoutingModule, + SharedModule + ] +}) +export class LevelsModule { +} diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts index b390b0b8..f51ea000 100644 --- a/kdb-web/src/app/modules/view/server/server-routing.module.ts +++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts @@ -1,18 +1,20 @@ -import { NgModule } from "@angular/core"; -import { RouterModule, Routes } from "@angular/router"; -import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component"; -import { ProfileComponent } from "./profile/profile.component"; -import { MembersComponent } from "./members/members.component"; +import {NgModule} from "@angular/core"; +import {RouterModule, Routes} from "@angular/router"; +import {ServerDashboardComponent} from "./server-dashboard/server-dashboard.component"; +import {ProfileComponent} from "./profile/profile.component"; +import {MembersComponent} from "./members/members.component"; const routes: Routes = [ - { path: '', component: ServerDashboardComponent }, - { path: 'members', component: MembersComponent }, - { path: 'members/:memberId', component: ProfileComponent }, - { path: 'auto-roles', loadChildren: () => import('./auto-role/auto-role.module').then(m => m.AutoRoleModule)}, + {path: '', component: ServerDashboardComponent}, + {path: 'members', component: MembersComponent}, + {path: 'members/:memberId', component: ProfileComponent}, + {path: 'auto-roles', loadChildren: () => import('./auto-role/auto-role.module').then(m => m.AutoRoleModule)}, + {path: 'levels', loadChildren: () => import('./levels/levels.module').then(m => m.LevelsModule)}, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) -export class ServerRoutingModule { } +export class ServerRoutingModule { +} diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index 021f434f..de11122f 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -24,6 +24,7 @@ export class SidebarService { serverMembers!: MenuItem; serverAutoRoles!: MenuItem; serverAutoRoleRules!: MenuItem; + serverLevels!: MenuItem; serverMenu!: MenuItem; adminConfig!: MenuItem; adminUsers!: MenuItem; @@ -66,7 +67,11 @@ export class SidebarService { } async buildMenu(user: UserDTO | null, hasPermission: boolean) { - this.dashboard = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", icon: "pi pi-th-large", routerLink: "dashboard" }; + this.dashboard = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", + icon: "pi pi-th-large", + routerLink: "dashboard" + }; this.serverDashboard = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.dashboard") : "", icon: "pi pi-th-large", @@ -74,7 +79,7 @@ export class SidebarService { }; this.serverProfile = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.profile") : "", - icon: "pi pi-user", + icon: "pi pi-id-card", routerLink: `server/${this.server$.value?.id}/members/${user?.id}` }; this.serverMembers = { @@ -91,14 +96,25 @@ export class SidebarService { routerLink: `server/${this.server$.value?.id}/auto-roles` }; + this.serverLevels = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.levels") : "", + icon: "pi pi-book", + visible: true, + routerLink: `server/${this.server$.value?.id}/levels` + }; + this.serverMenu = { label: this.isSidebarOpen ? this.server$.value?.name : "", icon: "pi pi-server", visible: false, expanded: true, - items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles] + items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels] + }; + this.adminConfig = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", + icon: "pi pi-cog", + routerLink: "/admin/settings" }; - this.adminConfig = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", icon: "pi pi-cog", routerLink: "/admin/settings" }; this.adminUsers = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.auth_user_list") : "", icon: "pi pi-user-edit", @@ -126,6 +142,7 @@ export class SidebarService { this.serverMenu.visible = true; this.serverMembers.visible = !!user?.isModerator; this.serverAutoRoles.visible = !!user?.isAdmin; + this.serverLevels.visible = !!user?.isAdmin; } else { this.serverMenu.visible = false; } diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 53632ad2..b36b602b 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -11,6 +11,7 @@ "dashboard": "Dashboard", "profile": "Dein Profil", "members": "Mitglieder", + "levels": "Level", "auto_roles": "Auto Rollen" }, "server_empty": "Kein Server ausgewählt", @@ -281,6 +282,27 @@ "auto_role_rule_delete_failed_d": "Die Löschung der Auto Rollen Regel {{id}} ist fehlgeschlagen!" } } + }, + "levels": { + "header": "Level", + "reset_filters": "Filter zurücksetzen", + "of": "von", + "add": "Hinzufügen", + "levels": "Level", + "headers": { + "id": "Id", + "name": "Name", + "color": "Farbe", + "min_xp": "Min. XP", + "permissions": "Rechte" + }, + "no_entries_found": "Keine Einträge gefunden", + "message": { + "level_changed": "Level geändert", + "level_changed_d": "Level {{name}} erfolgreich geändert", + "level_change_failed": "Level Änderung fehlgeschlagen", + "level_change_failed_d": "Level {{name}} konnte nicht geändert werden!" + } } }, "user-list": {}, From 15214b1c998217f7c8f91aaac3df617922984a13 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 20 Feb 2023 20:30:43 +0100 Subject: [PATCH 2/6] Fixed user filter #133 --- .../app/modules/view/server/members/members.component.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts index 19ddeebe..a81cd7c9 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.ts +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -18,6 +18,7 @@ import { Mutations } from "../../../../models/graphql/mutations.model"; import { throwError } from "rxjs"; import { UpdateUserMutationResult } from "../../../../models/graphql/result.model"; import { ActivatedRoute } from "@angular/router"; +import { Level } from "../../../../models/data/level.model"; @Component({ selector: "app-members", @@ -64,7 +65,7 @@ export class MembersComponent implements OnInit { discordId: FormControl, name: FormControl, leftServer: FormControl, - level: FormControl + level: FormControl }>; filter: UserFilter = {}; @@ -130,7 +131,7 @@ export class MembersComponent implements OnInit { discordId: new FormControl(null), name: [""], leftServer: new FormControl(null), - level: new FormControl(null) + level: new FormControl(null) }); this.filterForm.valueChanges.pipe( @@ -162,7 +163,7 @@ export class MembersComponent implements OnInit { if (changes.level) { this.filter.level = { - id: changes.level + id: changes.level.id }; } else { this.filter.level = undefined; From e463b19a736e86efb330d28ef3a926add2996a77 Mon Sep 17 00:00:00 2001 From: Jonas Drescher Date: Mon, 20 Feb 2023 22:46:01 +0100 Subject: [PATCH 3/6] added level table --- kdb-web/src/app/models/data/level.model.ts | 6 +- .../src/app/models/graphql/mutations.model.ts | 42 +++++ .../src/app/models/graphql/result.model.ts | 9 + .../components/levels/levels.component.html | 25 ++- .../components/levels/levels.component.ts | 154 ++++++++++++++++-- .../server/members/members.component.html | 23 ++- .../view/server/members/members.component.ts | 3 +- kdb-web/src/assets/i18n/de.json | 20 ++- 8 files changed, 240 insertions(+), 42 deletions(-) diff --git a/kdb-web/src/app/models/data/level.model.ts b/kdb-web/src/app/models/data/level.model.ts index 932070a7..f747628f 100644 --- a/kdb-web/src/app/models/data/level.model.ts +++ b/kdb-web/src/app/models/data/level.model.ts @@ -1,5 +1,5 @@ -import { Data } from "./data.model"; -import { Server, ServerFilter } from "./server.model"; +import {Data} from "./data.model"; +import {Server, ServerFilter} from "./server.model"; export interface Level extends Data { id?: number; @@ -12,6 +12,6 @@ export interface Level extends Data { export interface LevelFilter { id?: number; - name?: String; + name?: string; server?: ServerFilter; } diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index 4d10e87d..0cba6ef3 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -79,4 +79,46 @@ export class Mutations { } } `; + + static createLevel = ` + mutation createLevel($name: String, $color: String, $minXp: Int, $permissions: String, $serverId: ID) { + level { + createLevel(input: { name: $name, color: $color, minXp: $minXp, permissions: $permissions, serverId: $serverId}) { + id + name + color + minXp + permissions + server { + id + } + } + } + } + `; + + static updateLevel = ` + mutation updateLevel($id: ID, $name: String, $color: String, $minXp: Int, $permissions: String) { + level { + updateLevel(input: { id: $id, name: $name, color: $color, minXp: $minXp, permissions: $permissions }) { + id + name + color + minXp + permissions + } + } + } + `; + + static deleteLevel = ` + mutation deleteLevel($id: ID) { + level { + deleteLevel(id: $id) { + id + name + } + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts index 5ad5cd8a..bf3b660e 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -1,5 +1,6 @@ import { User } from "../data/user.model"; import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; +import { Level } from "../data/level.model"; export interface GraphQLResult { data: any; @@ -31,3 +32,11 @@ export interface AutoRoleRuleMutationResult { deleteAutoRoleRule?: AutoRoleRule }; } + +export interface LevelMutationResult { + level: { + createLevel?: Level + updateLevel?: Level + deleteLevel?: Level + }; +} diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html index 94888113..8e42c31c 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html @@ -18,10 +18,10 @@
@@ -121,7 +121,7 @@ - {{level.name}} + {{level.name}} @@ -132,7 +132,7 @@ - {{level.color}} + {{level.color}} @@ -143,7 +143,7 @@ - {{level.minXp}} + {{level.minXp}} @@ -154,7 +154,7 @@ - {{level.permissions}} + {{level.permissions}} @@ -182,18 +182,17 @@ -
- + (click)="onRowEditInit(dt, level, ri)"> + + icon="pi pi-check-circle" (click)="onRowEditSave(dt, level, ri)"> + icon="pi pi-times-circle" (click)="onRowEditCancel(ri)">
@@ -202,7 +201,7 @@ - {{'view.server.auto_roles.no_entries_found' | translate}} + {{'view.server.levels.no_entries_found' | translate}} diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts index d2b8cdaa..65052d71 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts @@ -13,8 +13,13 @@ import {Sort, SortDirection} from "../../../../../../models/graphql/filter/sort. import {Level, LevelFilter} from "../../../../../../models/data/level.model"; import {LevelListQuery} from "../../../../../../models/graphql/query.model"; import {Queries} from "../../../../../../models/graphql/queries.model"; -import {debounceTime} from "rxjs/operators"; +import {catchError, debounceTime} from "rxjs/operators"; import {LazyLoadEvent} from "primeng/api"; +import {Table} from "primeng/table"; +import {User} from "../../../../../../models/data/user.model"; +import {LevelMutationResult, UpdateUserMutationResult} from "../../../../../../models/graphql/result.model"; +import {Mutations} from "../../../../../../models/graphql/mutations.model"; +import {throwError} from "rxjs"; @Component({ selector: 'app-levels', @@ -23,12 +28,12 @@ import {LazyLoadEvent} from "primeng/api"; }) export class LevelsComponent { - levels!: Level[]; - loading = true; + public levels!: Level[]; + public loading = true; - isEditingNew: boolean = false; + public isEditingNew: boolean = false; - filterForm!: FormGroup<{ + public filterForm!: FormGroup<{ id: FormControl, name: FormControl, color: FormControl, @@ -36,17 +41,19 @@ export class LevelsComponent { permissions: FormControl, }>; - filter: LevelFilter = {}; - page: Page = { + public filter: LevelFilter = {}; + public page: Page = { pageSize: undefined, pageIndex: undefined }; - sort: Sort = { + public sort: Sort = { sortColumn: undefined, sortDirection: undefined }; - totalRecords!: number; + public totalRecords!: number; + + public clonedLevels: { [s: string]: Level; } = {}; public constructor( private authService: AuthService, @@ -67,7 +74,7 @@ export class LevelsComponent { this.loadNextPage(); } - public loadNextPage() { + public loadNextPage(): void { this.loading = true; this.data.query(Queries.levelQuery, { filter: this.filter, page: this.page, sort: this.sort @@ -80,7 +87,7 @@ export class LevelsComponent { }); } - public setFilterForm() { + public setFilterForm(): void { this.filterForm = this.fb.group({ id: new FormControl(null), name: new FormControl(null), @@ -114,7 +121,13 @@ export class LevelsComponent { }); } - public nextPage(event: LazyLoadEvent) { + public newLevelTemplate: Level = { + id: 0, + createdAt: "", + modifiedAt: "" + }; + + public nextPage(event: LazyLoadEvent): void { this.page.pageSize = event.rows ?? 0; if (event.first != null && event.rows != null) this.page.pageIndex = event.first / event.rows; @@ -124,4 +137,121 @@ export class LevelsComponent { this.loadNextPage(); } + public resetFilters(): void { + this.filterForm.reset(); + } + + public onRowEditInit(table: Table, user: User, index: number): void { + this.clonedLevels[index] = {...user}; + } + + public onRowEditSave(table: Table, newLevel: Level, index: number): void { + // const oldUser = this.clonedUsers[index]; + // delete this.clonedUsers[index]; + + // if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) { + // console.log(1, oldUser, newUser, JSON.stringify(oldUser) === JSON.stringify(newUser), !this.isEditingNew); + // return; + // } + + if (this.isEditingNew && JSON.stringify(newLevel) === JSON.stringify(this.newLevelTemplate)) { + this.isEditingNew = false; + this.levels.splice(index, 1); + return; + } + + if (!newLevel.id && !this.isEditingNew || !newLevel.minXp && !newLevel?.name && !newLevel?.permissions) { + return; + } + + if (this.isEditingNew) { + this.spinner.showSpinner(); + this.data.mutation(Mutations.createLevel, { + name: newLevel.name, + color: newLevel.color, + minXp: newLevel.minXp, + permissions: newLevel.permissions, + serverId: this.sidebar.server$.value?.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.levels.message.level_create_failed"), this.translate.instant("view.server.levels.message.level_create_failed_d")); + return throwError(err); + })).subscribe(result => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.levels.message.level_create"), this.translate.instant("view.server.levels.message.level_create_d", {name: result.level.createLevel?.name})); + this.loadNextPage(); + }); + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateLevel, { + id: newLevel.id, + name: newLevel.name, + color: newLevel.color, + minXp: newLevel.minXp, + permissions: newLevel.permissions, + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.levels.message.level_update_failed"), this.translate.instant("view.server.levels.message.level_update_failed_d", {name: newLevel.name})); + return throwError(err); + })).subscribe(_ => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.levels.message.level_update"), this.translate.instant("view.server.levels.message.level_update_d", {name: newLevel.name})); + this.loadNextPage(); + }); + + } + + public onRowEditCancel(index: number): void { + if (this.isEditingNew) { + this.levels.splice(index, 1); + delete this.clonedLevels[index]; + this.isEditingNew = false; + return; + } + + this.levels[index] = this.clonedLevels[index]; + delete this.clonedLevels[index]; + } + + public deleteLevel(level: Level): void { + this.confirmDialog.confirmDialog( + this.translate.instant("view.server.levels.message.level_delete"), this.translate.instant("view.server.levels.message.level_delete_q", {name: level.name}), + () => { + this.spinner.showSpinner(); + this.data.mutation(Mutations.deleteLevel, { + id: level.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failedd", {name: level.name})); + return throwError(err); + })).subscribe(l => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.levels.message.level_deleted"), this.translate.instant("view.server.levels.message.level_deleted_d", {name: level.name})); + this.loadNextPage(); + }); + }); + } + + public addLevel(table: Table): void { + const newLevel = JSON.parse(JSON.stringify(this.newLevelTemplate)); + newLevel.id = Math.max.apply(Math, this.levels.map(l => { + return l.id ?? 0; + })) + 1; + + this.levels.push(newLevel); + + table.initRowEdit(newLevel); + + const index = this.levels.findIndex(l => l.id == newLevel.id); + this.onRowEditInit(table, newLevel, index); + + this.isEditingNew = true; + } + } diff --git a/kdb-web/src/app/modules/view/server/members/members.component.html b/kdb-web/src/app/modules/view/server/members/members.component.html index 1c120f02..9fe65927 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.html +++ b/kdb-web/src/app/modules/view/server/members/members.component.html @@ -97,29 +97,34 @@
- +
- +
- +
- +
- +
@@ -194,7 +199,8 @@ - + {{member.level.name}} @@ -225,12 +231,13 @@
- + + icon="pi pi-times-circle" (click)="onRowEditCancel(ri)">
diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts index a81cd7c9..3728cc50 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.ts +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -88,6 +88,7 @@ export class MembersComponent implements OnInit { private fb: FormBuilder, private translate: TranslateService, private data: DataService, + private sidebar: SidebarService, private route: ActivatedRoute ) { } @@ -234,7 +235,7 @@ export class MembersComponent implements OnInit { } - onRowEditCancel(user: User, index: number) { + onRowEditCancel(index: number) { if (this.isEditingNew) { this.members.splice(index, 1); delete this.clonedUsers[index]; diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index b36b602b..26ceea96 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -221,7 +221,7 @@ "message": { "user_changed": "Benutzer geändert", "user_changed_d": "Benutzer {{name}} erfolgreich geändert", - "user_change_failed": "Benutzer änderung fehlgeschlagen", + "user_change_failed": "Benutzer Änderung fehlgeschlagen", "user_change_failed_d": "Benutzer {{name}} konnte nicht geändert werden!" } }, @@ -298,10 +298,20 @@ }, "no_entries_found": "Keine Einträge gefunden", "message": { - "level_changed": "Level geändert", - "level_changed_d": "Level {{name}} erfolgreich geändert", - "level_change_failed": "Level Änderung fehlgeschlagen", - "level_change_failed_d": "Level {{name}} konnte nicht geändert werden!" + "level_create": "Level erstellt", + "level_create_d": "Level {{name}} erfolgreich erstellt", + "level_create_failed": "Level Erstellung fehlgeschlagen", + "level_create_failed_d": "Die Erstellung des Levels ist fehlgeschlagen!", + "level_update": "Level bearbeitet", + "level_update_d": "Level {{name}} erfolgreich bearbeitet", + "level_update_failed": "Level Bearbeitung fehlgeschlagen", + "level_update_failed_d": "Die Bearbeitung des Levels ist fehlgeschlagen!", + "level_delete": "Level löschen", + "level_delete_q": "Sind Sie sich sicher, dass Sie das Level {{name}} löschen möchten?", + "level_deleted": "Level gelöscht", + "level_deleted_d": "Level {{name}} erfolgreich gelöscht", + "level_delete_failed": "Level Löschung fehlgeschlagen", + "level_delete_failed_d": "Die Löschung des Levels {{name}} ist fehlgeschlagen!" } } }, From f3024d2ea528c3a60e0ceb80e5e474c8caf01e56 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Feb 2023 17:24:18 +0100 Subject: [PATCH 4/6] Fixed changes of rebase #133 --- .../mutations/auto_role_mutation.py | 6 +- kdb-web/package.json | 2 +- .../auto-roles-rules.component.ts | 5 +- .../auto-roles/auto-roles.component.ts | 2 + .../components/levels/levels.component.ts | 77 ++++++++++--------- .../view/server/members/members.component.ts | 1 - kdb-web/src/assets/config.json | 2 +- 7 files changed, 49 insertions(+), 46 deletions(-) diff --git a/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py b/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py index 28bd9b2d..d936fc6e 100644 --- a/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py @@ -33,9 +33,9 @@ class AutoRoleMutation(QueryABC): def get_new(x: AutoRole): return ( - x.server.id == input["serverId"] - and x.discord_channel_id == input["channelId"] - and x.discord_message_id == input["messageId"] + x.server.id == int(input["serverId"]) + and x.discord_channel_id == int(input["channelId"]) + and x.discord_message_id == int(input["messageId"]) ) return self._auto_roles.get_auto_roles_by_server_id(auto_role.server.id).where(get_new).last() diff --git a/kdb-web/package.json b/kdb-web/package.json index 13ddc1d0..7d88a478 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "1.0.0", + "version": "1.0.dev133", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts index 2b6a0251..2c351051 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts @@ -121,7 +121,7 @@ export class AutoRolesRulesComponent implements OnInit { public loadNextPage(): void { this.loading = true; this.data.query(Queries.autoRoleRulesQuery, { - id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort + serverId: this.sidebar.server$.value?.id, autoRoleId: this.autoRoleId, filter: this.filter, page: this.page, sort: this.sort }, (x: { servers: Server[] }) => { if (!x.servers[0].autoRoles || x.servers[0].autoRoles?.length == 0) { @@ -212,13 +212,14 @@ export class AutoRolesRulesComponent implements OnInit { roleId: newAutoRoleRule.roleId } ).pipe(catchError(err => { + this.isEditingNew = false; this.spinner.hideSpinner(); this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed_d")); return throwError(err); })).subscribe(result => { + this.isEditingNew = false; this.spinner.hideSpinner(); this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_created"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_d", { id: result.autoRoleRule.createAutoRoleRule?.id })); - this.isEditingNew = false; this.loadNextPage(); }); return; diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts index 03d6b2f8..838a8c59 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts @@ -195,10 +195,12 @@ export class AutoRolesComponent implements OnInit { messageId: newAutoRole.messageId } ).pipe(catchError(err => { + this.isEditingNew = false; this.spinner.hideSpinner(); this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_create_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_create_failed_d")); return throwError(err); })).subscribe(result => { + this.isEditingNew = false; this.spinner.hideSpinner(); this.toastService.success(this.translate.instant("view.server.auto_roles.message.auto_role_created"), this.translate.instant("view.server.auto_roles.message.auto_role_create_d", { id: result.autoRole.createAutoRole?.id })); this.loadNextPage(); diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts index 65052d71..9ab6b264 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts @@ -1,30 +1,30 @@ -import {Component} from '@angular/core'; -import {AuthService} from "../../../../../../services/auth/auth.service"; -import {SpinnerService} from "../../../../../../services/spinner/spinner.service"; -import {ToastService} from "../../../../../../services/toast/toast.service"; -import {ConfirmationDialogService} from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; -import {FormBuilder, FormControl, FormGroup} from "@angular/forms"; -import {TranslateService} from "@ngx-translate/core"; -import {DataService} from "../../../../../../services/data/data.service"; -import {SidebarService} from "../../../../../../services/sidebar/sidebar.service"; -import {ActivatedRoute} from "@angular/router"; -import {Page} from "../../../../../../models/graphql/filter/page.model"; -import {Sort, SortDirection} from "../../../../../../models/graphql/filter/sort.model"; -import {Level, LevelFilter} from "../../../../../../models/data/level.model"; -import {LevelListQuery} from "../../../../../../models/graphql/query.model"; -import {Queries} from "../../../../../../models/graphql/queries.model"; -import {catchError, debounceTime} from "rxjs/operators"; -import {LazyLoadEvent} from "primeng/api"; -import {Table} from "primeng/table"; -import {User} from "../../../../../../models/data/user.model"; -import {LevelMutationResult, UpdateUserMutationResult} from "../../../../../../models/graphql/result.model"; -import {Mutations} from "../../../../../../models/graphql/mutations.model"; -import {throwError} from "rxjs"; +import { Component } from "@angular/core"; +import { AuthService } from "../../../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { TranslateService } from "@ngx-translate/core"; +import { DataService } from "../../../../../../services/data/data.service"; +import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; +import { ActivatedRoute } from "@angular/router"; +import { Page } from "../../../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; +import { Level, LevelFilter } from "../../../../../../models/data/level.model"; +import { LevelListQuery } from "../../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { catchError, debounceTime } from "rxjs/operators"; +import { LazyLoadEvent } from "primeng/api"; +import { Table } from "primeng/table"; +import { User } from "../../../../../../models/data/user.model"; +import { LevelMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; +import { throwError } from "rxjs"; @Component({ - selector: 'app-levels', - templateUrl: './levels.component.html', - styleUrls: ['./levels.component.scss'] + selector: "app-levels", + templateUrl: "./levels.component.html", + styleUrls: ["./levels.component.scss"] }) export class LevelsComponent { @@ -68,10 +68,10 @@ export class LevelsComponent { } public ngOnInit(): void { - this.data.getServerFromRoute(this.route); - - this.setFilterForm(); - this.loadNextPage(); + this.data.getServerFromRoute(this.route).then(server => { + this.setFilterForm(); + this.loadNextPage(); + }); } public loadNextPage(): void { @@ -93,7 +93,7 @@ export class LevelsComponent { name: new FormControl(null), color: new FormControl(null), min_xp: new FormControl(null), - permissions: new FormControl(null), + permissions: new FormControl(null) }); this.filterForm.valueChanges.pipe( @@ -142,7 +142,7 @@ export class LevelsComponent { } public onRowEditInit(table: Table, user: User, index: number): void { - this.clonedLevels[index] = {...user}; + this.clonedLevels[index] = { ...user }; } public onRowEditSave(table: Table, newLevel: Level, index: number): void { @@ -174,13 +174,14 @@ export class LevelsComponent { serverId: this.sidebar.server$.value?.id } ).pipe(catchError(err => { + this.isEditingNew = false; this.spinner.hideSpinner(); this.toastService.error(this.translate.instant("view.server.levels.message.level_create_failed"), this.translate.instant("view.server.levels.message.level_create_failed_d")); return throwError(err); })).subscribe(result => { this.isEditingNew = false; this.spinner.hideSpinner(); - this.toastService.success(this.translate.instant("view.server.levels.message.level_create"), this.translate.instant("view.server.levels.message.level_create_d", {name: result.level.createLevel?.name})); + this.toastService.success(this.translate.instant("view.server.levels.message.level_create"), this.translate.instant("view.server.levels.message.level_create_d", { name: result.level.createLevel?.name })); this.loadNextPage(); }); return; @@ -192,15 +193,15 @@ export class LevelsComponent { name: newLevel.name, color: newLevel.color, minXp: newLevel.minXp, - permissions: newLevel.permissions, + permissions: newLevel.permissions } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.levels.message.level_update_failed"), this.translate.instant("view.server.levels.message.level_update_failed_d", {name: newLevel.name})); + this.toastService.error(this.translate.instant("view.server.levels.message.level_update_failed"), this.translate.instant("view.server.levels.message.level_update_failed_d", { name: newLevel.name })); return throwError(err); })).subscribe(_ => { this.spinner.hideSpinner(); - this.toastService.success(this.translate.instant("view.server.levels.message.level_update"), this.translate.instant("view.server.levels.message.level_update_d", {name: newLevel.name})); + this.toastService.success(this.translate.instant("view.server.levels.message.level_update"), this.translate.instant("view.server.levels.message.level_update_d", { name: newLevel.name })); this.loadNextPage(); }); @@ -220,7 +221,7 @@ export class LevelsComponent { public deleteLevel(level: Level): void { this.confirmDialog.confirmDialog( - this.translate.instant("view.server.levels.message.level_delete"), this.translate.instant("view.server.levels.message.level_delete_q", {name: level.name}), + this.translate.instant("view.server.levels.message.level_delete"), this.translate.instant("view.server.levels.message.level_delete_q", { name: level.name }), () => { this.spinner.showSpinner(); this.data.mutation(Mutations.deleteLevel, { @@ -228,11 +229,11 @@ export class LevelsComponent { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failedd", {name: level.name})); + this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failedd", { name: level.name })); return throwError(err); })).subscribe(l => { this.spinner.hideSpinner(); - this.toastService.success(this.translate.instant("view.server.levels.message.level_deleted"), this.translate.instant("view.server.levels.message.level_deleted_d", {name: level.name})); + this.toastService.success(this.translate.instant("view.server.levels.message.level_deleted"), this.translate.instant("view.server.levels.message.level_deleted_d", { name: level.name })); this.loadNextPage(); }); }); diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts index 3728cc50..a684cb33 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.ts +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -88,7 +88,6 @@ export class MembersComponent implements OnInit { private fb: FormBuilder, private translate: TranslateService, private data: DataService, - private sidebar: SidebarService, private route: ActivatedRoute ) { } diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index c055d5cb..89caec01 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -3,7 +3,7 @@ "WebVersion": { "Major": "1", "Minor": "0", - "Micro": "0" + "Micro": "dev133" }, "Themes": [ { From 23ee963d654659b8e90404aed3fbffaadc0c5896 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Feb 2023 17:29:08 +0100 Subject: [PATCH 5/6] Fixed formattings #133 --- .../server/members/members.component.html | 21 +++++++------------ .../view/server/server-routing.module.ts | 20 +++++++++--------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/kdb-web/src/app/modules/view/server/members/members.component.html b/kdb-web/src/app/modules/view/server/members/members.component.html index 9fe65927..ab005b5f 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.html +++ b/kdb-web/src/app/modules/view/server/members/members.component.html @@ -97,34 +97,29 @@
- +
- +
- +
- +
- +
@@ -169,7 +164,8 @@ + inputId="minmax-buttons"> + {{member.xp}} @@ -199,8 +195,7 @@ - + {{member.level.name}} diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts index f51ea000..147c40ea 100644 --- a/kdb-web/src/app/modules/view/server/server-routing.module.ts +++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts @@ -1,15 +1,15 @@ -import {NgModule} from "@angular/core"; -import {RouterModule, Routes} from "@angular/router"; -import {ServerDashboardComponent} from "./server-dashboard/server-dashboard.component"; -import {ProfileComponent} from "./profile/profile.component"; -import {MembersComponent} from "./members/members.component"; +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component"; +import { ProfileComponent } from "./profile/profile.component"; +import { MembersComponent } from "./members/members.component"; const routes: Routes = [ - {path: '', component: ServerDashboardComponent}, - {path: 'members', component: MembersComponent}, - {path: 'members/:memberId', component: ProfileComponent}, - {path: 'auto-roles', loadChildren: () => import('./auto-role/auto-role.module').then(m => m.AutoRoleModule)}, - {path: 'levels', loadChildren: () => import('./levels/levels.module').then(m => m.LevelsModule)}, + { path: "", component: ServerDashboardComponent }, + { path: "members", component: MembersComponent }, + { path: "members/:memberId", component: ProfileComponent }, + { path: "auto-roles", loadChildren: () => import("./auto-role/auto-role.module").then(m => m.AutoRoleModule) }, + { path: "levels", loadChildren: () => import("./levels/levels.module").then(m => m.LevelsModule) } ]; @NgModule({ From 9ea1b1485227f3eb263d4750d218e055890cef91 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Feb 2023 22:44:42 +0100 Subject: [PATCH 6/6] Optimized code #133 --- kdb-web/src/app/app.component.ts | 37 +++++++++------ .../components/sidebar/sidebar.component.ts | 19 ++++++-- kdb-web/src/app/models/data/data.model.ts | 4 +- kdb-web/src/app/models/data/discord.model.ts | 6 +-- .../auth-user/auth-user.component.ts | 7 ++- .../dashboard/dashboard.component.ts | 46 +++++++++++-------- .../auto-roles-rules.component.ts | 12 +++-- .../auto-roles/auto-roles.component.ts | 12 +++-- .../components/levels/levels.component.html | 2 +- .../components/levels/levels.component.ts | 22 ++++++--- .../view/server/members/members.component.ts | 6 ++- kdb-web/src/app/services/data/data.service.ts | 2 +- .../app/services/sidebar/sidebar.service.ts | 21 ++++----- .../src/app/services/theme/theme.service.ts | 1 - kdb-web/src/assets/i18n/de.json | 3 +- 15 files changed, 121 insertions(+), 79 deletions(-) diff --git a/kdb-web/src/app/app.component.ts b/kdb-web/src/app/app.component.ts index 8b919479..ce1e4bb1 100644 --- a/kdb-web/src/app/app.component.ts +++ b/kdb-web/src/app/app.component.ts @@ -1,29 +1,27 @@ -import { Component, OnInit } from "@angular/core"; +import { Component, OnDestroy, OnInit } from "@angular/core"; import { TranslateService } from "@ngx-translate/core"; import { PrimeNGConfig } from "primeng/api"; import { AuthService } from "./services/auth/auth.service"; import { SocketService } from "./services/socket/socket.service"; import { ThemeService } from "./services/theme/theme.service"; -import { ActivatedRoute, Router } from "@angular/router"; -import { SpinnerService } from "./services/spinner/spinner.service"; -import { DataService } from "./services/data/data.service"; -import { SidebarService } from "./services/sidebar/sidebar.service"; -import { Server } from "./models/data/server.model"; -import { Queries } from "./models/graphql/queries.model"; -import { Query } from "./models/graphql/query.model"; +import { Subject } from "rxjs"; +import { Themes } from "./models/view/themes.enum"; +import { takeUntil } from "rxjs/operators"; @Component({ selector: "app-root", templateUrl: "./app.component.html", styleUrls: ["./app.component.scss"] }) -export class AppComponent implements OnInit { +export class AppComponent implements OnInit, OnDestroy { - themeName!: string; - sidebarWidth!: string; + themeName: string = Themes.Default; + sidebarWidth: string = '175px'; isLoggedIn: boolean = false; + private unsubscriber = new Subject(); + constructor( private authService: AuthService, private themeService: ThemeService, @@ -31,13 +29,19 @@ export class AppComponent implements OnInit { private translateService: TranslateService, private config: PrimeNGConfig, ) { - this.themeService.sidebarWidth$.subscribe(value => { + this.themeService.sidebarWidth$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.sidebarWidth = value; }); - this.themeService.themeName$.subscribe(value => { + this.themeService.themeName$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.themeName = value; }); - this.authService.isLoggedIn$.subscribe(value => { + this.authService.isLoggedIn$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.isLoggedIn = value; }); } @@ -49,6 +53,11 @@ export class AppComponent implements OnInit { this.socket.startSocket(); } + ngOnDestroy() { + this.unsubscriber.next(); + this.unsubscriber.unsubscribe(); + } + loadLang(): void { let lang = localStorage.getItem(`default_lang`); if (!lang) { diff --git a/kdb-web/src/app/components/sidebar/sidebar.component.ts b/kdb-web/src/app/components/sidebar/sidebar.component.ts index 955bec11..82df2511 100644 --- a/kdb-web/src/app/components/sidebar/sidebar.component.ts +++ b/kdb-web/src/app/components/sidebar/sidebar.component.ts @@ -1,19 +1,21 @@ -import { Component, OnInit } from "@angular/core"; +import { Component, OnDestroy, OnInit } from "@angular/core"; import { TranslateService } from "@ngx-translate/core"; import { MenuItem } from "primeng/api"; 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"; +import { Subject } from "rxjs"; +import { takeUntil } from "rxjs/operators"; @Component({ selector: "app-sidebar", templateUrl: "./sidebar.component.html", styleUrls: ["./sidebar.component.scss"] }) -export class SidebarComponent implements OnInit { +export class SidebarComponent implements OnInit, OnDestroy { - isSidebarOpen!: boolean; - menuItems!: MenuItem[]; + menuItems: MenuItem[]= []; + private unsubscriber = new Subject(); constructor( private authService: AuthService, @@ -21,7 +23,9 @@ export class SidebarComponent implements OnInit { private themeService: ThemeService, private sidebar: SidebarService ) { - this.sidebar.menuItems$.subscribe(value => { + this.sidebar.menuItems$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.menuItems = value; }); } @@ -30,4 +34,9 @@ export class SidebarComponent implements OnInit { this.themeService.loadMenu(); } + ngOnDestroy() { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + } diff --git a/kdb-web/src/app/models/data/data.model.ts b/kdb-web/src/app/models/data/data.model.ts index 2a6a82b8..dcd3c42c 100644 --- a/kdb-web/src/app/models/data/data.model.ts +++ b/kdb-web/src/app/models/data/data.model.ts @@ -1,4 +1,4 @@ export interface Data { - createdAt: string; - modifiedAt: string; + createdAt?: string; + modifiedAt?: string; } diff --git a/kdb-web/src/app/models/data/discord.model.ts b/kdb-web/src/app/models/data/discord.model.ts index 6e8bc0b0..680225ef 100644 --- a/kdb-web/src/app/models/data/discord.model.ts +++ b/kdb-web/src/app/models/data/discord.model.ts @@ -2,9 +2,9 @@ export interface Guild { id?: string; name?: string; - channels: [Channel] - roles: [Role] - emojis: [Emoji] + channels: Channel[]; + roles: Role[]; + emojis: Emoji[]; } export interface Channel { diff --git a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts index b4ac6706..390b4531 100644 --- a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts +++ b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { catchError, debounceTime } from "rxjs/operators"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; import { AuthRoles } from "src/app/models/auth/auth-roles.enum"; import { AuthUserDTO } from "src/app/models/auth/auth-user.dto"; import { AuthService } from "src/app/services/auth/auth.service"; @@ -13,7 +13,7 @@ import { ErrorDTO } from "src/app/models/error/error-dto"; import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; import { AuthUserSelectCriterion } from "src/app/models/selection/auth-user/auth-user-select-criterion.dto"; import { LazyLoadEvent } from "primeng/api"; -import { throwError } from "rxjs"; +import { Subject, throwError } from "rxjs"; import { TranslateService } from "@ngx-translate/core"; @@ -62,6 +62,8 @@ export class AuthUserComponent implements OnInit { searchCriterions!: AuthUserSelectCriterion; totalRecords!: number; + private unsubscriber = new Subject(); + constructor( private authService: AuthService, private spinnerService: SpinnerService, @@ -97,6 +99,7 @@ export class AuthUserComponent implements OnInit { }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(changes => { if (changes.firstName) { 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 5d266fd8..e44b0902 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 @@ -1,30 +1,30 @@ -import {Component, OnInit} from "@angular/core"; -import {FormBuilder, FormControl, FormGroup} from "@angular/forms"; -import {Router} from "@angular/router"; -import {TranslateService} from "@ngx-translate/core"; -import {debounceTime, throwError} from "rxjs"; -import {ConfirmationDialogService} from "src/app/services/confirmation-dialog/confirmation-dialog.service"; -import {DataService} from "src/app/services/data/data.service"; -import {SpinnerService} from "src/app/services/spinner/spinner.service"; -import {ToastService} from "src/app/services/toast/toast.service"; -import {Server, ServerFilter} from "../../../../../models/data/server.model"; -import {catchError} from "rxjs/operators"; -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"; +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; +import { debounceTime, Subject, throwError } from "rxjs"; +import { ConfirmationDialogService } from "src/app/services/confirmation-dialog/confirmation-dialog.service"; +import { DataService } from "src/app/services/data/data.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { Server, ServerFilter } from "../../../../../models/data/server.model"; +import { catchError, takeUntil } from "rxjs/operators"; +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", templateUrl: "./dashboard.component.html", styleUrls: ["./dashboard.component.scss"] }) -export class DashboardComponent implements OnInit { +export class DashboardComponent implements OnInit, OnDestroy { servers: Server[] = []; - totalRecords!: number; + totalRecords: number = 0; filter: ServerFilter = {}; @@ -33,12 +33,14 @@ export class DashboardComponent implements OnInit { pageSize: 10 }; - sort!: Sort; + sort: Sort = {}; filterForm!: FormGroup<{ name: FormControl, }>; + private unsubscriber = new Subject(); + constructor( private data: DataService, private spinnerService: SpinnerService, @@ -58,12 +60,18 @@ export class DashboardComponent implements OnInit { this.loadNextPage(); } + public ngOnDestroy() { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + setFilterForm() { this.filterForm = this.fb.group({ name: new FormControl(null) }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(async changes => { if (changes.name == "") { diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts index 2c351051..62a5de17 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts @@ -17,11 +17,11 @@ import { SidebarService } from "../../../../../../services/sidebar/sidebar.servi import { AutoRoleRuleQuery, SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; import { Queries } from "../../../../../../models/graphql/queries.model"; import { Server } from "../../../../../../models/data/server.model"; -import { catchError, debounceTime } from "rxjs/operators"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; import { Table } from "primeng/table"; import { AutoRoleMutationResult, AutoRoleRuleMutationResult } from "../../../../../../models/graphql/result.model"; import { Mutations } from "../../../../../../models/graphql/mutations.model"; -import { throwError } from "rxjs"; +import { Subject, throwError } from "rxjs"; @Component({ selector: "app-auto-roles-rules", @@ -30,8 +30,8 @@ import { throwError } from "rxjs"; }) export class AutoRolesRulesComponent implements OnInit { - rules!: AutoRoleRule[]; - guild!: Guild; + rules: AutoRoleRule[] = []; + guild: Guild = { channels: [], emojis: [], roles: [] }; emojis: MenuItem[] = []; roles: MenuItem[] = []; loading = true; @@ -63,7 +63,8 @@ export class AutoRolesRulesComponent implements OnInit { sortDirection: undefined }; - totalRecords!: number; + totalRecords: number = 0; + private unsubscriber = new Subject(); constructor( private authService: AuthService, @@ -145,6 +146,7 @@ export class AutoRolesRulesComponent implements OnInit { }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(changes => { if (changes.id) { diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts index 838a8c59..1631a811 100644 --- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts @@ -14,11 +14,11 @@ import { SidebarService } from "../../../../../../services/sidebar/sidebar.servi import { ActivatedRoute } from "@angular/router"; import { AutoRoleQuery, SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; import { Queries } from "../../../../../../models/graphql/queries.model"; -import { catchError, debounceTime } from "rxjs/operators"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; import { Table } from "primeng/table"; import { AutoRoleMutationResult } from "../../../../../../models/graphql/result.model"; import { Mutations } from "../../../../../../models/graphql/mutations.model"; -import { throwError } from "rxjs"; +import { Subject, throwError } from "rxjs"; import { AutoRole, AutoRoleFilter } from "../../../../../../models/data/auto_role.model"; import { ChannelType, Guild } from "../../../../../../models/data/discord.model"; import { Server } from "../../../../../../models/data/server.model"; @@ -29,9 +29,9 @@ import { Server } from "../../../../../../models/data/server.model"; styleUrls: ["./auto-roles.component.scss"] }) export class AutoRolesComponent implements OnInit { - auto_roles!: AutoRole[]; - guild!: Guild; - channels!: MenuItem[]; + auto_roles: AutoRole[] = []; + guild: Guild = { channels: [], emojis: [], roles: [] }; + channels: MenuItem[] = []; loading = true; clonedUsers: { [s: string]: User; } = {}; @@ -61,6 +61,7 @@ export class AutoRolesComponent implements OnInit { }; totalRecords!: number; + private unsubscriber = new Subject(); constructor( private authService: AuthService, @@ -123,6 +124,7 @@ export class AutoRolesComponent implements OnInit { }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(changes => { if (changes.id) { diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html index 8e42c31c..76d01eed 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html @@ -78,7 +78,7 @@
-
{{'view.server.members.headers.actions' | translate}}
+
{{'view.server.levels.headers.actions' | translate}}
diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts index 9ab6b264..e9cead67 100644 --- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts @@ -1,4 +1,4 @@ -import { Component } from "@angular/core"; +import { Component, OnDestroy, OnInit } from "@angular/core"; import { AuthService } from "../../../../../../services/auth/auth.service"; import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; import { ToastService } from "../../../../../../services/toast/toast.service"; @@ -13,20 +13,20 @@ import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sor import { Level, LevelFilter } from "../../../../../../models/data/level.model"; import { LevelListQuery } from "../../../../../../models/graphql/query.model"; import { Queries } from "../../../../../../models/graphql/queries.model"; -import { catchError, debounceTime } from "rxjs/operators"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; import { LazyLoadEvent } from "primeng/api"; import { Table } from "primeng/table"; import { User } from "../../../../../../models/data/user.model"; import { LevelMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; import { Mutations } from "../../../../../../models/graphql/mutations.model"; -import { throwError } from "rxjs"; +import { Subject, throwError } from "rxjs"; @Component({ selector: "app-levels", templateUrl: "./levels.component.html", styleUrls: ["./levels.component.scss"] }) -export class LevelsComponent { +export class LevelsComponent implements OnInit, OnDestroy { public levels!: Level[]; public loading = true; @@ -38,7 +38,7 @@ export class LevelsComponent { name: FormControl, color: FormControl, min_xp: FormControl, - permissions: FormControl, + permissions: FormControl, }>; public filter: LevelFilter = {}; @@ -55,6 +55,8 @@ export class LevelsComponent { public clonedLevels: { [s: string]: Level; } = {}; + private unsubscriber = new Subject(); + public constructor( private authService: AuthService, private spinner: SpinnerService, @@ -74,6 +76,11 @@ export class LevelsComponent { }); } + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + public loadNextPage(): void { this.loading = true; this.data.query(Queries.levelQuery, { @@ -93,10 +100,11 @@ export class LevelsComponent { name: new FormControl(null), color: new FormControl(null), min_xp: new FormControl(null), - permissions: new FormControl(null) + permissions: new FormControl(null) }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(changes => { if (changes.id) { @@ -229,7 +237,7 @@ export class LevelsComponent { } ).pipe(catchError(err => { this.spinner.hideSpinner(); - this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failedd", { name: level.name })); + this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failed_d", { name: level.name })); return throwError(err); })).subscribe(l => { this.spinner.hideSpinner(); diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts index a684cb33..a4f3e004 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.ts +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -5,7 +5,7 @@ import { SpinnerService } from "../../../../services/spinner/spinner.service"; import { ToastService } from "../../../../services/toast/toast.service"; import { ConfirmationDialogService } from "../../../../services/confirmation-dialog/confirmation-dialog.service"; import { TranslateService } from "@ngx-translate/core"; -import { catchError, debounceTime } from "rxjs/operators"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; import { LazyLoadEvent, MenuItem } from "primeng/api"; import { Table } from "primeng/table"; import { User, UserFilter } from "../../../../models/data/user.model"; @@ -15,7 +15,7 @@ import { DataService } from "../../../../services/data/data.service"; import { Page } from "../../../../models/graphql/filter/page.model"; import { Sort, SortDirection } from "../../../../models/graphql/filter/sort.model"; import { Mutations } from "../../../../models/graphql/mutations.model"; -import { throwError } from "rxjs"; +import { Subject, throwError } from "rxjs"; import { UpdateUserMutationResult } from "../../../../models/graphql/result.model"; import { ActivatedRoute } from "@angular/router"; import { Level } from "../../../../models/data/level.model"; @@ -79,6 +79,7 @@ export class MembersComponent implements OnInit { }; totalRecords!: number; + private unsubscriber = new Subject(); constructor( private authService: AuthService, @@ -135,6 +136,7 @@ export class MembersComponent implements OnInit { }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(changes => { if (changes.id) { diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts index 6112d96e..54d13057 100644 --- a/kdb-web/src/app/services/data/data.service.ts +++ b/kdb-web/src/app/services/data/data.service.ts @@ -28,7 +28,7 @@ export class DataService { public getServerFromRoute(route: ActivatedRoute): Promise { return new Promise((resolve, reject) => { this.spinner.showSpinner(); - if (!route.snapshot.params["serverId"]) { + if (!route.snapshot.params["serverId"] || route.snapshot.params["serverId"] == "undefined") { this.spinner.hideSpinner(); this.router.navigate(["/dashboard"]); reject(); diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index de11122f..925e6887 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -18,17 +18,16 @@ export class SidebarService { menuItems$ = new BehaviorSubject(new Array()); server$ = new BehaviorSubject(null); - dashboard!: MenuItem; - serverDashboard!: MenuItem; - serverProfile!: MenuItem; - serverMembers!: MenuItem; - serverAutoRoles!: MenuItem; - serverAutoRoleRules!: MenuItem; - serverLevels!: MenuItem; - serverMenu!: MenuItem; - adminConfig!: MenuItem; - adminUsers!: MenuItem; - adminMenu!: MenuItem; + dashboard: MenuItem = {}; + serverDashboard: MenuItem = {}; + serverProfile: MenuItem = {}; + serverMembers: MenuItem = {}; + serverAutoRoles: MenuItem = {}; + serverLevels: MenuItem = {}; + serverMenu: MenuItem = {}; + adminConfig: MenuItem = {}; + adminUsers: MenuItem = {}; + adminMenu: MenuItem = {}; constructor( private themeService: ThemeService, diff --git a/kdb-web/src/app/services/theme/theme.service.ts b/kdb-web/src/app/services/theme/theme.service.ts index 32d56f4c..c226dd98 100644 --- a/kdb-web/src/app/services/theme/theme.service.ts +++ b/kdb-web/src/app/services/theme/theme.service.ts @@ -12,7 +12,6 @@ export class ThemeService { sidebarWidth = '150px'; isSidebarOpen = false; - hasLangChanged = false; themeName$ = new BehaviorSubject(Themes.Default); isSidebarOpen$ = new BehaviorSubject(true); diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 26ceea96..840727b6 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -294,7 +294,8 @@ "name": "Name", "color": "Farbe", "min_xp": "Min. XP", - "permissions": "Rechte" + "permissions": "Rechte", + "actions": "Aktionen" }, "no_entries_found": "Keine Einträge gefunden", "message": {