diff --git a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py
index 22669a7c..2480be82 100644
--- a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py
+++ b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py
@@ -150,6 +150,12 @@ class ServerConfigMutation(QueryABC):
self._server_configs.delete_server_team_role_id_config(role_id)
+ for role_id in new_config.team_role_ids:
+ guild = self._bot.get_guild(new_config.server.discord_id)
+ role = guild.get_role(int(role_id.role_id))
+ if role is None:
+ raise ValueError(f"Invalid roleId")
+
for role_id in new_config.team_role_ids:
if role_id.role_id in old_config.team_role_ids.select(lambda x: str(x.role_id)):
continue
diff --git a/kdb-web/src/app/models/config/server-config.model.ts b/kdb-web/src/app/models/config/server-config.model.ts
new file mode 100644
index 00000000..b55c4136
--- /dev/null
+++ b/kdb-web/src/app/models/config/server-config.model.ts
@@ -0,0 +1,21 @@
+import { DataWithHistory } from "../data/data.model";
+
+export interface ServerConfig extends DataWithHistory {
+ id?: number;
+ messageDeleteTimer?: number;
+ notificationChatId?: string;
+ maxVoiceStateHours?: number;
+ xpPerMessage?: number;
+ xpPerReaction?: number;
+ maxMessageXpPerHour?: number;
+ xpPerOntimeHour?: number;
+ xpPerEventParticipation?: number;
+ xpPerAchievement?: number;
+ afkCommandChannelId?: string;
+ helpVoiceChannelId?: string;
+ teamChannelId?: string;
+ loginMessageChannelId?: string;
+ afkChannelIds: string[];
+ moderatorRoleIds: string[];
+ adminRoleIds: string[];
+}
diff --git a/kdb-web/src/app/models/config/technician-config.model.ts b/kdb-web/src/app/models/config/technician-config.model.ts
index 02ade32c..6e1430f0 100644
--- a/kdb-web/src/app/models/config/technician-config.model.ts
+++ b/kdb-web/src/app/models/config/technician-config.model.ts
@@ -6,6 +6,6 @@ export interface TechnicianConfig extends DataWithHistory {
waitForRestart?: number;
waitForShutdown?: number;
cacheMaxMessages?: number;
- pingURLs?: string[];
- technicianIds?: string[];
+ pingURLs: string[];
+ technicianIds: string[];
}
diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts
index 2aa447cd..7905eff4 100644
--- a/kdb-web/src/app/models/graphql/mutations.model.ts
+++ b/kdb-web/src/app/models/graphql/mutations.model.ts
@@ -166,8 +166,6 @@ export class Mutations {
}
`;
-
-
static updateTechnicianConfig = `
mutation updateTechnicianConfig($id: ID, $helpCommandReferenceUrl: String, $waitForRestart: Int, $waitForShutdown: Int, $cacheMaxMessages: Int, $pingURLs: [String], $technicianIds: [String]) {
technicianConfig {
@@ -191,4 +189,70 @@ export class Mutations {
}
}
`;
+
+ static updateServerConfig = `
+ mutation updateServerConfig(
+ $id: ID,
+ $messageDeleteTimer: Int,
+ $notificationChatId: String,
+ $maxVoiceStateHours: Int,
+ $xpPerMessage: Int,
+ $xpPerReaction: Int,
+ $maxMessageXpPerHour: Int,
+ $xpPerOntimeHour: Int,
+ $xpPerEventParticipation: Int,
+ $xpPerAchievement: Int,
+ $afkCommandChannelId: String,
+ $helpVoiceChannelId: String,
+ $teamChannelId: String,
+ $loginMessageChannelId: String,
+ $afkChannelIds: [String],
+ $moderatorRoleIds: [String],
+ $adminRoleIds: [String]
+ ) {
+ serverConfig {
+ updateServerConfig(input: {
+ id: $id,
+ messageDeleteTimer: $messageDeleteTimer
+ notificationChatId: $notificationChatId
+ maxVoiceStateHours: $maxVoiceStateHours
+ xpPerMessage: $xpPerMessage
+ xpPerReaction: $xpPerReaction
+ maxMessageXpPerHour: $maxMessageXpPerHour
+ xpPerOntimeHour: $xpPerOntimeHour
+ xpPerEventParticipation: $xpPerEventParticipation
+ xpPerAchievement: $xpPerAchievement
+ afkCommandChannelId: $afkCommandChannelId
+ helpVoiceChannelId: $helpVoiceChannelId
+ teamChannelId: $teamChannelId
+ loginMessageChannelId: $loginMessageChannelId
+ afkChannelIds: $afkChannelIds
+ moderatorRoleIds: $moderatorRoleIds
+ adminRoleIds: $adminRoleIds
+ }) {
+ id
+ messageDeleteTimer
+ notificationChatId
+ maxVoiceStateHours
+ xpPerMessage
+ xpPerReaction
+ maxMessageXpPerHour
+ xpPerOntimeHour
+ xpPerEventParticipation
+ xpPerAchievement
+ afkCommandChannelId
+ helpVoiceChannelId
+ teamChannelId
+ loginMessageChannelId
+ afkChannelIds
+ moderatorRoleIds
+ adminRoleIds
+
+ server {
+ id
+ }
+ }
+ }
+ }
+ `;
}
diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts
index 5311141e..55998599 100644
--- a/kdb-web/src/app/models/graphql/queries.model.ts
+++ b/kdb-web/src/app/models/graphql/queries.model.ts
@@ -1,22 +1,5 @@
export class Queries {
- static technicianConfigQuery = `
- query technicianConfigQuery {
- technicianConfig {
- id
- helpCommandReferenceUrl
- waitForRestart
- waitForShutdown
- cacheMaxMessages
- pingURLs
- technicianIds
-
- createdAt
- modifiedAt
- }
- }
- `;
-
static guildsQuery = `
query GuildsQuery($id: ID) {
guilds(filter: {id: $id}) {
@@ -71,7 +54,7 @@ export class Queries {
}
}
}
- `
+ `;
static levelQuery = `
query LevelsList($serverId: ID, $filter: LevelFilter, $page: Page, $sort: Sort) {
@@ -361,4 +344,52 @@ export class Queries {
}
}
`;
+
+ static technicianConfigQuery = `
+ query technicianConfigQuery {
+ technicianConfig {
+ id
+ helpCommandReferenceUrl
+ waitForRestart
+ waitForShutdown
+ cacheMaxMessages
+ pingURLs
+ technicianIds
+
+ createdAt
+ modifiedAt
+ }
+ }
+ `;
+
+ static serverConfigQuery = `
+ query serverConfigQuery($serverId: ID) {
+ servers(filter: { id: $serverId }) {
+ name
+ config {
+ id
+ messageDeleteTimer
+ notificationChatId
+ maxVoiceStateHours
+ xpPerMessage
+ xpPerReaction
+ maxMessageXpPerHour
+ xpPerOntimeHour
+ xpPerEventParticipation
+ xpPerAchievement
+ afkCommandChannelId
+ helpVoiceChannelId
+ teamChannelId
+ loginMessageChannelId
+ afkChannelIds
+ moderatorRoleIds
+ adminRoleIds
+
+ server {
+ id
+ }
+ }
+ }
+ }
+ `;
}
diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts
index 1cc35083..42eeb69d 100644
--- a/kdb-web/src/app/models/graphql/query.model.ts
+++ b/kdb-web/src/app/models/graphql/query.model.ts
@@ -5,6 +5,7 @@ import { Guild } from "../data/discord.model";
import { Level } from "../data/level.model";
import { Achievement, AchievementAttribute } from "../data/achievement.model";
import { TechnicianConfig } from "../config/technician-config.model";
+import { ServerConfig } from "../config/server-config.model";
export interface Query {
serverCount: number;
@@ -15,6 +16,10 @@ export interface TechnicianConfigQuery {
technicianConfig: TechnicianConfig;
}
+export interface ServerConfigQuery {
+ config: ServerConfig;
+}
+
export interface SingleDiscordQuery {
guilds: Guild[];
}
diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts
index 37445578..573f98ce 100644
--- a/kdb-web/src/app/models/graphql/result.model.ts
+++ b/kdb-web/src/app/models/graphql/result.model.ts
@@ -4,6 +4,7 @@ import { Level } from "../data/level.model";
import { Server } from "../data/server.model";
import { Achievement } from "../data/achievement.model";
import { TechnicianConfig } from "../config/technician-config.model";
+import { ServerConfig } from "../config/server-config.model";
export interface GraphQLResult {
data: {
@@ -54,6 +55,12 @@ export interface TechnicianConfigMutationResult {
};
}
+export interface ServerConfigMutationResult {
+ serverConfig: {
+ updateServerConfig?: ServerConfig
+ };
+}
+
export interface AchievementMutationResult {
achievement: {
createAchievement?: Achievement
diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html
index 76707043..b7e68a1b 100644
--- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html
+++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html
@@ -160,103 +160,13 @@
-
-
-
-
-
- {{'admin.settings.bot.ping_urls' | translate}}:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{pingUrl.value}}
-
-
- |
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
-
-
-
-
- {{'admin.settings.bot.technicianIds' | translate}}:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{technicianId.value}}
-
-
- |
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
+
+
+ (click)="saveTechnicianConfig()">
diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts
index c0cb39b8..c4b691a7 100644
--- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts
+++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts
@@ -1,5 +1,5 @@
import { Component, OnInit } from "@angular/core";
-import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms";
+import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { TranslateService } from "@ngx-translate/core";
import { catchError } from "rxjs/operators";
import { SettingsDTO } from "src/app/models/config/settings.dto";
@@ -17,17 +17,7 @@ import { DataService } from "../../../../../services/data/data.service";
import { TechnicianConfigMutationResult } from "../../../../../models/graphql/result.model";
import { Mutations } from "../../../../../models/graphql/mutations.model";
import { AuthService } from "../../../../../services/auth/auth.service";
-import { Table } from "primeng/table";
-type PingUrl = {
- id: number;
- value: string;
-};
-
-type TechnicianId = {
- id: number;
- value: string;
-};
@Component({
selector: "app-settings",
@@ -37,16 +27,6 @@ type TechnicianId = {
export class SettingsComponent implements OnInit {
testMailForm!: FormGroup;
- technicianConfigForm: FormGroup = this.formBuilder.group({
- helpCommandReferenceUrl: [null, [Validators.required]],
- waitForRestart: [null, [Validators.required]],
- waitForShutdown: [null, [Validators.required]],
- cacheMaxMessages: [null, [Validators.required]]
- });
- pingUrls: PingUrl[] = [];
- clonedPingUrls: { [s: number]: PingUrl } = {};
- technicianIds: TechnicianId[] = [];
- clonedTechnicianIds: { [s: number]: TechnicianId } = {};
data: SettingsDTO = {
webVersion: "",
apiVersion: "",
@@ -114,23 +94,6 @@ export class SettingsComponent implements OnInit {
this.testMailForm = this.formBuilder.group({
mail: [null, [Validators.required, Validators.email]]
});
- this.technicianConfigForm = this.formBuilder.group({
- helpCommandReferenceUrl: [this.config.helpCommandReferenceUrl, [Validators.required]],
- waitForRestart: [this.config.waitForRestart, [Validators.required]],
- waitForShutdown: [this.config.waitForShutdown, [Validators.required]],
- cacheMaxMessages: [this.config.cacheMaxMessages, [Validators.required]]
- });
- let id = 0;
- for (const url of this.config.pingURLs ?? []) {
- this.pingUrls.push({ id: id, value: url });
- id++;
- }
-
- id = 0;
- for (const technicianId of this.config.technicianIds ?? []) {
- this.technicianIds.push({ id: id, value: technicianId });
- id++;
- }
}
testMail(): void {
@@ -187,16 +150,11 @@ export class SettingsComponent implements OnInit {
waitForRestart: this.config.waitForRestart,
waitForShutdown: this.config.waitForShutdown,
cacheMaxMessages: this.config.cacheMaxMessages,
- pingURLs: this.pingUrls.filter(value => value.value).map(value => {
- return value.value;
- }),
- technicianIds: this.technicianIds.filter(value => value.value).map(value => {
- return value.value;
- })
+ pingURLs: this.config.pingURLs,
+ technicianIds: this.config.technicianIds
}
).pipe(catchError(err => {
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("admin.settings.message.technician_config_create_failed"), this.translate.instant("admin.settings.message.technician_config_create_failed_d"));
return throwError(err);
})).subscribe(result => {
this.spinner.hideSpinner();
@@ -204,71 +162,5 @@ export class SettingsComponent implements OnInit {
});
}
- pingUrlsAddNew(table: Table) {
- const id = Math.max.apply(Math, this.pingUrls.map(url => {
- return url.id ?? 0;
- })) + 1;
- const newItem = { id: id, value: "" };
- this.pingUrls.push(newItem);
-
- table.initRowEdit(newItem);
- const index = this.pingUrls.findIndex(l => l.id == newItem.id);
- this.pingUrlsEditInit(newItem, index);
- }
-
- pingUrlsEditInit(url: PingUrl, index: number) {
- this.clonedPingUrls[index] = { ...url };
- }
-
- pingUrlsDelete(index: number) {
- this.pingUrls.splice(index, 1);
- }
-
- pingUrlsEditSave(url: PingUrl, index: number) {
- if (!url.value || this.pingUrls[index] == this.clonedPingUrls[index]) {
- return;
- }
-
- delete this.clonedPingUrls[index];
- }
-
- pingUrlsEditCancel(url: PingUrl, index: number) {
- this.pingUrls[index] = this.clonedPingUrls[index];
- delete this.clonedPingUrls[index];
- }
-
-
- technicianIdsAddNew(table: Table) {
- const id = Math.max.apply(Math, this.technicianIds.map(url => {
- return url.id ?? 0;
- })) + 1;
- const newItem = { id: id, value: "" };
- this.technicianIds.push(newItem);
-
- table.initRowEdit(newItem);
- const index = this.technicianIds.findIndex(l => l.id == newItem.id);
- this.technicianIdsEditInit(newItem, index);
- }
-
- technicianIdsEditInit(url: PingUrl, index: number) {
- this.clonedTechnicianIds[index] = { ...url };
- }
-
- technicianIdsDelete(index: number) {
- this.technicianIds.splice(index, 1);
- }
-
- technicianIdsEditSave(url: PingUrl, index: number) {
- if (!url.value || this.technicianIds[index] == this.clonedTechnicianIds[index]) {
- return;
- }
-
- delete this.clonedTechnicianIds[index];
- }
-
- technicianIdsEditCancel(url: PingUrl, index: number) {
- this.technicianIds[index] = this.clonedTechnicianIds[index];
- delete this.clonedTechnicianIds[index];
- }
}
diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html
new file mode 100644
index 00000000..4e3ea7d2
--- /dev/null
+++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html
@@ -0,0 +1,45 @@
+
+
+
+ {{translationKey | translate}}:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{value.value}}
+
+
+ |
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.scss b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts
new file mode 100644
index 00000000..b571849c
--- /dev/null
+++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ConfigListComponent } from './config-list.component';
+
+describe('ConfigListComponent', () => {
+ let component: ConfigListComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ConfigListComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ConfigListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts
new file mode 100644
index 00000000..7fc92215
--- /dev/null
+++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.ts
@@ -0,0 +1,72 @@
+import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
+import { Table } from "primeng/table";
+
+@Component({
+ selector: "app-config-list",
+ templateUrl: "./config-list.component.html",
+ styleUrls: ["./config-list.component.scss"]
+})
+export class ConfigListComponent {
+ internal_data: any[] = [];
+
+ @Input() translationKey: string = "";
+
+ @Input()
+ set data(val: any[]) {
+ this.dataChange.emit(val);
+ let id = 0;
+ this.internal_data = val.map(value => {
+ value = { id: id, value: value };
+ id++;
+ return value;
+ });
+ }
+
+ get data() {
+ return this.getData();
+ }
+
+ @Output() dataChange: EventEmitter = new EventEmitter();
+ clonedData: { [s: number]: any } = {};
+
+ private getData(): any[] {
+ return this.internal_data.map(value => {
+ return value.value;
+ });
+ }
+
+ addNew(table: Table) {
+ const id = Math.max.apply(Math, this.internal_data.map(value => {
+ return value.id ?? 0;
+ })) + 1;
+ const newItem = { id: id, value: "" };
+ this.internal_data.push(newItem);
+
+ table.initRowEdit(newItem);
+ const index = this.internal_data.findIndex(l => l.id == newItem.id);
+ this.editInit(newItem, index);
+ }
+
+ editInit(value: any, index: number) {
+ this.clonedData[index] = { ...value };
+ }
+
+ delete(index: number) {
+ this.internal_data.splice(index, 1);
+ this.dataChange.emit(this.getData());
+ }
+
+ editSave(value: any, index: number) {
+ if (!value.value || this.internal_data[index] == this.clonedData[index]) {
+ return;
+ }
+
+ delete this.clonedData[index];
+ this.dataChange.emit(this.getData());
+ }
+
+ editCancel(index: number) {
+ this.internal_data[index] = this.clonedData[index];
+ delete this.clonedData[index];
+ }
+}
diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts
index 61a5db6c..b92aa75b 100644
--- a/kdb-web/src/app/modules/shared/shared.module.ts
+++ b/kdb-web/src/app/modules/shared/shared.module.ts
@@ -25,6 +25,7 @@ import { ImageModule } from "primeng/image";
import { SidebarModule } from "primeng/sidebar";
import { HistoryBtnComponent } from './components/history-btn/history-btn.component';
import { DataViewModule, DataViewLayoutOptions } from 'primeng/dataview';
+import { ConfigListComponent } from './components/config-list/config-list.component';
@NgModule({
@@ -33,6 +34,7 @@ import { DataViewModule, DataViewLayoutOptions } from 'primeng/dataview';
IpAddressPipe,
BoolPipe,
HistoryBtnComponent,
+ ConfigListComponent,
],
imports: [
CommonModule,
@@ -59,34 +61,35 @@ import { DataViewModule, DataViewLayoutOptions } from 'primeng/dataview';
SidebarModule,
DataViewModule,
],
- exports: [
- ButtonModule,
- PasswordModule,
- MenuModule,
- DialogModule,
- ProgressSpinnerModule,
- HttpClientModule,
- FormsModule,
- ReactiveFormsModule,
- ToastModule,
- ConfirmDialogModule,
- TableModule,
- InputTextModule,
- CheckboxModule,
- DropdownModule,
- TranslateModule,
- DynamicDialogModule,
- PanelMenuModule,
- PanelModule,
- AuthRolePipe,
- IpAddressPipe,
- BoolPipe,
- InputNumberModule,
- ImageModule,
- SidebarModule,
- HistoryBtnComponent,
- DataViewModule,
- DataViewLayoutOptions
- ]
+ exports: [
+ ButtonModule,
+ PasswordModule,
+ MenuModule,
+ DialogModule,
+ ProgressSpinnerModule,
+ HttpClientModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ToastModule,
+ ConfirmDialogModule,
+ TableModule,
+ InputTextModule,
+ CheckboxModule,
+ DropdownModule,
+ TranslateModule,
+ DynamicDialogModule,
+ PanelMenuModule,
+ PanelModule,
+ AuthRolePipe,
+ IpAddressPipe,
+ BoolPipe,
+ InputNumberModule,
+ ImageModule,
+ SidebarModule,
+ HistoryBtnComponent,
+ DataViewModule,
+ DataViewLayoutOptions,
+ ConfigListComponent
+ ]
})
export class SharedModule { }
diff --git a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts
index 114d1d8a..6a65d21c 100644
--- a/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts
+++ b/kdb-web/src/app/modules/view/server/achievements/components/achievement/achievement.component.ts
@@ -236,7 +236,6 @@ export class AchievementComponent implements OnInit, OnDestroy {
).pipe(catchError(err => {
this.isEditingNew = false;
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_create_failed"), this.translate.instant("view.server.achievements.message.achievement_create_failed_d"));
return throwError(err);
})).subscribe(result => {
this.isEditingNew = false;
@@ -258,7 +257,6 @@ export class AchievementComponent implements OnInit, OnDestroy {
}
).pipe(catchError(err => {
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_update_failed"), this.translate.instant("view.server.achievements.message.achievement_update_failed_d", { name: newAchievement.name }));
return throwError(err);
})).subscribe(_ => {
this.spinner.hideSpinner();
@@ -290,7 +288,6 @@ export class AchievementComponent implements OnInit, OnDestroy {
}
).pipe(catchError(err => {
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("view.server.achievements.message.achievement_delete_failed"), this.translate.instant("view.server.achievements.message.achievement_delete_failed_d", { name: achievement.name }));
return throwError(err);
})).subscribe(l => {
this.spinner.hideSpinner();
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 5fab0523..25257687 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
@@ -222,7 +222,6 @@ export class AutoRolesRulesComponent implements OnInit, OnDestroy {
).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;
@@ -241,7 +240,6 @@ export class AutoRolesRulesComponent implements OnInit, OnDestroy {
}
).pipe(catchError(err => {
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed_d"));
return throwError(err);
})).subscribe(result => {
this.spinner.hideSpinner();
@@ -272,7 +270,6 @@ export class AutoRolesRulesComponent implements OnInit, OnDestroy {
}
).pipe(catchError(err => {
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed_d", { id: autoRoleRule.id }));
return throwError(err);
})).subscribe(_ => {
this.spinner.hideSpinner();
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 77f249ad..876f3b4a 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
@@ -208,7 +208,6 @@ export class AutoRolesComponent implements OnInit, OnDestroy {
).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;
@@ -240,7 +239,6 @@ export class AutoRolesComponent implements OnInit, OnDestroy {
}
).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: autoRole.id }));
return throwError(err);
})).subscribe(_ => {
this.spinner.hideSpinner();
diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.html b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html
new file mode 100644
index 00000000..9f7701c1
--- /dev/null
+++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html
@@ -0,0 +1,123 @@
+
+ {{'view.server.config.header' | translate}}
+
+
+
+
+
+
+
+
+
{{'view.server.config.bot.message_delete_timer' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.notification_chat_id' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.max_voice_state_hours' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.xp_per_message' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.xp_per_reaction' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.max_message_xp_per_hour' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.xp_per_ontime_hour' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.xp_per_event_participation' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.xp_per_achievement' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.afk_command_channel_id' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.help_voice_channel_id' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.team_channel_id' | translate}}:
+
+
+
+
+
+
+
{{'view.server.config.bot.login_message_channel_id' | translate}}:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.scss b/kdb-web/src/app/modules/view/server/config/components/config/config.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts b/kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts
new file mode 100644
index 00000000..94dd19ba
--- /dev/null
+++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ConfigComponent } from './config.component';
+
+describe('ConfigComponent', () => {
+ let component: ConfigComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ConfigComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ConfigComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts b/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts
new file mode 100644
index 00000000..0de50e7c
--- /dev/null
+++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.ts
@@ -0,0 +1,116 @@
+import { Component, OnInit } from "@angular/core";
+import { FormBuilder } from "@angular/forms";
+import { TranslateService } from "@ngx-translate/core";
+import { catchError } from "rxjs/operators";
+import { GuiService } from "src/app/services/gui/gui.service";
+import { SettingsService } from "src/app/services/settings/settings.service";
+import { SpinnerService } from "src/app/services/spinner/spinner.service";
+import { ToastService } from "src/app/services/toast/toast.service";
+import { throwError } from "rxjs";
+import { Query, ServerConfigQuery } from "../../../../../../models/graphql/query.model";
+import { Queries } from "../../../../../../models/graphql/queries.model";
+import { DataService } from "../../../../../../services/data/data.service";
+import { ServerConfigMutationResult } from "../../../../../../models/graphql/result.model";
+import { Mutations } from "../../../../../../models/graphql/mutations.model";
+import { AuthService } from "../../../../../../services/auth/auth.service";
+import { ServerConfig } from "../../../../../../models/config/server-config.model";
+import { Server } from "../../../../../../models/data/server.model";
+import { ActivatedRoute } from "@angular/router";
+import { Table } from "primeng/table";
+
+type AFKChannelId = {
+ id: number;
+ value: string;
+};
+
+@Component({
+ selector: "app-config",
+ templateUrl: "./config.component.html",
+ styleUrls: ["./config.component.scss"]
+})
+export class ConfigComponent implements OnInit {
+ config: ServerConfig = {
+ messageDeleteTimer: 0,
+ afkChannelIds: [],
+ moderatorRoleIds: [],
+ adminRoleIds: []
+ };
+
+
+ afkChannelIds: AFKChannelId[] = [];
+ clonedAfkChannelIds: { [s: number]: AFKChannelId } = {};
+
+ private server: Server = {};
+
+ constructor(
+ private data: DataService,
+ private settingsService: SettingsService,
+ private spinnerService: SpinnerService,
+ private guiService: GuiService,
+ private formBuilder: FormBuilder,
+ private toastService: ToastService,
+ private translate: TranslateService,
+ private authService: AuthService,
+ private spinner: SpinnerService,
+ private route: ActivatedRoute
+ ) {
+ }
+
+ ngOnInit(): void {
+ this.spinnerService.showSpinner();
+
+ this.data.getServerFromRoute(this.route).then(async server => {
+ this.server = server;
+ this.loadConfig();
+ });
+ }
+
+ loadConfig() {
+ this.data.query(Queries.serverConfigQuery, {
+ serverId: this.server.id
+ },
+ (data: Query) => {
+ return data.servers[0];
+ }).subscribe(data => {
+ this.config = data.config;
+
+ let id = 0;
+ for (const afkChannelId of this.config.afkChannelIds ?? []) {
+ this.afkChannelIds.push({ id: id, value: afkChannelId });
+ id++;
+ }
+
+ this.spinnerService.hideSpinner();
+ });
+ }
+
+ saveServerConfig() {
+ this.spinner.showSpinner();
+ this.data.mutation(Mutations.updateServerConfig, {
+ id: this.config.id,
+ messageDeleteTimer: this.config.messageDeleteTimer,
+ notificationChatId: this.config.notificationChatId,
+ maxVoiceStateHours: this.config.maxVoiceStateHours,
+ xpPerMessage: this.config.xpPerMessage,
+ xpPerReaction: this.config.xpPerReaction,
+ maxMessageXpPerHour: this.config.maxMessageXpPerHour,
+ xpPerOntimeHour: this.config.xpPerOntimeHour,
+ xpPerEventParticipation: this.config.xpPerEventParticipation,
+ xpPerAchievement: this.config.xpPerAchievement,
+ afkCommandChannelId: this.config.afkCommandChannelId,
+ helpVoiceChannelId: this.config.helpVoiceChannelId,
+ teamChannelId: this.config.teamChannelId,
+ loginMessageChannelId: this.config.loginMessageChannelId,
+ afkChannelIds: this.config.afkChannelIds,
+ moderatorRoleIds: this.config.moderatorRoleIds,
+ adminRoleIds: this.config.adminRoleIds
+ }
+ ).pipe(catchError(err => {
+ this.spinner.hideSpinner();
+ return throwError(err);
+ })).subscribe(result => {
+ this.spinner.hideSpinner();
+ this.toastService.success(this.translate.instant("view.server.config.message.technician_config_create"), this.translate.instant("view.server.config.message.technician_config_create_d"));
+ });
+ }
+}
diff --git a/kdb-web/src/app/modules/view/server/config/config-routing.module.ts b/kdb-web/src/app/modules/view/server/config/config-routing.module.ts
new file mode 100644
index 00000000..afbbd84c
--- /dev/null
+++ b/kdb-web/src/app/modules/view/server/config/config-routing.module.ts
@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { ConfigComponent } from "./components/config/config.component";
+
+const routes: Routes = [
+ {path: '', component: ConfigComponent},
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class ConfigRoutingModule { }
diff --git a/kdb-web/src/app/modules/view/server/config/config.module.ts b/kdb-web/src/app/modules/view/server/config/config.module.ts
new file mode 100644
index 00000000..0dd2131b
--- /dev/null
+++ b/kdb-web/src/app/modules/view/server/config/config.module.ts
@@ -0,0 +1,19 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { ConfigRoutingModule } from './config-routing.module';
+import { ConfigComponent } from './components/config/config.component';
+import { SharedModule } from "../../../shared/shared.module";
+
+
+@NgModule({
+ declarations: [
+ ConfigComponent
+ ],
+ imports: [
+ CommonModule,
+ ConfigRoutingModule,
+ SharedModule,
+ ]
+})
+export class ConfigModule { }
diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts
index ae4e48ce..63e1e446 100644
--- a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts
+++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts
@@ -196,7 +196,6 @@ export class LevelsComponent implements OnInit, OnDestroy {
).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;
@@ -217,7 +216,6 @@ export class LevelsComponent implements OnInit, OnDestroy {
}
).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();
@@ -249,7 +247,6 @@ export class LevelsComponent implements OnInit, OnDestroy {
}
).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();
diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts
index 9cf115d1..e46afb61 100644
--- a/kdb-web/src/app/modules/view/server/members/members.component.ts
+++ b/kdb-web/src/app/modules/view/server/members/members.component.ts
@@ -237,7 +237,6 @@ export class MembersComponent implements OnInit, OnDestroy {
}
).pipe(catchError(err => {
this.spinner.hideSpinner();
- this.toastService.error(this.translate.instant("view.server.members.message.user_change_failed"), this.translate.instant("view.server.members.message.user_change_failed_d", { name: newUser.name }));
return throwError(err);
})).subscribe(_ => {
this.spinner.hideSpinner();
diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts
index a83dab96..c5626e9b 100644
--- a/kdb-web/src/app/modules/view/server/server-routing.module.ts
+++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts
@@ -10,7 +10,8 @@ const routes: Routes = [
{ path: "members/:memberId", component: ProfileComponent },
{ path: "auto-roles", loadChildren: () => import("./auto-role/auto-role.module").then(m => m.AutoRoleModule) },
{ path: "levels", loadChildren: () => import("./levels/levels.module").then(m => m.LevelsModule) },
- { path: "achievements", loadChildren: () => import("./achievements/achievements.module").then(m => m.AchievementsModule) }
+ { path: "achievements", loadChildren: () => import("./achievements/achievements.module").then(m => m.AchievementsModule) },
+ { path: "config", loadChildren: () => import("./config/config.module").then(m => m.ConfigModule) }
];
@NgModule({
diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts
index 54d13057..9d7d13b3 100644
--- a/kdb-web/src/app/services/data/data.service.ts
+++ b/kdb-web/src/app/services/data/data.service.ts
@@ -10,6 +10,8 @@ import { Query } from "../../models/graphql/query.model";
import { SidebarService } from "../sidebar/sidebar.service";
import { SpinnerService } from "../spinner/spinner.service";
import { GraphQLResult } from "../../models/graphql/result.model";
+import { ToastService } from "../toast/toast.service";
+import { TranslateService } from "@ngx-translate/core";
@Injectable({
providedIn: "root"
@@ -21,7 +23,9 @@ export class DataService {
private http: HttpClient,
private sidebar: SidebarService,
private spinner: SpinnerService,
- private router: Router
+ private router: Router,
+ private toast: ToastService,
+ private translate: TranslateService,
) {
}
@@ -72,6 +76,10 @@ export class DataService {
})
.pipe(map(d => {
if (d.errors && d.errors.length > 0) {
+ d.errors.forEach((error: Error) => {
+ this.toast.error(this.translate.instant("common.error"), error.message)
+ });
+
throw new Error(d.errors.toString());
}
return d.data;
diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts
index 81ab4548..196b7e25 100644
--- a/kdb-web/src/app/services/sidebar/sidebar.service.ts
+++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts
@@ -3,7 +3,7 @@ import { MenuItem } from "primeng/api";
import { BehaviorSubject } from "rxjs";
import { AuthRoles } from "../../models/auth/auth-roles.enum";
import { AuthService } from "../auth/auth.service";
-import { LangChangeEvent, TranslateService } from "@ngx-translate/core";
+import { TranslateService } from "@ngx-translate/core";
import { NavigationEnd, Router } from "@angular/router";
import { ThemeService } from "../theme/theme.service";
import { Server } from "../../models/data/server.model";
@@ -25,6 +25,7 @@ export class SidebarService {
serverAutoRoles: MenuItem = {};
serverLevels: MenuItem = {};
serverAchievements: MenuItem = {};
+ serverConfig: MenuItem = {};
serverMenu: MenuItem = {};
adminConfig: MenuItem = {};
adminUsers: MenuItem = {};
@@ -110,12 +111,19 @@ export class SidebarService {
routerLink: `server/${this.server$.value?.id}/achievements`
};
+ this.serverConfig = {
+ label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.config") : "",
+ icon: "pi pi-cog",
+ visible: true,
+ routerLink: `server/${this.server$.value?.id}/config`
+ };
+
this.serverMenu = {
label: this.isSidebarOpen ? this.server$.value?.name : "",
icon: "pi pi-server",
visible: false,
expanded: true,
- items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels, this.serverAchievements]
+ items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels, this.serverAchievements, this.serverConfig]
};
this.adminConfig = {
label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "",
@@ -151,6 +159,7 @@ export class SidebarService {
this.serverAutoRoles.visible = !!user?.isModerator;
this.serverLevels.visible = !!user?.isModerator;
this.serverAchievements.visible = !!user?.isModerator;
+ this.serverConfig.visible = !!user?.isAdmin;
} else {
this.serverMenu.visible = false;
}
diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json
index e499fedf..f346df54 100644
--- a/kdb-web/src/assets/i18n/de.json
+++ b/kdb-web/src/assets/i18n/de.json
@@ -37,7 +37,7 @@
"header": "Bot",
"help_url": "Befehlsreferenz",
"ping_urls": "Ping Adressen",
- "technicianIds": "Techniker Ids",
+ "technician_ids": "Techniker Ids",
"wait_for_restart": "Wartezeit vor Neustart",
"wait_for_shutdown": "Wartezeit vor Herunterfahren"
},
@@ -156,7 +156,7 @@
"id": "Id",
"leftServer": "Server verlassen",
"messageId": "Nachricht Id",
- "minXp": "Min. XP",
+ "min_xp": "Min. XP",
"name": "Name",
"operator": "Operator",
"permissions": "Berechtigung",
@@ -407,6 +407,28 @@
}
}
},
+ "config": {
+ "bot": {
+ "admin_roles": "Admin Rollen",
+ "afk_channels": "AFK Sprachkanäle",
+ "afk_command_channel_id": "AFK Kanal für den Befehl /afk",
+ "header": "Bot Konfiguration",
+ "help_voice_channel_id": "Sprachkanal für Hilfsbenachrichtung",
+ "login_message_channel_id": "Kanal für die Nachricht vom Bot nach Start",
+ "max_message_xp_per_hour": "Maximale XP pro Stunde durch Nachrichten",
+ "max_voice_state_hours": "Maximale Stunden für eine ontime nach Bot neustart",
+ "message_delete_timer": "Zeit bis zum löschen einer Botnachricht in sekunden",
+ "moderator_roles": "Moderator Rollen",
+ "notification_chat_id": "Benachrichtungskanal",
+ "team_channel_id": "Team chat",
+ "xp_per_achievement": "XP für Errungenschaft",
+ "xp_per_event_participation": "XP für Event Teilnahme",
+ "xp_per_message": "XP für eine Nachricht",
+ "xp_per_ontime_hour": "XP für eine Stunde im Sprachkanal",
+ "xp_per_reaction": "XP für eine Reaktion"
+ },
+ "header": "Server Konfiguration"
+ },
"dashboard": {
"deleted_message_count": "Gelöschte Nachrichten",
"header": "Server dashboard",
diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json
index 3d709daa..7dd4fa29 100644
--- a/kdb-web/src/assets/i18n/en.json
+++ b/kdb-web/src/assets/i18n/en.json
@@ -37,7 +37,7 @@
"header": "Bot",
"help_url": "Help URL",
"ping_urls": "Ping addresses",
- "technicianIds": "Technician Ids",
+ "technician_ids": "Technician Ids",
"wait_for_restart": "Time to wait before restart",
"wait_for_shutdown": "Time to wait before shutdown"
},
@@ -156,7 +156,7 @@
"id": "Id",
"leftServer": "Left server",
"messageId": "Message Id",
- "minXp": "Min. XP",
+ "min_xp": "Min. XP",
"name": "Name",
"operator": "Operator",
"permissions": "Permissions",
@@ -407,6 +407,28 @@
}
}
},
+ "config": {
+ "bot": {
+ "admin_roles": "Admin Roles",
+ "afk_channels": "AFK Voicechannel",
+ "afk_command_channel_id": "AFK Channel for the command /afk",
+ "header": "Bot configuration",
+ "help_voice_channel_id": "Voicechannel für help notifications",
+ "login_message_channel_id": "Channel for bot message after start",
+ "max_message_xp_per_hour": "Max xp per hour with message",
+ "max_voice_state_hours": "Max ontime hours after bot restart",
+ "message_delete_timer": "Time to wait before delete bot messages",
+ "moderator_roles": "Moderator roles",
+ "notification_chat_id": "Notification channel",
+ "team_channel_id": "Team chat",
+ "xp_per_achievement": "XP for achievement",
+ "xp_per_event_participation": "XP for event participation",
+ "xp_per_message": "XP for message",
+ "xp_per_ontime_hour": "XP for one hour in an voice channel",
+ "xp_per_reaction": "XP for an reaction"
+ },
+ "header": "Server configuration"
+ },
"dashboard": {
"deleted_message_count": "Deleted messages",
"header": "Server dashboard",
@@ -487,7 +509,7 @@
"ontime": "Ontime",
"permission_denied": "Access denied!",
"permission_denied_d": "You have to be moderator to see other profiles!",
- "xp": "Xp"
+ "xp": "XP"
}
},
"user_settings": {