#127_config_in_wi #327
							
								
								
									
										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", | ||||
|   | ||||
| @@ -51,4 +51,4 @@ | ||||
|         "tslib": "^2.4.1", | ||||
|         "typescript": "~4.9.5" | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
							
								
								
									
										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 | ||||
|   | ||||
| @@ -1,125 +1,168 @@ | ||||
| <h1> | ||||
|     {{'admin.settings.header' | translate}} | ||||
|   {{'admin.settings.header' | translate}} | ||||
| </h1> | ||||
| <div class="content-wrapper"> | ||||
|     <div class="content-header"> | ||||
|         <h2> | ||||
|             {{'admin.settings.website.header' | translate}} | ||||
|         </h2> | ||||
|   <div class="content-header"> | ||||
|     <h2> | ||||
|       {{'admin.settings.website.header' | translate}} | ||||
|     </h2> | ||||
|   </div> | ||||
|  | ||||
|   <div class="content"> | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.frontend_version' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.webVersion}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content"> | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.frontend_version' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.webVersion}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.backend_version' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.apiVersion}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.config_path' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.configPath}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.frontend_base_url' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.webBaseURL}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.backend_base_url' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.apiBaseURL}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-divider"></div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.token_expire_time' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.tokenExpireTime}} {{'general.minutes' | translate}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.website.refresh_token_expire_time' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.refreshTokenExpireTime}} {{'general.days' | translate}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.backend_version' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.apiVersion}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.config_path' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.configPath}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.frontend_base_url' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.webBaseURL}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.backend_base_url' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.apiBaseURL}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-divider"></div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.token_expire_time' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.tokenExpireTime}} {{'general.minutes' | translate}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.website.refresh_token_expire_time' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.refreshTokenExpireTime}} {{'general.days' | translate}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
|  | ||||
| <div class="content-wrapper"> | ||||
|     <div class="content-header"> | ||||
|         <h2> | ||||
|             {{'admin.settings.email.header' | translate}} | ||||
|         </h2> | ||||
|   <div class="content-header"> | ||||
|     <h2> | ||||
|       {{'admin.settings.email.header' | translate}} | ||||
|     </h2> | ||||
|   </div> | ||||
|  | ||||
|   <div class="content"> | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.email.user' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.mailUser}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content"> | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.email.user' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.mailUser}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.email.host' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.mailHost}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.email.port' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.mailPort}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.email.transceiver' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.mailTransceiver}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <div class="content-column"> | ||||
|                 <div class="content-data-name">{{'admin.settings.email.email_address' | translate}}:</div> | ||||
|                 <div class="content-data-value">{{data.mailTransceiverAddress}}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-row"> | ||||
|             <form [formGroup]="testMailForm" class="content-column"> | ||||
|                 <div class="content-data-name"> | ||||
|                     <div class="input-field content-input-field"> | ||||
|                         <input type="email" pInputText formControlName="mail" placeholder="{{'common.email' | translate}}" autocomplete="email"> | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|                 <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" | ||||
|                             (click)="testMail()" [disabled]="testMailForm.invalid"></button> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </form> | ||||
|         </div> | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.email.host' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.mailHost}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.email.port' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.mailPort}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.email.transceiver' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.mailTransceiver}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <div class="content-column"> | ||||
|         <div class="content-data-name">{{'admin.settings.email.email_address' | translate}}:</div> | ||||
|         <div class="content-data-value">{{data.mailTransceiverAddress}}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="content-row"> | ||||
|       <form [formGroup]="testMailForm" class="content-column"> | ||||
|         <div class="content-data-name"> | ||||
|           <div class="input-field content-input-field"> | ||||
|             <input type="email" pInputText formControlName="mail" placeholder="{{'common.email' | translate}}" autocomplete="email"> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="content-data-value"> | ||||
|           <div class="login-form-submit"> | ||||
|             <button pButton icon="pi pi-send" label="{{'common.email' | translate}}" class="btn login-form-submit-btn" | ||||
|                     (click)="testMail()" [disabled]="testMailForm.invalid"></button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </form> | ||||
|     </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.data.apiBaseURL = this.settingsService.getApiURL(); | ||||
|         if (!this.data.apiBaseURL.endsWith('/')) { | ||||
|           this.data.apiBaseURL += '/'; | ||||
|         } | ||||
|       }); | ||||
|       })), | ||||
|       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 += "/"; | ||||
|       } | ||||
|  | ||||
|       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": [ | ||||
|         { | ||||
| @@ -25,4 +25,4 @@ | ||||
|             "Name": "sh-edraft-dark-theme" | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user