feat: add setup/database page
This commit is contained in:
		
							
								
								
									
										156
									
								
								src/pages/setup/database/database.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/pages/setup/database/database.component.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <h1>Настройка базы данных</h1> | ||||
| <hr/> | ||||
| <p class="mat-body-2 secondary"> | ||||
|   На этой странице вы можете выбрать и настроить параметры подключения к базе данных. | ||||
| </p> | ||||
| <p class="mat-body-2 secondary"> | ||||
|   Укажите необходимую информацию, чтобы обеспечить правильное функционирование приложения. | ||||
| </p> | ||||
|  | ||||
| <p class="mat-headline-6" style="color: red;font-weight: lighter;"> | ||||
|   Данные настройки нельзя будет изменить в будущем! | ||||
| </p> | ||||
|  | ||||
| <form [formGroup]="databaseForm"> | ||||
|   <p> | ||||
|     Выберите базу данных: | ||||
|   </p> | ||||
|   <mat-form-field color="accent"> | ||||
|     <mat-label>База данных</mat-label> | ||||
|     <mat-select (valueChange)="onDatabaseChange($event)"> | ||||
|       <mat-option value="SetMysql">MySQL</mat-option> | ||||
|       <mat-option value="SetPsql">PostgreSQL</mat-option> | ||||
|       <mat-option value="sqlite">Sqlite</mat-option> | ||||
|     </mat-select> | ||||
|   </mat-form-field> | ||||
|  | ||||
|   @if (database) { | ||||
|     <hr/> | ||||
|   } | ||||
|  | ||||
|   <div style="display:flex; flex-direction: column;"> | ||||
|     @if (database === "sqlite") { | ||||
|       <mat-form-field color="accent"> | ||||
|         <mat-label>Папка</mat-label> | ||||
|         <input matInput | ||||
|                matTooltip="Укажите папку, в которой будет находиться база данных" | ||||
|                formControlName="folder" | ||||
|                value="database" | ||||
|                required> | ||||
|  | ||||
|         @if (databaseForm.get('folder')?.hasError('required')) { | ||||
|           <mat-error> | ||||
|             Название папки является <i>обязательным</i> | ||||
|           </mat-error> | ||||
|         } | ||||
|  | ||||
|         @if (databaseForm.get('folder')?.hasError('pattern')) { | ||||
|           <mat-error> | ||||
|             Название не может быть меньше 2 символов | ||||
|           </mat-error> | ||||
|         } | ||||
|       </mat-form-field> | ||||
|  | ||||
|     } @else if (database) { | ||||
|       <mat-form-field color="accent"> | ||||
|         <mat-label>Сервер</mat-label> | ||||
|         <input matInput | ||||
|                matTooltip='Укажите сервер в формате: "winsomnia.net" или ip адреса формата IPv4 или IPv6' | ||||
|                required | ||||
|                formControlName="server"> | ||||
|  | ||||
|         @if (databaseForm.get('server')?.hasError('required')) { | ||||
|           <mat-error> | ||||
|             Сервер является <i>обязательным</i> | ||||
|           </mat-error> | ||||
|         } | ||||
|  | ||||
|         @if (databaseForm.get('server')?.hasError('pattern')) { | ||||
|           <mat-error> | ||||
|             Сервер должен содержать доменное имя сервера или ip адрес IPv4 или IPv6 | ||||
|           </mat-error> | ||||
|         } | ||||
|       </mat-form-field> | ||||
|  | ||||
|       <mat-form-field color="accent"> | ||||
|         <mat-label>Порт</mat-label> | ||||
|         <input matInput | ||||
|                matTooltip="Укажите порт сервера" | ||||
|                required | ||||
|                formControlName="port"> | ||||
|  | ||||
|         @if (databaseForm.get('port')?.hasError('required')) { | ||||
|           <mat-error> | ||||
|             Порт является <i>обязательным</i> | ||||
|           </mat-error> | ||||
|         } | ||||
|  | ||||
|         @if (databaseForm.get('port')?.hasError('pattern')) { | ||||
|           <mat-error> | ||||
|             Порт должен содержать цифры начиная НЕ с 0 и далее не менее 2 и не более 5 цифр | ||||
|           </mat-error> | ||||
|         } | ||||
|       </mat-form-field> | ||||
|  | ||||
|       <mat-form-field color="accent"> | ||||
|         <mat-label>Название базы данных</mat-label> | ||||
|         <input matInput | ||||
|                matTooltip="Укажите название базы данных" | ||||
|                required | ||||
|                formControlName="database_name"> | ||||
|  | ||||
|         @if (databaseForm.get('database_name')?.hasError('required')) { | ||||
|           <mat-error> | ||||
|             Название базы данных является <i>обязательным</i> | ||||
|           </mat-error> | ||||
|         } | ||||
|  | ||||
|         @if (databaseForm.get('database_name')?.hasError('pattern')) { | ||||
|           <mat-error> | ||||
|             Название не может быть меньше 2 символов | ||||
|           </mat-error> | ||||
|         } | ||||
|       </mat-form-field> | ||||
|  | ||||
|       <mat-form-field color="accent"> | ||||
|         <mat-label>Пользователь</mat-label> | ||||
|         <input matInput | ||||
|                matTooltip="Укажите пользователя, который имеет доступ к базе данных" | ||||
|                required | ||||
|                formControlName="user"> | ||||
|  | ||||
|         @if (databaseForm.get('user')?.hasError('required')) { | ||||
|           <mat-error> | ||||
|             Имя пользователя базы данных является <i>обязательным</i> | ||||
|           </mat-error> | ||||
|         } | ||||
|  | ||||
|         @if (databaseForm.get('user')?.hasError('pattern')) { | ||||
|           <mat-error> | ||||
|             Имя не может быть меньше 2 символов | ||||
|           </mat-error> | ||||
|         } | ||||
|       </mat-form-field> | ||||
|  | ||||
|       <mat-form-field color="accent"> | ||||
|         <mat-label>Пароль</mat-label> | ||||
|         <input matInput | ||||
|                matTooltip="Укажите пароль" | ||||
|                formControlName="password" | ||||
|                [type]="hidePass ? 'password' : 'text'"> | ||||
|  | ||||
|         <button mat-icon-button matSuffix (click)="togglePassword($event)" [attr.aria-label]="'Hide password'" | ||||
|                 [attr.aria-pressed]="hidePass"> | ||||
|  | ||||
|           <mat-icon>{{ hidePass ? 'visibility_off' : 'visibility' }}</mat-icon> | ||||
|         </button> | ||||
|       </mat-form-field> | ||||
|  | ||||
|       <mat-checkbox | ||||
|         matTooltip="Использовать SSL/TLS для подключения к базе данных" | ||||
|         formControlName="ssl"> | ||||
|         Использовать SSL/TLS | ||||
|       </mat-checkbox> | ||||
|     } | ||||
|   </div> | ||||
| </form> | ||||
							
								
								
									
										108
									
								
								src/pages/setup/database/database.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/pages/setup/database/database.component.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| import {Component} from '@angular/core'; | ||||
