This is an automated email from the ASF dual-hosted git repository. ytykhun pushed a commit to branch DATALAB-2347 in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 5b309e756794ffb4b7b4726099d36f146c4d89e4 Author: Yurii Tykhun <[email protected]> AuthorDate: Thu Jul 29 11:51:21 2021 +0300 [DATALAB-2347] refactored Configuration component --- .../configuration/configuration.component.html | 104 ++++++++--- .../configuration/configuration.component.scss | 48 ++--- .../configuration/configuration.component.ts | 203 +++++++++++---------- 3 files changed, 201 insertions(+), 154 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.html index faab5da..62b11be 100644 --- a/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.html @@ -15,7 +15,7 @@ ~ KIND, either express or implied. See the License for the ~ specific language governing permissions and limitations ~ under the License. - --> +--> <div class="base-retreat configuration"> <div class="sub-nav"> @@ -49,15 +49,17 @@ </div> <div> <ng-template [ngIf]="activeTab.index !== 0"> - <button mat-raised-button class="butt" - (click)="action('save')" - [disabled]="!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged" + <button + mat-raised-button class="butt" + (click)="action('save')" + [disabled]="!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged" > Save </button> - <button mat-raised-button class="butt" - (click)="action('discard')" - [disabled]="!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged" + <button + mat-raised-button class="butt" + (click)="action('discard')" + [disabled]="!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged" > Discard changes </button> @@ -70,16 +72,28 @@ > Restart </button> - <button mat-raised-button class="butt" (click)="refreshConfig()"> + <button + mat-raised-button + class="butt" + (click)="refreshConfig()" + > <i class="material-icons refresh-icon">autorenew</i>Refresh </button> </div> </div> <mat-divider></mat-divider> <div class="configuration-wrapper"> - <mat-tab-group animationDuration="0.5ms" (selectedTabChange)="tabChanged($event)" [selectedIndex]=activeTab.index> - <mat-tab label="Main" - [disabled]="!(!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged) && activeTab.index !== 0" + <mat-tab-group + animationDuration="0.5ms" + (selectedTabChange)="tabChanged($event)" + [selectedIndex]="activeTab.index" + > + <mat-tab + label="Main" + [disabled]="!(!services['provisioning'].isConfigChanged && + !services['self-service'].isConfigChanged && + !services['billing'].isConfigChanged) && + activeTab.index !== 0" > <h4>Main settings</h4> <div class="main-wrapper"> @@ -89,16 +103,18 @@ <ul class="list-menu selection-list"> <li *ngFor="let service of services | keys"> <p + *ngIf="(activeEndpoint !== 'local' + && (service.key === 'provisioning' || service.key === 'billing') + || activeEndpoint === 'local')" class="list-item" role="menuitem" - *ngIf="(activeEndpoint !== 'local' && (service.key === 'provisioning' || service.key === 'billing') || activeEndpoint === 'local')"> + > <span (click)="toggleSettings(service.key);$event.stopPropagation()" class="d-flex"> <div class="checkbox-wrap"> <datalab-checkbox [checked]="services[service.key].selected" (toggleSelection)="toggleSettings(service.key)" - > - </datalab-checkbox> + ></datalab-checkbox> </div> {{service.value.label}} </span> @@ -110,36 +126,64 @@ </div> </mat-tab> - <mat-tab label="Self-service" - *ngIf="activeEndpoint === 'local'" - [disabled]="!(!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged) && activeTab.index !== 1" - + <mat-tab + label="Self-service" + *ngIf="activeEndpoint === 'local'" + [disabled]="!(!services['provisioning'].isConfigChanged + && !services['self-service'].isConfigChanged + && !services['billing'].isConfigChanged) + && activeTab.index !== 1" > <h4>Edit self-service.yml</h4> <div class="editor-wrap"> - <div #selfEditor ace-editor mode="yaml" [(text)]="services['self-service'].config" [autoUpdateContent]="true" (textChange)="configUpdate('self-service')"></div> + <div + #selfEditor + ace-editor + mode="yaml" + [(text)]="services['self-service'].config" + [autoUpdateContent]="true" + (textChange)="configUpdate('self-service')" + ></div> </div> </mat-tab> - <mat-tab label="Provisioning" - [disabled]="!(!services['provisioning'].isConfigChanged - && !services['self-service'].isConfigChanged - && !services['billing'].isConfigChanged) - && activeTab.index !== 2"> - + <mat-tab + label="Provisioning" + [disabled]="!(!services['provisioning'].isConfigChanged + && !services['self-service'].isConfigChanged + && !services['billing'].isConfigChanged) + && activeTab.index !== 2" + > <h4>Edit provisioning.yml</h4> <div class="editor-wrap"> - <div #provEditor ace-editor [(text)]="services['provisioning'].config" [autoUpdateContent]="true" mode="yaml" (textChange)="configUpdate('provisioning')"></div> + <div + #provEditor + ace-editor + mode="yaml" + [(text)]="services['provisioning'].config" + [autoUpdateContent]="true" + (textChange)="configUpdate('provisioning')" + ></div> </div> </mat-tab> - <mat-tab label="Billing" - [disabled]="!(!services['provisioning'].isConfigChanged && !services['self-service'].isConfigChanged && !services['billing'].isConfigChanged) && activeTab.index !== 3" + <mat-tab + label="Billing" + [disabled]="!(!services['provisioning'].isConfigChanged + && !services['self-service'].isConfigChanged + && !services['billing'].isConfigChanged) + && activeTab.index !== 3" > <h4>Edit billing.yml</h4> <div class="editor-wrap"> - <div #billingEditor ace-editor mode="yaml" [(text)]="services['billing'].config" [autoUpdateContent]="true" (textChange)="configUpdate('billing')"></div> - + <div + #billingEditor + ace-editor + mode="yaml" + [(text)]="services['billing'].config" + [autoUpdateContent]="true" + (textChange)="configUpdate('billing')" + ></div> </div> </mat-tab> </mat-tab-group> diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.scss index 2df3042..e230032 100644 --- a/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.scss @@ -17,44 +17,44 @@ * under the License. */ -.configuration-wrapper{ - box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12); - padding-top: 0; +.configuration-wrapper { height: calc(100vh - 130px); + padding-top: 0; + box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), + 0px 6px 10px 0px rgba(0, 0, 0, 0.14), + 0px 1px 18px 0px rgba(0, 0, 0, 0.12); - .sub-nav{ + .sub-nav { justify-content: flex-end; padding: 0 30px; } - h4{ + h4 { padding: 10px 30px; - color: rgba(0,0,0,.87); - font-family: 'Open Sans', sans-serif; + color: rgba(0, 0, 0, 0.87); + font-family: "Open Sans", sans-serif; } - .editor-wrap{ + .editor-wrap { height: calc(100% - 60px); - box-shadow: 0 2px 24px 0 rgba(73,93,112,0.3); margin: 0 30px; + box-shadow: 0 2px 24px 0 rgba(73, 93, 112, 0.3); } - .main-wrapper{ + .main-wrapper { padding: 10px 30px; - font-family: 'Open Sans', sans-serif; - - .section{ + font-family: "Open Sans", sans-serif; - &-title{ + .section { + &-title { font-size: 15px; } &-content { - .list-menu { + left: 0; width: 100%; max-height: 450px; - left: 0; padding: 10px 0; margin: 0; overflow-y: auto; @@ -66,15 +66,15 @@ margin: 0; } - .list-item{ - padding: 5px 10px; + .list-item { display: flex; + padding: 5px 10px; - span{ + span { cursor: pointer; } - .checkbox-wrap{ + .checkbox-wrap { display: flex; align-items: center; margin-right: 5px; @@ -86,10 +86,11 @@ } } } -.sub-nav{ + +.sub-nav { justify-content: space-between; - .label{ + .label { display: flex; align-items: center; margin-right: 10px; @@ -100,10 +101,9 @@ font-family: "Open Sans", sans-serif; } - .butt{ + .butt { margin-left: 10px; } - } .mat-option-disabled { diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.ts index 919799f..72157b7 100644 --- a/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/administration/configuration/configuration.component.ts @@ -17,17 +17,18 @@ * under the License. */ -import {Component, OnInit, Inject, HostListener, OnDestroy, ViewChild, ElementRef} from '@angular/core'; +import { Component, OnInit, Inject, HostListener, OnDestroy, ViewChild, ElementRef } from '@angular/core'; +import { Router } from '@angular/router'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import {HealthStatusService, AppRoutingService, EndpointService} from '../../core/services'; -import {MatTabChangeEvent} from '@angular/material/tabs'; -import {Router} from '@angular/router'; -import {ConfigurationService} from '../../core/services/configutration.service'; +import { MatTabChangeEvent } from '@angular/material/tabs'; import 'brace'; import 'brace/mode/yaml'; -import {ToastrService} from 'ngx-toastr'; -import {Observable, Subject} from 'rxjs'; -import {takeUntil} from 'rxjs/operators'; +import { Observable, Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { ToastrService } from 'ngx-toastr'; + +import { HealthStatusService, AppRoutingService, EndpointService } from '../../core/services'; +import { ConfigurationService } from '../../core/services/configutration.service'; import { EnvironmentsDataService } from '../management/management-data.service'; import { EnvironmentModel } from '../management/management.model'; @@ -42,12 +43,12 @@ export class ConfigurationComponent implements OnInit, OnDestroy { @ViewChild('billingEditor') billingEditor: ElementRef<HTMLElement>; private unsubscribe$ = new Subject(); private healthStatus: any; - public activeTab = {index: 0}; + public activeTab = { index: 0 }; public activeService: string; public services = { - 'self-service': {label: 'Self-service', selected: false, config: '', serverConfig: '', isConfigChanged: false}, - 'provisioning': {label: 'Provisioning', selected: false, config: '', serverConfig: '', isConfigChanged: false}, - 'billing': {label: 'Billing', selected: false, config: '', serverConfig: '', isConfigChanged: false}, + 'self-service': { label: 'Self-service', selected: false, config: '', serverConfig: '', isConfigChanged: false }, + 'provisioning': { label: 'Provisioning', selected: false, config: '', serverConfig: '', isConfigChanged: false }, + 'billing': { label: 'Billing', selected: false, config: '', serverConfig: '', isConfigChanged: false }, }; public messagesStatus = { @@ -55,7 +56,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy { error: [], counter: 0 }; - + public environmentStatuses = {}; public environments = []; public ingStatuses = ['creating', 'configuring', 'reconfiguring', 'creating image', 'stopping', 'starting', 'terminating']; @@ -96,25 +97,26 @@ export class ConfigurationComponent implements OnInit, OnDestroy { this.getEnvironmentHealthStatus(); this.getEndpoints() .subscribe(endpoints => { - this.endpoints = endpoints; - - this.endpoints = this.endpoints.map(endpoint => ({name: endpoint.name, status: endpoint.status })); - - this.activeEndpoint = this.endpoints[0].name; - this.getServicesConfig(this.activeEndpoint); - }); - - this.environmentsDataService.getEnvironmentDataDirect().subscribe((data: any) => { - this.environments = EnvironmentModel.loadEnvironments(data); - this.environments.map(env => { - this.checkResource(env.status, env.endpoint); - if(env.resources?.length > 0) { - env.resources.map(resource => { - this.checkResource(resource.status, env.endpoint); - }) - } + this.endpoints = endpoints; + + this.endpoints = this.endpoints.map(endpoint => ({ name: endpoint.name, status: endpoint.status })); + + this.activeEndpoint = this.endpoints[0].name; + this.getServicesConfig(this.activeEndpoint); + }); + + this.environmentsDataService.getEnvironmentDataDirect() + .subscribe((data: any) => { + this.environments = EnvironmentModel.loadEnvironments(data); + this.environments.map(env => { + this.checkResource(env.status, env.endpoint); + if (env.resources?.length > 0) { + env.resources.map(resource => { + this.checkResource(resource.status, env.endpoint); + }); + } + }); }); - }); } ngOnDestroy() { @@ -123,8 +125,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy { } public checkResource(resourceStatus: string, endpoint: string) { - if( this.ingStatuses.includes(resourceStatus) ) { - if(!this.environmentStatuses[endpoint]) { + if (this.ingStatuses.includes(resourceStatus)) { + if (!this.environmentStatuses[endpoint]) { this.environmentStatuses[endpoint] = []; this.environmentStatuses[endpoint].push(resourceStatus); } else { @@ -139,10 +141,9 @@ export class ConfigurationComponent implements OnInit, OnDestroy { takeUntil(this.unsubscribe$) ) .subscribe((result: any) => { - this.healthStatus = result; - !this.healthStatus.admin && !this.healthStatus.projectAdmin && this.appRoutingService.redirectToHomePage(); - } - ); + this.healthStatus = result; + !this.healthStatus.admin && !this.healthStatus.projectAdmin && this.appRoutingService.redirectToHomePage(); + }); } private getEndpoints(): Observable<{}> { @@ -154,34 +155,34 @@ export class ConfigurationComponent implements OnInit, OnDestroy { } public action(action: string): void { - this.dialog.open(SettingsConfirmationDialogComponent, { data: { - action: action, + this.dialog.open(SettingsConfirmationDialogComponent, { + data: { + action: action, message: action === 'discard' ? this.confirmMessages.discardChanges : this.confirmMessages.saveChanges, environmentStatuses: this.environmentStatuses, activeEndpoint: this.activeEndpoint - }, panelClass: 'modal-sm' }) + }, panelClass: 'modal-sm' + }) .afterClosed().subscribe(result => { - if (result && action === 'save') this.setServiceConfig(this.activeService, this.services[this.activeService].config); - if (result && action === 'discard') this.services[this.activeService].config = this.services[this.activeService].serverConfig; - this.configUpdate(this.activeService); - }); + if (result && action === 'save') this.setServiceConfig(this.activeService, this.services[this.activeService].config); + if (result && action === 'discard') this.services[this.activeService].config = this.services[this.activeService].serverConfig; + this.configUpdate(this.activeService); + }); } private getServicesConfig(endpoint): void { - this.configurationService.getServiceSettings(endpoint) - .pipe( - takeUntil(this.unsubscribe$) - ) - .subscribe(config => { - for (const service in this.services) { - const file = `${service}.yml`; - this.services[service].config = config[file]; - this.services[service].serverConfig = config[file]; - this.configUpdate(service); - } + this.configurationService.getServiceSettings(endpoint) + .pipe( + takeUntil(this.unsubscribe$) + ) + .subscribe(config => { + for (const service in this.services) { + const file = `${service}.yml`; + this.services[service].config = config[file]; + this.services[service].serverConfig = config[file]; + this.configUpdate(service); } - ); - + }); this.clearSelectedServices(); } @@ -190,16 +191,17 @@ export class ConfigurationComponent implements OnInit, OnDestroy { .pipe( takeUntil(this.unsubscribe$) ) - .subscribe(res => { - this.getServicesConfig(this.activeEndpoint); - this.toastr.success('Service configuration saved!', 'Success!'); - }, - error => this.toastr.error( error.message || 'Service configuration is not saved', 'Oops!') - ); + .subscribe( + res => { + this.getServicesConfig(this.activeEndpoint); + this.toastr.success('Service configuration saved!', 'Success!'); + }, + error => this.toastr.error(error.message || 'Service configuration is not saved', 'Oops!') + ); } refreshServiceEditor(editor: ElementRef<HTMLElement>) { - if(editor) { + if (editor) { editor.nativeElement.children[3].scrollTop = 100; editor.nativeElement.children[3].scrollTop = 0; } @@ -207,16 +209,16 @@ export class ConfigurationComponent implements OnInit, OnDestroy { public tabChanged(tabChangeEvent: MatTabChangeEvent): void { this.activeTab = tabChangeEvent; - + if (this.activeTab.index === 1 && this.activeEndpoint === 'local') { this.activeService = 'self-service'; this.refreshServiceEditor(this.selfEditor); - } else if ((this.activeEndpoint !== 'local' && this.activeTab.index === 1) || - (this.activeTab.index === 2 && this.activeEndpoint === 'local')) { + } else if ((this.activeEndpoint !== 'local' && this.activeTab.index === 1) || + (this.activeTab.index === 2 && this.activeEndpoint === 'local')) { this.activeService = 'provisioning'; this.refreshServiceEditor(this.provEditor); - } else if ((this.activeEndpoint !== 'local' && this.activeTab.index === 2) || - (this.activeTab.index === 3 && this.activeEndpoint === 'local')) { + } else if ((this.activeEndpoint !== 'local' && this.activeTab.index === 2) || + (this.activeTab.index === 3 && this.activeEndpoint === 'local')) { this.activeService = 'billing'; this.refreshServiceEditor(this.billingEditor); } else { @@ -225,18 +227,20 @@ export class ConfigurationComponent implements OnInit, OnDestroy { if (!!this.activeService) { if (this.services[this.activeService].config !== this.services[this.activeService].serverConfig) { - this.dialog.open(SettingsConfirmationDialogComponent, { data: { + this.dialog.open(SettingsConfirmationDialogComponent, { + data: { action: 'Was changed', environmentStatuses: this.environmentStatuses, activeEndpoint: this.activeEndpoint - }, panelClass: 'modal-sm' }) + }, panelClass: 'modal-sm' + }) .afterClosed().subscribe(result => { - if (result) { - this.services[this.activeService].serverConfig = this.services[this.activeService].config; - } else { - this.services[this.activeService].config = this.services[this.activeService].serverConfig; - } - }); + if (result) { + this.services[this.activeService].serverConfig = this.services[this.activeService].config; + } else { + this.services[this.activeService].config = this.services[this.activeService].serverConfig; + } + }); } } this.clearSelectedServices(); @@ -271,7 +275,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy { ); } - public restartServices(): void { + public restartServices(): void { const selectedServices = []; for (const service in this.services) { if (this.services[service].selected) { @@ -280,56 +284,56 @@ export class ConfigurationComponent implements OnInit, OnDestroy { } this.dialog.open( - SettingsConfirmationDialogComponent, - { + SettingsConfirmationDialogComponent, + { data: { - action: 'restart', + action: 'restart', services: selectedServices, environmentStatuses: this.environmentStatuses, - activeEndpoint: this.activeEndpoint - }, - panelClass: 'modal-sm' + activeEndpoint: this.activeEndpoint + }, + panelClass: 'modal-sm' }) .afterClosed().subscribe(result => { if (result) { this.messagesStatus.error = []; this.messagesStatus.success = []; - - if(this.environmentStatuses[this.activeEndpoint] && this.services['provisioning'].selected) { + + if (this.environmentStatuses[this.activeEndpoint] && this.services['provisioning'].selected) { this.services['provisioning'].selected = false; } - if(this.services['self-service'].selected) { + if (this.services['self-service'].selected) { this.messagesStatus.counter += 1; this.restartSingleService(true, false, false, 'Self-service') - } - if(this.services['provisioning'].selected) { + } + if (this.services['provisioning'].selected) { this.messagesStatus.counter += 1; this.restartSingleService(false, true, false, 'Provisioning service') - } - if(this.services['billing'].selected) { + } + if (this.services['billing'].selected) { this.messagesStatus.counter += 1; this.restartSingleService(false, false, true, 'Billing service') } let timer = setInterval(() => { - - if(this.messagesStatus.counter === 0) { - for(let key in this.messagesStatus) { - if(key === 'error' && this.messagesStatus[key].length > 0) { + + if (this.messagesStatus.counter === 0) { + for (let key in this.messagesStatus) { + if (key === 'error' && this.messagesStatus[key].length > 0) { this.toastr.error(`${this.messagesStatus[key].join(', ')} restarting failed`, 'Oops!'); - } else if(key === 'success' && this.messagesStatus[key].length > 0) { + } else if (key === 'success' && this.messagesStatus[key].length > 0) { this.toastr.success(`${this.messagesStatus[key].join(', ')} restarting started!`, 'Success!'); } } clearInterval(timer); - } + } }, 200); this.clearSelectedServices(); } else { this.clearSelectedServices(); } - }); + }); } public configUpdate(service: string): void { @@ -412,8 +416,7 @@ export class SettingsConfirmationDialogComponent implements OnInit { constructor( public dialogRef: MatDialogRef<SettingsConfirmationDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: any - ) { - } + ) {} ngOnInit() { this.filterProvisioning = this.data?.services?.filter(service => service !== 'provisioning'); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
