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()">&times;</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]

Reply via email to