Added technician config to frontend #127
This commit is contained in:
parent
33ed4328a1
commit
e0896700e7
10
kdb-web/package-lock.json
generated
10
kdb-web/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "kdb-web",
|
||||
"version": "1.0.dev251",
|
||||
"version": "1.0.dev127_config_in_wi",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "kdb-web",
|
||||
"version": "1.0.dev251",
|
||||
"version": "1.0.dev127_config_in_wi",
|
||||
"dependencies": {
|
||||
"@angular/animations": "^15.1.4",
|
||||
"@angular/common": "^15.1.4",
|
||||
@ -21,6 +21,7 @@
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@ngx-translate/http-loader": "^7.0.0",
|
||||
"@types/socket.io-client": "^3.0.0",
|
||||
"primeflex": "^3.3.1",
|
||||
"primeicons": "^6.0.1",
|
||||
"primeng": "^15.2.0",
|
||||
"rxjs": "~7.5.0",
|
||||
@ -9302,6 +9303,11 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/primeflex": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/primeflex/-/primeflex-3.3.1.tgz",
|
||||
"integrity": "sha512-zaOq3YvcOYytbAmKv3zYc+0VNS9Wg5d37dfxZnveKBFPr7vEIwfV5ydrpiouTft8MVW6qNjfkaQphHSnvgQbpQ=="
|
||||
},
|
||||
"node_modules/primeicons": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "kdb-web",
|
||||
"version": "1.0.dev268_achievements",
|
||||
"version": "1.0.dev127_config_in_wi",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"update-version": "ts-node-esm update-version.ts",
|
||||
@ -30,6 +30,7 @@
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@ngx-translate/http-loader": "^7.0.0",
|
||||
"@types/socket.io-client": "^3.0.0",
|
||||
"primeflex": "^3.3.1",
|
||||
"primeicons": "^6.0.1",
|
||||
"primeng": "^15.2.0",
|
||||
"rxjs": "~7.5.0",
|
||||
|
11
kdb-web/src/app/models/config/technician-config.model.ts
Normal file
11
kdb-web/src/app/models/config/technician-config.model.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { DataWithHistory } from "../data/data.model";
|
||||
|
||||
export interface TechnicianConfig extends DataWithHistory {
|
||||
id?: number;
|
||||
helpCommandReferenceUrl?: string;
|
||||
waitForRestart?: number;
|
||||
waitForShutdown?: number;
|
||||
cacheMaxMessages?: number;
|
||||
pingURLs?: string[];
|
||||
technicianIds?: string[];
|
||||
}
|
@ -165,4 +165,30 @@ export class Mutations {
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
|
||||
static updateTechnicianConfig = `
|
||||
mutation updateTechnicianConfig($id: ID, $helpCommandReferenceUrl: String, $waitForRestart: Int, $waitForShutdown: Int, $cacheMaxMessages: Int, $pingURLs: [String], $technicianIds: [String]) {
|
||||
technicianConfig {
|
||||
updateTechnicianConfig(input: {
|
||||
id: $id,
|
||||
helpCommandReferenceUrl: $helpCommandReferenceUrl,
|
||||
waitForRestart: $waitForRestart,
|
||||
waitForShutdown: $waitForShutdown,
|
||||
cacheMaxMessages: $cacheMaxMessages,
|
||||
pingURLs: $pingURLs,
|
||||
technicianIds: $technicianIds
|
||||
}) {
|
||||
id
|
||||
helpCommandReferenceUrl
|
||||
waitForRestart
|
||||
waitForShutdown
|
||||
cacheMaxMessages
|
||||
pingURLs
|
||||
technicianIds
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@ -1,5 +1,22 @@
|
||||
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}) {
|
||||
|
@ -4,12 +4,17 @@ import { AutoRole, AutoRoleRule } from "../data/auto_role.model";
|
||||
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";
|
||||
|
||||
export interface Query {
|
||||
serverCount: number;
|
||||
servers: Server[];
|
||||
}
|
||||
|
||||
export interface TechnicianConfigQuery {
|
||||
technicianConfig: TechnicianConfig;
|
||||
}
|
||||
|
||||
export interface SingleDiscordQuery {
|
||||
guilds: Guild[];
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { AutoRole, AutoRoleRule } from "../data/auto_role.model";
|
||||
import { Level } from "../data/level.model";
|
||||
import { Server } from "../data/server.model";
|
||||
import { Achievement } from "../data/achievement.model";
|
||||
import { TechnicianConfig } from "../config/technician-config.model";
|
||||
|
||||
export interface GraphQLResult {
|
||||
data: {
|
||||
@ -47,6 +48,12 @@ export interface LevelMutationResult {
|
||||
};
|
||||
}
|
||||
|
||||
export interface TechnicianConfigMutationResult {
|
||||
technicianConfig: {
|
||||
updateTechnicianConfig?: TechnicianConfig
|
||||
};
|
||||
}
|
||||
|
||||
export interface AchievementMutationResult {
|
||||
achievement: {
|
||||
createAchievement?: Achievement
|
||||
|
@ -115,7 +115,7 @@
|
||||
|
||||
<div class="content-data-value">
|
||||
<div class="login-form-submit">
|
||||
<button pButton icon="pi pi-save" label="{{'common.email' | translate}}" class="btn login-form-submit-btn"
|
||||
<button pButton icon="pi pi-send" label="{{'common.email' | translate}}" class="btn login-form-submit-btn"
|
||||
(click)="testMail()" [disabled]="testMailForm.invalid"></button>
|
||||
</div>
|
||||
</div>
|
||||
@ -123,3 +123,46 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content-header">
|
||||
<h2>
|
||||
{{'admin.settings.bot.header' | translate}}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'admin.settings.bot.help_url' | translate}}:</div>
|
||||
<input class="content-data-value" type="text" pInputText [(ngModel)]="config.helpCommandReferenceUrl" placeholder="{{'admin.settings.bot.help_url' | translate}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'admin.settings.bot.wait_for_restart' | translate}}:</div>
|
||||
<input class="content-data-value" type="number" pInputText [(ngModel)]="config.waitForRestart" placeholder="{{'admin.settings.bot.wait_for_restart' | translate}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'admin.settings.bot.wait_for_shutdown' | translate}}:</div>
|
||||
<input class="content-data-value" type="number" pInputText [(ngModel)]="config.waitForShutdown" placeholder="{{'admin.settings.bot.wait_for_shutdown' | translate}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<div class="content-column">
|
||||
<div class="content-data-name">{{'admin.settings.bot.cache_max_messages' | translate}}:</div>
|
||||
<input class="content-data-value" type="number" pInputText [(ngModel)]="config.cacheMaxMessages" placeholder="{{'admin.settings.bot.cache_max_messages' | translate}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-row">
|
||||
<button pButton icon="pi pi-save" label="{{'common.save' | translate}}" class="btn login-form-submit-btn"
|
||||
(click)="saveTechnicianConfig()" [disabled]="technicianConfigForm.invalid"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
|
||||
import { FormArray, FormBuilder, FormControl, 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";
|
||||
@ -9,66 +9,111 @@ 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 { forkJoin, throwError } from "rxjs";
|
||||
import { TechnicianConfig } from "../../../../../models/config/technician-config.model";
|
||||
import { TechnicianConfigQuery } from "../../../../../models/graphql/query.model";
|
||||
import { Queries } from "../../../../../models/graphql/queries.model";
|
||||
import { DataService } from "../../../../../services/data/data.service";
|
||||
import { LevelMutationResult, TechnicianConfigMutationResult } from "../../../../../models/graphql/result.model";
|
||||
import { Mutations } from "../../../../../models/graphql/mutations.model";
|
||||
import { AuthService } from "../../../../../services/auth/auth.service";
|
||||
import { ConfirmationDialogService } from "../../../../../services/confirmation-dialog/confirmation-dialog.service";
|
||||
import { SidebarService } from "../../../../../services/sidebar/sidebar.service";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['./settings.component.scss']
|
||||
selector: "app-settings",
|
||||
templateUrl: "./settings.component.html",
|
||||
styleUrls: ["./settings.component.scss"]
|
||||
})
|
||||
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: this.formBuilder.array([])
|
||||
});
|
||||
data: SettingsDTO = {
|
||||
webVersion: '',
|
||||
apiVersion: '',
|
||||
configPath: '',
|
||||
webBaseURL: '',
|
||||
apiBaseURL: '',
|
||||
webVersion: "",
|
||||
apiVersion: "",
|
||||
configPath: "",
|
||||
webBaseURL: "",
|
||||
apiBaseURL: "",
|
||||
|
||||
tokenExpireTime: 0,
|
||||
refreshTokenExpireTime: 0,
|
||||
|
||||
mailUser: '',
|
||||
mailUser: "",
|
||||
mailPort: 0,
|
||||
mailHost: '',
|
||||
mailTransceiver: '',
|
||||
mailTransceiverAddress: '',
|
||||
mailHost: "",
|
||||
mailTransceiver: "",
|
||||
mailTransceiverAddress: ""
|
||||
};
|
||||
|
||||
config: TechnicianConfig = {
|
||||
helpCommandReferenceUrl: "",
|
||||
waitForRestart: 0,
|
||||
waitForShutdown: 0,
|
||||
cacheMaxMessages: 0,
|
||||
pingURLs: [],
|
||||
technicianIds: []
|
||||
};
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
private settingsService: SettingsService,
|
||||
private spinnerService: SpinnerService,
|
||||
private guiService: GuiService,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
private translate: TranslateService
|
||||
) { }
|
||||
private translate: TranslateService,
|
||||
private authService: AuthService,
|
||||
private spinner: SpinnerService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.spinnerService.showSpinner();
|
||||
this.initForms();
|
||||
|
||||
this.guiService.getSettings()
|
||||
.pipe(catchError(error => {
|
||||
forkJoin([
|
||||
this.guiService.getSettings().pipe(catchError(error => {
|
||||
this.spinnerService.hideSpinner();
|
||||
return throwError(() => error);
|
||||
}))
|
||||
.subscribe(settings => {
|
||||
this.spinnerService.hideSpinner();
|
||||
this.data = settings;
|
||||
this.data.webVersion = this.settingsService.getWebVersion()?.getVersionString() ?? '0.0.0';
|
||||
})),
|
||||
this.dataService.query<TechnicianConfigQuery>(Queries.technicianConfigQuery)
|
||||
]).subscribe(data => {
|
||||
this.data = data[0];
|
||||
this.data.webVersion = this.settingsService.getWebVersion()?.getVersionString() ?? "0.0.0";
|
||||
this.data.apiBaseURL = this.settingsService.getApiURL();
|
||||
if (!this.data.apiBaseURL.endsWith('/')) {
|
||||
this.data.apiBaseURL += '/';
|
||||
if (!this.data.apiBaseURL.endsWith("/")) {
|
||||
this.data.apiBaseURL += "/";
|
||||
}
|
||||
|
||||
this.config = data[1].technicianConfig;
|
||||
this.initForms();
|
||||
this.spinnerService.hideSpinner();
|
||||
});
|
||||
}
|
||||
|
||||
initForms(): void {
|
||||
this.testMailForm = this.formBuilder.group({
|
||||
mail: [null, [Validators.required, Validators.email]],
|
||||
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]],
|
||||
pingUrls: this.formBuilder.array([])
|
||||
});
|
||||
const pingUrls = <FormArray>this.technicianConfigForm.controls["pingUrls"];
|
||||
for (const url of this.config.pingURLs ?? []) {
|
||||
pingUrls.push(new FormControl(url, [Validators.required]));
|
||||
}
|
||||
}
|
||||
|
||||
testMail(): void {
|
||||
@ -82,27 +127,27 @@ export class SettingsComponent implements OnInit {
|
||||
|
||||
this.guiService.sendTestMail(mail)
|
||||
.pipe(catchError(error => {
|
||||
let header = this.translate.instant('admin.settings.message.error');
|
||||
let message = this.translate.instant('admin.settings.message.could_not_send_mail');
|
||||
let header = this.translate.instant("admin.settings.message.error");
|
||||
let message = this.translate.instant("admin.settings.message.could_not_send_mail");
|
||||
|
||||
if (error.error !== null) {
|
||||
const err: ErrorDTO = error.error;
|
||||
|
||||
if (err.errorCode === ServiceErrorCode.ConnectionFailed) {
|
||||
header = this.translate.instant('admin.settings.message.connection_failed');
|
||||
message = this.translate.instant('admin.settings.message.connection_to_mail_failed');
|
||||
header = this.translate.instant("admin.settings.message.connection_failed");
|
||||
message = this.translate.instant("admin.settings.message.connection_to_mail_failed");
|
||||
error.error = null;
|
||||
}
|
||||
|
||||
if (err.errorCode === ServiceErrorCode.InvalidUser) {
|
||||
header = this.translate.instant('admin.settings.message.connection_failed');
|
||||
message = this.translate.instant('admin.settings.message.mail_login_failed');
|
||||
header = this.translate.instant("admin.settings.message.connection_failed");
|
||||
message = this.translate.instant("admin.settings.message.mail_login_failed");
|
||||
error.error = null;
|
||||
}
|
||||
|
||||
if (err.errorCode === ServiceErrorCode.MailError) {
|
||||
header = this.translate.instant('admin.settings.message.send_failed');
|
||||
message = this.translate.instant('admin.settings.message.test_mail_not_send');
|
||||
header = this.translate.instant("admin.settings.message.send_failed");
|
||||
message = this.translate.instant("admin.settings.message.test_mail_not_send");
|
||||
error.error = null;
|
||||
}
|
||||
}
|
||||
@ -113,9 +158,29 @@ export class SettingsComponent implements OnInit {
|
||||
}))
|
||||
.subscribe(res => {
|
||||
this.spinnerService.hideSpinner();
|
||||
this.toastService.success(this.translate.instant('admin.settings.message.success'), this.translate.instant('admin.settings.message.send_mail'));
|
||||
this.toastService.success(this.translate.instant("admin.settings.message.success"), this.translate.instant("admin.settings.message.send_mail"));
|
||||
this.testMailForm.reset();
|
||||
});
|
||||
}
|
||||
|
||||
saveTechnicianConfig() {
|
||||
this.spinner.showSpinner();
|
||||
this.dataService.mutation<TechnicianConfigMutationResult>(Mutations.updateTechnicianConfig, {
|
||||
helpCommandReferenceUrl: this.config.helpCommandReferenceUrl,
|
||||
waitForRestart: this.config.waitForRestart,
|
||||
waitForShutdown: this.config.waitForShutdown,
|
||||
cacheMaxMessages: this.config.cacheMaxMessages,
|
||||
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();
|
||||
this.toastService.success(this.translate.instant("admin.settings.message.technician_config_create"), this.translate.instant("admin.settings.message.technician_config_create_d"));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import { InputNumberModule } from "primeng/inputnumber";
|
||||
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';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -56,6 +57,7 @@ import { HistoryBtnComponent } from './components/history-btn/history-btn.compon
|
||||
InputNumberModule,
|
||||
ImageModule,
|
||||
SidebarModule,
|
||||
DataViewModule,
|
||||
],
|
||||
exports: [
|
||||
ButtonModule,
|
||||
@ -82,7 +84,9 @@ import { HistoryBtnComponent } from './components/history-btn/history-btn.compon
|
||||
InputNumberModule,
|
||||
ImageModule,
|
||||
SidebarModule,
|
||||
HistoryBtnComponent
|
||||
HistoryBtnComponent,
|
||||
DataViewModule,
|
||||
DataViewLayoutOptions
|
||||
]
|
||||
})
|
||||
export class SharedModule { }
|
||||
|
@ -5,7 +5,7 @@
|
||||
"WebVersion": {
|
||||
"Major": "1",
|
||||
"Minor": "0",
|
||||
"Micro": "dev268_achievements"
|
||||
"Micro": "dev127_config_in_wi"
|
||||
},
|
||||
"Themes": [
|
||||
{
|
||||
|
@ -177,6 +177,14 @@ header {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.content-data-value-row {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.content-divider {
|
||||
margin: 5px 0;
|
||||
}
|
||||
@ -477,6 +485,7 @@ footer {
|
||||
.right {
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
|
||||
.p-button-label {
|
||||
font-weight: unset !important;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user