This is an automated email from the ASF dual-hosted git repository. hshpak pushed a commit to branch feat/DATALAB-2771/add-create-image-btn-for-admin in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit fc283fc61744259f0c3eff4332f6a483b79dafbc Author: Hennadii_Shpak <[email protected]> AuthorDate: Tue May 3 18:18:27 2022 +0300 [DATALAB-2771] created create image btn --- .../management-grid/management-grid.component.html | 221 +++++++++++---------- .../management-grid/management-grid.component.ts | 47 +++-- .../management/management.component.ts | 19 +- .../administration/management/management.model.ts | 13 +- .../convert-action-type.pipe.ts | 28 +-- .../services/applicationServiceFacade.service.ts | 4 +- .../ami-create-dialog.component.html | 16 +- .../ami-create-dialog.component.ts | 32 ++- 8 files changed, 215 insertions(+), 165 deletions(-) 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 c8c793d8c..8b9e8a034 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 @@ -18,14 +18,14 @@ --> <div class="managment-wrapper scrolling" #pageWrapper (scroll)="scrollTable($event)" (resize)="onResize($event)"> <div class="ani scrolling scroll-wrapper" #wrapper (scroll)="scrollTable($event)"> - <div - class="nav-buttons" + <div + class="nav-buttons" [ngStyle]="{'width.px': userAgentIndex === -1 ? tableWrapperWidth - 3 : tableWrapperWidth - 7 }" - [ngClass]="{'border': tableEl['offsetHeight'] < tableWrapper.offsetHeight - 48}" + [ngClass]="{'border': tableEl['offsetHeight'] < tableWrapper.offsetHeight - 48}" [hidden]="!(tableWrapper.offsetWidth - tableEl['offsetWidth'] < 0)" > <div class="button-container"> - <button + <button mat-mini-fab aria-label="Scroll left" (click)="sctollTo('left')" [ngClass]="{'not-allowed': wrapper.scrollLeft === 0 }" @@ -34,7 +34,7 @@ </button> </div> <div class="button-container" [ngClass]="{'not-allowed': checkMaxRight()}"> - <button + <button mat-mini-fab aria-label="Scroll right" (click)="sctollTo('right')" [ngClass]="{'not-allowed': !(isMaxRight | async)}" @@ -61,10 +61,10 @@ </button> </th> <td mat-cell *matCellDef="let element"> - <ng-template - [ngIf]="element.type !== 'odahu' - && element.type !== 'edge node' - && (element.status==='running' || element.status==='stopped') + <ng-template + [ngIf]="element.type !== 'odahu' + && element.type !== 'edge node' + && (element.status==='running' || element.status==='stopped') && !clustersInProgress(element.resources)" > <datalab-checkbox @@ -79,10 +79,10 @@ <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" + <button + mat-icon-button + aria-label="More" + class="ar" (click)="toggleFilterRow()" > <i class="material-icons"> @@ -105,17 +105,17 @@ <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" + <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> + </button> </th> <td mat-cell *matCellDef="let element">{{ element.project }}</td> </ng-container> @@ -123,10 +123,10 @@ <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" + <button + mat-icon-button + aria-label="More" + class="ar" (click)="toggleFilterRow()" > <i class="material-icons"> @@ -141,10 +141,10 @@ <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" + <button + mat-icon-button + aria-label="More" + class="ar" (click)="toggleFilterRow()" > <i class="material-icons"> @@ -168,10 +168,10 @@ <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" + <button + mat-icon-button + aria-label="More" + class="ar" (click)="toggleFilterRow()" > <i class="material-icons"> @@ -190,10 +190,10 @@ <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" + <button + mat-icon-button + aria-label="More" + class="ar" (click)="toggleFilterRow()" > <i class="material-icons"> @@ -210,10 +210,10 @@ <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" + <button + mat-icon-button + aria-label="More" + class="ar" (click)="toggleFilterRow()" > <i class="material-icons"> @@ -236,8 +236,8 @@ <div class="resource-actions"> <span class="not-allow"> <a class="start-stop-action" *ngIf="resource.image === 'docker.datalab-dataengine'"> - <i - class="material-icons" + <i + class="material-icons" (click)="toggleResourceAction(element, 'stop', resource)" [ngClass]="{'not-allowed' : resource.status !== 'running' || selected?.length }" > @@ -246,8 +246,8 @@ </a> </span> <span class="not-allow"> - <a - class="remove_butt" + <a + class="remove_butt" (click)="toggleResourceAction(element, 'terminate', resource)" [ngClass]="{ 'disabled' : element.status !== 'running' || (resource.status !== 'running' && resource.status !== 'stopped') || selected?.length }" > @@ -267,10 +267,10 @@ </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)" + <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') @@ -281,39 +281,50 @@ <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' + 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" + matTooltipPosition="above" [matTooltipDisabled]="!isResourcesInProgress(element)" [hidden]="element.name === 'edge node' && element.status === 'stopped'" > - <div + <div (click)="toggleResourceAction(element, 'stop')" - [ngClass]="{'not-allowed' : element.status === 'stopped' || element.status === 'stopping' || - element.status === 'starting' || element.status === 'creating image' || + [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 + <li *ngIf="element.name !== 'edge node'" matTooltip="Unable to terminate notebook because at least one compute is in progress" - matTooltipPosition="above" + matTooltipPosition="above" [matTooltipDisabled]="!isResourcesInProgress(element)" > - <div + <div (click)="toggleResourceAction(element, 'terminate')" - [ngClass]="{'not-allowed' : element.status !== 'running' && - element.status !== 'stopped' || + [ngClass]="{'not-allowed' : element.status !== 'running' && + element.status !== 'stopped' || isResourcesInProgress(element)}" > <i class="material-icons">phonelink_off</i> <span>Terminate</span> </div> </li> + <li + *ngIf="element.status === 'running' && element.image !== 'docker.datalab-superset' + && element.image !== 'docker.datalab-jupyterlab'" + > + <div + (click)="toggleResourceAction(element, 'create image')" + > + <i class="material-icons">view_module</i> + <span>Create Image</span> + </div> + </li> <li *ngIf="element.status === 'stopped'"> <div (click)="toggleResourceAction(element, 'start')"> <i class="material-icons">play_circle_outline</i> @@ -333,9 +344,9 @@ <ng-container matColumnDef="user-filter" sticky> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown - (selectionChange)="onUpdate($event)" - [type]="'users'" + <multi-select-dropdown + (selectionChange)="onUpdate($event)" + [type]="'users'" [items]="filterConfiguration.users" [model]="filterForm.users" ></multi-select-dropdown> @@ -344,11 +355,11 @@ <ng-container matColumnDef="type-filter" sticky> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <input - placeholder="Filter by name" - type="text" + <input + placeholder="Filter by name" + type="text" class="form-control filter-field" - [value]="filterForm.type" + [value]="filterForm.type" (input)="onFilterNameUpdate($event.target['value'])" /> </th> @@ -356,20 +367,20 @@ <ng-container matColumnDef="project-filter" sticky> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown - (selectionChange)="onUpdate($event)" + <multi-select-dropdown + (selectionChange)="onUpdate($event)" [type]="'projects'" - [items]="filterConfiguration.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)" + <multi-select-dropdown + (selectionChange)="onUpdate($event)" [type]="'endpoints'" - [items]="filterConfiguration.endpoints" + [items]="filterConfiguration.endpoints" [model]="filterForm.endpoints" ></multi-select-dropdown> </th> @@ -377,10 +388,10 @@ <ng-container matColumnDef="shape-filter" sticky> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown - (selectionChange)="onUpdate($event)" + <multi-select-dropdown + (selectionChange)="onUpdate($event)" [type]="'shapes'" - [items]="filterConfiguration.shapes" + [items]="filterConfiguration.shapes" [model]="filterForm.shapes" ></multi-select-dropdown> </th> @@ -388,10 +399,10 @@ <ng-container matColumnDef="status-filter" sticky> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown - (selectionChange)="onUpdate($event)" + <multi-select-dropdown + (selectionChange)="onUpdate($event)" [type]="'statuses'" - [items]="filterConfiguration.statuses" + [items]="filterConfiguration.statuses" [model]="filterForm.statuses" ></multi-select-dropdown> </th> @@ -399,10 +410,10 @@ <ng-container matColumnDef="resource-filter" sticky> <th mat-header-cell *matHeaderCellDef class="filter-row-item"> - <multi-select-dropdown - (selectionChange)="onUpdate($event)" + <multi-select-dropdown + (selectionChange)="onUpdate($event)" [type]="'resources'" - [items]="filterConfiguration.resources" + [items]="filterConfiguration.resources" [model]="filterForm.resources" ></multi-select-dropdown> </th> @@ -411,22 +422,22 @@ <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()" + <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" + <button + mat-icon-button + class="btn apply" (click)="applyFilter(filterForm)" [disabled]="isFilterChanged" > - <i + <i class="material-icons" [ngClass]="{'not-allowed': allFilteredEnvironmentData?.length == 0 && !filtering}" > @@ -439,7 +450,7 @@ <ng-container matColumnDef="placeholder"> <td mat-footer-cell *matFooterCellDef colspan="8" class="no-border"> - <div + <div class="info" *ngIf="(!allFilteredEnvironmentData) && !filtering || (allFilteredEnvironmentData?.length == 0) && !filtering" > @@ -450,36 +461,36 @@ </ng-container> <ng-container matColumnDef="scrollButtons"> - <td - mat-footer-cell - *matFooterCellDef - colspan="9" + <td + mat-footer-cell + *matFooterCellDef + colspan="9" class="buttons-wrap" ></td> </ng-container> - <tr - mat-header-row - *matHeaderRowDef="displayedColumns; sticky: true" + <tr + mat-header-row + *matHeaderRowDef="displayedColumns; sticky: true" class="header-row" ></tr> - <tr - [hidden]="!collapsedFilterRow" - mat-header-row + <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']" + <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" + <tr + [hidden]="!tableEl || !tableEl['offsetWidth'] || tableWrapper.offsetWidth - tableEl['offsetWidth'] > -16 || !allFilteredEnvironmentData?.length" + mat-footer-row + *matFooterRowDef="['scrollButtons']; sticky: true" class="info" ></tr> </table> 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 a122af1c6..d757eedac 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 @@ -142,7 +142,7 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView this.applyFilter(this.cashedFilterForm || this.filterForm); } this.progressBarService.stopProgressBar(); - }, + }, () => { this.progressBarService.stopProgressBar(); } @@ -186,8 +186,8 @@ 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; }); } }; @@ -196,30 +196,30 @@ 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 + 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) + const isStatus = config.statuses.length > 0 + ? (config.statuses.indexOf(item.status) !== -1) : (config.type !== 'active'); - const isShape = config.shapes.length > 0 + 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) + config.shapes.indexOf(`GPU count: ${item.gpu_count}`) !== -1) : true; - const isProject = config.projects.length > 0 - ? (config.projects.indexOf(item.project) !== -1) + 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) + 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) + 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.length > 0 && modifiedResources && modifiedResources.length > 0) { + item.resources = modifiedResources; } if (config.resources && config.resources.length === 0 && config.type === 'active' || @@ -288,7 +288,13 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView } }); - this.filterConfiguration = new ManagementConfigModel(users, '', projects, [...shapes, ...gpuTypes, ...gpuCounts], statuses, resources, endpoints); + this.filterConfiguration = new ManagementConfigModel( + users, + '', + projects, + [...shapes, ...gpuTypes, ...gpuCounts], + statuses, resources, endpoints + ); } public openNotebookDetails(data) { @@ -352,7 +358,10 @@ export class ManagementGridComponent implements OnInit, AfterViewInit, AfterView selector: 'confirm-dialog', template: ` <div class="dialog-header"> - <h4 class="modal-title"><span class="capitalize">{{ data.action }}</span> resource</h4> + <h4 class="modal-title"> + <span class="capitalize">{{ data.action }}</span> + <span *ngIf="data.action !== 'create image'"> resource</span> + </h4> <button type="button" class="close" (click)="dialogRef.close()">×</button> </div> <div mat-dialog-content class="content"> 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 d6c414c58..f7d3179d0 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 @@ -29,7 +29,7 @@ import { StorageService } from '../../core/services'; -import { ActionsType, EnvironmentModel, GeneralEnvironmentStatus, ModalData, ModalDataType } from './management.model'; +import {ActionsType, ActionTypeOptions, EnvironmentModel, GeneralEnvironmentStatus, ModalData, ModalDataType} from './management.model'; import { HTTP_STATUS_CODES } from '../../core/util'; import { BackupDilogComponent } from './backup-dilog/backup-dilog.component'; import { SsnMonitorComponent } from './ssn-monitor/ssn-monitor.component'; @@ -43,6 +43,7 @@ import { ConfirmationDialogComponent, ConfirmationDialogType } from '../../share import { ManagementGridComponent, ReconfirmationDialogComponent } from './management-grid/management-grid.component'; import { FolderTreeComponent } from '../../resources/bucket-browser/folder-tree/folder-tree.component'; import { StatusTypes } from '../../core/models'; +import {AmiCreateDialogComponent} from '../../resources/exploratory/ami-create-dialog'; @Component({ selector: 'environments-management', @@ -225,8 +226,7 @@ export class ManagementComponent implements OnInit { this.isActionsOpen = !this.isActionsOpen; } - toggleResourceAction($event): void { - const { environment, action, resource } = $event; + toggleResourceAction({ environment, action, resource = null}): void { this.openDialog(environment, action, resource); } @@ -239,7 +239,7 @@ export class ManagementComponent implements OnInit { } } - public resourceAction(action) { + public resourceAction(action: ActionTypeOptions) { this.toggleResourceAction({ environment: this.selected, action: action }); } @@ -265,7 +265,14 @@ export class ManagementComponent implements OnInit { observer.next = (res) => { if (res) { notebooks.forEach((env) => { - this.getNotebookAction(env, action); + if (action === 'create image') { + env['isAdmin'] = true; + env['userName'] = env.user; + this.dialog.open(AmiCreateDialogComponent, { data: env, panelClass: 'modal-sm' }) + .afterClosed().subscribe(); + } else { + this.getNotebookAction(env, action); + } }); } this.clearSelection(); @@ -306,7 +313,7 @@ export class ManagementComponent implements OnInit { return {...config, notebooks}; } - private getNotebookAction(env: EnvironmentModel, action: ActionsType) { + private getNotebookAction(env: EnvironmentModel, action: ActionsType): void { this.manageEnvironmentsService.environmentManagement(env.user, action, env.project, env.name) .subscribe( () => this.buildGrid(), 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 56ce00ff7..5e7435302 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 @@ -117,10 +117,10 @@ export class ManagementConfigModel { export interface ModalData { action: ActionsType; - resource_name?: any; - user?: any, + resource_name?: any; + user?: any; type: string; - notebooks?: any + notebooks?: any; } export enum ModalDataType { @@ -133,5 +133,8 @@ export enum ActionsType { terminate = 'terminate', start = 'start', run = 'run', - recreate = 'recreate' -} \ No newline at end of file + recreate = 'recreate', + createImage = 'create image' +} + +export type ActionTypeOptions = 'stop' | 'terminate' | 'start' | 'run' | 'recreate' | 'createAmi'; diff --git a/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-type-pipe/convert-action-type.pipe.ts b/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-type-pipe/convert-action-type.pipe.ts index e1459fcf3..1c47afc10 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-type-pipe/convert-action-type.pipe.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/pipes/convert-action-type-pipe/convert-action-type.pipe.ts @@ -22,27 +22,31 @@ import { ActionsType } from '../../../administration/management/management.model const actionTypes = { stopped: 'Stopped', - terminated: ' Terminated', - started: 'Started' -} + terminated: 'Terminated', + started: 'Starting', + creating: 'Creating Image', + unknown: 'Unknown type' +}; @Pipe({ name: 'convertactiontype' }) export class ConvertActionTypePipe implements PipeTransform { - transform(value: string,): string { - if(value === ActionsType.stop) { - return actionTypes.stopped + transform(value: string): string { + if (value === ActionsType.stop) { + return actionTypes.stopped; } - if(value === ActionsType.start) { - return actionTypes.started + if (value === ActionsType.start) { + return actionTypes.started; } - if(value === ActionsType.terminate) { - return actionTypes.terminated + if (value === ActionsType.terminate) { + return actionTypes.terminated; } - else { - return 'Unknown type' + if (value === ActionsType.createImage) { + return actionTypes.creating; + } else { + return actionTypes.unknown; } } } diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts index 3bb326d3e..13167f3eb 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts @@ -475,7 +475,7 @@ export class ApplicationServiceFacade { data, { observe: 'response', - headers: { 'Content-Type': 'text/plain' } + headers: { 'Content-Type': 'application/json; charset=UTF-8' } }); } @@ -805,4 +805,4 @@ export class ApplicationServiceFacade { return this.http.get(body ? (url + body) : url, opt); } } -} \ No newline at end of file +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html index ae576f2d9..a5befe290 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html @@ -45,19 +45,19 @@ </div> </form> <div class="text-center m-top-30 m-bott-10"> - <button - mat-raised-button - type="button" - class="butt action" + <button + mat-raised-button + type="button" + class="butt action" (click)="dialogRef.close()" > Cancel </button> - <button - mat-raised-button - type="button" + <button + mat-raised-button + type="button" [disabled]="!createAMIForm.valid" - (click)="assignChanges(createAMIForm.value)" + (click)="assignChanges(createAMIForm.value)" class="butt butt-success action" > Create diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts index 315f8f3c6..455468a28 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts @@ -22,7 +22,7 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { ToastrService } from 'ngx-toastr'; -import { UserResourceService } from '../../../core/services'; +import {ManageEnvironmentsService, UserResourceService} from '../../../core/services'; import { HTTP_STATUS_CODES, PATTERNS } from '../../../core/util'; import { DICTIONARY } from '../../../../dictionary/global.dictionary'; @@ -38,6 +38,7 @@ export class AmiCreateDialogComponent implements OnInit { public provider: string; delimitersRegex = /[-_]?/g; imagesList: any; + private isAdmin: boolean = false; constructor( @Inject(MAT_DIALOG_DATA) public data: any, @@ -45,28 +46,43 @@ export class AmiCreateDialogComponent implements OnInit { public dialogRef: MatDialogRef<AmiCreateDialogComponent>, private _userResource: UserResourceService, private _fb: FormBuilder, + private manageEnvironmentsService: ManageEnvironmentsService, ) { } ngOnInit() { this.notebook = this.data; this.provider = this.data.cloud_provider; + this.checkRole(); this.initFormModel(); this._userResource.getImagesList(this.data.project).subscribe(res => this.imagesList = res); } - public assignChanges(data) { - this._userResource.createAMI(data).subscribe( - response => response.status === HTTP_STATUS_CODES.ACCEPTED && this.dialogRef.close(true), - error => this.toastr.error(error.message || `Image creation failed!`, 'Oops!')); + public assignChanges(data): void { + if (this.isAdmin) { + const { exploratory_name, project_name, name, description } = data; + const imageInfo = { user: this.data.userName, imageName: name, description, project_name, exploratory_name}; + this.manageEnvironmentsService.environmentManagement(imageInfo, 'createImage', project_name, exploratory_name).subscribe( + () => { this.dialogRef.close(true); }); + } else { + this._userResource.createAMI(data).subscribe( + response => response.status === HTTP_STATUS_CODES.ACCEPTED && this.dialogRef.close(true), + error => this.toastr.error(error.message || `Image creation failed!`, 'Oops!')); + } + } + + private checkRole(): void { + if (this.data?.isAdmin) { + this.isAdmin = this.data.isAdmin; + } } private initFormModel(): void { this.createAMIForm = this._fb.group({ name: ['', [ - Validators.required, - Validators.pattern(PATTERNS.namePattern), - Validators.maxLength(10), + Validators.required, + Validators.pattern(PATTERNS.namePattern), + Validators.maxLength(10), this.checkDuplication.bind(this) ]], description: [''], --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