| import {NavigationService} from "@service/navigation.service"; | ||||
| import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms"; | ||||
| import SetupService from "@api/v1/setup.service"; | ||||
| import {DatabaseRequest} from "@api/v1/databaseRequest"; | ||||
| import {MatFormFieldModule} from "@angular/material/form-field"; | ||||
| import {MatSelectModule} from "@angular/material/select"; | ||||
| import {MatInput} from "@angular/material/input"; | ||||
| import {MatTooltip} from "@angular/material/tooltip"; | ||||
| import {MatIconButton} from "@angular/material/button"; | ||||
| import {MatIcon} from "@angular/material/icon" | ||||
| import {MatCheckbox} from "@angular/material/checkbox"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-database', | ||||
|   standalone: true, | ||||
|   imports: [ | ||||
|     ReactiveFormsModule, | ||||
|     MatFormFieldModule, | ||||
|     MatSelectModule, | ||||
|     MatInput, | ||||
|     MatTooltip, | ||||
|     MatIconButton, | ||||
|     MatIcon, | ||||
|     MatCheckbox | ||||
|   ], | ||||
|   templateUrl: './database.component.html' | ||||
| }) | ||||
|  | ||||
| export class DatabaseComponent { | ||||
|   protected databaseForm!: FormGroup; | ||||
|   protected database = ''; | ||||
|   protected hidePass = true; | ||||
|  | ||||
|   constructor( | ||||
|     private navigationService: NavigationService, private formBuilder: FormBuilder, private api: SetupService) { | ||||
|     this.databaseForm = this.formBuilder.group({ | ||||
|       folder: ['', Validators.pattern(/^.{2,}$/)], | ||||
|       server: ['', Validators.pattern(/^localhost$|^([A-Za-z0-9]+\.)+[A-Za-z]{2,}$|^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$|^([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}$|^::1$/)], | ||||
|       port: ['', Validators.pattern(/^[1-9][0-9]{1,4}$/)], | ||||
|       database_name: ['', Validators.pattern(/^.{2,}$/)], | ||||
|       user: ['', Validators.pattern(/^.{2,}$/)], | ||||
|       password: [''], | ||||
|       ssl: [''] | ||||
|     }); | ||||
|  | ||||
|     this.databaseForm.get('ssl')?.setValue(false); | ||||
|     this.navigationService.setNextButtonState(false); | ||||
|     this.databaseForm.valueChanges.subscribe(() => { | ||||
|       this.navigationService.setNextButtonState(this.databaseForm.valid); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   private createForm(database: string) { | ||||
|     if (database === 'sqlite') { | ||||
|       this.disableControls(['server', 'port', 'database_name', 'user', 'password']); | ||||
|       this.enableControls(['folder']); | ||||
|     } else { | ||||
|       this.enableControls(['server', 'port', 'database_name', 'user', 'password']); | ||||
|       this.disableControls(['folder']); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private disableControls(controls: string[]) { | ||||
|     controls.forEach(control => { | ||||
|       this.databaseForm.get(control)!.disable({emitEvent: false}); | ||||
|       this.databaseForm.get(control)!.updateValueAndValidity({emitEvent: false}); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   private enableControls(controls: string[]) { | ||||
|     controls.forEach(control => { | ||||
|       this.databaseForm.get(control)!.enable({emitEvent: false}); | ||||
|       this.databaseForm.get(control)!.updateValueAndValidity({emitEvent: false}); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   protected onDatabaseChange(selectedDatabase: string) { | ||||
|     this.createForm(selectedDatabase); | ||||
|     this.database = selectedDatabase; | ||||
|  | ||||
|     if (this.database === "sqlite") { | ||||
|       this.navigationService.nextButtonAction = () => { | ||||
|         return this.api.setSqlite(this.databaseForm.get('folder')?.value ?? ''); | ||||
|       }; | ||||
|     } else { | ||||
|       this.navigationService.nextButtonAction = () => { | ||||
|         let databaseRequest: DatabaseRequest = { | ||||
|           "server": this.databaseForm.get('server')?.value, | ||||
|           "port": this.databaseForm.get('port')?.value, | ||||
|           "database": this.databaseForm.get('database_name')?.value, | ||||
|           "user": this.databaseForm.get('user')?.value, | ||||
|           "ssl": this.databaseForm.get('ssl')?.value, | ||||
|           "password": this.databaseForm.get('password')?.value, | ||||
|         }; | ||||
|         if (this.database === "mysql") | ||||
|           return this.api.setMysql(databaseRequest); | ||||
|         else | ||||
|           return this.api.setPsql(databaseRequest); | ||||
|       }; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected togglePassword(event: MouseEvent) { | ||||
|     this.hidePass = !this.hidePass; | ||||
|     event.stopPropagation(); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user