You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by an...@apache.org on 2019/06/19 12:56:16 UTC
[incubator-dlab] 03/03: [DLAB-805]: clusters creation validation
fixes
This is an automated email from the ASF dual-hosted git repository.
ankovalyshyn pushed a commit to branch feature/projects
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit a825837a397303dc7ae0e69f58ba605b6dbdc27f
Author: Andriana Kovalyshyn <An...@epam.com>
AuthorDate: Wed Jun 19 15:55:58 2019 +0300
[DLAB-805]: clusters creation validation fixes
---
...utational-resource-create-dialog.component.html | 35 +---
...mputational-resource-create-dialog.component.ts | 190 +++++++--------------
.../resources-grid/resources-grid.component.html | 88 +++++-----
3 files changed, 112 insertions(+), 201 deletions(-)
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html
index f63602d..627b7de 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html
@@ -24,34 +24,20 @@
</header>
<div class="dialog-content selection">
<div class="content-box mat-reset">
- <form [formGroup]="resourceForm" *ngIf="cluster_types.length && resourceForm; else empty">
+ <form [formGroup]="resourceForm" *ngIf="clusterTypes.length && resourceForm; else empty">
<div class="form-wrapper" [ngClass]="{ compress: selectedImage?.image === 'docker.dlab-dataengine' }">
<div class="col">
- <!-- <div class="control-group" *ngIf="PROVIDER !== 'azure'" [hidden]="model.resourceImages.length === 1">
- <label class="label">Select cluster type</label>
- <div class="control">
- <dropdown-list #clusterType (selectedItem)="onUpdate($event)"></dropdown-list>
- </div>
- </div>
-
- <div class="control-group" *ngIf="PROVIDER !== 'azure'" [hidden]="!selectedImage.templates.length">
- <label class="label">Select template</label>
- <div class="control">
- <dropdown-list #templatesList (selectedItem)="onUpdate($event)"></dropdown-list>
- </div>
- </div> -->
-
- <div class="control-group" *ngIf="PROVIDER !== 'azure'" [hidden]="cluster_types.length === 1">
+ <div class="control-group" *ngIf="PROVIDER !== 'azure'" [hidden]="clusterTypes.length === 1">
<label class="label">Select cluster type</label>
<div class="control selector-wrapper">
<mat-form-field>
<mat-label>Select cluster type</mat-label>
<mat-select formControlName="template_name" disableOptionCentering>
- <mat-option *ngFor="let type of cluster_types" [value]="type.template_name"
+ <mat-option *ngFor="let type of clusterTypes" [value]="type.template_name"
(click)="selectImage(type)">{{ type.template_name }}</mat-option>
- <mat-option *ngIf="!cluster_types.length" class="multiple-select ml-10" disabled>Clusters types list
+ <mat-option *ngIf="!clusterTypes.length" class="multiple-select ml-10" disabled>Clusters types list
is empty</mat-option>
</mat-select>
<button class="caret">
@@ -112,19 +98,6 @@
</span>
</div>
</div>
- <!-- <div class="control-group" *ngIf="selectedImage?.image">
- <label class="label" *ngIf="selectedImage">{{ DICTIONARY[selectedImage.image].data_engine_master_instance_size }}</label>
- <div class="control">
- <dropdown-list #masterShapesList (selectedItem)="onUpdate($event)"></dropdown-list>
- </div>
- </div> -->
-
- <!-- <div class="control-group" *ngIf="selectedImage?.image" [hidden]="selectedImage?.image === 'docker.dlab-dataengine'">
- <label class="label">{{ DICTIONARY[selectedImage.image].data_engine_slave_instance_size }}</label>
- <div class="control">
- <dropdown-list #shapesSlaveList (selectedItem)="onUpdate($event)"></dropdown-list>
- </div>
- </div> -->
<div class="control-group" *ngIf="selectedImage?.image">
<label class="label">{{ DICTIONARY[selectedImage.image].data_engine_master_instance_size }}</label>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts
index b7b77fe..85ade39 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { Component, OnInit, EventEmitter, Output, ViewChild, Inject } from '@angular/core';
+import { Component, OnInit, ViewChild, Inject } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { ToastrService } from 'ngx-toastr';
import { ComputationalResourceModel } from './computational-resource-create.model';
import { UserResourceService } from '../../../core/services';
-import { HTTP_STATUS_CODES, CheckUtils } from '../../../core/util';
+import { HTTP_STATUS_CODES, PATTERNS, CheckUtils } from '../../../core/util';
import { DICTIONARY } from '../../../../dictionary/global.dictionary';
import { CLUSTER_CONFIGURATION } from './cluster-configuration-templates';
@@ -42,17 +42,10 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
readonly CheckUtils = CheckUtils;
notebook_instance: any;
- full_list: any;
-
- cluster_types = [];
+ resourcesList: any;
+ clusterTypes = [];
selectedImage: any;
-
- shapes: any;
spotInstance: boolean = true;
- clusterNamePattern: string = '[-_a-zA-Z0-9]*[_-]*[a-zA-Z0-9]+';
- nodeCountPattern: string = '^[1-9]\\d*$';
- delimitersRegex = /[-_]?/g;
- integerRegex = '^[0-9]*$';
public minInstanceNumber: number;
public maxInstanceNumber: number;
@@ -62,85 +55,29 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
public maxSpotPrice: number = 0;
public resourceForm: FormGroup;
- // @ViewChild('name') name;
- // @ViewChild('templatesList') templates_list;
- // @ViewChild('masterShapesList') master_shapes_list;
- // @ViewChild('shapesSlaveList') slave_shapes_list;
@ViewChild('spotInstancesCheck') spotInstancesSelect;
@ViewChild('preemptibleNode') preemptible;
@ViewChild('configurationNode') configuration;
- @Output() buildGrid: EventEmitter<{}> = new EventEmitter();
-
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
public toastr: ToastrService,
+ public dialogRef: MatDialogRef<ComputationalResourceCreateDialogComponent>,
private userResourceService: UserResourceService,
private model: ComputationalResourceModel,
- private _fb: FormBuilder,
- public dialogRef: MatDialogRef<ComputationalResourceCreateDialogComponent>,
+ private _fb: FormBuilder
) { }
ngOnInit() {
this.initFormModel();
this.notebook_instance = this.data.notebook;
- this.full_list = this.data.full_list;
+ this.resourcesList = this.data.resourcesList;
this.getTemplates(this.notebook_instance.project);
}
- // public onUpdate($event): void {
- // if ($event.model.type === 'template') {
- // this.model.setSelectedTemplate($event.model.index);
- // this.master_shapes_list.setDefaultOptions(this.model.selectedImage.shapes.resourcesShapeTypes,
- // this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'description'), 'master_shape', 'description', 'json');
- // this.slave_shapes_list.setDefaultOptions(this.model.selectedImage.shapes.resourcesShapeTypes,
- // this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'description'), 'slave_shape', 'description', 'json');
-
- // this.shapes.master_shape = this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'type');
- // this.shapes.slave_shape = this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'type');
- // }
- // if ($event.model.type === 'cluster_type') {
- // this.model.setSelectedClusterType($event.model.index);
- // this.setDefaultParams();
- // this.getComputationalResourceLimits();
- // this.selectConfiguration();
- // }
-
- // if (this.shapes[$event.model.type])
- // this.shapes[$event.model.type] = $event.model.value.type;
-
- // if (DICTIONARY.cloud_provider === 'aws')
- // if ($event.model.type === 'slave_shape' && this.spotInstancesSelect.nativeElement['checked']) {
- // this.spotInstance = $event.model.value.spot;
- // }
- // }
-
- public createComputationalResource(data) {
- this.model.createComputationalResource(data, this.selectedImage, this.notebook_instance, this.spotInstance)
- .subscribe((response: any) => {
- if (response.status === HTTP_STATUS_CODES.OK) {
- this.dialogRef.close();
- this.buildGrid.emit();
- }
- });
- }
-
- public containsComputationalResource(conputational_resource_name: string): boolean {
- if (conputational_resource_name)
- for (let index = 0; index < this.full_list.length; index++) {
- if (this.notebook_instance.name === this.full_list[index].name) {
- for (let iindex = 0; iindex < this.full_list[index].resources.length; iindex++) {
- const computational_name = this.full_list[index].resources[iindex].computational_name.toString().toLowerCase();
- if (this.delimitersFiltering(conputational_resource_name) === this.delimitersFiltering(computational_name))
- return true;
- }
- }
- }
- return false;
- }
-
- public delimitersFiltering(resource): string {
- return resource.replace(this.delimitersRegex, '').toString().toLowerCase();
+ public selectImage($event) {
+ this.selectedImage = $event;
+ this.getComputationalResourceLimits();
}
public selectSpotInstances($event?): void {
@@ -154,15 +91,6 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
}
}
- public selectTemplate($event) {
- if (DICTIONARY.cloud_provider === 'aws') this.spotInstancesSelect.nativeElement['checked'];
- }
-
- public selectImage($event) {
- this.selectedImage = $event;
- this.getComputationalResourceLimits();
- }
-
public selectPreemptibleNodes($event) {
if ($event.target.checked)
this.resourceForm.controls['preemptible_instance_number'].setValue(this.minPreemptibleInstanceNumber);
@@ -179,15 +107,12 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
}
}
- private filterAvailableSpots() {
- const filtered = JSON.parse(JSON.stringify(this.selectedImage.computation_resources_shapes));
- for (const item in this.selectedImage.computation_resources_shapes) {
- filtered[item] = filtered[item].filter(el => el.spot);
- if (filtered[item].length <= 0) {
- delete filtered[item];
- }
- }
- return filtered;
+ public preemptibleCounter($event, action): void {
+ $event.preventDefault();
+
+ const value = this.resourceForm.controls['preemptible_instance_number'].value;
+ const newValue = (action === 'increment' ? Number(value) + 1 : Number(value) - 1);
+ this.resourceForm.controls.preemptible_instance_number.setValue(newValue);
}
public isAvailableSpots(): boolean {
@@ -197,12 +122,11 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
return false;
}
- public preemptibleCounter($event, action): void {
- $event.preventDefault();
-
- const value = this.resourceForm.controls['preemptible_instance_number'].value;
- const newValue = (action === 'increment' ? Number(value) + 1 : Number(value) - 1);
- this.resourceForm.controls.preemptible_instance_number.setValue(newValue);
+ public createComputationalResource(data) {
+ this.model.createComputationalResource(data, this.selectedImage, this.notebook_instance, this.spotInstance)
+ .subscribe((response: any) => {
+ if (response.status === HTTP_STATUS_CODES.OK) this.dialogRef.close();
+ });
}
private initFormModel(): void {
@@ -211,10 +135,10 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
version: [''],
shape_master: ['', Validators.required],
shape_slave: [''],
- cluster_alias_name: ['', [Validators.required, Validators.pattern(this.clusterNamePattern),
+ cluster_alias_name: ['', [Validators.required, Validators.pattern(PATTERNS.namePattern),
this.providerMaxLength, this.checkDuplication.bind(this)]],
- instance_number: ['', [Validators.required, Validators.pattern(this.nodeCountPattern), this.validInstanceNumberRange.bind(this)]],
- preemptible_instance_number: [0, Validators.compose([Validators.pattern(this.integerRegex), this.validPreemptibleRange.bind(this)])],
+ instance_number: ['', [Validators.required, Validators.pattern(PATTERNS.nodeCountPattern), this.validInstanceNumberRange.bind(this)]],
+ preemptible_instance_number: [0, Validators.compose([Validators.pattern(PATTERNS.integerRegex), this.validPreemptibleRange.bind(this)])],
instance_price: [0, [this.validInstanceSpotRange.bind(this)]],
configuration_parameters: ['', [this.validConfiguration.bind(this)]]
});
@@ -249,6 +173,7 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
}
}
+ // Validation
private validInstanceNumberRange(control) {
if (control && control.value)
if (DICTIONARY.cloud_provider === 'gcp' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
@@ -304,25 +229,15 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
return control.value.length <= 10 ? null : { valid: false };
}
- private setDefaultParams(): void {
- // if (this.model.selectedImage && this.model.selectedImage.shapes) {
- // this.filterShapes();
- // this.shapes = {
- // master_shape: this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'type'),
- // slave_shape: this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'type')
- // };
- // if (DICTIONARY.cloud_provider !== 'azure' && this.cluster_type) {
- // this.cluster_type.setDefaultOptions(this.model.resourceImages,
- // this.model.selectedImage.template_name, 'cluster_type', 'template_name', 'array');
- // // if (this.model.selectedImage.image === 'docker.dlab-dataengine-service')
- // // this.templates_list.setDefaultOptions(this.model.templates,
- // // this.model.selectedItem.version, 'template', 'version', 'array');
- // }
- // this.master_shapes_list && this.master_shapes_list.setDefaultOptions(this.model.selectedImage.shapes.resourcesShapeTypes,
- // this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'description'), 'master_shape', 'description', 'json');
- // this.slave_shapes_list && this.slave_shapes_list.setDefaultOptions(this.model.selectedImage.shapes.resourcesShapeTypes,
- // this.shapePlaceholder(this.model.selectedImage.shapes.resourcesShapeTypes, 'description'), 'slave_shape', 'description', 'json');
- // }
+ private getTemplates(project) {
+ this.userResourceService.getComputationalTemplates(project).subscribe(
+ clusterTypes => {
+ this.clusterTypes = clusterTypes;
+ this.selectedImage = clusterTypes[0];
+ this.getComputationalResourceLimits();
+ this.filterShapes();
+ this.resourceForm.get('template_name').setValue(this.selectedImage.template_name)
+ });
}
private filterShapes(): void {
@@ -337,22 +252,35 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
}, {});
if (DICTIONARY.cloud_provider !== 'azure') {
- const images = this.cluster_types.filter(image => image.image === 'docker.dlab-dataengine');
- this.cluster_types = images;
- // (images.length > 0) ? this.model.setSelectedClusterType(0) : this.model.availableTemplates = false;
+ const images = this.clusterTypes.filter(image => image.image === 'docker.dlab-dataengine');
+ this.clusterTypes = images;
}
this.selectedImage.computation_resources_shapes = filtered;
}
}
- private getTemplates(project) {
- this.userResourceService.getComputationalTemplates(project).subscribe(
- cluster_types => {
- this.cluster_types = cluster_types;
- this.selectedImage = cluster_types[0];
- this.getComputationalResourceLimits();
- this.filterShapes();
- this.resourceForm.get('template_name').setValue(this.selectedImage.template_name)
- });
+ private filterAvailableSpots() {
+ const filtered = JSON.parse(JSON.stringify(this.selectedImage.computation_resources_shapes));
+ for (const item in this.selectedImage.computation_resources_shapes) {
+ filtered[item] = filtered[item].filter(el => el.spot);
+ if (filtered[item].length <= 0) {
+ delete filtered[item];
+ }
+ }
+ return filtered;
+ }
+
+ private containsComputationalResource(conputational_resource_name: string): boolean {
+ if (conputational_resource_name)
+ for (let index = 0; index < this.resourcesList.length; index++) {
+ if (this.notebook_instance.name === this.resourcesList[index].name) {
+ for (let iindex = 0; iindex < this.resourcesList[index].resources.length; iindex++) {
+ const computational_name = this.resourcesList[index].resources[iindex].computational_name.toString().toLowerCase();
+ if (CheckUtils.delimitersFiltering(conputational_resource_name) === CheckUtils.delimitersFiltering(computational_name))
+ return true;
+ }
+ }
+ }
+ return false;
}
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
index 68d7125..80b35f0 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
@@ -19,8 +19,8 @@
<table class="dashboard_table data-grid">
<tr>
- <th *ngFor="let column of filteringColumns"
- ngClass="{{column.className || ''}}" [hidden]="column.name === 'cost' && !healthStatus?.billingEnabled">
+ <th *ngFor="let column of filteringColumns" ngClass="{{column.className || ''}}"
+ [hidden]="column.name === 'cost' && !healthStatus?.billingEnabled">
{{column.title}}
<button mat-icon-button *ngIf="column.filtering" aria-label="More" class="ar" (click)="toggleFilterRow()">
<i class="material-icons">
@@ -33,16 +33,21 @@
<tr *ngIf="filteredEnvironments && collapseFilterRow" class="filter-row">
<td>
- <input placeholder="Filter by environment name" type="text" class="form-control filter-field" [value]="filterForm.name" (input)="filterForm.name = $event.target.value" />
+ <input placeholder="Filter by environment name" type="text" class="form-control filter-field"
+ [value]="filterForm.name" (input)="filterForm.name = $event.target.value" />
</td>
<td>
- <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>
</td>
<td>
- <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="DICTIONARY.cloud_provider === 'aws' ? 'shapes': 'sizes'" [items]="filterConfiguration.shapes" [model]="filterForm.shapes"></multi-select-dropdown>
+ <multi-select-dropdown (selectionChange)="onUpdate($event)"
+ [type]="DICTIONARY.cloud_provider === 'aws' ? 'shapes': 'sizes'" [items]="filterConfiguration.shapes"
+ [model]="filterForm.shapes"></multi-select-dropdown>
</td>
<td>
- <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>
</td>
<td *ngIf="healthStatus?.billingEnabled"></td>
<td>
@@ -51,37 +56,44 @@
<i class="material-icons">close</i>
</button>
- <button mat-icon-button class="btn apply" (click)="applyFilter_btnClick(filterForm)" [disabled]="filteredEnvironments.length == 0 && !filtering">
+ <button mat-icon-button class="btn apply" (click)="applyFilter_btnClick(filterForm)"
+ [disabled]="filteredEnvironments.length == 0 && !filtering">
<i class="material-icons" [ngClass]="{'not-allowed': filteredEnvironments.length == 0 && !filtering}">done</i>
</button>
</div>
</td>
</tr>
- <tr *ngIf="(!filteredEnvironments) && !filtering || (filteredEnvironments.length == 0) && !filtering" class="message_block">
- <td [colSpan]="!healthStatus?.billingEnabled ? filteringColumns.length -1 : filteringColumns.length">To start working, please, create new environment</td>
+ <tr *ngIf="(!filteredEnvironments) && !filtering || (filteredEnvironments.length == 0) && !filtering"
+ class="message_block">
+ <td [colSpan]="!healthStatus?.billingEnabled ? filteringColumns.length -1 : filteringColumns.length">To start
+ working, please, create new environment</td>
</tr>
<tr *ngIf="(filteredEnvironments.length == 0) && filtering" class="message_block">
- <td [colSpan]="!healthStatus?.billingEnabled ? filteringColumns.length -1 : filteringColumns.length">No matches found</td>
+ <td [colSpan]="!healthStatus?.billingEnabled ? filteringColumns.length -1 : filteringColumns.length">No matches
+ found</td>
</tr>
- <tr *ngFor="let env of filteredEnvironments;" class="dashboard_table_body" [ngClass]="{'dropdown-outscreen': isOutscreenDropdown}">
+ <tr *ngFor="let env of filteredEnvironments;" class="dashboard_table_body"
+ [ngClass]="{'dropdown-outscreen': isOutscreenDropdown}">
<td (click)="printDetailEnvironmentModal(env)">{{env.name}}</td>
<td class="status" ngClass="{{env.status.toLowerCase() || ''}}">{{ env.status | underscoreless }}</td>
<td>{{env.shape}}</td>
<td>
- <computational-resources-list [resources]="env.resources" [environment]="env" (buildGrid)="buildGrid($event)"></computational-resources-list>
+ <computational-resources-list [resources]="env.resources" [environment]="env" (buildGrid)="buildGrid($event)">
+ </computational-resources-list>
</td>
<td *ngIf="healthStatus?.billingEnabled">
<span class="total_cost">{{ env.cost || 'N/A' }} {{ env.currency_code || '' }}</span>
- <span (click)="env.billing && printCostDetails(env)" class="currency_details" [ngClass]="{ 'not-allowed' : !env.billing }">
+ <span (click)="env.billing && printCostDetails(env)" class="currency_details"
+ [ngClass]="{ 'not-allowed' : !env.billing }">
<i class="material-icons">help_outline</i>
</span>
</td>
<td class="settings">
<span #settings (click)="actions.toggle($event, settings)" class="actions"
- [ngClass]="{ 'disabled': env.status.toLowerCase() === 'creating' }">
+ [ngClass]="{ 'disabled': env.status.toLowerCase() === 'creating' }">
</span>
<bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left">
@@ -90,50 +102,48 @@
&& env.status !== 'terminating'
&& env.status !== 'terminated'
&& env.status !== 'creating image'">
- <li *ngIf="env.status !== 'stopped' && env.status !== 'stopping' && env.status !== 'starting' && env.status !== 'creating image'"
- matTooltip="Unable to stop notebook because at least one computational resource is in progress"
- matTooltipPosition="above"
- [matTooltipDisabled]="!isResourcesInProgress(env)">
- <div (click)="exploratoryAction(env, 'stop')" [ngClass]="{'not-allowed': isResourcesInProgress(env) }">
- <i class="material-icons">pause_circle_outline</i>
- <span>Stop</span>
- </div>
+ <li
+ *ngIf="env.status !== 'stopped' && env.status !== 'stopping' && env.status !== 'starting' && env.status !== 'creating image'"
+ matTooltip="Unable to stop notebook because at least one computational resource is in progress"
+ matTooltipPosition="above" [matTooltipDisabled]="!isResourcesInProgress(env)">
+ <div (click)="exploratoryAction(env, 'stop')" [ngClass]="{'not-allowed': isResourcesInProgress(env) }">
+ <i class="material-icons">pause_circle_outline</i>
+ <span>Stop</span>
+ </div>
</li>
<li *ngIf="env.status.toLowerCase() === 'stopped' || env.status.toLowerCase() === 'stopping'"
- matTooltip="Unable to run notebook until it will be stopped"
- matTooltipPosition="above"
- [matTooltipDisabled]="!isResourcesInProgress(env) && env.status.toLowerCase() !== 'stopping'">
- <div (click)="exploratoryAction(env, 'run')" [ngClass]="{'not-allowed': isResourcesInProgress(env) || env.status.toLowerCase() === 'stopping' }">
+ matTooltip="Unable to run notebook until it will be stopped" matTooltipPosition="above"
+ [matTooltipDisabled]="!isResourcesInProgress(env) && env.status.toLowerCase() !== 'stopping'">
+ <div (click)="exploratoryAction(env, 'run')"
+ [ngClass]="{'not-allowed': isResourcesInProgress(env) || env.status.toLowerCase() === 'stopping' }">
<i class="material-icons">play_circle_outline</i>
<span>Run</span>
</div>
</li>
<li *ngIf="env.status.toLowerCase() === 'running' || env.status.toLowerCase() === 'stopped'"
- matTooltip="Unable to terminate notebook because at least one computational resource is in progress"
- matTooltipPosition="above"
- [matTooltipDisabled]="!isResourcesInProgress(env)">
- <div (click)="exploratoryAction(env, 'terminate')" [ngClass]="{'not-allowed': isResourcesInProgress(env) }">
+ matTooltip="Unable to terminate notebook because at least one computational resource is in progress"
+ matTooltipPosition="above" [matTooltipDisabled]="!isResourcesInProgress(env)">
+ <div (click)="exploratoryAction(env, 'terminate')"
+ [ngClass]="{'not-allowed': isResourcesInProgress(env) }">
<i class="material-icons">phonelink_off</i>
<span>Terminate</span>
</div>
</li>
- <li (click)="exploratoryAction(env, 'deploy')"
- *ngIf="env.status != 'stopping'
+ <li (click)="exploratoryAction(env, 'deploy')" *ngIf="env.status != 'stopping'
&& env.status !== 'stopped'
&& env.status !== 'starting'
&& env.status !== 'creating image'">
<i class="material-icons">memory</i>
<span>Add compute</span>
</li>
- <li (click)="exploratoryAction(env, 'schedule')"
- *ngIf="env.status.toLowerCase() === 'running'
+ <li (click)="exploratoryAction(env, 'schedule')" *ngIf="env.status.toLowerCase() === 'running'
|| env.status.toLowerCase() === 'stopped'">
- <i class="material-icons">schedule</i>
+ <i class="material-icons">schedule</i>
<span>Scheduler</span>
</li>
</div>
<li (click)="exploratoryAction(env, 'ami')"
- *ngIf="env.status === 'running' && DICTIONARY.cloud_provider !== 'gcp'">
+ *ngIf="env.status === 'running' && DICTIONARY.cloud_provider !== 'gcp'">
<i class="material-icons">view_module</i>
<span>Create {{ DICTIONARY.image }}</span>
</li>
@@ -141,12 +151,12 @@
<i class="material-icons">developer_board</i>
<span>Manage libraries</span>
</li>
- <li>
- <a target="_blank" [routerLink]="['/terminal', env.ip]" class="navigate">
+ <!-- <li>
+ <a target="_blank" [routerLink]="['/terminal', env.ip]" class="navigate">
<i class="material-icons">laptop</i>
<span>Open terminal</span>
</a>
- </li>
+ </li> -->
</ul>
</bubble-up>
</td>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org