Verwarnungssystem #35 #235
@@ -69,11 +69,11 @@ class ApiKey(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            INSERT INTO `ApiKeys` (
 | 
			
		||||
                `Identifier`, `Key`, {"" if self._creator is None else "`CreatorId`,"} `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
                `Identifier`, `Key`, `CreatorId`, `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
            ) VALUES (
 | 
			
		||||
                '{self._identifier}',
 | 
			
		||||
                '{self._key}',
 | 
			
		||||
                {"" if self._creator is None else f"{self._creator.id},"}
 | 
			
		||||
                {"NULL" if self._creator is None else f"'{self._creator.id}'"},
 | 
			
		||||
                '{self._created_at}',
 | 
			
		||||
                '{self._modified_at}'
 | 
			
		||||
            );
 | 
			
		||||
@@ -87,7 +87,7 @@ class ApiKey(TableABC):
 | 
			
		||||
            UPDATE `ApiKeys`
 | 
			
		||||
            SET `Identifier` = '{self._identifier}',
 | 
			
		||||
            `Key` = '{self._key}',
 | 
			
		||||
            {"" if self._creator is None else f"`CreatorId` = {self._creator.id},"}
 | 
			
		||||
            `CreatorId` = {"NULL" if self._creator is None else f"'{self._creator.id}'"},
 | 
			
		||||
            `LastModifiedAt` = '{self._modified_at}'
 | 
			
		||||
            WHERE `Id` = {self._id};
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -215,10 +215,10 @@ class AuthUser(TableABC):
 | 
			
		||||
                `EMail`,
 | 
			
		||||
                `Password`,
 | 
			
		||||
                `PasswordSalt`,
 | 
			
		||||
                {"" if self._refresh_token is None else f"`RefreshToken`,"}
 | 
			
		||||
                {"" if self._confirmation_id is None else f"`ConfirmationId`,"}
 | 
			
		||||
                {"" if self._forgot_password_id is None else f"`ForgotPasswordId`,"}
 | 
			
		||||
                {"" if self._oauth_id is None else f"`OAuthId`,"}
 | 
			
		||||
                `RefreshToken`,
 | 
			
		||||
                `ConfirmationId`,
 | 
			
		||||
                `ForgotPasswordId`,
 | 
			
		||||
                `OAuthId`,
 | 
			
		||||
                `RefreshTokenExpiryTime`,
 | 
			
		||||
                `AuthRole`,
 | 
			
		||||
                `CreatedAt`,
 | 
			
		||||
@@ -230,10 +230,10 @@ class AuthUser(TableABC):
 | 
			
		||||
                '{self._email}',
 | 
			
		||||
                '{self._password}', 
 | 
			
		||||
                '{self._password_salt}', 
 | 
			
		||||
                {"" if self._refresh_token is None else f"'{self._refresh_token}',"}
 | 
			
		||||
                {"" if self._confirmation_id is None else f"'{self._confirmation_id}',"}
 | 
			
		||||
                {"" if self._forgot_password_id is None else f"'{self._forgot_password_id}',"}
 | 
			
		||||
                {"" if self._oauth_id is None else f"'{self._oauth_id}',"}
 | 
			
		||||
                {"NULL" if self._refresh_token is None else f"'{self._refresh_token}'"},
 | 
			
		||||
                {"NULL" if self._confirmation_id is None else f"'{self._confirmation_id}'"},
 | 
			
		||||
                {"NULL" if self._forgot_password_id is None else f"'{self._forgot_password_id}'"},
 | 
			
		||||
                {"NULL" if self._oauth_id is None else f"'{self._oauth_id}'"},
 | 
			
		||||
                '{self._refresh_token_expire_time.isoformat()}',
 | 
			
		||||
                {self._auth_role_id.value},
 | 
			
		||||
                '{self._created_at}', 
 | 
			
		||||
@@ -252,10 +252,10 @@ class AuthUser(TableABC):
 | 
			
		||||
            `EMail` = '{self._email}', 
 | 
			
		||||
            `Password` = '{self._password}', 
 | 
			
		||||
            `PasswordSalt` = '{self._password_salt}', 
 | 
			
		||||
            {'' if self._refresh_token is None else f"`RefreshToken` = '{self._refresh_token}',"} 
 | 
			
		||||
            {'' if self._confirmation_id is None else f"'`ConfirmationId` = '{self._confirmation_id}',"} 
 | 
			
		||||
            {'' if self._forgot_password_id is None else f"`ForgotPasswordId` = '{self._forgot_password_id}',"}
 | 
			
		||||
            {'' if self._oauth_id is None else f"`OAuthId` = '{self._oauth_id}',"} 
 | 
			
		||||
            `RefreshToken` = {"NULL" if self._refresh_token is None else f"'{self._refresh_token}'"},
 | 
			
		||||
            `ConfirmationId` = {"NULL" if self._confirmation_id is None else f"'{self._confirmation_id}'"},
 | 
			
		||||
            `ForgotPasswordId` = {"NULL" if self._forgot_password_id is None else f"'{self._forgot_password_id}'"},
 | 
			
		||||
            `OAuthId` = {"NULL" if self._oauth_id is None else f"'{self._oauth_id}'"},
 | 
			
		||||
            `RefreshTokenExpiryTime` = '{self._refresh_token_expire_time.isoformat()}',
 | 
			
		||||
            `AuthRole` = {self._auth_role_id.value},
 | 
			
		||||
            `LastModifiedAt` = '{self._modified_at}'
 | 
			
		||||
 
 | 
			
		||||
@@ -150,11 +150,11 @@ class User(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            INSERT INTO `Users` (
 | 
			
		||||
                `DiscordId`, `XP`, {"" if self._minecraft_id is None else "`MinecraftId`,"} `ServerId`, `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
                `DiscordId`, `XP`, `MinecraftId`, `ServerId`, `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
            ) VALUES (
 | 
			
		||||
                {self._discord_id},
 | 
			
		||||
                {self._xp},
 | 
			
		||||
                {"" if self._minecraft_id is None else f"'{self._minecraft_id}',"}
 | 
			
		||||
                {"NULL" if self._minecraft_id is None else f"'{self._minecraft_id}'"},
 | 
			
		||||
                {self._server.id},
 | 
			
		||||
                '{self._created_at}',
 | 
			
		||||
                '{self._modified_at}'
 | 
			
		||||
@@ -168,7 +168,7 @@ class User(TableABC):
 | 
			
		||||
            f"""
 | 
			
		||||
            UPDATE `Users`
 | 
			
		||||
            SET `XP` = {self._xp},
 | 
			
		||||
            {"" if self._minecraft_id is None else f"`MinecraftId` = '{self._minecraft_id}',"}
 | 
			
		||||
            `MinecraftId` = {"NULL" if self._minecraft_id is None else f"'{self._minecraft_id}'"},
 | 
			
		||||
            `LastModifiedAt` = '{self._modified_at}'
 | 
			
		||||
            WHERE `UserId` = {self._user_id};
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -101,12 +101,12 @@ class UserJoinedGameServer(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            INSERT INTO `UserJoinedGameServer` (
 | 
			
		||||
                `UserId`, `GameServer`, `JoinedOn`, {"" if self._leaved_on is None else "`LeavedOn`,"} `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
                `UserId`, `GameServer`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
            ) VALUES (
 | 
			
		||||
                {self._user.id},
 | 
			
		||||
                '{self._game_server}',
 | 
			
		||||
                '{self._joined_on}',
 | 
			
		||||
                {"" if self._leaved_on is None else f"'{self._leaved_on}',"}
 | 
			
		||||
                {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"},
 | 
			
		||||
                '{self._created_at}',
 | 
			
		||||
                '{self._modified_at}'
 | 
			
		||||
            );
 | 
			
		||||
@@ -118,8 +118,7 @@ class UserJoinedGameServer(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            UPDATE `UserJoinedGameServer`
 | 
			
		||||
            SET
 | 
			
		||||
            {"" if self._leaved_on is None else f"`LeavedOn` = '{self._leaved_on}',"}
 | 
			
		||||
            SET `LeavedOn` = {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"},
 | 
			
		||||
            `LastModifiedAt` = '{self._modified_at}'
 | 
			
		||||
            WHERE `Id` = {self._id};
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -100,11 +100,11 @@ class UserJoinedServer(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            INSERT INTO `UserJoinedServers` (
 | 
			
		||||
                `UserId`, `JoinedOn`, {"" if self._leaved_on is None else "`LeavedOn`,"} `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
                `UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
            ) VALUES (
 | 
			
		||||
                {self._user.id},
 | 
			
		||||
                '{self._joined_on}',
 | 
			
		||||
                {"" if self._leaved_on is None else f"'{self._leaved_on}',"}
 | 
			
		||||
                {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"},
 | 
			
		||||
                '{self._created_at}',
 | 
			
		||||
                '{self._modified_at}'
 | 
			
		||||
            );
 | 
			
		||||
@@ -116,8 +116,7 @@ class UserJoinedServer(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            UPDATE `UserJoinedServers`
 | 
			
		||||
            SET
 | 
			
		||||
            {"" if self._leaved_on is None else f"`LeavedOn` = '{self._leaved_on}',"}
 | 
			
		||||
            SET `LeavedOn` = {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"},
 | 
			
		||||
            `LastModifiedAt` = '{self._modified_at}'
 | 
			
		||||
            WHERE `UserId` = {self._user.id};
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -108,12 +108,12 @@ class UserJoinedVoiceChannel(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            INSERT INTO `UserJoinedVoiceChannel` (
 | 
			
		||||
                `UserId`, `DiscordChannelId`, `JoinedOn`, {"" if self._leaved_on is None else "`LeavedOn`,"} `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
                `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt`
 | 
			
		||||
            ) VALUES (
 | 
			
		||||
                {self._user.id},
 | 
			
		||||
                {self._channel_id},
 | 
			
		||||
                '{self._joined_on}',
 | 
			
		||||
                {"" if self._leaved_on is None else f"'{self._leaved_on}',"}
 | 
			
		||||
                {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"},
 | 
			
		||||
                '{self._created_at}',
 | 
			
		||||
                '{self._modified_at}'
 | 
			
		||||
            );
 | 
			
		||||
@@ -125,8 +125,7 @@ class UserJoinedVoiceChannel(TableABC):
 | 
			
		||||
        return str(
 | 
			
		||||
            f"""
 | 
			
		||||
            UPDATE `UserJoinedVoiceChannel`
 | 
			
		||||
            SET
 | 
			
		||||
            {"" if self._leaved_on is None else f"`LeavedOn` = '{self._leaved_on}',"}
 | 
			
		||||
            SET `LeavedOn` = {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"},
 | 
			
		||||
            `LastModifiedAt` = '{self._modified_at}'
 | 
			
		||||
            WHERE `JoinId` = {self._join_id};
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _get_value_from_result(value: any) -> Optional[any]:
 | 
			
		||||
        if isinstance(value, str) and "null" in value:
 | 
			
		||||
        if isinstance(value, str) and "NULL" in value:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        return value
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "kdb-web",
 | 
			
		||||
    "version": "1.0.0",
 | 
			
		||||
    "version": "1.0.dev220",
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "ng": "ng",
 | 
			
		||||
        "update-version": "ts-node-esm update-version.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<void>();
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<void>();
 | 
			
		||||
 | 
			
		||||
  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();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
export interface Data {
 | 
			
		||||
  createdAt: string;
 | 
			
		||||
  modifiedAt: string;
 | 
			
		||||
  createdAt?: string;
 | 
			
		||||
  modifiedAt?: string;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ export class Queries {
 | 
			
		||||
 | 
			
		||||
  static serversQuery = `
 | 
			
		||||
    query ServerInfo($filter: ServerFilter, $page: Page, $sort: Sort) {
 | 
			
		||||
      serverCount
 | 
			
		||||
      servers(filter: $filter, page: $page, sort: $sort) {
 | 
			
		||||
        id
 | 
			
		||||
        name
 | 
			
		||||
@@ -46,112 +47,76 @@ export class Queries {
 | 
			
		||||
  `;
 | 
			
		||||
 | 
			
		||||
  static levelQuery = `
 | 
			
		||||
    query LevelsList($filter: LevelFilter, $page: Page, $sort: Sort) {
 | 
			
		||||
      levelCount
 | 
			
		||||
      levels(filter: $filter, page: $page, sort: $sort) {
 | 
			
		||||
        id
 | 
			
		||||
        name
 | 
			
		||||
        color
 | 
			
		||||
        minXp
 | 
			
		||||
        permissions
 | 
			
		||||
        server {
 | 
			
		||||
    query LevelsList($serverId: ID, $filter: LevelFilter, $page: Page, $sort: Sort) {
 | 
			
		||||
      servers(filter: {id: $serverId}) {
 | 
			
		||||
        levelCount
 | 
			
		||||
        levels(filter: $filter, page: $page, sort: $sort) {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
          color
 | 
			
		||||
          minXp
 | 
			
		||||
          permissions
 | 
			
		||||
          server {
 | 
			
		||||
            id
 | 
			
		||||
            name
 | 
			
		||||
          }
 | 
			
		||||
          createdAt
 | 
			
		||||
          modifiedAt
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
 | 
			
		||||
  static usersQuery = `
 | 
			
		||||
    query UsersList($filter: UserFilter, $page: Page, $sort: Sort) {
 | 
			
		||||
      userCount
 | 
			
		||||
      users(filter: $filter, page: $page, sort: $sort) {
 | 
			
		||||
        id
 | 
			
		||||
        discordId
 | 
			
		||||
        name
 | 
			
		||||
        xp
 | 
			
		||||
        ontime
 | 
			
		||||
        level {
 | 
			
		||||
    query UsersList($serverId: ID, $filter: UserFilter, $page: Page, $sort: Sort) {
 | 
			
		||||
      servers(filter: {id: $serverId}) {
 | 
			
		||||
        userCount
 | 
			
		||||
        users(filter: $filter, page: $page, sort: $sort) {
 | 
			
		||||
          id
 | 
			
		||||
          discordId
 | 
			
		||||
          name
 | 
			
		||||
        }
 | 
			
		||||
        server {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
        }
 | 
			
		||||
        leftServer
 | 
			
		||||
          xp
 | 
			
		||||
          ontime
 | 
			
		||||
          minecraftId
 | 
			
		||||
          level {
 | 
			
		||||
            id
 | 
			
		||||
            name
 | 
			
		||||
          }
 | 
			
		||||
          leftServer
 | 
			
		||||
          server {
 | 
			
		||||
            id
 | 
			
		||||
            name
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        joinedServerCount
 | 
			
		||||
        joinedServers {
 | 
			
		||||
          id
 | 
			
		||||
        }
 | 
			
		||||
          joinedServerCount
 | 
			
		||||
          joinedServers {
 | 
			
		||||
            id
 | 
			
		||||
            joinedOn
 | 
			
		||||
            leavedOn
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        joinedVoiceChannelCount
 | 
			
		||||
        joinedVoiceChannels {
 | 
			
		||||
          id
 | 
			
		||||
          channelId
 | 
			
		||||
          channelName
 | 
			
		||||
        }
 | 
			
		||||
          joinedVoiceChannelCount
 | 
			
		||||
          joinedVoiceChannels {
 | 
			
		||||
            id
 | 
			
		||||
            channelId
 | 
			
		||||
            channelName
 | 
			
		||||
            time
 | 
			
		||||
            joinedOn
 | 
			
		||||
            leavedOn
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        userJoinedGameServerCount
 | 
			
		||||
        userJoinedGameServers {
 | 
			
		||||
          id
 | 
			
		||||
          gameServer
 | 
			
		||||
        }
 | 
			
		||||
          userJoinedGameServerCount
 | 
			
		||||
          userJoinedGameServers {
 | 
			
		||||
            id
 | 
			
		||||
            gameServer
 | 
			
		||||
            time
 | 
			
		||||
            joinedOn
 | 
			
		||||
            leavedOn
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        createdAt
 | 
			
		||||
        modifiedAt
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
 | 
			
		||||
  static singleUserQuery = `
 | 
			
		||||
    query singleUserQuery($filter: UserFilter) {
 | 
			
		||||
      users(filter: $filter) {
 | 
			
		||||
        id
 | 
			
		||||
        discordId
 | 
			
		||||
        name
 | 
			
		||||
        xp
 | 
			
		||||
        ontime
 | 
			
		||||
        minecraftId
 | 
			
		||||
        level {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
          createdAt
 | 
			
		||||
          modifiedAt
 | 
			
		||||
        }
 | 
			
		||||
        leftServer
 | 
			
		||||
        server {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        joinedServerCount
 | 
			
		||||
        joinedServers {
 | 
			
		||||
          id
 | 
			
		||||
          joinedOn
 | 
			
		||||
          leavedOn
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        joinedVoiceChannelCount
 | 
			
		||||
        joinedVoiceChannels {
 | 
			
		||||
          id
 | 
			
		||||
          channelId
 | 
			
		||||
          channelName
 | 
			
		||||
          time
 | 
			
		||||
          joinedOn
 | 
			
		||||
          leavedOn
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        userJoinedGameServerCount
 | 
			
		||||
        userJoinedGameServers {
 | 
			
		||||
          id
 | 
			
		||||
          gameServer
 | 
			
		||||
          time
 | 
			
		||||
          joinedOn
 | 
			
		||||
          leavedOn
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        createdAt
 | 
			
		||||
        modifiedAt
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,19 @@
 | 
			
		||||
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";
 | 
			
		||||
 | 
			
		||||
export interface GraphQLResult {
 | 
			
		||||
  data: any;
 | 
			
		||||
  data: {
 | 
			
		||||
    servers?: Server[];
 | 
			
		||||
  };
 | 
			
		||||
  errors?: [];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface QueryResult {
 | 
			
		||||
  data: any;
 | 
			
		||||
  data: {
 | 
			
		||||
    servers?: Server[];
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface UpdateUserMutationResult {
 | 
			
		||||
@@ -31,3 +37,11 @@ export interface AutoRoleRuleMutationResult {
 | 
			
		||||
    deleteAutoRoleRule?: AutoRoleRule
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface LevelMutationResult {
 | 
			
		||||
  level: {
 | 
			
		||||
    createLevel?: Level
 | 
			
		||||
    updateLevel?: Level
 | 
			
		||||
    deleteLevel?: Level
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<string | null>,
 | 
			
		||||
  }>;
 | 
			
		||||
 | 
			
		||||
  private unsubscriber = new Subject<void>();
 | 
			
		||||
 | 
			
		||||
  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<string | null>(null)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.filterForm.valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.unsubscriber),
 | 
			
		||||
      debounceTime(600)
 | 
			
		||||
    ).subscribe(async changes => {
 | 
			
		||||
      if (changes.name == "") {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -42,7 +42,6 @@ export class AutoRolesRulesComponent implements OnInit {
 | 
			
		||||
  isEditingNew: boolean = false;
 | 
			
		||||
 | 
			
		||||
  newAutoRoleTemplate: AutoRoleRule = {
 | 
			
		||||
    id: 0,
 | 
			
		||||
    createdAt: "",
 | 
			
		||||
    modifiedAt: ""
 | 
			
		||||
  };
 | 
			
		||||
@@ -63,7 +62,9 @@ export class AutoRolesRulesComponent implements OnInit {
 | 
			
		||||
    sortDirection: undefined
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  totalRecords!: number;
 | 
			
		||||
  totalRecords: number = 0;
 | 
			
		||||
  private unsubscriber = new Subject<void>();
 | 
			
		||||
  private server: Server = {};
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private authService: AuthService,
 | 
			
		||||
@@ -87,7 +88,7 @@ export class AutoRolesRulesComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    this.setFilterForm();
 | 
			
		||||
    this.data.getServerFromRoute(this.route).then(server => {
 | 
			
		||||
 | 
			
		||||
      this.server = server;
 | 
			
		||||
      this.spinner.showSpinner();
 | 
			
		||||
      if (!this.route.snapshot.params["autoRoleId"]) {
 | 
			
		||||
        this.spinner.hideSpinner();
 | 
			
		||||
@@ -121,7 +122,7 @@ export class AutoRolesRulesComponent implements OnInit {
 | 
			
		||||
  public loadNextPage(): void {
 | 
			
		||||
    this.loading = true;
 | 
			
		||||
    this.data.query<AutoRoleRuleQuery>(Queries.autoRoleRulesQuery, {
 | 
			
		||||
        id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort
 | 
			
		||||
        serverId: this.server.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) {
 | 
			
		||||
@@ -145,6 +146,7 @@ export class AutoRolesRulesComponent implements OnInit {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.filterForm.valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.unsubscriber),
 | 
			
		||||
      debounceTime(600)
 | 
			
		||||
    ).subscribe(changes => {
 | 
			
		||||
      if (changes.id) {
 | 
			
		||||
@@ -212,13 +214,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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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,16 +29,15 @@ 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; } = {};
 | 
			
		||||
  isEditingNew: boolean = false;
 | 
			
		||||
 | 
			
		||||
  newAutoRoleTemplate: AutoRole = {
 | 
			
		||||
    id: 0,
 | 
			
		||||
    createdAt: "",
 | 
			
		||||
    modifiedAt: ""
 | 
			
		||||
  };
 | 
			
		||||
@@ -60,7 +59,9 @@ export class AutoRolesComponent implements OnInit {
 | 
			
		||||
    sortDirection: undefined
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  totalRecords!: number;
 | 
			
		||||
  totalRecords: number = 0;
 | 
			
		||||
  private unsubscriber = new Subject<void>();
 | 
			
		||||
  private server: Server = {};
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private authService: AuthService,
 | 
			
		||||
@@ -79,6 +80,7 @@ export class AutoRolesComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    this.setFilterForm();
 | 
			
		||||
    this.data.getServerFromRoute(this.route).then(server => {
 | 
			
		||||
      this.server = server;
 | 
			
		||||
      this.spinner.showSpinner();
 | 
			
		||||
      this.data.query<SingleDiscordQuery>(Queries.guildsQuery, {
 | 
			
		||||
          filter: {
 | 
			
		||||
@@ -101,7 +103,7 @@ export class AutoRolesComponent implements OnInit {
 | 
			
		||||
  public loadNextPage(): void {
 | 
			
		||||
    this.loading = true;
 | 
			
		||||
    this.data.query<AutoRoleQuery>(Queries.autoRolesQuery, {
 | 
			
		||||
        id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort
 | 
			
		||||
        serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort
 | 
			
		||||
      },
 | 
			
		||||
      (x: { servers: Server[] }) => {
 | 
			
		||||
        return x.servers[0];
 | 
			
		||||
@@ -123,6 +125,7 @@ export class AutoRolesComponent implements OnInit {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.filterForm.valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.unsubscriber),
 | 
			
		||||
      debounceTime(600)
 | 
			
		||||
    ).subscribe(changes => {
 | 
			
		||||
      if (changes.id) {
 | 
			
		||||
@@ -190,15 +193,17 @@ export class AutoRolesComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    this.spinner.showSpinner();
 | 
			
		||||
    this.data.mutation<AutoRoleMutationResult>(Mutations.createAutoRole, {
 | 
			
		||||
        serverId: this.sidebar.server$.value?.id,
 | 
			
		||||
        serverId: this.server.id,
 | 
			
		||||
        channelId: newAutoRole.channelId,
 | 
			
		||||
        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();
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,214 @@
 | 
			
		||||
<h1>
 | 
			
		||||
  {{'view.server.levels.header' | translate}}
 | 
			
		||||
</h1>
 | 
			
		||||
<div class="content-wrapper">
 | 
			
		||||
  <div class="content">
 | 
			
		||||
    <p-table #dt [value]="levels" dataKey="id" editMode="row" [rowHover]="true" [rows]="10"
 | 
			
		||||
             [rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords"
 | 
			
		||||
             [lazy]="true" (onLazyLoad)="nextPage($event)">
 | 
			
		||||
 | 
			
		||||
      <ng-template pTemplate="caption">
 | 
			
		||||
        <div class="table-caption">
 | 
			
		||||
          <div class="table-caption-text">
 | 
			
		||||
            <ng-container *ngIf="!loading">{{levels.length}} {{'view.server.levels.of' | translate}}
 | 
			
		||||
              {{dt.totalRecords}}
 | 
			
		||||
            </ng-container>
 | 
			
		||||
            {{'view.server.levels.levels' | translate}}
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div class="table-caption-btn-wrapper btn-wrapper">
 | 
			
		||||
            <button pButton label="{{'admin.auth_users.add' | translate}}" class="icon-btn btn"
 | 
			
		||||
                    icon="pi pi-user-plus" (click)="addLevel(dt)" [disabled]="isEditingNew">
 | 
			
		||||
            </button>
 | 
			
		||||
            <button pButton label="{{'view.server.levels.reset_filters' | translate}}" icon="pi pi-undo"
 | 
			
		||||
                    class="icon-btn btn" (click)="resetFilters()">
 | 
			
		||||
            </button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
 | 
			
		||||
      <ng-template pTemplate="header">
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th pSortableColumn="id">
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'view.server.levels.headers.id' | translate}}</div>
 | 
			
		||||
              <p-sortIcon field="id" class="table-header-icon"></p-sortIcon>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th pSortableColumn="name">
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'view.server.levels.headers.name' | translate}}</div>
 | 
			
		||||
              <p-sortIcon field="name" class="table-header-icon"></p-sortIcon>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th pSortableColumn="color">
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'view.server.levels.headers.color' | translate}}</div>
 | 
			
		||||
              <p-sortIcon field="color" class="table-header-icon"></p-sortIcon>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th pSortableColumn="minXp">
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'view.server.levels.headers.min_xp' | translate}}</div>
 | 
			
		||||
              <p-sortIcon field="minXp" class="table-header-icon"></p-sortIcon>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th pSortableColumn="permissions">
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'view.server.levels.headers.permissions' | translate}}</div>
 | 
			
		||||
              <p-sortIcon field="permissions" class="table-header-icon"></p-sortIcon>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th>
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'common.created_at' | translate}}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th>
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'common.modified_at' | translate}}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
 | 
			
		||||
          <th>
 | 
			
		||||
            <div class="table-header-label">
 | 
			
		||||
              <div class="table-header-text">{{'view.server.levels.headers.actions' | translate}}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </th>
 | 
			
		||||
        </tr>
 | 
			
		||||
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th class="table-header-small">
 | 
			
		||||
            <form [formGroup]="filterForm">
 | 
			
		||||
              <input type="text" pInputText formControlName="id"
 | 
			
		||||
                     placeholder="{{'view.server.levels.headers.id' | translate}}">
 | 
			
		||||
            </form>
 | 
			
		||||
          </th>
 | 
			
		||||
          <th>
 | 
			
		||||
            <form [formGroup]="filterForm">
 | 
			
		||||
              <input type="text" pInputText formControlName="name"
 | 
			
		||||
                     placeholder="{{'view.server.levels.headers.name' | translate}}">
 | 
			
		||||
            </form>
 | 
			
		||||
          </th>
 | 
			
		||||
          <th></th>
 | 
			
		||||
          <th></th>
 | 
			
		||||
          <th></th>
 | 
			
		||||
          <th class="table-header-small-dropdown"></th>
 | 
			
		||||
          <th class="table-header-small-dropdown"></th>
 | 
			
		||||
          <th class="table-header-actions"></th>
 | 
			
		||||
        </tr>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
 | 
			
		||||
      <ng-template pTemplate="body" let-level let-editing="editing" let-ri="rowIndex">
 | 
			
		||||
        <tr [pEditableRow]="level">
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                {{level.id}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.id}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                <input class="table-edit-input" pInputText type="text" [(ngModel)]="level.name">
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.name}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                <input class="table-edit-input" pInputText type="text" [(ngModel)]="level.color">
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.color}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                <input class="table-edit-input" pInputText min="0" type="number" [(ngModel)]="level.minXp">
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.minXp}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                <input class="table-edit-input" pInputText min="0" type="text" [(ngModel)]="level.permissions">
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.permissions}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                {{level.createdAt | date:'dd.MM.yy HH:mm'}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.createdAt | date:'dd.MM.yy HH:mm'}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td>
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                {{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{level.modifiedAt | date:'dd.MM.yy HH:mm'}}
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </p-cellEditor>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td>
 | 
			
		||||
            <div class="btn-wrapper">
 | 
			
		||||
              <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
 | 
			
		||||
                      (click)="onRowEditInit(dt, level, ri)"></button>
 | 
			
		||||
              <button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash"
 | 
			
		||||
                      (click)="deleteLevel(level)"></button>
 | 
			
		||||
 | 
			
		||||
              <button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
 | 
			
		||||
                      icon="pi pi-check-circle" (click)="onRowEditSave(dt, level, ri)"></button>
 | 
			
		||||
              <button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
 | 
			
		||||
                      icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
 | 
			
		||||
            </div>
 | 
			
		||||
          </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
 | 
			
		||||
      <ng-template pTemplate="emptymessage">
 | 
			
		||||
        <tr></tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <td colspan="10">{{'view.server.levels.no_entries_found' | translate}}</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr></tr>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
 | 
			
		||||
      <ng-template pTemplate="paginatorleft">
 | 
			
		||||
      </ng-template>
 | 
			
		||||
    </p-table>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { LevelsComponent } from './levels.component';
 | 
			
		||||
 | 
			
		||||
describe('LevelsComponent', () => {
 | 
			
		||||
  let component: LevelsComponent;
 | 
			
		||||
  let fixture: ComponentFixture<LevelsComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    await TestBed.configureTestingModule({
 | 
			
		||||
      declarations: [ LevelsComponent ]
 | 
			
		||||
    })
 | 
			
		||||
    .compileComponents();
 | 
			
		||||
 | 
			
		||||
    fixture = TestBed.createComponent(LevelsComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,272 @@
 | 
			
		||||
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";
 | 
			
		||||
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, Query } from "../../../../../../models/graphql/query.model";
 | 
			
		||||
import { Queries } from "../../../../../../models/graphql/queries.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 { LevelMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model";
 | 
			
		||||
import { Mutations } from "../../../../../../models/graphql/mutations.model";
 | 
			
		||||
import { Subject, throwError } from "rxjs";
 | 
			
		||||
import { Server } from "../../../../../../models/data/server.model";
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: "app-levels",
 | 
			
		||||
  templateUrl: "./levels.component.html",
 | 
			
		||||
  styleUrls: ["./levels.component.scss"]
 | 
			
		||||
})
 | 
			
		||||
export class LevelsComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  public levels: Level[] = [];
 | 
			
		||||
  public loading = true;
 | 
			
		||||
 | 
			
		||||
  public isEditingNew: boolean = false;
 | 
			
		||||
 | 
			
		||||
  public filterForm!: FormGroup<{
 | 
			
		||||
    id: FormControl<number | null>,
 | 
			
		||||
    name: FormControl<string | null>,
 | 
			
		||||
    color: FormControl<string | null>,
 | 
			
		||||
    min_xp: FormControl<number | null>,
 | 
			
		||||
    permissions: FormControl<string | null>,
 | 
			
		||||
  }>;
 | 
			
		||||
 | 
			
		||||
  public filter: LevelFilter = {};
 | 
			
		||||
  public page: Page = {
 | 
			
		||||
    pageSize: undefined,
 | 
			
		||||
    pageIndex: undefined
 | 
			
		||||
  };
 | 
			
		||||
  public sort: Sort = {
 | 
			
		||||
    sortColumn: undefined,
 | 
			
		||||
    sortDirection: undefined
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  public totalRecords: number = 0;
 | 
			
		||||
 | 
			
		||||
  public clonedLevels: { [s: string]: Level; } = {};
 | 
			
		||||
 | 
			
		||||
  private unsubscriber = new Subject<void>();
 | 
			
		||||
  private server: Server = {};
 | 
			
		||||
 | 
			
		||||
  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(server => {
 | 
			
		||||
      this.server = server;
 | 
			
		||||
      this.loadNextPage();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public ngOnDestroy(): void {
 | 
			
		||||
    this.unsubscriber.next();
 | 
			
		||||
    this.unsubscriber.complete();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public loadNextPage(): void {
 | 
			
		||||
    this.loading = true;
 | 
			
		||||
    this.data.query<LevelListQuery>(Queries.levelQuery, {
 | 
			
		||||
        serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort
 | 
			
		||||
      },
 | 
			
		||||
      (data: Query) => {
 | 
			
		||||
          return data.servers[0];
 | 
			
		||||
        }
 | 
			
		||||
    ).subscribe(data => {
 | 
			
		||||
      this.totalRecords = data.levelCount;
 | 
			
		||||
      this.levels = data.levels;
 | 
			
		||||
      this.spinner.hideSpinner();
 | 
			
		||||
      this.loading = false;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public setFilterForm(): void {
 | 
			
		||||
    this.filterForm = this.fb.group({
 | 
			
		||||
      id: new FormControl<number | null>(null),
 | 
			
		||||
      name: new FormControl<string | null>(null),
 | 
			
		||||
      color: new FormControl<string | null>(null),
 | 
			
		||||
      min_xp: new FormControl<number | null>(null),
 | 
			
		||||
      permissions: new FormControl<string | null>(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 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;
 | 
			
		||||
    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.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<LevelMutationResult>(Mutations.createLevel, {
 | 
			
		||||
          name: newLevel.name,
 | 
			
		||||
          color: newLevel.color,
 | 
			
		||||
          minXp: newLevel.minXp,
 | 
			
		||||
          permissions: newLevel.permissions,
 | 
			
		||||
          serverId: this.server.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.loadNextPage();
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.spinner.showSpinner();
 | 
			
		||||
    this.data.mutation<UpdateUserMutationResult>(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<LevelMutationResult>(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_failed_d", { 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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								kdb-web/src/app/modules/view/server/levels/levels.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								kdb-web/src/app/modules/view/server/levels/levels.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -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 {
 | 
			
		||||
}
 | 
			
		||||
@@ -164,7 +164,8 @@
 | 
			
		||||
            <p-cellEditor>
 | 
			
		||||
              <ng-template pTemplate="input">
 | 
			
		||||
                <p-inputNumber class="table-edit-input" styleClass="input-number" [(ngModel)]="member.xp" mode="decimal" [min]="0" [useGrouping]="false" [showButtons]="true"
 | 
			
		||||
                               inputId="minmax-buttons"></p-inputNumber>
 | 
			
		||||
                               inputId="minmax-buttons">
 | 
			
		||||
                </p-inputNumber>
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template pTemplate="output">
 | 
			
		||||
                {{member.xp}}
 | 
			
		||||
@@ -225,12 +226,13 @@
 | 
			
		||||
            <div class="btn-wrapper">
 | 
			
		||||
              <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"
 | 
			
		||||
                      (click)="onRowEditInit(dt, member, ri)"></button>
 | 
			
		||||
              <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-user" [routerLink]="member.id"></button>
 | 
			
		||||
              <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-user"
 | 
			
		||||
                      [routerLink]="member.id"></button>
 | 
			
		||||
 | 
			
		||||
              <button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn"
 | 
			
		||||
                      icon="pi pi-check-circle" (click)="onRowEditSave(dt, member, ri)"></button>
 | 
			
		||||
              <button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn"
 | 
			
		||||
                      icon="pi pi-times-circle" (click)="onRowEditCancel(member, ri)"></button>
 | 
			
		||||
                      icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button>
 | 
			
		||||
            </div>
 | 
			
		||||
          </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,19 +5,21 @@ 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";
 | 
			
		||||
import { Queries } from "../../../../models/graphql/queries.model";
 | 
			
		||||
import { LevelListQuery, UserListQuery } from "../../../../models/graphql/query.model";
 | 
			
		||||
import { LevelListQuery, Query, UserListQuery } from "../../../../models/graphql/query.model";
 | 
			
		||||
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";
 | 
			
		||||
import { Server } from "../../../../models/data/server.model";
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: "app-members",
 | 
			
		||||
@@ -26,7 +28,6 @@ import { ActivatedRoute } from "@angular/router";
 | 
			
		||||
})
 | 
			
		||||
export class MembersComponent implements OnInit {
 | 
			
		||||
  members!: User[];
 | 
			
		||||
  // levelsFilter!: MenuItem[];
 | 
			
		||||
  levels!: MenuItem[];
 | 
			
		||||
  leftServerOptions = [
 | 
			
		||||
    { label: this.translate.instant("common.bool_as_string.true"), value: false },
 | 
			
		||||
@@ -64,7 +65,7 @@ export class MembersComponent implements OnInit {
 | 
			
		||||
    discordId: FormControl<number | null>,
 | 
			
		||||
    name: FormControl<string | null>,
 | 
			
		||||
    leftServer: FormControl<boolean | null>,
 | 
			
		||||
    level: FormControl<number | null>
 | 
			
		||||
    level: FormControl<Level | null>
 | 
			
		||||
  }>;
 | 
			
		||||
 | 
			
		||||
  filter: UserFilter = {};
 | 
			
		||||
@@ -78,6 +79,8 @@ export class MembersComponent implements OnInit {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  totalRecords!: number;
 | 
			
		||||
  private unsubscriber = new Subject<void>();
 | 
			
		||||
  private server: Server = {};
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private authService: AuthService,
 | 
			
		||||
@@ -95,11 +98,13 @@ export class MembersComponent implements OnInit {
 | 
			
		||||
    this.setFilterForm();
 | 
			
		||||
 | 
			
		||||
    this.data.getServerFromRoute(this.route).then(server => {
 | 
			
		||||
      this.server = server;
 | 
			
		||||
      this.spinner.showSpinner();
 | 
			
		||||
      this.data.query<LevelListQuery>(Queries.levelQuery, {
 | 
			
		||||
          filter: {
 | 
			
		||||
            server: { id: server.id }
 | 
			
		||||
          }
 | 
			
		||||
          serverId: server.id
 | 
			
		||||
        },
 | 
			
		||||
        (data: Query) => {
 | 
			
		||||
          return data.servers[0];
 | 
			
		||||
        }
 | 
			
		||||
      ).subscribe(data => {
 | 
			
		||||
        this.levels = data.levels.map(level => {
 | 
			
		||||
@@ -114,7 +119,10 @@ export class MembersComponent implements OnInit {
 | 
			
		||||
    this.spinner.showSpinner();
 | 
			
		||||
    this.loading = true;
 | 
			
		||||
    this.data.query<UserListQuery>(Queries.usersQuery, {
 | 
			
		||||
        filter: this.filter, page: this.page, sort: this.sort
 | 
			
		||||
        serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort
 | 
			
		||||
      },
 | 
			
		||||
      (x: { servers: Server[] }) => {
 | 
			
		||||
        return x.servers[0];
 | 
			
		||||
      }
 | 
			
		||||
    ).subscribe(data => {
 | 
			
		||||
      this.totalRecords = data.userCount;
 | 
			
		||||
@@ -130,10 +138,11 @@ export class MembersComponent implements OnInit {
 | 
			
		||||
      discordId: new FormControl<number | null>(null),
 | 
			
		||||
      name: [""],
 | 
			
		||||
      leftServer: new FormControl<boolean | null>(null),
 | 
			
		||||
      level: new FormControl<number | null>(null)
 | 
			
		||||
      level: new FormControl<Level | null>(null)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.filterForm.valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.unsubscriber),
 | 
			
		||||
      debounceTime(600)
 | 
			
		||||
    ).subscribe(changes => {
 | 
			
		||||
      if (changes.id) {
 | 
			
		||||
@@ -162,7 +171,7 @@ export class MembersComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
      if (changes.level) {
 | 
			
		||||
        this.filter.level = {
 | 
			
		||||
          id: changes.level
 | 
			
		||||
          id: changes.level.id
 | 
			
		||||
        };
 | 
			
		||||
      } else {
 | 
			
		||||
        this.filter.level = undefined;
 | 
			
		||||
@@ -233,7 +242,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];
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ import { UserDTO } from "../../../../models/auth/auth-user.dto";
 | 
			
		||||
import { AuthService } from "src/app/services/auth/auth.service";
 | 
			
		||||
import { ToastService } from "src/app/services/toast/toast.service";
 | 
			
		||||
import { TranslateService } from "@ngx-translate/core";
 | 
			
		||||
import { Server } from "../../../../models/data/server.model";
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: "app-profile",
 | 
			
		||||
@@ -18,6 +19,7 @@ import { TranslateService } from "@ngx-translate/core";
 | 
			
		||||
export class ProfileComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  user: User = { createdAt: "", modifiedAt: "" };
 | 
			
		||||
  private server: Server = {};
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
@@ -36,6 +38,7 @@ export class ProfileComponent implements OnInit {
 | 
			
		||||
        this.router.navigate([`/server/${server.id}`]);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.server = server;
 | 
			
		||||
 | 
			
		||||
      let authUser = await this.auth.getLoggedInUser();
 | 
			
		||||
      this.spinner.showSpinner();
 | 
			
		||||
@@ -47,16 +50,20 @@ export class ProfileComponent implements OnInit {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.data.query<User>(Queries.singleUserQuery, {
 | 
			
		||||
      this.data.query<UserListQuery>(Queries.usersQuery, {
 | 
			
		||||
          serverId: this.server.id,
 | 
			
		||||
          filter: {
 | 
			
		||||
            id: this.route.snapshot.params["memberId"]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        function(data: UserListQuery) {
 | 
			
		||||
          return data.users.length > 0 ? data.users[0] : null;
 | 
			
		||||
        (x: { servers: Server[] }) => {
 | 
			
		||||
          return x.servers[0];
 | 
			
		||||
        }
 | 
			
		||||
      ).subscribe(user => {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
      ).subscribe(users => {
 | 
			
		||||
        if (!users.users[0]) {
 | 
			
		||||
          this.router.navigate([`/server/${server.id}`]);
 | 
			
		||||
        }
 | 
			
		||||
        this.user = users.users[0];
 | 
			
		||||
        this.spinner.hideSpinner();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,14 +5,16 @@ 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 {
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ export class DataService {
 | 
			
		||||
  public getServerFromRoute(route: ActivatedRoute): Promise<Server> {
 | 
			
		||||
    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();
 | 
			
		||||
 
 | 
			
		||||
@@ -18,16 +18,16 @@ export class SidebarService {
 | 
			
		||||
  menuItems$ = new BehaviorSubject<MenuItem[]>(new Array<MenuItem>());
 | 
			
		||||
  server$ = new BehaviorSubject<Server | null>(null);
 | 
			
		||||
 | 
			
		||||
  dashboard!: MenuItem;
 | 
			
		||||
  serverDashboard!: MenuItem;
 | 
			
		||||
  serverProfile!: MenuItem;
 | 
			
		||||
  serverMembers!: MenuItem;
 | 
			
		||||
  serverAutoRoles!: MenuItem;
 | 
			
		||||
  serverAutoRoleRules!: 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,
 | 
			
		||||
@@ -66,7 +66,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 +78,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 +95,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 +141,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;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ export class ThemeService {
 | 
			
		||||
 | 
			
		||||
  sidebarWidth = '150px';
 | 
			
		||||
  isSidebarOpen = false;
 | 
			
		||||
  hasLangChanged = false;
 | 
			
		||||
 | 
			
		||||
  themeName$ = new BehaviorSubject<string>(Themes.Default);
 | 
			
		||||
  isSidebarOpen$ = new BehaviorSubject<boolean>(true);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
    "WebVersion": {
 | 
			
		||||
        "Major": "1",
 | 
			
		||||
        "Minor": "0",
 | 
			
		||||
        "Micro": "0"
 | 
			
		||||
        "Micro": "dev220"
 | 
			
		||||
    },
 | 
			
		||||
    "Themes": [
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
      "dashboard": "Dashboard",
 | 
			
		||||
      "profile": "Dein Profil",
 | 
			
		||||
      "members": "Mitglieder",
 | 
			
		||||
      "levels": "Level",
 | 
			
		||||
      "auto_roles": "Auto Rollen"
 | 
			
		||||
    },
 | 
			
		||||
    "server_empty": "Kein Server ausgewählt",
 | 
			
		||||
@@ -220,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!"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
@@ -281,6 +282,38 @@
 | 
			
		||||
            "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",
 | 
			
		||||
          "actions": "Aktionen"
 | 
			
		||||
        },
 | 
			
		||||
        "no_entries_found": "Keine Einträge gefunden",
 | 
			
		||||
        "message": {
 | 
			
		||||
          "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!"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "user-list": {},
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user