From 109bbf3729c48960c7efcf618a7aed83f60cb389 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 12 Jul 2023 11:56:52 +0200 Subject: [PATCH] First step to add achievements to frontend #268_achievements --- kdb-bot/src/bot_graphql/model/server.gql | 3 + .../src/bot_graphql/queries/server_query.py | 7 +- .../src/app/models/data/achievement.model.ts | 20 ++ .../src/app/models/graphql/mutations.model.ts | 42 +++ .../src/app/models/graphql/queries.model.ts | 44 +++ kdb-web/src/app/models/graphql/query.model.ts | 6 + .../src/app/models/graphql/result.model.ts | 9 + .../achievements-routing.module.ts | 16 ++ .../achievements/achievements.module.ts | 18 ++ .../achievement/achievement.component.html | 215 ++++++++++++++ .../achievement/achievement.component.scss | 0 .../achievement/achievement.component.spec.ts | 23 ++ .../achievement/achievement.component.ts | 268 ++++++++++++++++++ .../view/server/server-routing.module.ts | 3 +- .../app/services/sidebar/sidebar.service.ts | 11 +- kdb-web/src/assets/i18n/de.json | 26 ++ 16 files changed, 708 insertions(+), 3 deletions(-) create mode 100644 kdb-web/src/app/models/data/achievement.model.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/achievements.module.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.scss create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts create mode 100644 kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts diff --git a/kdb-bot/src/bot_graphql/model/server.gql b/kdb-bot/src/bot_graphql/model/server.gql index db94dc89..90f07f95 100644 --- a/kdb-bot/src/bot_graphql/model/server.gql +++ b/kdb-bot/src/bot_graphql/model/server.gql @@ -16,6 +16,9 @@ type Server implements TableWithHistoryQuery { userCount: Int users(filter: UserFilter, page: Page, sort: Sort): [User] + achievementCount: Int + achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement] + createdAt: String modifiedAt: String diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py index 39012d49..52d53d23 100644 --- a/kdb-bot/src/bot_graphql/queries/server_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -1,6 +1,7 @@ from cpl_core.database.context import DatabaseContextABC from cpl_discord.service import DiscordBotServiceABC +from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC @@ -9,8 +10,8 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoic from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.model.server import Server from bot_data.model.server_history import ServerHistory -from bot_graphql.abc.data_query_abc import DataQueryABC from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC +from bot_graphql.filter.achievement_filter import AchievementFilter from bot_graphql.filter.auto_role_filter import AutoRoleFilter from bot_graphql.filter.client_filter import ClientFilter from bot_graphql.filter.level_filter import LevelFilter @@ -28,6 +29,7 @@ class ServerQuery(DataQueryWithHistoryABC): users: UserRepositoryABC, ujs: UserJoinedServerRepositoryABC, ujvs: UserJoinedVoiceChannelRepositoryABC, + achievements: AchievementRepositoryABC, ): DataQueryWithHistoryABC.__init__(self, "Server", "ServersHistory", ServerHistory, db) @@ -54,6 +56,9 @@ class ServerQuery(DataQueryWithHistoryABC): ) self.add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.id), LevelFilter) self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.id), UserFilter) + self.add_collection( + "achievement", lambda server, *_: achievements.get_achievements_by_server_id(server.id), AchievementFilter + ) @staticmethod def resolve_id(server: Server, *_): diff --git a/kdb-web/src/app/models/data/achievement.model.ts b/kdb-web/src/app/models/data/achievement.model.ts new file mode 100644 index 00000000..0b1af096 --- /dev/null +++ b/kdb-web/src/app/models/data/achievement.model.ts @@ -0,0 +1,20 @@ +import { DataWithHistory } from "./data.model"; +import { Server, ServerFilter } from "./server.model"; + +export interface Achievement extends DataWithHistory { + id?: number; + name?: string; + attribute?: string; + operator?: string; + value?: string; + server?: Server; +} + +export interface AchievementFilter { + id?: number; + name?: string; + attribute?: string; + operator?: string; + value?: 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 0cba6ef3..db95bd86 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -121,4 +121,46 @@ export class Mutations { } } `; + + static createAchievement = ` + mutation createAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { + level { + createAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { + id + name + attribute + operator + value + server { + id + } + } + } + } + `; + + static updateAchievement = ` + mutation updateAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { + level { + updateAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value}) { + id + name + attribute + operator + value + } + } + } + `; + + static deleteAchievement = ` + mutation deleteAchievement($id: ID) { + level { + deleteLevel(id: $id) { + id + name + } + } + } + `; } diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index f3d68257..df3cf125 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -90,6 +90,50 @@ export class Queries { } `; + static achievementQuery = ` + query AchievementList($serverId: ID, $filter: AchievementFilter, $page: Page, $sort: Sort) { + servers(filter: {id: $serverId}) { + achievementCount + achievements(filter: $filter, page: $page, sort: $sort) { + id + name + attribute + operator + value + server { + id + name + } + createdAt + modifiedAt + } + } + } + `; + + static achievementWithHistoryQuery = ` + query AchievementHistory($serverId: ID, $id: ID) { + servers(filter: {id: $serverId}) { + achievementCount + achievements(filter: {id: $id}) { + id + + history { + id + name + attribute + operator + value + server + deleted + dateFrom + dateTo + } + } + } + } + `; + static usersQuery = ` query UsersList($serverId: ID, $filter: UserFilter, $page: Page, $sort: Sort) { servers(filter: {id: $serverId}) { diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index 3f7e85a1..60e1964d 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -3,6 +3,7 @@ import { User } from "../data/user.model"; import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Guild } from "../data/discord.model"; import { Level } from "../data/level.model"; +import { Achievement } from "../data/achievement.model"; export interface Query { serverCount: number; @@ -23,6 +24,11 @@ export interface LevelListQuery { levels: Level[]; } +export interface AchievementListQuery { + achievementCount: number; + achievements: Achievement[]; +} + export interface AutoRoleQuery { autoRoleCount: number; autoRoles: AutoRole[]; diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts index d3d6e4a4..d77c2cdc 100644 --- a/kdb-web/src/app/models/graphql/result.model.ts +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -2,6 +2,7 @@ import { User } from "../data/user.model"; import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; import { Level } from "../data/level.model"; import { Server } from "../data/server.model"; +import { Achievement } from "../data/achievement.model"; export interface GraphQLResult { data: { @@ -45,3 +46,11 @@ export interface LevelMutationResult { deleteLevel?: Level }; } + +export interface AchievementMutationResult { + achievement: { + createAchievement?: Achievement + updateAchievement?: Achievement + deleteAchievement?: Achievement + }; +} diff --git a/kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts b/kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts new file mode 100644 index 00000000..ae847fb9 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/achievements-routing.module.ts @@ -0,0 +1,16 @@ +import {NgModule} from "@angular/core"; +import {RouterModule, Routes} from "@angular/router"; +import { AchievementComponent } from "./components/achievement/achievement.component"; + +const routes: Routes = [ + + {path: '', component: AchievementComponent}, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AchievementsRoutingModule { + +} diff --git a/kdb-web/src/app/modules/view/server/achievements/achievements.module.ts b/kdb-web/src/app/modules/view/server/achievements/achievements.module.ts new file mode 100644 index 00000000..ccf7e426 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/achievements.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { AchievementComponent } from "./components/achievement/achievement.component"; +import { AchievementsRoutingModule } from "./achievements-routing.module"; +import { SharedModule } from "../../../shared/shared.module"; + + +@NgModule({ + declarations: [ + AchievementComponent + ], + imports: [ + CommonModule, + AchievementsRoutingModule, + SharedModule + ] +}) +export class AchievementsModule { } diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html new file mode 100644 index 00000000..83879d48 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.html @@ -0,0 +1,215 @@ +

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

