You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datalab.apache.org by yt...@apache.org on 2021/08/10 07:59:12 UTC
[incubator-datalab] 02/09: [DATALAB-2347] refactored Manegement
component
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 f59aaaba2c0b31acca4d6471f533c7f5e9466bb2
Author: Yurii Tykhun <ty...@gmail.com>
AuthorDate: Thu Jul 29 13:59:47 2021 +0300
[DATALAB-2347] refactored Manegement component
---
.../backup-dilog/backup-dilog.component.html | 41 ++-
.../backup-dilog/backup-dilog.component.ts | 41 +--
.../management/endpoints/endpoints.component.html | 122 +++++---
.../management/endpoints/endpoints.component.scss | 24 +-
.../management/endpoints/endpoints.component.ts | 103 ++++---
.../manage-environment-dilog.component.html | 99 +++++--
.../manage-environment-dilog.component.scss | 8 +-
.../manage-environment-dilog.component.ts | 34 ++-
.../management/management-data.service.ts | 6 +-
.../management-grid/management-grid.component.html | 330 +++++++++++++++------
.../management-grid/management-grid.component.scss | 113 ++++---
.../management-grid/management-grid.component.ts | 112 ++++---
.../management/management.component.html | 59 ++--
.../management/management.component.ts | 128 ++++----
.../administration/management/management.model.ts | 1 -
.../ssn-monitor/ssn-monitor.component.html | 9 +-
.../ssn-monitor/ssn-monitor.component.scss | 8 +-
.../ssn-monitor/ssn-monitor.component.ts | 7 +-
18 files changed, 801 insertions(+), 444 deletions(-)
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.html
index 545c236..3b3c9f7 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.html
@@ -20,7 +20,11 @@
<div class="backup-dialog" id="dialog-box">
<header class="dialog-header">
<h4 class="modal-title">Backup options</h4>
- <button type="button" class="close" (click)="dialogRef.close()">×</button>
+ <button
+ type="button"
+ class="close"
+ (click)="dialogRef.close()"
+ >×</button>
</header>
<div class="dialog-content">
<div id="backup-options" class="content-box" *ngIf="backupOptions">
@@ -28,7 +32,8 @@
<mat-slide-toggle
labelPosition="before"
[checked]="backupOptions.configFiles[0] === 'all'"
- (change)="onHoldChanged($event, 'configFiles')">
+ (change)="onHoldChanged($event, 'configFiles')"
+ >
<span class="hold-label">Configuration files</span>
</mat-slide-toggle>
</div>
@@ -36,7 +41,8 @@
<mat-slide-toggle
labelPosition="before"
[checked]="backupOptions.keys[0] === 'all'"
- (change)="onHoldChanged($event, 'keys')">
+ (change)="onHoldChanged($event, 'keys')"
+ >
<span class="hold-label">User keys</span>
</mat-slide-toggle>
</div>
@@ -44,7 +50,8 @@
<mat-slide-toggle
labelPosition="before"
[checked]="backupOptions.databaseBackup"
- (change)="onHoldChanged($event, 'databaseBackup')">
+ (change)="onHoldChanged($event, 'databaseBackup')"
+ >
<span class="hold-label">Database</span>
</mat-slide-toggle>
</div>
@@ -52,7 +59,8 @@
<mat-slide-toggle
labelPosition="before"
[checked]="backupOptions.certificates[0] === 'all'"
- (change)="onHoldChanged($event, 'certificates')">
+ (change)="onHoldChanged($event, 'certificates')"
+ >
<span class="hold-label">SSL Certificates</span>
</mat-slide-toggle>
</div>
@@ -60,7 +68,8 @@
<mat-slide-toggle
labelPosition="before"
[checked]="backupOptions.jars[0] === 'all'"
- (change)="onHoldChanged($event, 'jars')">
+ (change)="onHoldChanged($event, 'jars')"
+ >
<span class="hold-label">JAR files</span>
</mat-slide-toggle>
</div>
@@ -68,15 +77,29 @@
<mat-slide-toggle
labelPosition="before"
[checked]="backupOptions.logsBackup"
- (change)="onHoldChanged($event, 'logsBackup')">
+ (change)="onHoldChanged($event, 'logsBackup')"
+ >
<span class="hold-label">Log files</span>
</mat-slide-toggle>
</div>
<div class="text-center m-top-30 m-bott-10">
- <button mat-raised-button type="button" class="butt" (click)="dialogRef.close(); backupOptions.setDegault()">
+ <button
+ mat-raised-button
+ type="button"
+ class="butt"
+ (click)="dialogRef.close(); backupOptions.setDegault()"
+ >
Cancel
</button>
- <button mat-raised-button type="button" (click)="applyOptions()" class="butt butt-success" [disabled]="!valid">Apply</button>
+ <button
+ mat-raised-button
+ type="button"
+ class="butt butt-success"
+ (click)="applyOptions()"
+ [disabled]="!valid"
+ >
+ Apply
+ </button>
</div>
</div>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.ts
index fd7b4bd..3ee9f7d 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/backup-dilog/backup-dilog.component.ts
@@ -18,10 +18,10 @@
*/
import { Component, OnInit, Output, EventEmitter, Inject } from '@angular/core';
-import { DICTIONARY } from '../../../../dictionary/global.dictionary';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
+import { DICTIONARY } from '../../../../dictionary/global.dictionary';
import { BackupOptionsModel } from '../management.model';
import { BackupService } from '../../../core/services';
@@ -54,18 +54,20 @@ export class BackupDilogComponent implements OnInit {
this.backupOptions[key] instanceof Array
? (this.backupOptions[key][0] = $event.checked ? 'all' : 'skip')
: (this.backupOptions[key] = !this.backupOptions[key]);
-
this.checkValidity();
}
public applyOptions(): void {
- this.backupService.createBackup(this.backupOptions).subscribe(result => {
- this.getBackupStatus(result);
- this.toastr.success('Backup configuration is processing!', 'Processing!');
- this.clear = window.setInterval(() => this.getBackupStatus(result), 3000);
- this.dialogRef.close(this.backupOptions);
- },
- error => this.toastr.error(error.message, 'Oops!'));
+ this.backupService.createBackup(this.backupOptions)
+ .subscribe(
+ result => {
+ this.getBackupStatus(result);
+ this.toastr.success('Backup configuration is processing!', 'Processing!');
+ this.clear = window.setInterval(() => this.getBackupStatus(result), 3000);
+ this.dialogRef.close(this.backupOptions);
+ },
+ error => this.toastr.error(error.message, 'Oops!')
+ );
}
private checkValidity(): void {
@@ -85,17 +87,20 @@ export class BackupDilogComponent implements OnInit {
private getBackupStatus(result) {
const uuid = result.body;
this.backupService.getBackupStatus(uuid)
- .subscribe((backupStatus: any) => {
- if (!this.creatingBackup) {
- backupStatus.status === 'FAILED'
- ? this.toastr.error('Backup configuration failed!', 'Oops!')
- : this.toastr.success('Backup configuration completed!', 'Success!');
+ .subscribe(
+ (backupStatus: any) => {
+ if (!this.creatingBackup) {
+ backupStatus.status === 'FAILED'
+ ? this.toastr.error('Backup configuration failed!', 'Oops!')
+ : this.toastr.success('Backup configuration completed!', 'Success!');
+ clearInterval(this.clear);
+ }
+ },
+ () => {
clearInterval(this.clear);
+ this.toastr.error('Backup configuration failed!', 'Oops!');
}
- }, () => {
- clearInterval(this.clear);
- this.toastr.error('Backup configuration failed!', 'Oops!');
- });
+ );
}
get creatingBackup(): boolean {
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.html
index 2181f9b..f198e53 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.html
@@ -21,7 +21,11 @@
<div class="endpoints-dialog" id="dialog-box">
<header class="dialog-header">
<h4 class="modal-title">Connect endpoint</h4>
- <button type="button" class="close" (click)="dialogRef.close()">×</button>
+ <button
+ type="button"
+ class="close"
+ (click)="dialogRef.close()"
+ >×</button>
</header>
<div class="dialog-content tabs">
<div class="content-box">
@@ -32,24 +36,33 @@
<div class="control-group">
<label class="label">Name</label>
<div class="control">
- <input type="text" formControlName="name" placeholder="Enter endpoint name"
- (blur)="generateEndpointTag($event)">
- <span class="error"
+ <input
+ type="text"
+ formControlName="name"
+ placeholder="Enter endpoint name"
+ (blur)="generateEndpointTag($event)"
+ />
+ <span
+ class="error"
*ngIf="!createEndpointForm?.controls.name.valid
- && createEndpointForm?.controls.name.touched
- && !createEndpointForm?.controls['name'].hasError('isDuplicate')
- && !createEndpointForm?.controls['name'].hasError('limit')"
+ && createEndpointForm?.controls.name.touched
+ && !createEndpointForm?.controls['name'].hasError('isDuplicate')
+ && !createEndpointForm?.controls['name'].hasError('limit')"
>
Endpoint name can only contain letters, numbers, hyphens and '_' but can not end with special
characters.
</span>
- <span class="error"
- *ngIf="createEndpointForm?.controls['name'].hasError('isDuplicate')">
+ <span
+ class="error"
+ *ngIf="createEndpointForm?.controls['name'].hasError('isDuplicate')"
+ >
This endpoint name already exists.
</span>
- <span class="error"
- *ngIf="createEndpointForm?.controls['name'].hasError('limit')">
- Endpoint name cannot be longer than {{ maxEndpointNameLength }} characters.
+ <span
+ class="error"
+ *ngIf="createEndpointForm?.controls['name'].hasError('limit')"
+ >
+ Endpoint name cannot be longer than {{ maxEndpointNameLength }} characters.
</span>
</div>
</div>
@@ -58,8 +71,12 @@
<div class="control">
<input type="text" formControlName="url" placeholder="Enter endpoint url">
<span class="error" *ngIf="createEndpointForm?.controls['url'].hasError('isDuplicate')">This endpoint url already exists.</span>
- <span class="error"
- *ngIf="!createEndpointForm?.controls.url.valid && createEndpointForm.controls.url.touched && !createEndpointForm?.controls['url'].hasError('isDuplicate')">
+ <span
+ class="error"
+ *ngIf="!createEndpointForm?.controls.url.valid
+ && createEndpointForm.controls.url.touched
+ && !createEndpointForm?.controls['url'].hasError('isDuplicate')"
+ >
Please provide a valid endpoint url with slash in the end.
</span>
</div>
@@ -68,8 +85,10 @@
<label class="label">Account</label>
<div class="control">
<input type="text" formControlName="account" placeholder="Enter account">
- <span class="error"
- *ngIf="!createEndpointForm?.controls.account.valid && createEndpointForm.controls.account.touched">
+ <span
+ class="error"
+ *ngIf="!createEndpointForm?.controls.account.valid && createEndpointForm.controls.account.touched"
+ >
Endpoint account can only contain letters, numbers, hyphens and '_' but can not end with special
characters.
</span>
@@ -78,10 +97,18 @@
<div class="control-group">
<label class="label">Endpoint tag</label>
<div class="control">
- <input readonly type="text" formControlName="endpoint_tag" placeholder="< equal to endpoint name >"
- class="not-allowed">
- <span class="error"
- *ngIf="!createEndpointForm?.controls.endpoint_tag.valid && createEndpointForm.controls.endpoint_tag.touched">
+ <input
+ readonly
+ type="text"
+ formControlName="endpoint_tag"
+ placeholder="< equal to endpoint name >"
+ class="not-allowed"
+ />
+ <span
+ class="error"
+ *ngIf="!createEndpointForm?.controls.endpoint_tag.valid
+ && createEndpointForm.controls.endpoint_tag.touched"
+ >
Endpoint tag can only contain letters, numbers, hyphens and '_' but can not end with special
characters.
</span>
@@ -89,25 +116,45 @@
</div>
</form>
<div class="action-group m-bott-10">
- <button mat-raised-button
- type="button"
- [disabled]="!this.createEndpointForm.value.url || !createEndpointForm.valid"
- class="butt action"
- (click)="getEndpoinConnectionStatus(createEndpointForm.value.url)"
+ <button
+ mat-raised-button
+ type="button"
+ [disabled]="!this.createEndpointForm.value.url || !createEndpointForm.valid"
+ class="butt action"
+ (click)="getEndpoinConnectionStatus(createEndpointForm.value.url)"
>
Test
</button>
<div class="action-butt">
- <button mat-raised-button type="button" class="butt action" (click)="dialogRef.close()">Cancel</button>
- <button mat-raised-button type="button" [disabled]="!createEndpointForm.valid"
- (click)="assignChanges(createEndpointForm.value)" class="butt butt-success action">Connect</button>
+ <button
+ mat-raised-button
+ type="button"
+ class="butt action"
+ (click)="dialogRef.close()"
+ >
+ Cancel
+ </button>
+ <button
+ mat-raised-button
+ type="button"
+ [disabled]="!createEndpointForm.valid"
+ (click)="assignChanges(createEndpointForm.value)"
+ class="butt butt-success action"
+ >
+ Connect
+ </button>
</div>
</div>
</div>
</mat-tab>
<mat-tab label="ENDPOINTS LIST">
<div class="endpoints scrolling">
- <table mat-table [dataSource]="endpoints" class="endpoints-table" *ngIf="endpoints?.length; else empty">
+ <table
+ mat-table
+ [dataSource]="endpoints"
+ class="endpoints-table"
+ *ngIf="endpoints?.length; else empty"
+ >
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="name"> Endpoint name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
@@ -115,9 +162,7 @@
<ng-container matColumnDef="url">
<th mat-header-cell *matHeaderCellDef class="url"> Url </th>
- <td mat-cell
- *matCellDef="let element"
- >
+ <td mat-cell *matCellDef="let element">
<span matTooltip="{{element.url}}" matTooltipPosition="above">{{element.url}}</span>
</td>
</ng-container>
@@ -135,10 +180,18 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="actions"></th>
<td mat-cell *matCellDef="let element" class="actions">
- <span (click)="getEndpoinConnectionStatus(element.url)" matTooltip="Test" matTooltipPosition="above">
+ <span
+ matTooltip="Test"
+ matTooltipPosition="above"
+ (click)="getEndpoinConnectionStatus(element.url)"
+ >
<mat-icon>compare_arrows</mat-icon>
</span>
- <span (click)="deleteEndpoint(element)" matTooltip="Disconnect" matTooltipPosition="above">
+ <span
+ matTooltip="Disconnect"
+ matTooltipPosition="above"
+ (click)="deleteEndpoint(element)"
+ >
<mat-icon>delete_forever</mat-icon>
</span>
</td>
@@ -152,7 +205,6 @@
<div class="info empty-box">
<div class="content">
<p>Looks like you don't have any endpoints</p>
-
<button mat-raised-button class="butt" (click)="tabGroup.selectedIndex = 0">
<i class="material-icons">settings_system_daydream</i>New endpoint
</button>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.scss
index 53eaaf6..520faf7 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.scss
@@ -18,8 +18,8 @@
*/
.endpoints-dialog {
.content-box {
- padding: 10px 30px 30px;
height: 400px;
+ padding: 10px 30px 30px;
.split {
display: flex;
@@ -35,9 +35,9 @@
position: absolute;
right: 0;
bottom: 5px;
- font-family: 'Open Sans', sans-serif;
- font-weight: 300;
top: 34px;
+ font-family: "Open Sans", sans-serif;
+ font-weight: 300;
}
}
}
@@ -56,37 +56,37 @@
table.mat-table {
width: 100%;
- thead{
+ thead {
background: transparent;
- .mat-header-row{
- background-clip:padding-box;
+ .mat-header-row {
+ background-clip: padding-box;
}
}
tr {
td {
- vertical-align: middle;
max-width: 150px;
+ vertical-align: middle;
overflow: hidden;
text-overflow: ellipsis;
- &::after{
- content: '';
+ &::after {
+ content: "";
display: block;
}
}
}
.actions {
+ width: 14%;
color: #607d8b;
text-align: center;
- width: 14%;
span {
- transition: all .5s ease-in-out;
+ transition: all 0.5s ease-in-out;
cursor: pointer;
.mat-icon {
- font-size: 18px;
padding-top: 5px;
+ font-size: 18px;
}
&:hover {
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.ts
index 5f13786..0dfffeb 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/endpoints/endpoints.component.ts
@@ -21,11 +21,11 @@ import { Component, OnInit, Inject } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
+import { map } from 'rxjs/operators';
import { EndpointService } from '../../../core/services';
import { NotificationDialogComponent } from '../../../shared/modal-dialog/notification-dialog';
import { PATTERNS } from '../../../core/util';
-import { map } from 'rxjs/operators';
export interface Endpoint {
name: string;
@@ -71,51 +71,75 @@ export class EndpointsComponent implements OnInit {
public deleteEndpoint(data): void {
this.endpointService.getEndpointsResource(data.name)
- .pipe(map(resource =>
- resource.projects.map(project =>
- EndpointsComponent.createResourceList(
- project.name,
- resource.exploratories.filter(notebook => notebook.project === project.name),
- project.endpoints.filter(endpoint => endpoint.name === data.name)[0].status))
- .filter(project => project.nodeStatus !== 'TERMINATED'
- && project.nodeStatus !== 'TERMINATING'
- && project.nodeStatus !== 'FAILED'
- )))
+ .pipe(
+ map(resource =>
+ resource.projects
+ .map(project =>
+ EndpointsComponent.createResourceList(
+ project.name,
+ resource.exploratories.filter(notebook => notebook.project === project.name),
+ project.endpoints.filter(endpoint => endpoint.name === data.name)[0].status)
+ )
+ .filter(project => project.nodeStatus !== 'TERMINATED'
+ && project.nodeStatus !== 'TERMINATING'
+ && project.nodeStatus !== 'FAILED'
+ )
+ )
+ )
.subscribe((resource: any) => {
- this.dialog.open(NotificationDialogComponent, { data: {
- type: 'confirmation', item: data, list: resource
- }, panelClass: 'modal-sm' })
- .afterClosed().subscribe(result => {
- result && this.deleteEndpointOption(data);
- });
- });
+ this.dialog.open(NotificationDialogComponent, {
+ data: {
+ type: 'confirmation', item: data, list: resource
+ }, panelClass: 'modal-sm'
+ })
+ .afterClosed().subscribe(result => {
+ result && this.deleteEndpointOption(data);
+ });
+ });
}
public getEndpoinConnectionStatus(url) {
const getStatus = this.endpointService.getEndpoinConnectionStatus(encodeURIComponent(url));
- this.dialog.open(EndpointTestResultDialogComponent, { data: {url: url, getStatus}, panelClass: 'modal-sm' });
+ this.dialog.open(EndpointTestResultDialogComponent, { data: { url: url, getStatus }, panelClass: 'modal-sm' });
}
private static createResourceList(name: string, resource: Array<any>, nodeStatus: string): Object {
- return {name, resource, nodeStatus};
+ return { name, resource, nodeStatus };
}
private initFormModel(): void {
this.createEndpointForm = this._fb.group({
name: ['', Validators.compose([
- Validators.required, Validators.pattern(PATTERNS.namePattern), this.validateName.bind(this), this.providerMaxLength.bind(this)
+ Validators.required,
+ Validators.pattern(PATTERNS.namePattern),
+ this.validateName.bind(this),
+ this.providerMaxLength.bind(this)
])],
- url: ['', Validators.compose([Validators.required, Validators.pattern(PATTERNS.fullUrl), this.validateUrl.bind(this)])],
- account: ['', Validators.compose([Validators.required, Validators.pattern(PATTERNS.namePattern)])],
- endpoint_tag: ['', Validators.compose([Validators.required, Validators.pattern(PATTERNS.namePattern)])]
+ url: ['', Validators.compose([
+ Validators.required,
+ Validators.pattern(PATTERNS.fullUrl),
+ this.validateUrl.bind(this)
+ ])],
+ account: ['', Validators.compose([
+ Validators.required,
+ Validators.pattern(PATTERNS.namePattern)
+ ])],
+ endpoint_tag: ['', Validators.compose([
+ Validators.required,
+ Validators.pattern(PATTERNS.namePattern)
+ ])]
});
}
private deleteEndpointOption(data): void {
- this.endpointService.deleteEndpoint(`${data.name}`).subscribe(() => {
- this.toastr.success( 'Endpoint successfully disconnected. All related resources are terminating!', 'Success!');
- this.getEndpointList();
- }, error => this.toastr.error(error.message || 'Endpoint creation failed!', 'Oops!'));
+ this.endpointService.deleteEndpoint(`${data.name}`)
+ .subscribe(
+ () => {
+ this.toastr.success('Endpoint successfully disconnected. All related resources are terminating!', 'Success!');
+ this.getEndpointList();
+ },
+ error => this.toastr.error(error.message || 'Endpoint creation failed!', 'Oops!')
+ );
}
private getEndpointList(): void {
@@ -218,19 +242,20 @@ export class EndpointTestResultDialogComponent {
public dialogRef: MatDialogRef<EndpointTestResultDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
- this.data.getStatus.subscribe(() => {
- this.isConnected = true;
- this.response = true;
- return;
- },
- () => {
- this.isConnected = false;
- this.response = true;
- return;
- });
+ this.data.getStatus
+ .subscribe(
+ () => {
+ this.isConnected = true;
+ this.response = true;
+ return;
+ },
+ () => {
+ this.isConnected = false;
+ this.response = true;
+ return;
+ });
}
public cutToLongUrl(url) {
return url.length > 25 ? url.slice(0, 25) + '...' : url;
}
-
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.html
index 8c879af..6e2b288 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.html
@@ -25,7 +25,11 @@
<div class="dialog-content">
<div class="content-box">
<div *ngIf="data.projectsList?.length">
- <form [formGroup]="manageUsersForm" (submit)="setBudgetLimits(manageUsersForm.value)" novalidate>
+ <form
+ [formGroup]="manageUsersForm"
+ (submit)="setBudgetLimits(manageUsersForm.value)"
+ novalidate
+ >
<mat-list>
<mat-list-item class="list-header">
<div class="username">Project</div>
@@ -33,54 +37,93 @@
<div class="quotes">Limit</div>
</mat-list-item>
<div class="scrolling-content" id="scrolling" formArrayName="projects">
- <mat-list-item *ngFor="let item of usersEnvironments.controls; let i=index" [formGroupName]="i"
- class="list-item">
+ <mat-list-item
+ *ngFor="let item of usersEnvironments.controls; let i=index"
+ [formGroupName]="i"
+ class="list-item"
+ >
<div class="username ellipsis">
- <span class="ellipsis"
- matTooltip="{{ manageUsersForm.controls['projects']['controls'][i].value['project'] }}"
- matTooltipPosition="above">{{ manageUsersForm.controls['projects']['controls'][i].value['project'] }}
- </span>
+ <span
+ class="ellipsis"
+ matTooltip="{{ manageUsersForm.controls['projects']['controls'][i].value['project'] }}"
+ matTooltipPosition="above"
+ >
+ {{ manageUsersForm.controls['projects']['controls'][i].value['project'] }}
+ </span>
</div>
<div class="period">
- <mat-slide-toggle formControlName="monthlyBudget">
- </mat-slide-toggle>
+ <mat-slide-toggle formControlName="monthlyBudget"></mat-slide-toggle>
</div>
<div class="quotes">
- <input type="number" (keypress)="CheckUtils.numberOnly($event)" min="0"
- placeholder="Enter limit, in USD" formControlName="budget">
- <span class="error"
- *ngIf="manageUsersForm?.controls['projects']['controls'][i].controls['budget'].hasError('overrun') &&
- !manageUsersForm?.controls['projects']['controls'][i].controls['budget'].hasError('max')"
+ <input
+ type="number"
+ (keypress)="CheckUtils.numberOnly($event)"
+ min="0"
+ placeholder="Enter limit, in USD" formControlName="budget"
+ />
+ <span
+ class="error"
+ *ngIf="manageUsersForm?.controls['projects']['controls'][i].controls['budget'].hasError('overrun')
+ && !manageUsersForm?.controls['projects']['controls'][i].controls['budget'].hasError('max')"
>
Projects budget cannot be higher than total budget.
</span>
- <span class="error"
- *ngIf="manageUsersForm?.controls['projects']['controls'][i].controls['budget'].hasError('max')">Project budget cannot be higher than 1000000000.</span>
+ <span
+ class="error"
+ *ngIf="manageUsersForm?.controls['projects']['controls'][i].controls['budget'].hasError('max')"
+ >
+ Project budget cannot be higher than 1000000000.
+ </span>
</div>
</mat-list-item>
</div>
<div class="control-group total-budget">
-
<mat-list-item class="list-item">
<div class="username ellipsis">
<span class="ellipsis">Total budget</span>
</div>
- <div class="period">
- </div>
+ <div class="period"></div>
<div class="quotes">
- <input type="number" (keypress)="CheckUtils.numberOnly($event)" formControlName="total"
- placeholder="Enter total budget, in USD">
- <span class="error" *ngIf="manageUsersForm?.controls['total'].hasError('overrun')
- && !manageUsersForm?.controls['total'].hasError('max')">Total budget cannot be lower than a sum of project quotes.</span>
- <span class="error"
- *ngIf="manageUsersForm?.controls['total'].hasError('max')">Total budget cannot be higher than 1000000000.</span>
+ <input
+ type="number"
+ (keypress)="CheckUtils.numberOnly($event)"
+ formControlName="total"
+ placeholder="Enter total budget, in USD"
+ />
+ <span
+ class="error"
+ *ngIf="manageUsersForm?.controls['total'].hasError('overrun')
+ && !manageUsersForm?.controls['total'].hasError('max')"
+ >
+ Total budget cannot be lower than a sum of project quotes.
+ </span>
+ <span
+ class="error"
+ *ngIf="manageUsersForm?.controls['total'].hasError('max')"
+ >
+ Total budget cannot be higher than 1000000000.
+ </span>
</div>
</mat-list-item>
</div>
<div class="text-center m-top-30">
- <button mat-raised-button type="button" (click)="dialogRef.close()" class="butt action">Cancel</button>
- <button mat-raised-button type="submit" [disabled]="!manageUsersForm.valid || isFormChanged" class="butt butt-success"
- [ngClass]="{'not-allowed': !manageUsersForm.valid}">Apply</button>
+ <button
+ mat-raised-button
+ type="button"
+ (click)="dialogRef.close()"
+ class="butt action"
+ >
+ Cancel
+ </button>
+ <button
+ mat-raised-button
+ type="submit"
+ [disabled]="!manageUsersForm.valid || isFormChanged"
+ class="butt butt-success"
+ [ngClass]="{'not-allowed': !manageUsersForm.valid}"
+ >
+ Apply
+ </button>
</div>
</mat-list>
</form>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.scss
index 1cea435..d04b101 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.scss
@@ -20,9 +20,9 @@
.manage-env-dialog {
.mat-list {
.mat-list-item {
+ position: relative;
height: 63px;
margin: 5px 0;
- position: relative;
.mat-list-item-content {
padding: 0 !important;
@@ -43,20 +43,20 @@
}
.quotes {
+ position: relative;
width: 45%;
margin-right: 10px;
- position: relative;
.error {
position: absolute;
left: 0;
top: 37px;
- font-family: 'Open Sans', sans-serif;
+ font-family: "Open Sans", sans-serif;
font-size: 11px;
}
}
- .period{
+ .period {
width: 25%;
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts
index 6fd04c9..2c154ef 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/manage-environment/manage-environment-dilog.component.ts
@@ -20,6 +20,7 @@
import { Component, Output, EventEmitter, ViewEncapsulation, Inject, OnInit } from '@angular/core';
import { Validators, FormBuilder, FormGroup, FormArray } from '@angular/forms';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+
import { DICTIONARY } from '../../../../dictionary/global.dictionary';
import { CheckUtils } from '../../../core/util';
@@ -63,12 +64,12 @@ export class ManageEnvironmentComponent implements OnInit {
if (this.getCurrentTotalValue()) {
if (this.getCurrentTotalValue() >= this.getCurrentUsersTotal()) {
this.manageUsersForm.controls['total'].setErrors(null);
- if (this.manageUsersForm.controls['total'].value > 1000000000) this.manageUsersForm.controls['total'].setErrors({max: true});
+ if (this.manageUsersForm.controls['total'].value > 1000000000) this.manageUsersForm.controls['total'].setErrors({ max: true });
this.manageUsersForm.controls['projects']['controls'].forEach(v => {
- v.controls['budget'].errors &&
- 'max' in v.controls['budget'].errors ? null : v.controls['budget'].setErrors(null);
- }
- );
+ v.controls['budget'].errors && 'max' in v.controls['budget'].errors
+ ? null
+ : v.controls['budget'].setErrors(null);
+ });
} else {
this.manageUsersForm.controls['total'].setErrors({ overrun: true });
}
@@ -85,8 +86,8 @@ export class ManageEnvironmentComponent implements OnInit {
value.projects = value.projects.filter((v, i) =>
this.initialFormState.projects[i].budget !== v.budget ||
this.initialFormState.projects[i].monthlyBudget !== v.monthlyBudget);
- value.isTotalChanged = this.initialFormState.total !== value.total;
- this.dialogRef.close(value);
+ value.isTotalChanged = this.initialFormState.total !== value.total;
+ this.dialogRef.close(value);
} else {
this.manageUsersForm.controls['total'].setErrors({ overrun: true });
}
@@ -94,16 +95,19 @@ export class ManageEnvironmentComponent implements OnInit {
public setProjectsControl() {
this.manageUsersForm.setControl('projects',
- this._fb.array((this.data.projectsList || []).map((x: any, index: number) => this._fb.group({
- project: x.name,
- budget: [x.budget.value, [ Validators.max(1000000000), this.userValidityCheck.bind(this)]],
- monthlyBudget: x.budget.monthlyBudget,
- }))));
+ this._fb.array((this.data.projectsList || [])
+ .map((x: any, index: number) => this._fb.group({
+ project: x.name,
+ budget: [x.budget.value, [Validators.max(1000000000), this.userValidityCheck.bind(this)]],
+ monthlyBudget: x.budget.monthlyBudget,
+ }))
+ )
+ );
}
private initForm(): void {
this.manageUsersForm = this._fb.group({
- total: [null, [Validators.min(0), this.totalValidityCheck.bind(this), Validators.max(1000000000) ]],
+ total: [null, [Validators.min(0), this.totalValidityCheck.bind(this), Validators.max(1000000000)]],
projects: this._fb.array([this._fb.group({ project: '', budget: null, status: '' })])
});
}
@@ -124,7 +128,9 @@ export class ManageEnvironmentComponent implements OnInit {
private userValidityCheck(control) {
if (control && control.value) {
- if (control.parent)this.manageUsersForm.value.projects.find(v => v.project === control.parent.value.project).budget = control.value;
+ if (control.parent) {
+ this.manageUsersForm.value.projects.find(v => v.project === control.parent.value.project).budget = control.value;
+ }
return (this.getCurrentTotalValue() && this.getCurrentTotalValue() < this.getCurrentUsersTotal()) ? { overrun: true } : null;
}
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-data.service.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-data.service.ts
index a3aa218..5779249 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-data.service.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-data.service.ts
@@ -40,7 +40,9 @@ export class EnvironmentsDataService {
}
private getAllEnvironmentData() {
- this.manageEnvironmentsService.getAllEnvironmentData().subscribe(
- (response) => this._data.next(response));
+ this.manageEnvironmentsService.getAllEnvironmentData()
+ .subscribe(
+ (response) => this._data.next(response)
+ );
}
}
\ No newline at end of file
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html
index 8686e4b..54d9b2c 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.html
@@ -27,22 +27,25 @@
*ngIf="allActiveNotebooks?.length"
[checked]="selected?.length === allActiveNotebooks?.length"
(toggleSelection)="toggleSelectionAll()"
- >
- </datalab-checkbox>
+ ></datalab-checkbox>
<button mat-icon-button aria-label="More" class="ar checkbox-border" (click)="toggleFilterRow()">
<i class="material-icons">
- <!-- <span *ngIf="filtering && filterForm.users.length > 0 && !collapsedFilterRow">filter_list</span>-->
+ <!-- <span *ngIf="filtering && filterForm.users.length > 0 && !collapsedFilterRow">filter_list</span> -->
<span>more_vert</span>
</i>
</button>
</th>
<td mat-cell *matCellDef="let element">
- <ng-template [ngIf]="element.type !== 'odahu' && element.type !== 'edge node' && (element.status==='running' || element.status==='stopped') && !clustersInProgress(element.resources)">
+ <ng-template
+ [ngIf]="element.type !== 'odahu'
+ && element.type !== 'edge node'
+ && (element.status==='running' || element.status==='stopped')
+ && !clustersInProgress(element.resources)"
+ >
<datalab-checkbox
[checked]="element.isSelected"
(toggleSelection)="toggleActionForAll(element)"
- >
- </datalab-checkbox>
+ ></datalab-checkbox>
</ng-template>
</td>
</ng-container>
@@ -50,12 +53,18 @@
<ng-container matColumnDef="user">
<th mat-header-cell *matHeaderCellDef class="user label-header">
<span class="label">User</span>
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.users.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.users.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td
mat-cell *matCellDef="let element"
class="user-name ellipsis"
@@ -70,36 +79,54 @@
<ng-container matColumnDef="project">
<th mat-header-cell *matHeaderCellDef class="project label-header">
<span class="label">Project</span>
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.projects.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.projects.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td mat-cell *matCellDef="let element">{{ element.project }}</td>
</ng-container>
<ng-container matColumnDef="endpoint">
<th mat-header-cell *matHeaderCellDef class="endpoint label-header">
<span class="label">Endpoint</span>
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.endpoints.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.endpoints.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td mat-cell *matCellDef="let element">{{ element.endpoint }}</td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef class="type label-header">
<span class="label">Name</span>
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.type.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.type.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td type mat-cell *matCellDef="let element">
<span
*ngIf="element.name"
@@ -115,12 +142,18 @@
<ng-container matColumnDef="shape">
<th mat-header-cell *matHeaderCellDef class="shape label-header">
<span class="label">Shape / Resource id</span>
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.shapes.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.shapes.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td mat-cell *matCellDef="let element" class="shape">
<div>{{ element.shape || element.ip }}</div>
<div *ngIf="element.gpu_type">{{ element.gpu_type }}</div>
@@ -131,13 +164,18 @@
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="status label-header">
<span class="label">Status</span>
-
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.statuses.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.statuses.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td mat-cell *matCellDef="let element" class="ani status" >
<span ngClass="{{element.status || ''}}">{{ element.status }}</span>
</td>
@@ -146,12 +184,18 @@
<ng-container matColumnDef="resources">
<th mat-header-cell *matHeaderCellDef class="resources label-header">
<span class="label">Compute</span>
- <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <button
+ mat-icon-button
+ aria-label="More"
+ class="ar"
+ (click)="toggleFilterRow()"
+ >
<i class="material-icons">
<span *ngIf="filtering && filterForm.resources.length > 0 && !collapsedFilterRow">filter_list</span>
<span [hidden]="filtering && filterForm.resources.length > 0 && !collapsedFilterRow">more_vert</span>
</i>
- </button> </th>
+ </button>
+ </th>
<td mat-cell *matCellDef="let element" class="ani resources">
<div class="source" *ngIf="element.resources">
<div *ngIf="!element.resources?.length">
@@ -160,21 +204,27 @@
<div *ngIf="element.resources?.length">
<div *ngFor="let resource of element.resources" class="resource-wrap">
<div class="resource-name">
- <a>
- {{ resource.computational_name }}
- </a>
+ <a>{{ resource.computational_name }}</a>
</div>
<span ngClass="{{resource.status || ''}}" class="resource-status">{{ resource.status }}</span>
<div class="resource-actions">
<span class="not-allow">
<a class="start-stop-action" *ngIf="resource.image === 'docker.datalab-dataengine'">
- <i class="material-icons" (click)="toggleResourceAction(element, 'stop', resource)"
- [ngClass]="{'not-allowed' : resource.status !== 'running' || selected?.length }">pause_circle_outline</i>
+ <i
+ class="material-icons"
+ (click)="toggleResourceAction(element, 'stop', resource)"
+ [ngClass]="{'not-allowed' : resource.status !== 'running' || selected?.length }"
+ >
+ pause_circle_outline
+ </i>
</a>
</span>
<span class="not-allow">
- <a class="remove_butt" (click)="toggleResourceAction(element, 'terminate', resource)"
- [ngClass]="{ 'disabled' : element.status !== 'running' || (resource.status !== 'running' && resource.status !== 'stopped') || selected?.length }">
+ <a
+ class="remove_butt"
+ (click)="toggleResourceAction(element, 'terminate', resource)"
+ [ngClass]="{ 'disabled' : element.status !== 'running' || (resource.status !== 'running' && resource.status !== 'stopped') || selected?.length }"
+ >
<i class="material-icons">highlight_off</i>
</a>
</span>
@@ -191,30 +241,49 @@
</th>
<td mat-cell *matCellDef="let element" class="settings actions-col">
<span [ngClass]="{'not-allow' : selected?.length}">
- <span #settings class="actions" (click)="actions.toggle($event, settings)" *ngIf="element.type !== 'edge node' && element.type !== 'odahu'"
+ <span
+ #settings
+ class="actions"
+ (click)="actions.toggle($event, settings)"
+ *ngIf="element.type !== 'edge node' && element.type !== 'odahu'"
[ngClass]="{
'disabled' : (element.status !== 'running' && element.status !== 'stopped')
- || selected?.length || inProgress(element.resources)}">
-
+ || selected?.length || inProgress(element.resources)}"
+ >
</span>
</span>
<bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left">
<ul class="list-unstyled">
<li
- matTooltip="{{ element.type !== 'edge node' ? 'Unable to stop notebook because at least one computational resource is in progress' : 'Unable to stop edge node because at least one resource of this user is in progress' }}"
- matTooltipPosition="above" [matTooltipDisabled]="!isResourcesInProgress(element)"
- [hidden]="element.name === 'edge node' && element.status === 'stopped'">
- <div (click)="toggleResourceAction(element, 'stop')"
- [ngClass]="{'not-allowed' : element.status === 'stopped' || element.status === 'stopping' || element.status === 'starting' || element.status === 'creating image' || element.status === 'failed' || isResourcesInProgress(element)}">
+ matTooltip="{{ element.type !== 'edge node'
+ ? 'Unable to stop notebook because at least one computational resource is in progress'
+ : 'Unable to stop edge node because at least one resource of this user is in progress' }}"
+ matTooltipPosition="above"
+ [matTooltipDisabled]="!isResourcesInProgress(element)"
+ [hidden]="element.name === 'edge node' && element.status === 'stopped'"
+ >
+ <div
+ (click)="toggleResourceAction(element, 'stop')"
+ [ngClass]="{'not-allowed' : element.status === 'stopped' || element.status === 'stopping' ||
+ element.status === 'starting' || element.status === 'creating image' ||
+ element.status === 'failed' || isResourcesInProgress(element)}"
+ >
<i class="material-icons">pause_circle_outline</i>
<span>Stop</span>
</div>
</li>
- <li *ngIf="element.name !== 'edge node'"
+ <li
+ *ngIf="element.name !== 'edge node'"
matTooltip="Unable to terminate notebook because at least one compute is in progress"
- matTooltipPosition="above" [matTooltipDisabled]="!isResourcesInProgress(element)">
- <div (click)="toggleResourceAction(element, 'terminate')"
- [ngClass]="{'not-allowed' : element.status !== 'running' && element.status !== 'stopped' || isResourcesInProgress(element)}">
+ matTooltipPosition="above"
+ [matTooltipDisabled]="!isResourcesInProgress(element)"
+ >
+ <div
+ (click)="toggleResourceAction(element, 'terminate')"
+ [ngClass]="{'not-allowed' : element.status !== 'running' &&
+ element.status !== 'stopped' ||
+ isResourcesInProgress(element)}"
+ >
<i class="material-icons">phonelink_off</i>
<span>Terminate</span>
</div>
@@ -234,113 +303,186 @@
<!-- FILTERING -->
<ng-container matColumnDef="checkbox-filter" sticky>
- <th mat-header-cell *matHeaderCellDef class="filter-row-item">
-
- </th>
+ <th mat-header-cell *matHeaderCellDef class="filter-row-item"></th>
</ng-container>
<ng-container matColumnDef="user-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'users'" [items]="filterConfiguration.users"
- [model]="filterForm.users"></multi-select-dropdown>
+ <multi-select-dropdown
+ (selectionChange)="onUpdate($event)"
+ [type]="'users'"
+ [items]="filterConfiguration.users"
+ [model]="filterForm.users"
+ ></multi-select-dropdown>
</th>
</ng-container>
+
<ng-container matColumnDef="type-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <input placeholder="Filter by name" type="text" class="form-control filter-field"
- [value]="filterForm.type" (input)="onFilterNameUpdate($event.target['value'])"/>
+ <input
+ placeholder="Filter by name"
+ type="text"
+ class="form-control filter-field"
+ [value]="filterForm.type"
+ (input)="onFilterNameUpdate($event.target['value'])"
+ />
</th>
</ng-container>
+
<ng-container matColumnDef="project-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'projects'"
- [items]="filterConfiguration.projects" [model]="filterForm.projects"></multi-select-dropdown>
+ <multi-select-dropdown
+ (selectionChange)="onUpdate($event)"
+ [type]="'projects'"
+ [items]="filterConfiguration.projects"
+ [model]="filterForm.projects"
+ ></multi-select-dropdown>
</th>
</ng-container>
<ng-container matColumnDef="endpoint-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'endpoints'"
- [items]="filterConfiguration.endpoints" [model]="filterForm.endpoints"></multi-select-dropdown>
+ <multi-select-dropdown
+ (selectionChange)="onUpdate($event)"
+ [type]="'endpoints'"
+ [items]="filterConfiguration.endpoints"
+ [model]="filterForm.endpoints"
+ ></multi-select-dropdown>
</th>
</ng-container>
+
<ng-container matColumnDef="shape-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'shapes'"
- [items]="filterConfiguration.shapes" [model]="filterForm.shapes"></multi-select-dropdown>
+ <multi-select-dropdown
+ (selectionChange)="onUpdate($event)"
+ [type]="'shapes'"
+ [items]="filterConfiguration.shapes"
+ [model]="filterForm.shapes"
+ ></multi-select-dropdown>
</th>
</ng-container>
+
<ng-container matColumnDef="status-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'statuses'"
- [items]="filterConfiguration.statuses" [model]="filterForm.statuses"></multi-select-dropdown>
+ <multi-select-dropdown
+ (selectionChange)="onUpdate($event)"
+ [type]="'statuses'"
+ [items]="filterConfiguration.statuses"
+ [model]="filterForm.statuses"
+ ></multi-select-dropdown>
</th>
</ng-container>
+
<ng-container matColumnDef="resource-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="filter-row-item">
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'resources'"
- [items]="filterConfiguration.resources" [model]="filterForm.resources"></multi-select-dropdown>
+ <multi-select-dropdown
+ (selectionChange)="onUpdate($event)"
+ [type]="'resources'"
+ [items]="filterConfiguration.resources"
+ [model]="filterForm.resources"
+ ></multi-select-dropdown>
</th>
</ng-container>
+
<ng-container matColumnDef="actions-filter" sticky>
<th mat-header-cell *matHeaderCellDef class="actions-col filter-row-item">
<div class="actions">
- <button mat-icon-button class="btn reset" (click)="resetFilterConfigurations()" [disabled]="!isFilterSelected">
+ <button
+ mat-icon-button
+ class="btn reset"
+ (click)="resetFilterConfigurations()"
+ [disabled]="!isFilterSelected"
+ >
<i class="material-icons">close</i>
</button>
- <button mat-icon-button class="btn apply" (click)="applyFilter(filterForm)"
- [disabled]="isFilterChanged">
- <i class="material-icons"
- [ngClass]="{'not-allowed': allFilteredEnvironmentData?.length == 0 && !filtering}">done</i>
+ <button
+ mat-icon-button
+ class="btn apply"
+ (click)="applyFilter(filterForm)"
+ [disabled]="isFilterChanged"
+ >
+ <i
+ class="material-icons"
+ [ngClass]="{'not-allowed': allFilteredEnvironmentData?.length == 0 && !filtering}"
+ >
+ done
+ </i>
</button>
</div>
</th>
</ng-container>
-
<ng-container matColumnDef="placeholder">
<td mat-footer-cell *matFooterCellDef colspan="8">
- <div class="info"
- *ngIf="(!allFilteredEnvironmentData) && !filtering || (allFilteredEnvironmentData?.length == 0) && !filtering">
- To start working, please, create new environment</div>
+ <div
+ class="info"
+ *ngIf="(!allFilteredEnvironmentData) && !filtering || (allFilteredEnvironmentData?.length == 0) && !filtering"
+ >
+ To start working, please, create new environment
+ </div>
<div *ngIf="(allFilteredEnvironmentData?.length == 0) && filtering" class="info">No matches found</div>
</td>
</ng-container>
<ng-container matColumnDef="scrollButtons">
- <td mat-footer-cell *matFooterCellDef colspan="9" class="buttons-wrap">
- <div class="buttons" [ngStyle]="{'width.px': tableWrapperWidth }" [hidden]="!tableWrapperWidth">
- <div class="button-container">
- <button mat-mini-fab aria-label="Scroll left"
- (click)="sctollTo('left')"
- [ngClass]="{'not-allowed': wrapper.scrollLeft === 0 }"
- >
- <mat-icon [ngClass]="{'highlight': wrapper.scrollLeft !== 0 }">keyboard_arrow_left</mat-icon>
- </button>
- </div>
- <div class="button-container" [ngClass]="{'not-allowed': checkMaxRight()}">
- <button mat-mini-fab aria-label="Scroll right"
- (click)="sctollTo('right')"
-
- [ngClass]="{'not-allowed': !(isMaxRight | async)}"
- >
- <mat-icon [ngClass]="{'highlight': (isMaxRight | async) || false}">keyboard_arrow_right</mat-icon>
- </button>
- </div>
+ <td
+ mat-footer-cell
+ *matFooterCellDef
+ colspan="9"
+ class="buttons-wrap"
+ >
+ <div
+ class="buttons"
+ [ngStyle]="{'width.px': tableWrapperWidth }"
+ [hidden]="!tableWrapperWidth"
+ >
+ <div class="button-container">
+ <button
+ mat-mini-fab aria-label="Scroll left"
+ (click)="sctollTo('left')"
+ [ngClass]="{'not-allowed': wrapper.scrollLeft === 0 }"
+ >
+ <mat-icon [ngClass]="{'highlight': wrapper.scrollLeft !== 0 }">keyboard_arrow_left</mat-icon>
+ </button>
</div>
- </td>
- </ng-container>
+ <div class="button-container" [ngClass]="{'not-allowed': checkMaxRight()}">
+ <button
+ mat-mini-fab aria-label="Scroll right"
+ (click)="sctollTo('right')"
+ [ngClass]="{'not-allowed': !(isMaxRight | async)}"
+ >
+ <mat-icon [ngClass]="{'highlight': (isMaxRight | async) || false}">keyboard_arrow_right</mat-icon>
+ </button>
+ </div>
+ </div>
+ </td>
+ </ng-container>
- <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="header-row"></tr>
- <tr [hidden]="!collapsedFilterRow" mat-header-row *matHeaderRowDef="displayedFilterColumns; sticky: true"
- class="filter-row"></tr>
+ <tr
+ mat-header-row
+ *matHeaderRowDef="displayedColumns; sticky: true"
+ class="header-row"
+ ></tr>
+ <tr
+ [hidden]="!collapsedFilterRow"
+ mat-header-row
+ *matHeaderRowDef="displayedFilterColumns; sticky: true"
+ class="filter-row"
+ ></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
-
- <tr [hidden]="allFilteredEnvironmentData?.length" mat-footer-row *matFooterRowDef="['placeholder']" class="info"></tr>
- <tr [hidden]="!tableEl || !tableEl['offsetWidth'] || tableWrapper.offsetWidth - tableEl['offsetWidth'] > -16 || !allFilteredEnvironmentData?.length" mat-footer-row *matFooterRowDef="['scrollButtons']; sticky: true" class="info"></tr>
+ <tr
+ [hidden]="allFilteredEnvironmentData?.length"
+ mat-footer-row *matFooterRowDef="['placeholder']"
+ class="info"
+ ></tr>
+ <tr
+ [hidden]="!tableEl || !tableEl['offsetWidth'] || tableWrapper.offsetWidth - tableEl['offsetWidth'] > -16 || !allFilteredEnvironmentData?.length"
+ mat-footer-row
+ *matFooterRowDef="['scrollButtons']; sticky: true"
+ class="info"
+ ></tr>
</table>
-
</div>
</div>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.scss
index 59d5254..888cfbb 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.scss
@@ -17,60 +17,61 @@
* under the License.
*/
-.managment-wrapper{
+.managment-wrapper {
position: relative;
height: calc(100vh - 130px);
- scroll-behavior: smooth;
margin-left: -15px;
margin-right: -15px;
padding-left: 15px;
padding-right: 15px;
+ scroll-behavior: smooth;
overflow: auto;
.scroll-wrapper {
overflow: auto;
scroll-behavior: smooth;
- 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);
+ 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);
}
- .ani{
+ .ani {
max-height: calc(100vh - 130px);
position: relative;
- .wrapper{
- width: 100%;
+ .wrapper {
+ position: relative;
display: block;
+ width: 100%;
max-height: calc(100vh - 130px);
overflow: unset;
- position: relative;
scroll-behavior: smooth;
}
}
}
.data-grid {
-
&.management {
- .filter-row-item{
+ .filter-row-item {
padding: 5px;
}
- .settings{
+ .settings {
min-width: 7%;
}
- .mat-column-checkbox{
+ .mat-column-checkbox {
+ min-width: 38px;
padding-left: 10px;
padding-right: 0px;
- min-width: 38px;
- &.label-header{
- .empty-checkbox{
- z-index: 1011
- }
+ &.label-header {
+ .empty-checkbox {
+ z-index: 1011;
+ }
}
}
- .user{
+ .user {
width: 15%;
min-width: 180px;
}
@@ -87,13 +88,13 @@
.shape {
width: 15% !important;
- .label{
+ .label {
position: absolute;
}
min-width: 150px;
}
- .endpoint{
+ .endpoint {
width: 10% !important;
min-width: 140px;
}
@@ -115,15 +116,13 @@
.settings {
padding-right: 14px;
-
-
}
.actions {
+ position: sticky;
margin-top: 0px;
padding-right: 10px;
- position: sticky;
- .label{
+ .label {
padding-right: 5px;
}
}
@@ -132,39 +131,37 @@
width: 6%;
}
- .label-header{
+ .label-header {
padding-left: 15px;
height: 56px;
- .ar{
- left: 21px;
+ .ar {
+ left: 20px;
top: 2px;
- &.checkbox-border
- {
- left: 19px;
+ &.checkbox-border {
+ left: 18px;
}
}
- .settings{
+ .settings {
min-width: 7%;
}
- &.mat-column-checkbox{
+ &.mat-column-checkbox {
z-index: 12 !important;
padding-left: 10px;
- .ar{
+ .ar {
position: absolute;
top: 10px;
}
}
- &.user{
+ &.user {
z-index: 11 !important;
-
}
- &.type{
+ &.type {
z-index: 10 !important;
}
@@ -203,37 +200,36 @@
}
.dashboard_table_body {
-
td:first-child {
cursor: default;
}
}
- .user-name{
+ .user-name {
+ max-width: 250px;
padding-right: 22px;
overflow: hidden;
word-break: break-all;
white-space: nowrap;
- max-width: 250px;
}
- .buttons-wrap{
+ .buttons-wrap {
padding: 0;
- border-top: 1px solid rgba(0,0,0,.12);
+ border-top: 1px solid rgba(0, 0, 0, 0.12);
transform: translateY(-1px);
}
- .buttons{
+ .buttons {
position: sticky;
left: 0;
}
- button{
+ button {
background-color: #fff;
box-shadow: none;
- mat-icon{
+ mat-icon {
color: lightgrey;
- &.highlight{
+ &.highlight {
color: #35afd5;
}
}
@@ -258,8 +254,8 @@ table.management {
.label {
display: inline-block;
padding-top: 14px;
- vertical-align: super !important;
padding-left: 5px;
+ vertical-align: super !important;
}
.actions {
text-align: right;
@@ -273,26 +269,26 @@ table.management {
.filter-row {
background: inherit;
- .filter-row-item{
+ .filter-row-item {
left: auto !important;
- &.actions-col{
- right: -15px;
- }
+ &.actions-col {
+ right: -15px;
+ }
}
- .filter-field{
+ .filter-field {
font-size: 13px;
padding-left: 15px;
}
}
- .info{
+ .info {
padding: 40px;
text-align: center;
}
.source .resource-wrap {
- .resource-actions{
+ .resource-actions {
padding-right: 0;
}
.resource-name .detailed-link {
@@ -301,24 +297,22 @@ table.management {
}
}
-.computation{
+.computation {
cursor: pointer;
color: #35afd5;
}
-.table-footer{
+.table-footer {
height: 48px;
}
-.header-checkbox{
+.header-checkbox {
margin-top: 7px;
float: left;
}
-
-
@media screen and (max-width: 1550px) {
- .managment-wrapper{
+ .managment-wrapper {
.source {
.resource-wrap {
.resource-name {
@@ -331,11 +325,8 @@ table.management {
.resource-actions {
width: 20%;
-
}
}
}
}
}
-
-
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts
index 7871156..78ecf28 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management-grid/management-grid.component.ts
@@ -30,18 +30,17 @@ import {
AfterViewChecked,
ApplicationRef
} from '@angular/core';
+import { ChangeDetectorRef } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
+import { BehaviorSubject, Subject, timer } from 'rxjs';
-import { HealthStatusService } from '../../../core/services';
import { SortUtils } from '../../../core/util';
import { EnvironmentsDataService } from '../management-data.service';
import { EnvironmentModel, ManagementConfigModel } from '../management.model';
-import {ProgressBarService} from '../../../core/services/progress-bar.service';
-import {DetailDialogComponent} from '../../../resources/exploratory/detail-dialog';
-import {BehaviorSubject, Subject, timer} from 'rxjs';
-import { ChangeDetectorRef } from '@angular/core';
-import {CompareUtils} from '../../../core/util/compareUtils';
+import { ProgressBarService } from '../../../core/services/progress-bar.service';
+import { DetailDialogComponent } from '../../../resources/exploratory/detail-dialog';
+import { CompareUtils } from '../../../core/util/compareUtils';
export interface ManageAction {
action: string;
@@ -93,7 +92,7 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
this.checkMaxRight();
}
- displayedColumns: string[] = [ 'checkbox', 'user', 'type', 'project', 'endpoint', 'shape', 'status', 'resources', 'actions'];
+ displayedColumns: string[] = ['checkbox', 'user', 'type', 'project', 'endpoint', 'shape', 'status', 'resources', 'actions'];
displayedFilterColumns: string[] = ['checkbox-filter', 'user-filter', 'type-filter', 'project-filter', 'endpoint-filter', 'shape-filter', 'status-filter', 'resource-filter', 'actions-filter'];
public selected;
public allActiveNotebooks: any;
@@ -102,7 +101,6 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
public isFilterChanged: boolean;
constructor(
- private healthStatusService: HealthStatusService,
private environmentsDataService: EnvironmentsDataService,
public toastr: ToastrService,
public dialog: MatDialog,
@@ -115,7 +113,6 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
this.getEnvironmentData();
}
-
ngAfterViewInit() {
this.progressBarService.startProgressBar();
this.tableEl = this.table._elementRef.nativeElement;
@@ -134,16 +131,20 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
getEnvironmentData() {
this.progressBarService.startProgressBar();
- this.environmentsDataService._data.subscribe(data => {
- if (data) {
- this.allEnvironmentData = EnvironmentModel.loadEnvironments(data);
- this.getDefaultFilterConfiguration(data);
- this.applyFilter(this.cashedFilterForm || this.filterForm);
- }
- this.progressBarService.stopProgressBar();
- }, () => {
- this.progressBarService.stopProgressBar();
- });
+ this.environmentsDataService._data
+ .subscribe(
+ data => {
+ if (data) {
+ this.allEnvironmentData = EnvironmentModel.loadEnvironments(data);
+ this.getDefaultFilterConfiguration(data);
+ this.applyFilter(this.cashedFilterForm || this.filterForm);
+ }
+ this.progressBarService.stopProgressBar();
+ },
+ () => {
+ this.progressBarService.stopProgressBar();
+ }
+ );
}
buildGrid(): void {
@@ -183,7 +184,9 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
const containsStatus = (list, selectedItems) => {
if (list) {
- return list.filter((item: any) => { if (selectedItems.indexOf(item.status) !== -1) return item; });
+ return list.filter((item: any) => {
+ if (selectedItems.indexOf(item.status) !== -1) return item;
+ });
}
};
@@ -191,19 +194,31 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
if (config) {
filteredData = filteredData.filter(item => {
const isUser = config.users.length > 0 ? (config.users.indexOf(item.user) !== -1) : true;
- const isTypeName = item.name ? item.name.toLowerCase()
- .indexOf(config.type.toLowerCase()) !== -1 : item.type.toLowerCase().indexOf(config.type.toLowerCase()) !== -1;
- const isStatus = config.statuses.length > 0 ? (config.statuses.indexOf(item.status) !== -1) : (config.type !== 'active');
- const isShape = config.shapes.length > 0 ?
- (config.shapes.indexOf(item.shape) !== -1 ||
- config.shapes.indexOf(item.gpu_type) !== -1 ||
- config.shapes.indexOf(`GPU count: ${item.gpu_count}`) !== -1 ) : true;
- const isProject = config.projects.length > 0 ? (config.projects.indexOf(item.project) !== -1) : true;
- const isEndpoint = config.endpoints.length > 0 ? (config.endpoints.indexOf(item.endpoint) !== -1) : true;
+ const isTypeName = item.name
+ ? item.name.toLowerCase().indexOf(config.type.toLowerCase()) !== -1
+ : item.type.toLowerCase().indexOf(config.type.toLowerCase()) !== -1;
+ const isStatus = config.statuses.length > 0
+ ? (config.statuses.indexOf(item.status) !== -1)
+ : (config.type !== 'active');
+ const isShape = config.shapes.length > 0
+ ? (config.shapes.indexOf(item.shape) !== -1 ||
+ config.shapes.indexOf(item.gpu_type) !== -1 ||
+ config.shapes.indexOf(`GPU count: ${item.gpu_count}`) !== -1)
+ : true;
+ const isProject = config.projects.length > 0
+ ? (config.projects.indexOf(item.project) !== -1)
+ : true;
+ const isEndpoint = config.endpoints.length > 0
+ ? (config.endpoints.indexOf(item.endpoint) !== -1)
+ : true;
const modifiedResources = containsStatus(item.resources, config.resources);
- let isResources = config.resources.length > 0 ? (modifiedResources && modifiedResources.length > 0) : true;
- if (config.resources.length > 0 && modifiedResources && modifiedResources.length > 0) { item.resources = modifiedResources; }
+ let isResources = config.resources.length > 0
+ ? (modifiedResources && modifiedResources.length > 0)
+ : true;
+ if (config.resources.length > 0 && modifiedResources && modifiedResources.length > 0) {
+ item.resources = modifiedResources;
+ }
if (config.resources && config.resources.length === 0 && config.type === 'active' ||
modifiedResources && modifiedResources.length >= 0 && config.resources.length > 0 && config.type === 'active') {
@@ -217,8 +232,8 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
this.allFilteredEnvironmentData = filteredData;
this.allActiveNotebooks = this.allFilteredEnvironmentData
.filter(v => v.name &&
- (v.status === 'running' || v.status === 'stopped') &&
- !this.clustersInProgress(v.resources || []));
+ (v.status === 'running' || v.status === 'stopped') &&
+ !this.clustersInProgress(v.resources || []));
this.checkFilters();
}
@@ -252,8 +267,8 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
}
private getDefaultFilterConfiguration(data): void {
- const users = [], projects = [], shapes = [], statuses = [],
- resources = [], endpoints = [], gpuTypes = [], gpuCounts = [];
+ const users = [], projects = [], shapes = [], statuses = [],
+ resources = [], endpoints = [], gpuTypes = [], gpuCounts = [];
data && data.forEach((item: any) => {
if (item.user && users.indexOf(item.user) === -1) users.push(item.user);
@@ -264,10 +279,10 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
if (item.gpu_type && gpuTypes.indexOf(item.gpu_type) === -1) gpuTypes.push(item.gpu_type);
if (item.gpu_count && gpuCounts.indexOf(`GPU count: ${item.gpu_count}`) === -1) gpuCounts.push(`GPU count: ${item.gpu_count}`);
if (item.computational_resources) {
- item.computational_resources.map((resource: any) => {
- if (resources.indexOf(resource.status) === -1) resources.push(resource.status);
- resources.sort(SortUtils.statusSort);
- });
+ item.computational_resources.map((resource: any) => {
+ if (resources.indexOf(resource.status) === -1) resources.push(resource.status);
+ resources.sort(SortUtils.statusSort);
+ });
}
});
@@ -278,8 +293,9 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
if (!data.exploratory_urls || !data.exploratory_urls.length) {
return;
}
- this.dialog.open(DetailDialogComponent, { data:
- {notebook: data, buckets: [], type: 'environment'},
+ this.dialog.open(DetailDialogComponent, {
+ data:
+ { notebook: data, buckets: [], type: 'environment' },
panelClass: 'modal-lg'
})
.afterClosed().subscribe(() => {});
@@ -321,12 +337,12 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView
public checkMaxRight() {
let arg;
- if (this.wrapper && this.table) {
- arg = this.wrapper.nativeElement.offsetWidth +
- this.wrapper.nativeElement.scrollLeft + 2 <= this.table._elementRef.nativeElement.offsetWidth;
- }
-
- return this.isMaxRight.next(arg);
+ if (this.wrapper && this.table) {
+ arg = this.wrapper.nativeElement.offsetWidth +
+ this.wrapper.nativeElement.scrollLeft + 2 <= this.table._elementRef.nativeElement.offsetWidth;
+ }
+
+ return this.isMaxRight.next(arg);
}
}
@@ -436,7 +452,7 @@ export class ReconfirmationDialogComponent {
if (notebook.resources.length) {
this.isClusterLength = true;
}
- return notebook;
+ return notebook;
});
}
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.html
index 240a9e0..4a4cf55 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.html
@@ -23,7 +23,8 @@
<div class="action-select-wrapper admin-group" >
<span class="action-button-wrapper">
<button
- type="button" class="butt actions-btn"
+ type="button"
+ class="butt actions-btn"
mat-raised-button
[disabled]="!selected.length"
(click)="toogleActions();$event.stopPropagation()"
@@ -34,18 +35,20 @@
</span>
<div class="action-menu" *ngIf="isActionsOpen">
<span>
+ <button
+ type="button"
+ class="butt action-menu-item"
+ [ngClass]="{'disabled': selectedRunning.length === 0 || selectedStopped.length !== 0 }"
+ mat-raised-button
+ [disabled]="selectedRunning.length === 0"
+ (click)="resourseAction('stop');$event.stopPropagation()"
+ >
+ Stop
+ </button>
+ </span>
<button
- type="button" class="butt action-menu-item"
- [ngClass]="{'disabled': selectedRunning.length === 0 || selectedStopped.length !== 0 }"
- mat-raised-button
- [disabled]="selectedRunning.length === 0"
- (click)="resourseAction('stop');$event.stopPropagation()"
- >
- Stop
- </button>
- </span>
- <button
- type="button" class="butt action-menu-item"
+ type="button"
+ class="butt action-menu-item"
mat-raised-button
(click)="resourseAction('terminate');$event.stopPropagation()"
>
@@ -53,26 +56,42 @@
</button>
</div>
</div>
- <button mat-raised-button class="butt ssn" (click)="showEndpointsDialog()">
+ <button
+ mat-raised-button
+ class="butt ssn"
+ (click)="showEndpointsDialog()"
+ >
<i class="material-icons"></i>Endpoints
</button>
<!-- <button mat-raised-button class="butt ssn" (click)="openSsnMonitorDialog()">
<i class="material-icons"></i>SSN Monitor
</button> -->
- <button mat-raised-button class="butt env" (click)="openManageEnvironmentDialog()">
- Manage DataLab quotas
+ <button
+ mat-raised-button
+ class="butt env"
+ (click)="openManageEnvironmentDialog()"
+ >
+ Manage DataLab quotas
</button>
<!-- <button mat-raised-button class="butt" (click)="showBackupDialog()" [disabled]="creatingBackup">
<i class="material-icons">backup</i>Backup
</button> -->
</div>
- <button mat-raised-button class="butt" (click)="refreshGrid()">
+ <button
+ mat-raised-button
+ class="butt"
+ (click)="refreshGrid()"
+ >
<i class="material-icons refresh-icon">autorenew</i>Refresh
</button>
</div>
<mat-divider></mat-divider>
- <management-grid [currentUser]="user.toLowerCase()" [isAdmin]="healthStatus?.admin"
- [environmentsHealthStatuses]="healthStatus?.list_resources" (refreshGrid)="buildGrid()"
- (actionToggle)="toggleResourceAction($event)" (emitSelectedList)="selectedList($event)">
- </management-grid>
+ <management-grid
+ [currentUser]="user.toLowerCase()"
+ [isAdmin]="healthStatus?.admin"
+ [environmentsHealthStatuses]="healthStatus?.list_resources"
+ (refreshGrid)="buildGrid()"
+ (actionToggle)="toggleResourceAction($event)"
+ (emitSelectedList)="selectedList($event)"
+ ></management-grid>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.ts
index 38779fc..9ce01ad 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.component.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import {Component, OnInit, ViewChild} from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
@@ -39,9 +39,9 @@ import { ExploratoryModel } from '../../resources/resources-grid/resources-grid.
import { EnvironmentsDataService } from './management-data.service';
import { ProjectService } from '../../core/services';
-import {ConfirmationDialogComponent, ConfirmationDialogType} from '../../shared/modal-dialog/confirmation-dialog';
-import {ManagementGridComponent, ReconfirmationDialogComponent} from './management-grid/management-grid.component';
-import {FolderTreeComponent} from '../../resources/bucket-browser/folder-tree/folder-tree.component';
+import { ConfirmationDialogComponent, ConfirmationDialogType } from '../../shared/modal-dialog/confirmation-dialog';
+import { ManagementGridComponent, ReconfirmationDialogComponent } from './management-grid/management-grid.component';
+import { FolderTreeComponent } from '../../resources/bucket-browser/folder-tree/folder-tree.component';
@Component({
selector: 'environments-management',
@@ -58,8 +58,7 @@ export class ManagementComponent implements OnInit {
public selectedRunning: any[];
public selectedStopped: any[];
- @ViewChild(ManagementGridComponent, {static: true}) managementGrid;
-
+ @ViewChild(ManagementGridComponent, { static: true }) managementGrid;
constructor(
public toastr: ToastrService,
@@ -84,7 +83,7 @@ export class ManagementComponent implements OnInit {
}
public refreshGrid() {
- this.buildGrid();
+ this.buildGrid();
}
public manageEnvironmentAction($event) {
@@ -95,9 +94,11 @@ export class ManagementComponent implements OnInit {
$event.environment.project,
$event.environment.type === 'edge node' ? 'edge' : $event.environment.name,
$event.resource ? $event.resource.computational_name : null
- ).subscribe(
+ )
+ .subscribe(
() => this.buildGrid(),
- error => this.toastr.error('Environment management failed!', 'Oops!'));
+ error => this.toastr.error('Environment management failed!', 'Oops!')
+ );
}
// showBackupDialog() {
@@ -111,10 +112,14 @@ export class ManagementComponent implements OnInit {
openManageEnvironmentDialog() {
this.projectService.getProjectsList().subscribe(projectsList => {
- this.getTotalBudgetData().subscribe(total => {
- this.dialogRef = this.dialog.open(ManageEnvironmentComponent, { data: { projectsList, total }, panelClass: 'modal-xl-s' });
- this.dialogRef.afterClosed().subscribe(result => result && this.setBudgetLimits(result));
- }, () => this.toastr.error('Failed users list loading!', 'Oops!'));
+ this.getTotalBudgetData()
+ .subscribe(
+ total => {
+ this.dialogRef = this.dialog.open(ManageEnvironmentComponent, { data: { projectsList, total }, panelClass: 'modal-xl-s' });
+ this.dialogRef.afterClosed().subscribe(result => result && this.setBudgetLimits(result));
+ },
+ () => this.toastr.error('Failed users list loading!', 'Oops!')
+ );
});
}
@@ -131,28 +136,31 @@ export class ManagementComponent implements OnInit {
setBudgetLimits($event) {
if ($event.projects.length) {
- this.projectService.updateProjectsBudget($event.projects).subscribe((result: any) => {
- if ($event.isTotalChanged) {
- this.healthStatusService.updateTotalBudgetData($event.total).subscribe((res: any) => {
- result.status === HTTP_STATUS_CODES.OK
- && res.status === HTTP_STATUS_CODES.NO_CONTENT
+ this.projectService.updateProjectsBudget($event.projects)
+ .subscribe(
+ (result: any) => {
+ if ($event.isTotalChanged) {
+ this.healthStatusService.updateTotalBudgetData($event.total).subscribe((res: any) => {
+ result.status === HTTP_STATUS_CODES.OK
+ && res.status === HTTP_STATUS_CODES.NO_CONTENT
+ && this.toastr.success('Budget limits updated!', 'Success!');
+ this.buildGrid();
+ });
+ } else {
+ result.status === HTTP_STATUS_CODES.OK && this.toastr.success('Budget limits updated!', 'Success!');
+ this.buildGrid();
+ }
+ },
+ error => this.toastr.error(error.message, 'Oops!'));
+ } else {
+ this.healthStatusService.updateTotalBudgetData($event.total)
+ .subscribe((res: any) => {
+ res.status === HTTP_STATUS_CODES.NO_CONTENT
&& this.toastr.success('Budget limits updated!', 'Success!');
- this.buildGrid();
- });
- } else {
- result.status === HTTP_STATUS_CODES.OK && this.toastr.success('Budget limits updated!', 'Success!');
this.buildGrid();
- }
-
- }, error => this.toastr.error(error.message, 'Oops!'));
- } else {
- this.healthStatusService.updateTotalBudgetData($event.total).subscribe((res: any) => {
- res.status === HTTP_STATUS_CODES.NO_CONTENT
- && this.toastr.success('Budget limits updated!', 'Success!');
- this.buildGrid();
- });
- }
+ });
}
+ }
// manageEnvironment(event: { action: string, project: any }) {
@@ -216,12 +224,18 @@ export class ManagementComponent implements OnInit {
}
toggleResourceAction($event): void {
- const {environment, action, resource} = $event;
+ const { environment, action, resource } = $event;
if (resource) {
const resource_name = resource ? resource.computational_name : environment.name;
this.dialog.open(ReconfirmationDialogComponent, {
- data: { action, resource_name, user: environment.user, type: 'cluster'},
- width: '550px', panelClass: 'error-modalbox'
+ data: {
+ action,
+ resource_name,
+ user: environment.user,
+ type: 'cluster'
+ },
+ width: '550px',
+ panelClass: 'error-modalbox'
}).afterClosed().subscribe(result => {
result && this.manageEnvironmentAction({ action, environment, resource });
});
@@ -230,15 +244,20 @@ export class ManagementComponent implements OnInit {
if (action === 'stop') {
notebooks = notebooks.filter(note => note.status !== 'stopped');
this.dialog.open(ReconfirmationDialogComponent, {
- data: { notebooks: notebooks, type: 'notebook', action },
- width: '550px', panelClass: 'error-modalbox'
+ data: {
+ notebooks: notebooks,
+ type: 'notebook',
+ action
+ },
+ width: '550px',
+ panelClass: 'error-modalbox'
}).afterClosed().subscribe((res) => {
if (res) {
notebooks.forEach((env) => {
this.manageEnvironmentsService.environmentManagement(env.user, 'stop', env.project, env.name)
.subscribe(response => {
- this.buildGrid();
- },
+ this.buildGrid();
+ },
error => console.log(error)
);
});
@@ -250,7 +269,13 @@ export class ManagementComponent implements OnInit {
});
} else if (action === 'terminate') {
this.dialog.open(ReconfirmationDialogComponent, {
- data: { notebooks: notebooks, type: 'notebook', action }, width: '550px', panelClass: 'error-modalbox'
+ data: {
+ notebooks: notebooks,
+ type: 'notebook',
+ action
+ },
+ width: '550px',
+ panelClass: 'error-modalbox'
}).afterClosed().subscribe((res) => {
if (res) {
notebooks.forEach((env) => {
@@ -268,16 +293,16 @@ export class ManagementComponent implements OnInit {
}
this.isActionsOpen = false;
});
- // } else if (action === 'run') {
- // this.healthStatusService.runEdgeNode().subscribe(() => {
- // this.buildGrid();
- // this.toastr.success('Edge node is starting!', 'Processing!');
- // }, () => this.toastr.error('Edge Node running failed!', 'Oops!'));
- // } else if (action === 'recreate') {
- // this.healthStatusService.recreateEdgeNode().subscribe(() => {
- // this.buildGrid();
- // this.toastr.success('Edge Node recreation is processing!', 'Processing!');
- // }, () => this.toastr.error('Edge Node recreation failed!', 'Oops!'));
+ // } else if (action === 'run') {
+ // this.healthStatusService.runEdgeNode().subscribe(() => {
+ // this.buildGrid();
+ // this.toastr.success('Edge node is starting!', 'Processing!');
+ // }, () => this.toastr.error('Edge Node running failed!', 'Oops!'));
+ // } else if (action === 'recreate') {
+ // this.healthStatusService.recreateEdgeNode().subscribe(() => {
+ // this.buildGrid();
+ // this.toastr.success('Edge Node recreation is processing!', 'Processing!');
+ // }, () => this.toastr.error('Edge Node recreation failed!', 'Oops!'));
}
}
}
@@ -291,8 +316,7 @@ export class ManagementComponent implements OnInit {
}
}
-
public resourseAction(action) {
- this.toggleResourceAction({environment: this.selected, action: action});
+ this.toggleResourceAction({ environment: this.selected, action: action });
}
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts
index 7e9dda2..2e67871 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts
@@ -102,7 +102,6 @@ export class ManagementConfigModel {
public statuses: Array<string>,
public resources: Array<string>,
public endpoints: Array<string>,
-
) { }
defaultConfigurations(): void {
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.html
index 30c818d..a1b2e9f 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.html
@@ -107,7 +107,14 @@
</mat-tab>
</mat-tab-group>
<div class="text-center">
- <button type="button" class="butt" mat-raised-button (click)="dialogRef.close()">Close</button>
+ <button
+ type="button"
+ class="butt"
+ mat-raised-button
+ (click)="dialogRef.close()"
+ >
+ Close
+ </button>
</div>
</div>
<div class="info message" *ngIf="isEmpty(data)">
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.scss
index 9881165..107908c 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.scss
@@ -19,8 +19,8 @@
.ssn-monitor-dialog {
.content-box {
- padding-top: 10px !important;
position: relative;
+ padding-top: 10px !important;
}
.ssn-info {
min-height: 400px;
@@ -39,13 +39,13 @@
.mat-list-item-content {
display: flex;
justify-content: initial;
- color: #577289;
padding: 15px 5px;
- border-bottom: 1px solid #f3f2f2;
+ color: #577289;
font-size: 15px;
+ border-bottom: 1px solid #f3f2f2;
.col {
width: 50%;
font-weight: 300;
- }
+ }
}
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.ts
index 1ef7634..5aedc1f 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/ssn-monitor/ssn-monitor.component.ts
@@ -20,6 +20,7 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
+
import { DICTIONARY } from '../../../../dictionary/global.dictionary';
import { HealthStatusService } from '../../../core/services';
@@ -42,9 +43,11 @@ export class SsnMonitorComponent implements OnInit {
) { }
ngOnInit() {
- this.healthStatusService.getSsnMonitorData().subscribe(
+ this.healthStatusService.getSsnMonitorData()
+ .subscribe(
monitorData => this.data = monitorData,
- () => this.toastr.error('Failed ssn data loading!', 'Oops!'));
+ () => this.toastr.error('Failed ssn data loading!', 'Oops!')
+ );
}
public isEmpty(obj) {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datalab.apache.org
For additional commands, e-mail: commits-help@datalab.apache.org