This is an automated email from the ASF dual-hosted git repository. ankovalyshyn pushed a commit to branch DLAB-1294 in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit d7d21c38a6d6d2513eed5368514fa9a2b86dfeb5 Author: Andriana Kovalyshyn <[email protected]> AuthorDate: Mon Nov 25 16:44:48 2019 +0200 [DLAB-1294]: added list statuses check on active filtering --- .../webapp/src/app/core/util/sortUtils.ts | 4 + .../resources-grid/resources-grid.component.html | 176 +-------------------- .../resources-grid/resources-grid.component.ts | 128 +++++++-------- 3 files changed, 66 insertions(+), 242 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/core/util/sortUtils.ts b/services/self-service/src/main/resources/webapp/src/app/core/util/sortUtils.ts index 88c5a22..1c7fb03 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/util/sortUtils.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/util/sortUtils.ts @@ -24,6 +24,10 @@ export class SortUtils { return order.indexOf(arg1) - order.indexOf(arg2); } + public static activeStatuses(): String[] { + return ['running', 'stopping', 'stopped', 'creating', 'configuring', 'starting', 'creating_image']; + } + public static shapesSort(shapesJson) { const sortOrder = ['For testing', 'Memory optimized', 'GPU optimized', 'Compute optimized']; const sortedShapes = {}; 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 28ca38f..a896e32 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 @@ -103,13 +103,8 @@ [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'" sticky> <tr *ngFor="let element of element.exploratory; let i = index" class="element-row mat-row"> - <td - class="name-col" - (click)="printDetailEnvironmentModal(element)" - matTooltip="{{ element.name }}" - [matTooltipShowDelay]="2000" - matTooltipPosition="above" - > + <td class="name-col" (click)="printDetailEnvironmentModal(element)" matTooltip="{{ element.name }}" + [matTooltipShowDelay]="2000" matTooltipPosition="above"> {{ element.name }} </td> <td class="status-col status" ngClass="{{ element.status.toLowerCase() || ''}}"> @@ -301,170 +296,3 @@ <tr [hidden]="filteredEnvironments?.length" mat-footer-row *matFooterRowDef="['placeholder']"></tr> </table> </section> - - - - - - - - -<!-- <table class=" dashboard_table data-grid"> - <tr> - <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"> - <span *ngIf="filtering && filterForm[column.name].length > 0 && !collapseFilterRow">filter_list</span> - <span [hidden]="filtering && filterForm[column.name].length > 0 && !collapseFilterRow">more_vert</span> - </i> - </button> - </th> - </tr> - - - - - <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" /> - </td> - <td> - <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> - </td> - <td> - <multi-select-dropdown (selectionChange)="onUpdate($event)" [type]="'resources'" - [items]="filterConfiguration.resources" [model]="filterForm.resources"></multi-select-dropdown> - </td> - <td *ngIf="healthStatus?.billingEnabled"></td> - <td> - <div class="actions"> - <button mat-icon-button class="btn reset" (click)="resetFilterConfigurations()"> - <i class="material-icons">close</i> - </button> - - <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> - - <tr *ngIf="(filteredEnvironments.length == 0) && filtering" class="message_block"> - <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}"> - <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> - </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 }"> - <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' }"> - </span> - - <bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left"> - <ul class="list-unstyled"> - <div class="active-items" *ngIf="env.status.toLowerCase() !== 'failed' - && 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> - <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' }"> - <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) }"> - <i class="material-icons">phonelink_off</i> - <span>Terminate</span> - </div> - </li> - <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' - || env.status.toLowerCase() === 'stopped'"> - <i class="material-icons">schedule</i> - <span>Scheduler</span> - </li> - </div> - <li (click)="exploratoryAction(env, 'ami')" - *ngIf="env.status === 'running' && DICTIONARY.cloud_provider !== 'gcp'"> - <i class="material-icons">view_module</i> - <span>Create {{ DICTIONARY.image }}</span> - </li> - <li (click)="exploratoryAction(env, 'install')"> - <i class="material-icons">developer_board</i> - <span>Manage libraries</span> - </li> - <li *ngIf="env.status === 'running'"> - <a target="_blank" [attr.href]="'/#/terminal/' + env.private_ip" class="navigate"> - <i class="material-icons">laptop</i> - <span>Open terminal</span> - </a> - </li> - </ul> - </bubble-up> - </td> - </tr> - </table> --> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts index c29d76f..33ca68d 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts @@ -118,7 +118,9 @@ export class ResourcesGridComponent implements OnInit { } public showActiveInstances(): void { + this.filterForm = this.loadUserPreferences(this.filterActiveInstances()); + this.applyFilter_btnClick(this.filterForm); this.buildGrid(); } @@ -140,6 +142,59 @@ export class ResourcesGridComponent implements OnInit { return false; } + public filterActiveInstances(): FilterConfigurationModel { + return (<FilterConfigurationModel | any>Object).assign({}, this.filterConfiguration, { + statuses: SortUtils.activeStatuses(), + resources: SortUtils.activeStatuses(), + type: 'active', + project: this.activeProject || '' + }); + } + + public resetFilterConfigurations(): void { + this.filterForm.resetConfigurations(); + this.updateUserPreferences(this.filterForm); + this.buildGrid(); + } + + public printDetailEnvironmentModal(data): void { + this.dialog.open(DetailDialogComponent, { data: data, panelClass: 'modal-lg' }) + .afterClosed().subscribe(() => this.buildGrid()); + } + + public printCostDetails(data): void { + this.dialog.open(CostDetailsDialogComponent, { data: data, panelClass: 'modal-xl' }) + .afterClosed().subscribe(() => this.buildGrid()); + } + + public exploratoryAction(data, action: string) { + if (action === 'deploy') { + this.dialog.open(ComputationalResourceCreateDialogComponent, { data: { notebook: data, full_list: this.environments }, panelClass: 'modal-xxl' }) + .afterClosed().subscribe(() => this.buildGrid()); + } else if (action === 'run') { + this.userResourceService + .runExploratoryEnvironment({ notebook_instance_name: data.name, project_name: data.project }) + .subscribe( + () => this.buildGrid(), + error => this.toastr.error(error.message || 'Exploratory starting failed!', 'Oops!')); + } else if (action === 'stop') { + this.dialog.open(ConfirmationDialogComponent, { data: { notebook: data, type: ConfirmationDialogType.StopExploratory }, panelClass: 'modal-sm' }) + .afterClosed().subscribe(() => this.buildGrid()); + } else if (action === 'terminate') { + this.dialog.open(ConfirmationDialogComponent, { data: { notebook: data, type: ConfirmationDialogType.TerminateExploratory }, panelClass: 'modal-sm' }) + .afterClosed().subscribe(() => this.buildGrid()); + } else if (action === 'install') { + this.dialog.open(InstallLibrariesComponent, { data: data, panelClass: 'modal-fullscreen' }) + .afterClosed().subscribe(() => this.buildGrid()); + } else if (action === 'schedule') { + this.dialog.open(SchedulerComponent, { data: { notebook: data, type: 'EXPLORATORY' }, panelClass: 'modal-xl-s' }) + .afterClosed().subscribe(() => this.buildGrid()); + } else if (action === 'ami') { + this.dialog.open(AmiCreateDialogComponent, { data: data, panelClass: 'modal-sm' }) + .afterClosed().subscribe(() => this.buildGrid()); + } + } + // PRIVATE private getResourceByName(notebook_name: string) { @@ -212,30 +267,12 @@ export class ResourcesGridComponent implements OnInit { this.filteredEnvironments = filteredData; } - private modifyGrid() { + private modifyGrid(): void { this.displayedColumns = this.displayedColumns.filter(el => el !== 'cost'); this.displayedFilterColumns = this.displayedFilterColumns.filter(el => el !== 'cost-filter'); } - - - filterActiveInstances(): FilterConfigurationModel { - const filteredData = (<any>Object).assign({}, this.filterConfiguration); - filteredData.project = this.activeProject || ''; - - for (const index in filteredData) { - if (filteredData[index] instanceof Array) - filteredData[index] = filteredData[index].filter((item: string) => { - return (item !== 'failed' && item !== 'terminated' && item !== 'terminating'); - }); - if (index === 'shapes') { filteredData[index] = []; } - } - filteredData.type = 'active'; - - return filteredData; - } - - aliveStatuses(сonfig): void { + private aliveStatuses(сonfig): void { for (const index in this.filterConfiguration) { if (сonfig[index] && сonfig[index] instanceof Array) сonfig[index] = сonfig[index].filter(item => this.filterConfiguration[index].includes(item)); @@ -250,14 +287,7 @@ export class ResourcesGridComponent implements OnInit { if (filterConfig[index].length) this.activeFiltering = true; } - resetFilterConfigurations(): void { - this.filterForm.resetConfigurations(); - this.updateUserPreferences(this.filterForm); - this.buildGrid(); - } - - - getUserPreferences(): void { + private getUserPreferences(): void { this.userResourceService.getUserPreferences() .subscribe((result: FilterConfigurationModel) => { if (result) { @@ -268,51 +298,13 @@ export class ResourcesGridComponent implements OnInit { }, () => this.applyFilter_btnClick(null)); } - loadUserPreferences(config): FilterConfigurationModel { + private loadUserPreferences(config): FilterConfigurationModel { return new FilterConfigurationModel(config.name, config.statuses, config.shapes, config.resources, config.type, config.project); } - updateUserPreferences(filterConfiguration: FilterConfigurationModel): void { + private updateUserPreferences(filterConfiguration: FilterConfigurationModel): void { this.userResourceService.updateUserPreferences(filterConfiguration) .subscribe((result) => { }, (error) => console.log('UPDATE USER PREFERENCES ERROR ', error)); } - - printDetailEnvironmentModal(data): void { - this.dialog.open(DetailDialogComponent, { data: data, panelClass: 'modal-lg' }) - .afterClosed().subscribe(() => this.buildGrid()); - } - - printCostDetails(data): void { - this.dialog.open(CostDetailsDialogComponent, { data: data, panelClass: 'modal-xl' }) - .afterClosed().subscribe(() => this.buildGrid()); - } - - exploratoryAction(data, action: string) { - if (action === 'deploy') { - this.dialog.open(ComputationalResourceCreateDialogComponent, { data: { notebook: data, full_list: this.environments }, panelClass: 'modal-xxl' }) - .afterClosed().subscribe(() => this.buildGrid()); - } else if (action === 'run') { - this.userResourceService - .runExploratoryEnvironment({ notebook_instance_name: data.name, project_name: data.project }) - .subscribe( - () => this.buildGrid(), - error => this.toastr.error(error.message || 'Exploratory starting failed!', 'Oops!')); - } else if (action === 'stop') { - this.dialog.open(ConfirmationDialogComponent, { data: { notebook: data, type: ConfirmationDialogType.StopExploratory }, panelClass: 'modal-sm' }) - .afterClosed().subscribe(() => this.buildGrid()); - } else if (action === 'terminate') { - this.dialog.open(ConfirmationDialogComponent, { data: { notebook: data, type: ConfirmationDialogType.TerminateExploratory }, panelClass: 'modal-sm' }) - .afterClosed().subscribe(() => this.buildGrid()); - } else if (action === 'install') { - this.dialog.open(InstallLibrariesComponent, { data: data, panelClass: 'modal-fullscreen' }) - .afterClosed().subscribe(() => this.buildGrid()); - } else if (action === 'schedule') { - this.dialog.open(SchedulerComponent, { data: { notebook: data, type: 'EXPLORATORY' }, panelClass: 'modal-xl-s' }) - .afterClosed().subscribe(() => this.buildGrid()); - } else if (action === 'ami') { - this.dialog.open(AmiCreateDialogComponent, { data: data, panelClass: 'modal-sm' }) - .afterClosed().subscribe(() => this.buildGrid()); - } - } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
