diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 24a2458..a0ef43d 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,8 +3,7 @@ import {Routes, RouterModule} from '@angular/router' import {CatalogComponent} from './pages/catalog/catalog.component' import {AdministrationComponent} from './pages/administration/administration.component' import {MiscComponent} from './pages/others/misc.component' -import {CreConfigEditor} from './modules/configuration/config' - +import {CreConfigEditor} from './modules/configuration/config-editor' const routes: Routes = [{ path: 'color', diff --git a/src/app/modules/configuration/bool.html b/src/app/modules/configuration/bool.html deleted file mode 100644 index 48709db..0000000 --- a/src/app/modules/configuration/bool.html +++ /dev/null @@ -1,4 +0,0 @@ -
- - {{lastUpdated}} -
diff --git a/src/app/modules/configuration/config-bool.html b/src/app/modules/configuration/config-bool.html new file mode 100644 index 0000000..0f7a298 --- /dev/null +++ b/src/app/modules/configuration/config-bool.html @@ -0,0 +1,6 @@ + +
+ + {{inputHint}} +
+
diff --git a/src/app/modules/configuration/config-container.html b/src/app/modules/configuration/config-container.html new file mode 100644 index 0000000..8c928f0 --- /dev/null +++ b/src/app/modules/configuration/config-container.html @@ -0,0 +1,6 @@ +
+ +
diff --git a/src/app/modules/configuration/config-date.html b/src/app/modules/configuration/config-date.html new file mode 100644 index 0000000..2f443e3 --- /dev/null +++ b/src/app/modules/configuration/config-date.html @@ -0,0 +1,12 @@ + + + + diff --git a/src/app/modules/configuration/config-editor.html b/src/app/modules/configuration/config-editor.html new file mode 100644 index 0000000..11982bc --- /dev/null +++ b/src/app/modules/configuration/config-editor.html @@ -0,0 +1,120 @@ +
+ + + Retour + + + Enregistrer + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Redémarrer le serveur + + +
+
+ + + + diff --git a/src/app/modules/configuration/config-editor.ts b/src/app/modules/configuration/config-editor.ts new file mode 100644 index 0000000..b6d7a67 --- /dev/null +++ b/src/app/modules/configuration/config-editor.ts @@ -0,0 +1,94 @@ +import {Component, ViewChild} from '@angular/core' +import {ErrorHandlingComponent} from '../shared/components/subscribing.component' +import {ConfirmBoxComponent} from '../shared/components/confirm-box/confirm-box.component' +import {buildFormControl, Config, ConfigControl} from '../shared/model/config.model' +import {FormBuilder, FormControl, FormGroup} from '@angular/forms' +import {ConfigService} from '../shared/service/config.service' +import {ErrorService} from '../shared/service/error.service' +import {ActivatedRoute, Router} from '@angular/router' + +@Component({ + selector: 'cre-config-editor', + templateUrl: 'config-editor.html' +}) +export class CreConfigEditor extends ErrorHandlingComponent { + @ViewChild('restartingConfirmBox', {static: true}) restartConfirmBox: ConfirmBoxComponent + + keys = { + INSTANCE_NAME: Config.INSTANCE_NAME, + INSTANCE_LOGO_PATH: Config.INSTANCE_LOGO_PATH, + INSTANCE_ICON_PATH: Config.INSTANCE_ICON_PATH, + INSTANCE_URL: Config.INSTANCE_URL, + DATABASE_URL: Config.DATABASE_URL, + DATABASE_USER: Config.DATABASE_USER, + DATABASE_PASSWORD: Config.DATABASE_PASSWORD, + DATABASE_VERSION: Config.DATABASE_VERSION, + RECIPE_APPROBATION_EXPIRATION: Config.RECIPE_APPROBATION_EXPIRATION, + TOUCH_UP_KIT_CACHE_PDF: Config.TOUCH_UP_KIT_CACHE_PDF, + TOUCH_UP_KIT_EXPIRATION: Config.TOUCH_UP_KIT_EXPIRATION, + BACKEND_BUILD_VERSION: Config.BACKEND_BUILD_VERSION, + BACKEND_BUILD_TIME: Config.BACKEND_BUILD_TIME, + JAVA_VERSION: Config.JAVA_VERSION, + OPERATING_SYSTEM: Config.OPERATING_SYSTEM + } + + configs = new Map() + form: FormGroup | null + + constructor( + private configService: ConfigService, + formBuilder: FormBuilder, + errorService: ErrorService, + activatedRoute: ActivatedRoute, + router: Router + ) { + super(errorService, activatedRoute, router) + + this.fetchConfigurations(formBuilder) + } + + getConfigControl(key: string): ConfigControl { + return { + config: this.configs.get(key), + control: this.form.controls[key] as FormControl + } + } + + onSubmit() { + this.subscribe( + this.configService.setFromForm(this.form), + () => this.reload() + ) + } + + restart() { + this.subscribe( + this.configService.restart(), + () => this.restartConfirmBox.show() + ) + } + + reload() { + window.location.reload() + } + + get emergencyMode(): boolean { + return this.configs.get(Config.EMERGENCY_MODE).content === 'true'; + } + + private fetchConfigurations(formBuilder: FormBuilder) { + this.subscribe( + this.configService.all, + configurations => this.buildForm(formBuilder, configurations) + ) + } + + private buildForm(formBuilder: FormBuilder, configurations: Config[]) { + const group = {} + configurations.forEach(config => { + group[config.key] = buildFormControl(config) + this.configs.set(config.key, config) + }) + this.form = formBuilder.group(group) + } +} diff --git a/src/app/modules/configuration/config-image.html b/src/app/modules/configuration/config-image.html new file mode 100644 index 0000000..084aad1 --- /dev/null +++ b/src/app/modules/configuration/config-image.html @@ -0,0 +1,28 @@ +
+

+ {{label}} +

+
+ + +
+ + +
+
+ +
+ {{lastUpdated}} +
+
+
diff --git a/src/app/modules/configuration/config-period.html b/src/app/modules/configuration/config-period.html new file mode 100644 index 0000000..90d8af9 --- /dev/null +++ b/src/app/modules/configuration/config-period.html @@ -0,0 +1,7 @@ + + + + diff --git a/src/app/modules/configuration/config-section.html b/src/app/modules/configuration/config-section.html index 08c2b94..8d02e34 100644 --- a/src/app/modules/configuration/config-section.html +++ b/src/app/modules/configuration/config-section.html @@ -1,8 +1,6 @@ - - - + {{label}} diff --git a/src/app/modules/configuration/config-secure.html b/src/app/modules/configuration/config-secure.html new file mode 100644 index 0000000..aaea0b0 --- /dev/null +++ b/src/app/modules/configuration/config-secure.html @@ -0,0 +1,24 @@ + + + {{buttonLabel}} + + + + + + + + + diff --git a/src/app/modules/configuration/config-text.html b/src/app/modules/configuration/config-text.html new file mode 100644 index 0000000..1878b43 --- /dev/null +++ b/src/app/modules/configuration/config-text.html @@ -0,0 +1,11 @@ + + + + diff --git a/src/app/modules/configuration/config.html b/src/app/modules/configuration/config.html deleted file mode 100644 index 8f23ca1..0000000 --- a/src/app/modules/configuration/config.html +++ /dev/null @@ -1,12 +0,0 @@ -
- - -
diff --git a/src/app/modules/configuration/config.module.ts b/src/app/modules/configuration/config.module.ts index 6d16826..d3d6bba 100644 --- a/src/app/modules/configuration/config.module.ts +++ b/src/app/modules/configuration/config.module.ts @@ -1,33 +1,35 @@ import {NgModule} from '@angular/core' import { - CreConfig, - CreConfigLabel, - CreConfigEditor, - CreConfigSection, - CreImageConfig, - CreConfigList, + CreBoolConfig, CreConfigActions, - CreConfigTooltip, CrePeriodConfig, CreBoolConfig, CreDateConfig, CreSecureConfig + CreConfigContainer, + CreConfigList, + CreConfigSection, + CreDateConfig, + CreImageConfig, + CrePeriodConfig, + CreSecureConfig, + CreTextConfig } from './config' import {SharedModule} from '../shared/shared.module' import {CreInputsModule} from '../shared/components/inputs/inputs.module' import {CreActionBarModule} from '../shared/components/action-bar/action-bar.module' import {CreButtonsModule} from '../shared/components/buttons/buttons.module' +import {CreConfigEditor} from './config-editor' @NgModule({ declarations: [ - CreConfigLabel, - CreConfigTooltip, - CreConfigEditor, - CreConfig, - CreImageConfig, - CreConfigSection, CreConfigList, CreConfigActions, + CreConfigSection, + CreConfigContainer, + CreTextConfig, + CreImageConfig, CreBoolConfig, CrePeriodConfig, CreDateConfig, - CreSecureConfig + CreSecureConfig, + CreConfigEditor ], imports: [ SharedModule, @@ -36,4 +38,5 @@ import {CreButtonsModule} from '../shared/components/buttons/buttons.module' CreButtonsModule ] }) -export class ConfigModule { } +export class ConfigModule { +} diff --git a/src/app/modules/configuration/config.sass b/src/app/modules/configuration/config.sass index 062d34e..0e8f839 100644 --- a/src/app/modules/configuration/config.sass +++ b/src/app/modules/configuration/config.sass @@ -1,10 +1,10 @@ mat-hint font-size: .8em -cre-config +cre-config-container display: block - cre-input.has-hint + .cre-config:not(.cre-editable-config) margin-bottom: 1em mat-hint @@ -50,6 +50,3 @@ cre-image-config mat-hint margin-top: .2em - -//cre-secure-config button -// diff --git a/src/app/modules/configuration/config.ts b/src/app/modules/configuration/config.ts index 9ba1d5b..ff20401 100644 --- a/src/app/modules/configuration/config.ts +++ b/src/app/modules/configuration/config.ts @@ -1,58 +1,13 @@ -import { - AfterViewInit, - Component, - ContentChild, - Directive, - ElementRef, - EventEmitter, - Input, - Output, - ViewChild, - ViewEncapsulation -} from '@angular/core' +import {AfterViewInit, Component, ContentChild, Directive, EventEmitter, Input, Output, ViewChild, ViewEncapsulation} from '@angular/core' import {ConfigService} from '../shared/service/config.service' -import {Config} from '../shared/model/config.model' -import {ErrorHandlingComponent, SubscribingComponent} from '../shared/components/subscribing.component' +import {Config, ConfigControl} from '../shared/model/config.model' +import {SubscribingComponent} from '../shared/components/subscribing.component' import {ErrorService} from '../shared/service/error.service' import {ActivatedRoute, Router} from '@angular/router' import {formatDate, formatDateTime, getFileUrl, readFile} from '../shared/utils/utils' -import {FormControl, Validators} from '@angular/forms' -import {ConfirmBoxComponent} from '../shared/components/confirm-box/confirm-box.component' -import {MatDialog} from '@angular/material/dialog' +import {AbstractControl} from '@angular/forms' import {CrePromptDialog} from '../shared/components/dialogs/dialogs' -@Directive({ - selector: 'cre-config-label' -}) -export class CreConfigLabel implements AfterViewInit { - content: string - - constructor( - private element: ElementRef - ) { - } - - ngAfterViewInit(): void { - this.content = this.element.nativeElement.innerHTML - } -} - -@Directive({ - selector: 'cre-config-tooltip' -}) -export class CreConfigTooltip implements AfterViewInit { - content: string - - constructor( - private element: ElementRef - ) { - } - - ngAfterViewInit(): void { - this.content = this.element.nativeElement.innerHTML - } -} - @Directive({ selector: 'cre-config-list' }) @@ -71,6 +26,8 @@ export class CreConfigActions { templateUrl: 'config-section.html' }) export class CreConfigSection { + @Input() label: string + @ContentChild(CreConfigActions) actions: CreConfigActions get hasActions(): boolean { @@ -79,17 +36,25 @@ export class CreConfigSection { } @Component({ - selector: 'cre-config', - templateUrl: 'config.html', - styleUrls: ['config.sass'] + selector: 'cre-config-container', + templateUrl: 'config-container.html', + styleUrls: ['config.sass'], + encapsulation: ViewEncapsulation.None }) -export class CreConfig extends SubscribingComponent { - @Input() config: { key: string, control: FormControl } +export class CreConfigContainer { + @Input() configuration?: Config + @Input() tooltip: string - @ContentChild(CreConfigLabel, {static: true}) label: CreConfigLabel - @ContentChild(CreConfigTooltip, {static: true}) tooltip: CreConfigTooltip + get readOnly(): boolean { + return !this.configuration?.editable ?? true + } +} - configuration: Config | null +@Directive() +abstract class _CreConfigBase extends SubscribingComponent { + @Input() configControl: ConfigControl + @Input() label: string + @Input() tooltip?: string constructor( private configService: ConfigService, @@ -102,92 +67,99 @@ export class CreConfig extends SubscribingComponent { ngOnInit() { super.ngOnInit() - - this.subscribe( - this.configService.get(this.config.key), - config => this.setConfig(config) - ) } - protected setConfig(config: Config) { - this.configuration = config - this.config.control.setValue(config.content) - if (!config.editable) { - this.config.control.disable() - } + get config(): Config { + return this.configControl.config + } + + get control(): AbstractControl { + return this.configControl.control } get lastUpdated(): string { - return 'Dernière mise à jour: ' + formatDateTime(this.configuration.lastUpdated) + return 'Dernière mise à jour: ' + formatDateTime(this.config.lastUpdated) + } + + get inputHint(): string { + return this.config?.editable ? this.lastUpdated : null + } +} + +@Directive() +abstract class _CreTextConfigBase extends _CreConfigBase { + private static readonly REQUIRE_RESTART_ICON = 'alert' + private static readonly REQUIRE_RESTART_ICON_TITLE = 'Requiert un redémarrage' + + get inputIcon(): string { + return this.config?.requireRestart ? _CreTextConfigBase.REQUIRE_RESTART_ICON : null + } + + get inputIconTitle(): string { + return this.config?.requireRestart ? _CreTextConfigBase.REQUIRE_RESTART_ICON_TITLE : null } } +@Component({ + selector: 'cre-text-config', + templateUrl: 'config-text.html', + styleUrls: ['config.sass'] +}) +export class CreTextConfig extends _CreTextConfigBase { +} + @Component({ selector: 'cre-image-config', - templateUrl: 'image.html', + templateUrl: 'config-image.html', styleUrls: ['config.sass'], encapsulation: ViewEncapsulation.None }) -export class CreImageConfig extends CreConfig { +export class CreImageConfig extends _CreConfigBase { @Input() previewWidth: string | null @Output() invalidFormat = new EventEmitter() updatedImage: any | null - constructor( - configService: ConfigService, - errorService: ErrorService, - activatedRoute: ActivatedRoute, - router: Router - ) { - super(configService, errorService, activatedRoute, router) - } - updateImage(file: File): any { readFile(file, (content) => this.updatedImage = content) } get configuredImageUrl(): string { - return getFileUrl(this.configuration.content) + return getFileUrl(this.config.content) } } @Component({ selector: 'cre-bool-config', - templateUrl: 'bool.html' + templateUrl: 'config-bool.html' }) -export class CreBoolConfig extends CreConfig { - protected setConfig(config: Config) { - super.setConfig(config) - this.config.control.setValue(config.content === 'true') - } +export class CreBoolConfig extends _CreConfigBase { } @Component({ selector: 'cre-period-config', - templateUrl: 'period.html' + templateUrl: 'config-period.html' }) -export class CrePeriodConfig extends CreConfig { +export class CrePeriodConfig extends _CreConfigBase { } @Component({ selector: 'cre-date-config', - templateUrl: 'date.html' + templateUrl: 'config-date.html' }) -export class CreDateConfig extends CreConfig { - protected setConfig(config: Config) { - super.setConfig(config) - this.config.control.setValue(formatDate(config.content)) +export class CreDateConfig extends _CreTextConfigBase implements AfterViewInit { + ngAfterViewInit(): void { + this.control.setValue(formatDate(this.config.content)) } } @Component({ selector: 'cre-secure-config', - templateUrl: 'secure.html' + templateUrl: 'config-secure.html' }) -export class CreSecureConfig extends CreConfig { +export class CreSecureConfig extends _CreTextConfigBase { @ViewChild(CrePromptDialog) dialog: CrePromptDialog @Input() buttonLabel: string @@ -200,91 +172,15 @@ export class CreSecureConfig extends CreConfig { activatedRoute: ActivatedRoute, router: Router ) { - super(configService, errorService, activatedRoute, router); - } - - protected setConfig(config: Config) { - super.setConfig(config) + super(configService, errorService, activatedRoute, router) } onOpen() { - this.initialValue = this.config.control.value + this.initialValue = this.control.value this.dialog.show() } onCancel() { - this.config.control.setValue(this.initialValue) - } -} - -@Component({ - selector: 'cre-config-editor', - templateUrl: 'editor.html' -}) -export class CreConfigEditor extends ErrorHandlingComponent { - @ViewChild('restartingConfirmBox', {static: true}) restartConfirmBox: ConfirmBoxComponent - - keys = { - INSTANCE_NAME: Config.INSTANCE_NAME, - INSTANCE_LOGO_PATH: Config.INSTANCE_LOGO_PATH, - INSTANCE_ICON_PATH: Config.INSTANCE_ICON_PATH, - INSTANCE_URL: Config.INSTANCE_URL, - DATABASE_URL: Config.DATABASE_URL, - DATABASE_USER: Config.DATABASE_USER, - DATABASE_PASSWORD: Config.DATABASE_PASSWORD, - DATABASE_VERSION: Config.DATABASE_VERSION, - RECIPE_APPROBATION_EXPIRATION: Config.RECIPE_APPROBATION_EXPIRATION, - TOUCH_UP_KIT_CACHE_PDF: Config.TOUCH_UP_KIT_CACHE_PDF, - TOUCH_UP_KIT_EXPIRATION: Config.TOUCH_UP_KIT_EXPIRATION, - BACKEND_BUILD_VERSION: Config.BACKEND_BUILD_VERSION, - BACKEND_BUILD_TIME: Config.BACKEND_BUILD_TIME, - JAVA_VERSION: Config.JAVA_VERSION, - OPERATING_SYSTEM: Config.OPERATING_SYSTEM - } - controls = new Map() - emergencyMode: string | null - - constructor( - private configService: ConfigService, - errorService: ErrorService, - activatedRoute: ActivatedRoute, - router: Router - ) { - super(errorService, activatedRoute, router) - - for (let key in this.keys) { - this.controls.set(this.keys[key], new FormControl(null, Validators.required)) - } - } - - ngOnInit() { - this.subscribe( - this.configService.get(Config.EMERGENCY_MODE), - config => { - this.emergencyMode = config.content - } - ) - } - - getConfig(key: string) { - return {key, control: this.controls.get(key)} - } - - save() { - this.subscribe( - this.configService.set(this.controls), - () => this.reload() - ) - } - - restart() { - this.subscribe( - this.configService.restart(), - () => this.restartConfirmBox.show() - ) - } - - reload() { - window.location.reload() + this.control.setValue(this.initialValue) } } diff --git a/src/app/modules/configuration/date.html b/src/app/modules/configuration/date.html deleted file mode 100644 index 83e8af4..0000000 --- a/src/app/modules/configuration/date.html +++ /dev/null @@ -1,12 +0,0 @@ -
- - -
diff --git a/src/app/modules/configuration/editor.html b/src/app/modules/configuration/editor.html deleted file mode 100644 index ec78574..0000000 --- a/src/app/modules/configuration/editor.html +++ /dev/null @@ -1,128 +0,0 @@ - - - Retour - - - Enregistrer - - - -
- - Apparence - - - - - - - - - - Logo - - Affiché dans la bannière de l'application web. Il peut être nécessaire de forcer le - rafraîchissement du cache du navigateur pour que ce changement prenne effet (généralement avec les touches - 'Ctrl+F5'). - - - - - Icône - - Affiché dans l'onglet de la page dans le navigateur. Il peut être nécessaire de forcer le - rafraîchissement du cache du navigateur pour que ce changement prenne effet (généralement avec les touches - 'Ctrl+F5'). - - - - - - - Données - - - Période d'expiration de l'approbation de l'échantillon des recettes - - - - Période d'expiration des kits de retouches complets - - Les kits de retouche complétés expirent après la période configurée. Les kits de retouche expirés seront - supprimés automatiquement. - - - - - Activer le cache des PDFs générés - - Cette option permet de stocker les PDFs générés sur le disque, ce qui permet d'accélérer - l'accès aux PDFs si la lecture des fichiers cachés sur le disque est plus rapide que la génération d'un - nouveau PDF. - - - - - - - Système - - - URL de l'instance - - Utilisé pour générer l'URL de certaines ressources, comme les images et les fiches signalitiques. - - - - - URL de la base de données - - - - Utilisateur de la base de données - - - - - - - - Mot de passe de la base de données - - - - Version de la base de données - - - - Version de Color Recipes Explorer - - - - Date de compilation de Color Recipes Explorer - - - - Version de Java - - - - Système d'exploitation - - - - Redémarrer le serveur - - -
- - - - diff --git a/src/app/modules/configuration/image.html b/src/app/modules/configuration/image.html deleted file mode 100644 index 21459eb..0000000 --- a/src/app/modules/configuration/image.html +++ /dev/null @@ -1,26 +0,0 @@ -
-

- -

-
- -
- - -
-
- -
- {{lastUpdated}} -
-
diff --git a/src/app/modules/configuration/period.html b/src/app/modules/configuration/period.html deleted file mode 100644 index 722ec27..0000000 --- a/src/app/modules/configuration/period.html +++ /dev/null @@ -1,7 +0,0 @@ -
- - -
diff --git a/src/app/modules/configuration/secure.html b/src/app/modules/configuration/secure.html deleted file mode 100644 index 1c1fcae..0000000 --- a/src/app/modules/configuration/secure.html +++ /dev/null @@ -1,25 +0,0 @@ -
- - {{buttonLabel}} - - - - - - - - -
diff --git a/src/app/modules/shared/components/buttons/buttons.ts b/src/app/modules/shared/components/buttons/buttons.ts index a388f90..80ab652 100644 --- a/src/app/modules/shared/components/buttons/buttons.ts +++ b/src/app/modules/shared/components/buttons/buttons.ts @@ -4,7 +4,7 @@ import {ThemePalette} from '@angular/material/core' @Component({ selector: 'cre-button', template: ` - `, @@ -13,44 +13,48 @@ import {ThemePalette} from '@angular/material/core' }) export class CreButtonComponent { @Input() color: ThemePalette + @Input() type = 'button' @Input() disabled = false } @Component({ selector: 'cre-primary-button', template: ` - + `, styleUrls: ['buttons.sass'] }) export class CrePrimaryButtonComponent { + @Input() type = 'button' @Input() disabled = false } @Component({ selector: 'cre-accent-button', template: ` - + `, styleUrls: ['buttons.sass'] }) export class CreAccentButtonComponent { + @Input() type = 'button' @Input() disabled = false } @Component({ selector: 'cre-warn-button', template: ` - + `, styleUrls: ['buttons.sass'] }) export class CreWarnButtonComponent { + @Input() type = 'button' @Input() disabled = false } diff --git a/src/app/modules/shared/components/inputs/input.html b/src/app/modules/shared/components/inputs/input.html index d123b75..2bf813e 100644 --- a/src/app/modules/shared/components/inputs/input.html +++ b/src/app/modules/shared/components/inputs/input.html @@ -1,25 +1,21 @@ {{label}} - - + + + + + + + + () + @ViewChild('input') input: any @ContentChild(TemplateRef) errors: TemplateRef + + ngAfterViewInit() { + const element = this.input.nativeElement + element.type = this.type + element.step = this.step.toString() + element.placeholder = this.placeholder + element.required = this.required + element.autocomplete = this.autocomplete ? 'on' : 'off' + } } @Component({ @@ -51,7 +66,7 @@ export class CreInputComponent { encapsulation: ViewEncapsulation.None }) export class CreAutocompleteInputComponent { - @Input() control: FormControl | null + @Input() control: AbstractControl | null @Input() label: string @Input() icon: string @Input() required = true @@ -69,7 +84,7 @@ export class CreAutocompleteInputComponent { encapsulation: ViewEncapsulation.None }) export class CreChipInputComponent implements OnInit { - @Input() control: FormControl + @Input() control: AbstractControl @Input() label: string @Input() icon: string @Input() required = true @@ -118,7 +133,7 @@ export class CreChipInputComponent implements OnInit { encapsulation: ViewEncapsulation.None }) export class CreComboBoxComponent { - @Input() control: FormControl + @Input() control: AbstractControl @Input() label: string @Input() icon: string @Input() required = true @@ -184,12 +199,16 @@ export class CreChipComboBoxComponent extends CreChipInputComponent implements O selector: 'cre-checkbox-input', templateUrl: 'checkbox.html' }) -export class CreCheckboxInputComponent { +export class CreCheckboxInputComponent implements OnInit { @Input() label: string - @Input() control: FormControl + @Input() control: AbstractControl @Input() checked: boolean @Output() checkedChange = new EventEmitter() + + ngOnInit(): void { + this.control?.setValue(this.control.value === 'true') + } } @Component({ @@ -200,7 +219,7 @@ export class CreFileInputComponent implements OnInit { @Input() label: string @Input() icon: string @Input() accept = '' - @Input() control: FormControl | null + @Input() control: AbstractControl | null @Output() selection = new EventEmitter() @Output() invalidFormat = new EventEmitter() @@ -234,7 +253,7 @@ export class CreFileInputComponent implements OnInit { encapsulation: ViewEncapsulation.None }) export class CrePeriodInputComponent implements OnInit { - @Input() control: FormControl + @Input() control: AbstractControl @Input() label: string @Input() hint: string | null @@ -264,9 +283,12 @@ export class CrePeriodInputComponent implements OnInit { } private setValuesFromPeriod(period: string) { + if (!period) { + return + } + const periodTypeChar = period.slice(-1) period = period.slice(1, -1) - this.selectControl.setValue(periodTypeChar) this.inputControl.setValue(period) } diff --git a/src/app/modules/shared/model/config.model.ts b/src/app/modules/shared/model/config.model.ts index 80a559a..edbd0f8 100644 --- a/src/app/modules/shared/model/config.model.ts +++ b/src/app/modules/shared/model/config.model.ts @@ -1,4 +1,4 @@ -import {Form, FormControl} from '@angular/forms' +import {AbstractControl, Form, FormControl, Validators} from '@angular/forms' import {filterMap} from '../utils/map.utils' export class Config { @@ -24,6 +24,10 @@ export class Config { Config.INSTANCE_ICON_PATH ] + static readonly PASSWORD_CONFIG_KEYS = [ + Config.DATABASE_PASSWORD + ] + public key: string public requireRestart: boolean public editable: boolean @@ -36,7 +40,20 @@ export class ConfigKeyContent { public content: string } -export function filterConfigKeyControlMap(map: Map): Map { +export class ConfigControl { + public config: Config + public control: AbstractControl +} + +export function buildFormControl(config: Config): AbstractControl { + return new FormControl({value: config.content, disabled: !config.editable}, Validators.required) +} + +export function configKeyIsPassword(key: string): boolean { + return Config.PASSWORD_CONFIG_KEYS.indexOf(key) >= 0 +} + +export function filterConfigKeyControlMap(map: Map): Map { return filterMap(map, (key, control) => { return control.dirty && Config.IMAGE_CONFIG_KEYS.indexOf(key) < 0 && // Filter image configs because they are sent to a different endpoint @@ -45,17 +62,17 @@ export function filterConfigKeyControlMap(map: Map): Map): Map { +export function filterImageConfigKeyControlMap(map: Map): Map { return filterMap(map, (key, control) => { return Config.IMAGE_CONFIG_KEYS.indexOf(key) >= 0 && control.dirty }) } -export function mapToConfigKeyContent(key: string, control: FormControl): ConfigKeyContent { +export function mapToConfigKeyContent(key: string, control: AbstractControl): ConfigKeyContent { return {key, content: control.value} } -export function mapToConfigKeyContentArray(map: Map): ConfigKeyContent[] { +export function mapToConfigKeyContentArray(map: Map): ConfigKeyContent[] { const array: ConfigKeyContent[] = [] map.forEach((control, key) => { array.push(mapToConfigKeyContent(key, control)) diff --git a/src/app/modules/shared/service/config.service.ts b/src/app/modules/shared/service/config.service.ts index 7ebe376..dcfd95d 100644 --- a/src/app/modules/shared/service/config.service.ts +++ b/src/app/modules/shared/service/config.service.ts @@ -2,7 +2,7 @@ import {Injectable} from '@angular/core' import {Config, filterConfigKeyControlMap, filterImageConfigKeyControlMap, mapToConfigKeyContentArray} from '../model/config.model' import {Observable} from 'rxjs' import {ApiService} from './api.service' -import {FormControl} from '@angular/forms' +import {AbstractControl, FormGroup} from '@angular/forms' import {transformMap} from '../utils/map.utils' @Injectable({ @@ -14,11 +14,23 @@ export class ConfigService { ) { } + get all(): Observable { + return this.api.get('/config') + } + get(key: string): Observable { return this.api.get(`/config/${key}`) } - set(configs: Map): Observable { + setFromForm(form: FormGroup): Observable { + const map = new Map() + for (let key in form.controls) { + map.set(key, form.controls[key]) + } + return this.set(map); + } + + set(configs: Map): Observable { const body = mapToConfigKeyContentArray(filterConfigKeyControlMap(configs)) const imageConfigs = filterImageConfigKeyControlMap(configs) @@ -38,7 +50,7 @@ export class ConfigService { return this.api.post('/config/restart') } - private setImages(configs: Map) { + private setImages(configs: Map) { const subscriptions = this.getImageConfigsSubscriptions(configs) while (subscriptions.length > 0) { const subscription = subscriptions.pop().subscribe({ @@ -47,7 +59,7 @@ export class ConfigService { } } - private getImageConfigsSubscriptions(configs: Map): Observable[] { + private getImageConfigsSubscriptions(configs: Map): Observable[] { return transformMap(configs, (key, control) => { return this.setImage(key, control.value) })