diff --git a/kdb-web/src/app/components/footer/footer.component.ts b/kdb-web/src/app/components/footer/footer.component.ts
index bd4f1e61..47f24b99 100644
--- a/kdb-web/src/app/components/footer/footer.component.ts
+++ b/kdb-web/src/app/components/footer/footer.component.ts
@@ -13,8 +13,8 @@ import { SpinnerService } from "src/app/services/spinner/spinner.service";
export class FooterComponent implements OnInit {
- frontendVersion!: SoftwareVersion;
- backendVersion!: SoftwareVersion;
+ frontendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0");
+ backendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0");
constructor(
private settings: SettingsService,
diff --git a/kdb-web/src/app/models/data/discord.model.ts b/kdb-web/src/app/models/data/discord.model.ts
index 9f9ac6ba..6e8bc0b0 100644
--- a/kdb-web/src/app/models/data/discord.model.ts
+++ b/kdb-web/src/app/models/data/discord.model.ts
@@ -3,7 +3,7 @@ export interface Guild {
name?: string;
channels: [Channel]
- role: [Role]
+ roles: [Role]
emojis: [Emoji]
}
diff --git a/kdb-web/src/app/models/data/server.model.ts b/kdb-web/src/app/models/data/server.model.ts
index 8df91d13..cc160e68 100644
--- a/kdb-web/src/app/models/data/server.model.ts
+++ b/kdb-web/src/app/models/data/server.model.ts
@@ -2,6 +2,7 @@ import {Data} from "./data.model";
import {User} from "./user.model";
import {Level} from "./level.model";
import {Client} from "./client.model";
+import { AutoRole } from "./auto_role.model";
export interface Server extends Data {
id?: number;
@@ -9,7 +10,7 @@ export interface Server extends Data {
name?: string;
iconURL?: string;
autoRoleCount?: number;
- autoRoles?: [];
+ autoRoles?: AutoRole[];
clientCount?: number;
clients?: Client[];
levelCount?: number;
diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts
index 1824c577..82bb40af 100644
--- a/kdb-web/src/app/models/graphql/queries.model.ts
+++ b/kdb-web/src/app/models/graphql/queries.model.ts
@@ -157,28 +157,30 @@ export class Queries {
`;
static autoRolesQuery = `
- query AutoRoleQuery($filter: AutoRoleFilter, $page: Page, $sort: Sort) {
- autoRoleCount
- autoRoles(filter: $filter, page: $page, sort: $sort) {
- id
- channelId
- channelName
- messageId
- autoRoleRuleCount
-
- server {
+ query AutoRoleQuery($serverId: ID, $filter: AutoRoleFilter, $page: Page, $sort: Sort) {
+ servers(filter: {id: $serverId}) {
+ autoRoleCount
+ autoRoles(filter: $filter, page: $page, sort: $sort) {
id
- }
+ channelId
+ channelName
+ messageId
+ autoRoleRuleCount
- createdAt
- modifiedAt
+ server {
+ id
+ }
+
+ createdAt
+ modifiedAt
+ }
}
}
`;
static autoRoleRulesQuery = `
- query AutoRoleRuleQuery($serverId: ID, $autoRoleId: ID, $filter: AutoRoleFilter, $page: Page, $sort: Sort) {
- servers(filter: {id: $serverId} {
+ query AutoRoleRuleQuery($serverId: ID, $autoRoleId: ID, $filter: AutoRoleRuleFilter, $page: Page, $sort: Sort) {
+ servers(filter: {id: $serverId}) {
autoRoles(filter: {id: $autoRoleId}) {
autoRoleRuleCount
autoRoleRules(filter: $filter, page: $page, sort: $sort) {
diff --git a/kdb-web/src/app/models/graphql/variables.model.ts b/kdb-web/src/app/models/graphql/variables.model.ts
index fdc5d93f..8acb41a6 100644
--- a/kdb-web/src/app/models/graphql/variables.model.ts
+++ b/kdb-web/src/app/models/graphql/variables.model.ts
@@ -5,4 +5,5 @@ export interface Variables {
filter?: object;
page?: Page;
sort?: Sort;
+ [x: string | number | symbol]: unknown;
}
diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts
index 1402c6ef..986ddd26 100644
--- a/kdb-web/src/app/modules/shared/shared.module.ts
+++ b/kdb-web/src/app/modules/shared/shared.module.ts
@@ -21,6 +21,7 @@ import { BoolPipe } from './pipes/bool.pipe';
import { PanelMenuModule } from 'primeng/panelmenu';
import { PanelModule } from "primeng/panel";
import { InputNumberModule } from 'primeng/inputnumber';
+import { ImageModule } from "primeng/image";
@@ -51,6 +52,7 @@ import { InputNumberModule } from 'primeng/inputnumber';
PanelMenuModule,
PanelModule,
InputNumberModule,
+ ImageModule
],
exports: [
ButtonModule,
@@ -75,6 +77,7 @@ import { InputNumberModule } from 'primeng/inputnumber';
IpAddressPipe,
BoolPipe,
InputNumberModule,
+ ImageModule
]
})
export class SharedModule { }
diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html
index 03f26bd4..fd1a4536 100644
--- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html
+++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html
@@ -1 +1,188 @@
-
auto-roles-rules works!
+
+ {{'view.server.auto_roles.rules.header' | translate}}
+
+
+
+
+
+
+
+
+ {{rules.length}} {{'view.server.auto_roles.rules.of' | translate}}
+ {{dt.totalRecords}}
+
+ {{'view.server.auto_roles.rules.auto_roles' | translate}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
+
+
+
+
+ {{autoRoleRule.id}}
+
+
+ {{autoRoleRule.id}}
+
+
+ |
+
+
+
+
+
+
+
+ {{autoRoleRule.roleName}}
+
+
+ |
+
+
+
+
+
+
+
+
+ {{autoRoleRule.emojiName}}
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+ {{autoRoleRule.createdAt | date:'dd.MM.yy HH:mm'}}
+
+
+ {{autoRoleRule.createdAt | date:'dd.MM.yy HH:mm'}}
+
+
+ |
+
+
+
+
+ {{autoRoleRule.modifiedAt | date:'dd.MM.yy HH:mm'}}
+
+
+ {{autoRoleRule.modifiedAt | date:'dd.MM.yy HH:mm'}}
+
+
+ |
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+ {{'view.server.auto_roles.rules.no_entries_found' | translate}} |
+
+
+
+
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts
index 538afde3..cca972a0 100644
--- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts
+++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts
@@ -1,6 +1,27 @@
import { Component, OnInit } from "@angular/core";
import { DataService } from "../../../../../../services/data/data.service";
-import { ActivatedRoute } from "@angular/router";
+import { ActivatedRoute, Router } from "@angular/router";
+import { AutoRoleRule, AutoRoleRuleFilter } from "../../../../../../models/data/auto_role.model";
+import { Guild } from "../../../../../../models/data/discord.model";
+import { LazyLoadEvent, MenuItem } from "primeng/api";
+import { User } from "../../../../../../models/data/user.model";
+import { FormBuilder, FormControl, FormGroup } from "@angular/forms";
+import { Page } from "../../../../../../models/graphql/filter/page.model";
+import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model";
+import { AuthService } from "../../../../../../services/auth/auth.service";
+import { SpinnerService } from "../../../../../../services/spinner/spinner.service";
+import { ToastService } from "../../../../../../services/toast/toast.service";
+import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service";
+import { TranslateService } from "@ngx-translate/core";
+import { SidebarService } from "../../../../../../services/sidebar/sidebar.service";
+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 { Table } from "primeng/table";
+import { AutoRoleMutationResult } from "../../../../../../models/graphql/result.model";
+import { Mutations } from "../../../../../../models/graphql/mutations.model";
+import { throwError } from "rxjs";
@Component({
selector: "app-auto-roles-rules",
@@ -9,14 +30,243 @@ import { ActivatedRoute } from "@angular/router";
})
export class AutoRolesRulesComponent implements OnInit {
+ rules!: AutoRoleRule[];
+ guild!: Guild;
+ emojis!: MenuItem[];
+ roles!: MenuItem[];
+ loading = true;
+
+ autoRoleId!: number;
+
+ clonedUsers: { [s: string]: User; } = {};
+ isEditingNew: boolean = false;
+
+ newAutoRoleTemplate: AutoRoleRule = {
+ id: 0,
+ createdAt: "",
+ modifiedAt: ""
+ };
+
+ filterForm!: FormGroup<{
+ id: FormControl,
+ emojiName: FormControl,
+ roleId: FormControl,
+ }>;
+
+ filter: AutoRoleRuleFilter = {};
+ page: Page = {
+ pageSize: undefined,
+ pageIndex: undefined
+ };
+ sort: Sort = {
+ sortColumn: undefined,
+ sortDirection: undefined
+ };
+
+ totalRecords!: number;
+
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,
+ private router: Router
) {
}
+ getEmojiUrl(name: string): string {
+ return this.guild.emojis.filter(x => x.name == name)[0].url ?? "";
+ }
+
ngOnInit(): void {
this.data.getServerFromRoute(this.route);
+ this.spinner.showSpinner();
+ if (!this.route.snapshot.params["autoRoleId"]) {
+ this.spinner.hideSpinner();
+ this.router.navigate(["../"]);
+ return;
+ }
+ this.autoRoleId = +this.route.snapshot.params["autoRoleId"];
+
+ this.spinner.showSpinner();
+ this.data.query(Queries.guildsQuery, {
+ filter: {
+ id: this.sidebar.server$.value?.discordId
+ }
+ }
+ ).subscribe(data => {
+ this.guild = data.guilds[0];
+ this.emojis = this.guild.emojis
+ .map(x => {
+ return { label: x.name, value: x };
+ });
+ this.roles = this.guild.roles
+ .map(x => {
+ return { label: x.name, value: x };
+ });
+ this.spinner.hideSpinner();
+ });
+
+ this.setFilterForm();
+ this.loadNextPage();
+ }
+
+ loadNextPage() {
+ this.loading = true;
+ this.data.query(Queries.autoRoleRulesQuery, {
+ id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort
+ },
+ (x: { servers: Server[] }) => {
+ if (!x.servers[0].autoRoles || x.servers[0].autoRoles?.length == 0) {
+ return undefined;
+ }
+ return x.servers[0].autoRoles[0];
+ }
+ ).subscribe(data => {
+ this.totalRecords = data.autoRoleRuleCount;
+ this.rules = data.autoRoleRules;
+ this.spinner.hideSpinner();
+ this.loading = false;
+ });
+ }
+
+ setFilterForm() {
+ this.filterForm = this.fb.group({
+ id: new FormControl(null),
+ emojiName: new FormControl(null),
+ roleId: new FormControl(null)
+ });
+
+ this.filterForm.valueChanges.pipe(
+ debounceTime(600)
+ ).subscribe(changes => {
+ if (changes.id) {
+ this.filter.id = changes.id;
+ } else {
+ this.filter.id = undefined;
+ }
+
+ if (changes.emojiName) {
+ this.filter.emojiName = changes.emojiName;
+ } else {
+ this.filter.emojiName = undefined;
+ }
+
+ if (changes.roleId) {
+ this.filter.roleId = changes.roleId;
+ } else {
+ this.filter.roleId = undefined;
+ }
+
+ if (this.page.pageSize)
+ this.page.pageSize = 10;
+
+ if (this.page.pageIndex)
+ this.page.pageIndex = 0;
+
+ this.loadNextPage();
+ });
+ }
+
+ nextPage(event: LazyLoadEvent) {
+ this.page.pageSize = event.rows ?? 0;
+ if (event.first != null && event.rows != null)
+ this.page.pageIndex = event.first / event.rows;
+ this.sort.sortColumn = event.sortField ?? undefined;
+ this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC;
+
+ this.loadNextPage();
+ }
+
+ resetFilters() {
+ this.filterForm.reset();
+ }
+
+ onRowEditInit(table: Table, autoRoleRule: AutoRoleRule, index: number) {
+ this.clonedUsers[index] = { ...autoRoleRule };
+ }
+
+ onRowEditSave(table: Table, newAutoRole: AutoRoleRule, index: number) {
+ if (this.isEditingNew && JSON.stringify(newAutoRole) === JSON.stringify(this.newAutoRoleTemplate)) {
+ this.isEditingNew = false;
+ this.rules.splice(index, 1);
+ return;
+ }
+
+ if (!newAutoRole.id || !newAutoRole.emojiName && !newAutoRole.roleId) {
+ return;
+ }
+
+ this.spinner.showSpinner();
+ this.data.mutation(Mutations.createAutoRoleRule, {
+ serverId: this.sidebar.server$.value?.id,
+ emojiName: newAutoRole.emojiName,
+ roleId: newAutoRole.roleId
+ }
+ ).pipe(catchError(err => {
+ 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.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();
+ });
+ }
+
+ onRowEditCancel(index: number) {
+ if (this.isEditingNew) {
+ this.rules.splice(index, 1);
+ delete this.clonedUsers[index];
+ this.isEditingNew = false;
+ return;
+ }
+
+ this.rules[index] = this.clonedUsers[index];
+ delete this.clonedUsers[index];
+ }
+
+ deleteAutoRoleRule(autoRoleRule: AutoRoleRule) {
+ this.confirmDialog.confirmDialog(
+ this.translate.instant("view.server.auto_roles.message.auto_role_delete"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_q", { id: autoRoleRule.id }),
+ () => {
+ this.spinner.showSpinner();
+ this.data.mutation(Mutations.deleteAutoRole, {
+ id: autoRoleRule.id
+ }
+ ).pipe(catchError(err => {
+ this.spinner.hideSpinner();
+ this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed_d", { id: autoRoleRule.id }));
+ return throwError(err);
+ })).subscribe(_ => {
+ this.spinner.hideSpinner();
+ this.toastService.success(this.translate.instant("view.server.auto_roles.message.auto_role_deleted"), this.translate.instant("view.server.auto_roles.message.auto_role_deleted_d", { id: autoRoleRule.id }));
+ this.loadNextPage();
+ });
+ });
+
+
+ }
+
+ addAutoRoleRule(table: Table) {
+ const newAutoRole = JSON.parse(JSON.stringify(this.newAutoRoleTemplate));
+ newAutoRole.id = Math.max.apply(Math, this.rules.map(u => {
+ return u.id ?? 0;
+ })) + 1;
+
+ this.rules.push(newAutoRole);
+
+ table.initRowEdit(newAutoRole);
+
+ const index = this.rules.findIndex(u => u.id == newAutoRole.id);
+ this.onRowEditInit(table, newAutoRole, index);
+
+ this.isEditingNew = true;
}
}
diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts
index 6659fc68..e7718ca7 100644
--- a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts
+++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts
@@ -21,6 +21,7 @@ import { Mutations } from "../../../../../../models/graphql/mutations.model";
import { 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";
@Component({
selector: "app-auto-roles",
@@ -100,7 +101,10 @@ export class AutoRolesComponent implements OnInit {
loadNextPage() {
this.loading = true;
this.data.query(Queries.autoRolesQuery, {
- filter: this.filter, page: this.page, sort: this.sort
+ id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort
+ },
+ (x: { servers: Server[] }) => {
+ return x.servers[0];
}
).subscribe(data => {
this.totalRecords = data.autoRoleCount;
diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts
index 5a6b37ed..fbcb7c45 100644
--- a/kdb-web/src/app/services/data/data.service.ts
+++ b/kdb-web/src/app/services/data/data.service.ts
@@ -53,7 +53,7 @@ export class DataService {
})
.pipe(map(d => {
if (d.errors && d.errors.length > 0) {
- throw new Error(d.errors.toString());
+ throw new Error(d.errors.map((x: {message: String}) => x.message).toString());
}
return d.data;
}))
diff --git a/kdb-web/src/app/services/error-handler/error-handler.service.ts b/kdb-web/src/app/services/error-handler/error-handler.service.ts
index b2ed4f6d..89786ef2 100644
--- a/kdb-web/src/app/services/error-handler/error-handler.service.ts
+++ b/kdb-web/src/app/services/error-handler/error-handler.service.ts
@@ -1,16 +1,17 @@
-import { HttpErrorResponse } from '@angular/common/http';
-import { ErrorHandler, Injectable, Injector } from '@angular/core';
-import { Observable, throwError } from 'rxjs';
-import { ErrorDTO } from 'src/app/models/error/error-dto';
-import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum';
-import { AuthService } from '../auth/auth.service';
-import { ToastService } from '../toast/toast.service';
+import { HttpErrorResponse } from "@angular/common/http";
+import { ErrorHandler, Injectable } from "@angular/core";
+import { Observable, throwError } from "rxjs";
+import { ErrorDTO } from "src/app/models/error/error-dto";
+import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum";
+import { AuthService } from "../auth/auth.service";
+import { ToastService } from "../toast/toast.service";
@Injectable()
export class ErrorHandlerService implements ErrorHandler {
constructor(
- private injector: Injector
+ private auth: AuthService,
+ private toast: ToastService,
) { }
handleError(error: HttpErrorResponse): Observable {
@@ -20,7 +21,7 @@ export class ErrorHandlerService implements ErrorHandler {
const errorDto: ErrorDTO = error.error;
if (errorDto.errorCode === ServiceErrorCode.Unauthorized) {
- this.injector.get(AuthService).logout();
+ this.auth.logout();
return throwError(() => error);
}
@@ -34,11 +35,13 @@ export class ErrorHandlerService implements ErrorHandler {
message = error.message;
}
- this.injector.get(ToastService).error(header, message);
+ this.toast.error(header, message);
+ } else {
+ console.error(error.message);
}
if (error.status === 401) {
- this.injector.get(AuthService).logout();
+ this.auth.logout();
}
return throwError(() => error);
}
diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts
index 601a8ad0..021f434f 100644
--- a/kdb-web/src/app/services/sidebar/sidebar.service.ts
+++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts
@@ -8,7 +8,6 @@ import { NavigationEnd, Router } from "@angular/router";
import { ThemeService } from "../theme/theme.service";
import { Server } from "../../models/data/server.model";
import { UserDTO } from "../../models/auth/auth-user.dto";
-import { AutoRole } from "../../models/data/auto_role.model";
@Injectable({
providedIn: "root"
@@ -18,7 +17,6 @@ export class SidebarService {
isSidebarOpen: boolean = true;
menuItems$ = new BehaviorSubject