+
+
+ + + +
+
+ {{achievements.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.achievements.achievements' | translate}} +
+ +
+ + +
+
+
+ + + + +
+
{{'common.id' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.name' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.attribute' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.operator' | translate}}
+ +
+ + + +
+
{{'view.server.achievements.headers.value' | translate}}
+ +
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'common.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + + + + + + + +
+ + + + + + + {{achievement.id}} + + + {{achievement.id}} + + + + + + + + + + + {{achievement.name}} + + + + + + + + + + + {{achievement.attribute}} + + + + + + + + + + + {{achievement.operator}} + + + + + + + + + + + {{achievement.value}} + + + + + + + + {{achievement.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{achievement.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{achievement.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{achievement.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + +
+ + + + + + +
+ + +
+ + + + + {{'common.no_entries_found' | translate}} + + + + + + +
+
+
+ diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.scss b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts new file mode 100644 index 00000000..771e808b --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AchievementComponent } from './achievement.component'; + +describe('AchievementComponent', () => { + let component: AchievementComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AchievementComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AchievementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts new file mode 100644 index 00000000..5eb90432 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts @@ -0,0 +1,268 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { Achievement, AchievementFilter } from "../../../../../../models/data/achievement.model"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Page } from "../../../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; +import { Subject, throwError } from "rxjs"; +import { Server } from "../../../../../../models/data/server.model"; +import { UserDTO } from "../../../../../../models/auth/auth-user.dto"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +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 { 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 { AchievementListQuery, Query } from "../../../../../../models/graphql/query.model"; +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 { AchievementMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; + +@Component({ + selector: "app-achievement", + templateUrl: "./achievement.component.html", + styleUrls: ["./achievement.component.scss"] +}) +export class AchievementComponent implements OnInit, OnDestroy { + public achievements: Achievement[] = []; + public loading = true; + + public isEditingNew: boolean = false; + + public filterForm!: FormGroup<{ + id: FormControl, + name: FormControl, + color: FormControl, + min_xp: FormControl, + permissions: FormControl, + }>; + + public filter: AchievementFilter = {}; + public page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + public sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + public totalRecords: number = 0; + + public clonedAchievements: { [s: string]: Achievement; } = {}; + + private unsubscriber = new Subject(); + private server: Server = {}; + public user: UserDTO | null = null; + + query: string = Queries.achievementWithHistoryQuery; + + 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.setFilterForm(); + this.data.getServerFromRoute(this.route).then(async server => { + this.server = server; + this.loadNextPage(); + let authUser = await this.authService.getLoggedInUser(); + this.user = authUser?.users?.find(u => u.server == this.server.id) ?? null; + }); + } + + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + + public loadNextPage(): void { + this.loading = true; + this.data.query(Queries.achievementQuery, { + serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort + }, + (data: Query) => { + return data.servers[0]; + } + ).subscribe(data => { + this.totalRecords = data.achievementCount; + this.achievements = data.achievements; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + public setFilterForm(): void { + 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( + takeUntil(this.unsubscriber), + 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 newAchievementTemplate: Achievement = { + 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; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + + public resetFilters(): void { + this.filterForm.reset(); + } + + public onRowEditInit(table: Table, user: User, index: number): void { + this.clonedAchievements[index] = { ...user }; + } + + public onRowEditSave(table: Table, newAchievement: Achievement, index: number): void { + if (this.isEditingNew && JSON.stringify(newAchievement) === JSON.stringify(this.newAchievementTemplate)) { + this.isEditingNew = false; + this.achievements.splice(index, 1); + return; + } + + if (!newAchievement.id && !this.isEditingNew || !newAchievement.name && !newAchievement.attribute && !newAchievement?.operator && !newAchievement?.value) { + return; + } + + if (this.isEditingNew) { + this.spinner.showSpinner(); + this.data.mutation(Mutations.createAchievement, { + name: newAchievement.name, + attribute: newAchievement.attribute, + operator: newAchievement.operator, + value: newAchievement.value, + serverId: this.server.id + } + ).pipe(catchError(err => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_create_failed"), this.translate.instant("view.server.achievements.message.achievement_create_failed_d")); + return throwError(err); + })).subscribe(result => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.achievements.message.achievement_create"), this.translate.instant("view.server.achievements.message.achievement_create_d", { name: result.achievement.createAchievement?.name })); + this.loadNextPage(); + }); + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateAchievement, { + id: newAchievement.id, + name: newAchievement.name, + attribute: newAchievement.attribute, + operator: newAchievement.operator, + value: newAchievement.value + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_update_failed"), this.translate.instant("view.server.achievements.message.achievement_update_failed_d", { name: newAchievement.name })); + return throwError(err); + })).subscribe(_ => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.achievements.message.achievement_update"), this.translate.instant("view.server.achievements.message.achievement_update_d", { name: newAchievement.name })); + this.loadNextPage(); + }); + + } + + public onRowEditCancel(index: number): void { + if (this.isEditingNew) { + this.achievements.splice(index, 1); + delete this.clonedAchievements[index]; + this.isEditingNew = false; + return; + } + + this.achievements[index] = this.clonedAchievements[index]; + delete this.clonedAchievements[index]; + } + + public deleteAchievement(achievement: Achievement): void { + this.confirmDialog.confirmDialog( + this.translate.instant("view.server.achievements.message.achievement_delete"), this.translate.instant("view.server.achievements.message.achievement_delete_q", { name: achievement.name }), + () => { + this.spinner.showSpinner(); + this.data.mutation(Mutations.deleteAchievement, { + id: achievement.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_delete_failed"), this.translate.instant("view.server.achievements.message.achievement_delete_failed_d", { name: achievement.name })); + return throwError(err); + })).subscribe(l => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.achievements.message.achievement_deleted"), this.translate.instant("view.server.achievements.message.achievement_deleted_d", { name: achievement.name })); + this.loadNextPage(); + }); + }); + } + + public addAchievement(table: Table): void { + const newAchievement = JSON.parse(JSON.stringify(this.newAchievementTemplate)); + newAchievement.id = Math.max.apply(Math, this.achievements.map(l => { + return l.id ?? 0; + })) + 1; + + this.achievements.push(newAchievement); + + table.initRowEdit(newAchievement); + + const index = this.achievements.findIndex(l => l.id == newAchievement.id); + this.onRowEditInit(table, newAchievement, index); + + this.isEditingNew = true; + } +} 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 147c40ea..a83dab96 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 @@ -9,7 +9,8 @@ const routes: Routes = [ { 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: "levels", loadChildren: () => import("./levels/levels.module").then(m => m.LevelsModule) }, + { path: "achievements", loadChildren: () => import("./achievements/achievements.module").then(m => m.AchievementsModule) } ]; @NgModule({ diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index 1bd9476a..81ab4548 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 = {}; serverLevels: MenuItem = {}; + serverAchievements: MenuItem = {}; serverMenu: MenuItem = {}; adminConfig: MenuItem = {}; adminUsers: MenuItem = {}; @@ -102,12 +103,19 @@ export class SidebarService { routerLink: `server/${this.server$.value?.id}/levels` }; + this.serverAchievements = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.achievements") : "", + icon: "pi pi-angle-double-up", + visible: true, + routerLink: `server/${this.server$.value?.id}/achievements` + }; + 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, this.serverLevels] + items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels, this.serverAchievements] }; this.adminConfig = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", @@ -142,6 +150,7 @@ export class SidebarService { this.serverMembers.visible = !!user?.isModerator; this.serverAutoRoles.visible = !!user?.isModerator; this.serverLevels.visible = !!user?.isModerator; + this.serverAchievements.visible = !!user?.isModerator; } else { this.serverMenu.visible = false; } diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 7a1cdf40..4078a0be 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -397,6 +397,32 @@ "level_update_failed_d": "Die Bearbeitung des Levels ist fehlgeschlagen!" } }, + "achievements": { + "header": "Errungenschaften", + "headers": { + "name": "Name", + "attribute": "Attribut", + "operator": "Operator", + "value": "Wert" + }, + "achievements": "Errungenschaften", + "message": { + "achievement_create": "Errungenschaft erstellt", + "achievement_create_d": "Errungenschaft {{name}} erfolgreich erstellt", + "achievement_create_failed": "Errungenschaft Erstellung fehlgeschlagen", + "achievement_create_failed_d": "Die Erstellung der Errungenschaft ist fehlgeschlagen!", + "achievement_delete": "Errungenschaft löschen", + "achievement_delete_failed": "Errungenschaft Löschung fehlgeschlagen", + "achievement_delete_failed_d": "Die Löschung der Errungenschaft {{name}} ist fehlgeschlagen!", + "achievement_delete_q": "Sind Sie sich sicher, dass Sie das Errungenschaft {{name}} löschen möchten?", + "achievement_deleted": "Errungenschaft gelöscht", + "achievement_deleted_d": "Errungenschaft {{name}} erfolgreich gelöscht", + "achievement_update": "Errungenschaft bearbeitet", + "achievement_update_d": "Errungenschaft {{name}} erfolgreich bearbeitet", + "achievement_update_failed": "Errungenschaft Bearbeitung fehlgeschlagen", + "achievement_update_failed_d": "Die Bearbeitung der Errungenschaft ist fehlgeschlagen!" + } + }, "members": { "header": "Mitglieder", "headers": {