You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datalab.apache.org by dg...@apache.org on 2020/12/03 14:11:31 UTC
[incubator-datalab] branch develop updated: [DATALAB-2163]: Merge
odahu (UI part) to develop (#997)
This is an automated email from the ASF dual-hosted git repository.
dgnatyshyn pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
The following commit(s) were added to refs/heads/develop by this push:
new ce468db [DATALAB-2163]: Merge odahu (UI part) to develop (#997)
ce468db is described below
commit ce468db6024e19ea176035340cc3de72820db88b
Author: Dmytro Gnatyshyn <42...@users.noreply.github.com>
AuthorDate: Thu Dec 3 16:07:20 2020 +0200
[DATALAB-2163]: Merge odahu (UI part) to develop (#997)
[DATALAB-2163]: Merge odahu (UI part) to develop
---
.../app/administration/administration.module.ts | 5 +-
.../management-grid/management-grid.component.html | 2 +-
.../create-odahu-cluster.component.html | 93 +++++++++++++++++++
.../create-odahu-cluster.component.scss | 7 ++
.../create-odahu-cluster.component.ts | 103 +++++++++++++++++++++
.../create-odahu-claster/index.ts} | 27 ++++--
.../webapp/src/app/administration/odahu/index.ts | 50 ++++++++++
.../app/administration/odahu/odahu-data.service.ts | 27 ++++++
.../odahu/odahu-grid/odahu-grid.component.html | 94 +++++++++++++++++++
.../odahu/odahu-grid/odahu-grid.component.scss | 77 +++++++++++++++
.../odahu/odahu-grid/odahu-grid.component.ts | 48 ++++++++++
.../app/administration/odahu/odahu.component.html | 42 +++++++++
.../app/administration/odahu/odahu.component.scss} | 0
.../app/administration/odahu/odahu.component.ts | 59 ++++++++++++
.../resources/webapp/src/app/app.routing.module.ts | 8 +-
.../resources/webapp/src/app/core/core.module.ts | 3 +-
.../services/applicationServiceFacade.service.ts | 20 ++++
.../webapp/src/app/core/services/index.ts | 1 +
.../app/core/services/odahu-deployment.service.ts | 37 ++++++++
.../webapp/src/app/core/util/errorUtils.ts | 2 +-
.../detail-dialog/detail-dialog.component.html | 35 ++++++-
.../detail-dialog/detail-dialog.component.scss | 27 +++++-
.../detail-dialog/detail-dialog.component.ts | 10 +-
.../resources-grid/resources-grid.component.html | 30 +++++-
.../resources-grid/resources-grid.component.scss | 13 +++
.../resources-grid/resources-grid.component.ts | 23 ++++-
.../resources-grid/resources-grid.model.ts | 86 +++++++++++++++++
.../modal-dialog/odahu-action-dialog/index.ts | 15 +++
.../odahu-action-dialog.component.ts | 50 ++++++++++
.../src/app/shared/navbar/navbar.component.html | 5 +
30 files changed, 977 insertions(+), 22 deletions(-)
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts b/services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts
index e535bda..6d5b6d0 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts
@@ -23,10 +23,11 @@ import { CommonModule } from '@angular/common';
import { ManagenementModule } from './management';
import { ProjectModule } from './project';
import { RolesModule } from './roles';
+import {OdahuModule} from './odahu';
@NgModule({
- imports: [CommonModule, ManagenementModule, ProjectModule, RolesModule],
+ imports: [CommonModule, ManagenementModule, ProjectModule, RolesModule, OdahuModule],
declarations: [],
- exports: [ManagenementModule, ProjectModule, RolesModule]
+ exports: [ManagenementModule, ProjectModule, RolesModule, OdahuModule]
})
export class AdministrationModule { }
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 523cd59..4be7e7d 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
@@ -188,7 +188,7 @@
</th>
<td mat-cell *matCellDef="let element" class="settings actions-col">
<span [ngClass]="{'not-allow' : selected?.length}">
- <span #settings class="actions" (click)="actions.toggle($event, settings)" *ngIf="element.type !== 'edge node'"
+ <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' && element.status !== 'stopping' && element.status !== 'failed')
|| selected?.length || inProgress(element.resources)}">
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.html
new file mode 100644
index 0000000..836e630
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.html
@@ -0,0 +1,93 @@
+<div class="create-odahu-cluster" id="dialog-box">
+ <header class="dialog-header">
+ <h4 class="modal-title">Create Odahu cluster</h4>
+ <button type="button" class="close" (click)="dialogRef.close()">×</button>
+ </header>
+ <div class="dialog-content selection">
+ <div id="scrolling" class="content-box mat-reset scrolling-content">
+ <form [formGroup]="createOdahuForm" *ngIf="createOdahuForm" novalidate>
+ <div class="control-group">
+ <label class="label">Select project</label>
+ <div class="control selector-wrapper">
+ <mat-form-field>
+ <mat-label>Select project</mat-label>
+ <mat-select formControlName="project" panelClass="create-resources-dialog">
+ <mat-option *ngFor="let project of projects" [value]="project.name" (click)="setEndpoints(project)">
+ {{ project.name }}</mat-option>
+ <mat-option *ngIf="!projects.length" class="multiple-select ml-10" disabled>
+ No projects for creating Odahu clusters
+ </mat-option>
+ </mat-select>
+ <button class="caret">
+ <i class="material-icons">keyboard_arrow_down</i>
+ </button>
+ </mat-form-field>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="label">Select endpoint</label>
+ <div class="control selector-wrapper" [ngClass]="{ 'not-active' : !endpoints.length }">
+ <mat-form-field>
+ <mat-label>Select endpoint</mat-label>
+ <mat-select formControlName="endpoint" disableOptionCentering [disabled]="!endpoints.length"
+ panelClass="create-resources-dialog">
+ <mat-option *ngFor="let endpoint of endpoints" [value]="endpoint">
+ {{ endpoint }}
+ </mat-option>
+ <mat-option *ngIf="!endpoints.length" class="multiple-select ml-10" disabled>Endpoints list is empty</mat-option>
+ </mat-select>
+ <button class="caret">
+ <i class="material-icons">keyboard_arrow_down</i>
+ </button>
+ </mat-form-field>
+ </div>
+ </div>
+
+ <div class="control-group name-control">
+ <label class="label">Name</label>
+ <div class="control">
+ <input type="text" class="form-control" placeholder="Enter Name" formControlName="name">
+ <span class="error" *ngIf="!createOdahuForm.controls.name.valid && createOdahuForm.controls.name.dirty && !createOdahuForm.controls.name.hasError('duplication')">
+ Odahu cluster name can only contain letters and numbers
+ </span>
+ <span class="error" *ngIf="createOdahuForm.controls.name.hasError('duplication')">This Odahu cluster name already exists.</span>
+ </div>
+ </div>
+
+ <div class="control-group name-control">
+ <label class="label">Custom tag</label>
+ <div class="control">
+ <input type="text" class="form-control" placeholder="Enter custom tag" formControlName="custom_tag">
+ <span class="error"
+ *ngIf="!createOdahuForm.controls.custom_tag.valid && createOdahuForm.controls.custom_tag.dirty">
+ Custom tag can only contain letters, numbers, hyphens and '_' but can not end with special characters</span>
+ </div>
+ </div>
+
+<!-- <div class="control-group">-->
+<!-- <label class="label" [ngStyle]="!createLegionClusterForm.controls.useExistingClusterUrl.value && {'width': '100%' }">-->
+<!-- <input type="checkbox" formControlName="useExistingClusterUrl"/> Use existing k8s cluster-->
+<!-- </label>-->
+<!-- <div class="control" *ngIf="createLegionClusterForm.controls.useExistingClusterUrl.value">-->
+<!-- <input type="text" class="form-control"-->
+<!-- formControlName="existingClusterUrl" placeholder="Enter ODAHU k8s cluster URL"/>-->
+<!-- <span class="error url-error">-->
+<!-- <span *ngIf="!createLegionClusterForm.controls.existingClusterUrl.valid">Please enter valid cluster URL</span>-->
+<!-- </span>-->
+<!-- </div>-->
+<!-- </div>-->
+
+ <div class="text-center m-top-30">
+ <button mat-raised-button type="button" class="butt action" (click)="dialogRef.close()">Cancel</button>
+ <button mat-raised-button type="button" class="butt butt-success action"
+ [disabled]="!createOdahuForm.valid" (click)="createOdahuCluster(createOdahuForm.value)">
+ Create
+ </button>
+ </div>
+
+ </form>
+ </div>
+ </div>
+</div>
+
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.scss
new file mode 100644
index 0000000..51dcf57
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.scss
@@ -0,0 +1,7 @@
+.create-odahu-cluster{
+ .error{
+ position: absolute;
+ left: 0;
+ top: 36px;
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.ts
new file mode 100644
index 0000000..20e84b4
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/create-odahu-cluster.component.ts
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Component, OnInit, Inject } from '@angular/core';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { ToastrService } from 'ngx-toastr';
+
+import { Project } from '../../project/project.component';
+import { ProjectService, OdahuDeploymentService } from '../../../core/services';
+
+import { DICTIONARY } from '../../../../dictionary/global.dictionary';
+import {CheckUtils, PATTERNS} from '../../../core/util';
+
+
+@Component({
+ selector: 'create-odahu-cluster',
+ templateUrl: 'create-odahu-cluster.component.html',
+ styleUrls: ['./create-odahu-cluster.component.scss']
+})
+
+export class CreateOdahuClusterComponent implements OnInit {
+ readonly DICTIONARY = DICTIONARY;
+ public createOdahuForm: FormGroup;
+
+ projects: Project[] = [];
+ endpoints: Array<String> = [];
+
+ constructor(
+ @Inject(MAT_DIALOG_DATA) public data: any,
+ public toastr: ToastrService,
+ public dialogRef: MatDialogRef<CreateOdahuClusterComponent>,
+ private _fb: FormBuilder,
+ private projectService: ProjectService,
+ private odahuDeploymentService: OdahuDeploymentService,
+ ) {
+ }
+
+ ngOnInit() {
+ this.getUserProjects();
+ this.initFormModel();
+ }
+
+ public getUserProjects(): void {
+ this.projectService.getUserProjectsList(true).subscribe((projects: any) => {
+ this.projects = projects.filter(project => {
+ return project.endpoints.length > project.odahu.filter(od => od.status !== 'FAILED' && od.status !== 'TERMINATED').length; }
+ );
+ });
+ }
+
+ public setEndpoints(project): void {
+ this.endpoints = project.endpoints
+ .filter(e => e.status === 'RUNNING' && !this.data.some(odahu => odahu.status !== 'FAILED'
+ && odahu.status !== 'TERMINATED'
+ && odahu.endpoint === e.name
+ && odahu.project === project.name)
+ )
+ .map(e => e.name);
+ }
+
+ private initFormModel(): void {
+ this.createOdahuForm = this._fb.group({
+ name: ['', [Validators.required, Validators.pattern(PATTERNS.namePattern), this.checkDuplication.bind(this)]],
+ project: ['', Validators.required],
+ endpoint: ['', [Validators.required]],
+ custom_tag: ['', [Validators.pattern(PATTERNS.namePattern)]]
+ });
+ }
+
+ private createOdahuCluster(value): void {
+ this.dialogRef.close();
+ this.odahuDeploymentService.createOdahuNewCluster(value).subscribe(() => {
+ this.toastr.success('Odahu cluster creation is processing!', 'Success!');
+ }, error => this.toastr.error(error.message || 'Odahu cluster creation failed!', 'Oops!')
+ );
+ }
+
+ private checkDuplication(control) {
+ if (control && control.value) {
+ for (let index = 0; index < this.data.length; index++) {
+ if (CheckUtils.delimitersFiltering(control.value) === CheckUtils.delimitersFiltering(this.data[index].name))
+ return { duplication: true };
+ }
+ }
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/index.ts
similarity index 54%
copy from services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts
copy to services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/index.ts
index e535bda..bd465fa 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/administration.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/create-odahu-claster/index.ts
@@ -19,14 +19,27 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { ManagenementModule } from './management';
-import { ProjectModule } from './project';
-import { RolesModule } from './roles';
+import { MaterialModule } from '../../../shared/material.module';
+import { FormControlsModule } from '../../../shared/form-controls';
+import { KeysPipeModule, UnderscorelessPipeModule } from '../../../core/pipes';
+import {CreateOdahuClusterComponent} from './create-odahu-cluster.component';
+
+export * from './create-odahu-cluster.component';
@NgModule({
- imports: [CommonModule, ManagenementModule, ProjectModule, RolesModule],
- declarations: [],
- exports: [ManagenementModule, ProjectModule, RolesModule]
+ imports: [
+ CommonModule,
+ FormsModule,
+ ReactiveFormsModule,
+ FormControlsModule,
+ MaterialModule,
+ KeysPipeModule,
+ UnderscorelessPipeModule,
+ ],
+ declarations: [CreateOdahuClusterComponent],
+ entryComponents: [CreateOdahuClusterComponent],
+ exports: [CreateOdahuClusterComponent]
})
-export class AdministrationModule { }
+export class CreateOdahuClusterModule { }
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/index.ts b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/index.ts
new file mode 100644
index 0000000..1564326
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/index.ts
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+
+import { MaterialModule } from '../../shared/material.module';
+import { FormControlsModule } from '../../shared/form-controls';
+import { UnderscorelessPipeModule } from '../../core/pipes/underscoreless-pipe';
+
+import {BubbleModule} from '../../shared/bubble';
+import {OdahuComponent} from './odahu.component';
+import {OdahuDataService} from './odahu-data.service';
+import {OdahuGridComponent} from './odahu-grid/odahu-grid.component';
+import {CreateOdahuClusterModule} from './create-odahu-claster';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ ReactiveFormsModule,
+ MaterialModule,
+ FormControlsModule,
+ UnderscorelessPipeModule,
+ BubbleModule,
+ CreateOdahuClusterModule
+ ],
+ declarations: [OdahuComponent, OdahuGridComponent],
+ entryComponents: [],
+ providers: [OdahuDataService],
+ exports: [OdahuComponent]
+})
+export class OdahuModule { }
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-data.service.ts b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-data.service.ts
new file mode 100644
index 0000000..d8a30a6
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-data.service.ts
@@ -0,0 +1,27 @@
+import { Injectable } from '@angular/core';
+import {BehaviorSubject, Observable} from 'rxjs';
+import {OdahuDeploymentService} from '../../core/services';
+
+
+@Injectable({
+ providedIn: 'root'
+})
+
+export class OdahuDataService {
+ _odahuClasters = new BehaviorSubject<any>(null);
+
+ constructor(private odahuDeploymentService: OdahuDeploymentService) {
+ this.getClastersList();
+ }
+
+ public updateClasters(): void {
+ this.getClastersList();
+ }
+
+ private getClastersList(): void {
+ this.odahuDeploymentService.getOduhuClustersList().subscribe(
+ (response: any ) => {
+ return this._odahuClasters.next(response);
+ });
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.html
new file mode 100644
index 0000000..73d7952
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.html
@@ -0,0 +1,94 @@
+
+<table mat-table [dataSource]="dataSource" class="odahu-clasters-table mat-elevation-z6 selection">
+ <ng-container matColumnDef="project">
+ <th mat-header-cell *matHeaderCellDef class="project"> Project name </th>
+ <td mat-cell *matCellDef="let element" class="project">
+ <span *ngIf="element && element.project">{{element.project}}</span>
+ </td>
+ <td mat-footer-cell *matFooterCellDef></td>
+ </ng-container>
+
+ <ng-container matColumnDef="endpoint-url">
+ <th mat-header-cell *matHeaderCellDef class="endpoint"> Endpoint </th>
+ <td mat-cell *matCellDef="let element" class="endpoint">
+ <span *ngIf="element && element.endpoint" matTooltip="{{element.endpoint}}" [matTooltipPosition]="'above'">
+ {{element.endpoint}}
+ </span>
+ </td>
+ <td mat-footer-cell *matFooterCellDef></td>
+ </ng-container>
+
+ <ng-container matColumnDef="odahu-name">
+ <th mat-header-cell *matHeaderCellDef class="odahu-name"> Odahu cluster name </th>
+ <td mat-cell *matCellDef="let element" class="odahu-name">
+ <span *ngIf="element && element.name">{{element.name}}</span>
+ </td>
+ <td mat-footer-cell *matFooterCellDef></td>
+ </ng-container>
+
+ <ng-container matColumnDef="odahu-status">
+ <th mat-header-cell *matHeaderCellDef class="odahu-status"> Odahu cluster status </th>
+ <td mat-cell *matCellDef="let element" class="odahu-status">
+ <span *ngIf="element && element.name" [ngClass]="element.status.toLowerCase()">{{ element.status | titlecase}}</span>
+ </td>
+ <td mat-footer-cell *matFooterCellDef></td>
+ </ng-container>
+
+ <ng-container matColumnDef="actions">
+ <th mat-header-cell *matHeaderCellDef class="odahu-actions"></th>
+ <td mat-cell *matCellDef="let element" class="settings">
+ <span *ngIf="element && element.name" #settings (click)="actions.toggle($event, settings)" class="actions" [ngClass]="{'disabled': element.status !== 'RUNNING' && element.status !== 'STOPPED'}"></span>
+ <bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left">
+ <ul class="list-unstyled">
+ <div class="active-items"></div>
+ <li class="project-seting-item" *ngIf="element.status === 'STOPPED'" (click)="odahuAction(element, 'start')">
+ <i class="material-icons">play_circle_outline</i>
+ <a class="action">
+ Start
+ </a>
+ </li>
+ <li class="project-seting-item" *ngIf="element.status === 'RUNNING'" (click)="odahuAction(element, 'stop')">
+ <i class="material-icons">pause_circle_outline</i>
+ <a class="action" >
+ Stop
+ </a>
+ </li>
+ <li class="project-seting-item" [ngClass]="{'disabled' : element.status === 'STOPPED'}" *ngIf="element.status !== 'TERMINATED' && element.status !== 'TERMINATING'" (click)="odahuAction(element, 'terminate')">
+ <i class="material-icons">phonelink_off</i>
+ <a class="action">
+ Terminate
+ </a>
+ </li>
+ <!--<li class="project-seting-item">-->
+ <!--<i class="material-icons">arrow_downward</i>-->
+ <!--<a>-->
+ <!--Scale-down-->
+ <!--</a>-->
+ <!--</li>-->
+ <!--<li class="project-seting-item">-->
+ <!--<i class="material-icons">arrow_upward</i>-->
+ <!--<a class="action">-->
+ <!--Scale-up-->
+ <!--</a>-->
+ <!--</li>-->
+ </ul>
+ </bubble-up>
+ </td>
+ <td mat-footer-cell *matFooterCellDef></td>
+ </ng-container>
+
+ <ng-container matColumnDef="placeholder">
+ <td mat-footer-cell *matFooterCellDef
+ [colSpan]="displayedColumns.length"
+ class="info">
+ <span>No Odahu clusters</span>
+ </td>
+ <td mat-footer-cell *matFooterCellDef></td>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+ <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+ <tr [hidden]="odahuList && odahuList.length" mat-footer-row *matFooterRowDef="['placeholder']"></tr>
+</table>
+
+
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.scss
new file mode 100644
index 0000000..62e6200
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.scss
@@ -0,0 +1,77 @@
+.odahu-clasters-table {
+ width: 100%;
+
+ .project, .endpoint, .odahu-name, .odahu-status{
+ width: 23%;
+ }
+
+ td.settings {
+ position: relative;
+ vertical-align: middle !important;
+ text-align: right;
+ }
+
+ .list-menu {
+ min-width: 190px;
+ }
+
+ .material-icons {
+ font-size: 18px;
+ padding-top: 1px;
+ }
+
+ td.settings .actions {
+ background-image: url(../../../../assets/svg/settings_icon.svg);
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ text-align: center;
+ cursor: pointer;
+ &.disabled {
+ opacity: 0.4;
+ cursor: not-allowed;
+ pointer-events: none;
+ }
+ }
+
+ td {
+ &.info.mat-footer-cell{
+ text-align: center;
+ padding: 40px;
+ }
+ .settings {
+ position: relative;
+ vertical-align: middle !important;
+ text-align: right;
+
+ .actions {
+ background-image: url(../../../../assets/svg/settings_icon.svg);
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ text-align: center;
+ cursor: pointer;
+ }
+ }
+
+ .project-seting-item {
+ display: flex;
+ padding: 10px;
+ align-items: center;
+ border-bottom: 1px solid #edf1f5;
+ cursor: pointer;
+ color: #577289;
+
+ &:hover {
+ color: #36afd5;
+ transition: all .45s ease-in-out;
+ }
+
+ a {
+ padding-left: 5px;
+ }
+ }
+ }
+}
+
+
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.ts
new file mode 100644
index 0000000..817d12b
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu-grid/odahu-grid.component.ts
@@ -0,0 +1,48 @@
+import { Component, OnInit } from '@angular/core';
+import {Subscription} from 'rxjs';
+import {OdahuDataService} from '../odahu-data.service';
+import { MatTableDataSource } from '@angular/material/table';
+import {OdahuDeploymentService} from '../../../core/services';
+import {ToastrService} from 'ngx-toastr';
+import {MatDialog} from '@angular/material/dialog';
+import {OdahuActionDialogComponent} from '../../../shared/modal-dialog/odahu-action-dialog';
+
+@Component({
+ selector: 'odahu-grid',
+ templateUrl: './odahu-grid.component.html',
+ styleUrls: ['./odahu-grid.component.scss']
+})
+export class OdahuGridComponent implements OnInit {
+ private odahuList: any[];
+ private subscriptions: Subscription = new Subscription();
+ public dataSource: MatTableDataSource<any>;
+ displayedColumns: string[] = [ 'odahu-name', 'project', 'endpoint-url', 'odahu-status', 'actions'];
+
+ constructor(
+ private odahuDataService: OdahuDataService,
+ private odahuDeploymentService: OdahuDeploymentService,
+ public toastr: ToastrService,
+ public dialog: MatDialog
+ ) { }
+
+ ngOnInit() {
+ this.subscriptions.add(this.odahuDataService._odahuClasters.subscribe(
+ (value) => {
+ if (value) {
+ this.odahuList = value;
+ this.dataSource = new MatTableDataSource(value);
+ }
+ }));
+ }
+
+ private odahuAction(element: any, action: string) {
+ this.dialog.open(OdahuActionDialogComponent, {data: {type: action, item: element}, panelClass: 'modal-sm'})
+ .afterClosed().subscribe(result => {
+ result && this.odahuDeploymentService.odahuAction(element, action).subscribe(v =>
+ this.odahuDataService.updateClasters(),
+ error => this.toastr.error(`Odahu cluster ${action} failed!`, 'Oops!')
+ ) ;
+ }, error => this.toastr.error(error.message || `Odahu cluster ${action} failed!`, 'Oops!')
+ );
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.html
new file mode 100644
index 0000000..a59a5d5
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.html
@@ -0,0 +1,42 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+
+<div class="base-retreat">
+ <div class="sub-nav">
+ <div>
+ <button mat-raised-button class="butt butt-create" (click)="createOdahuCluster()">
+ <i class="material-icons">add</i>Create new
+ </button>
+ </div>
+ <div>
+ <button mat-raised-button class="butt" (click)="refreshGrid()">
+ <i class="material-icons">autorenew</i>Refresh
+ </button>
+ </div>
+ </div>
+
+ <mat-divider></mat-divider>
+
+ <div>
+ <odahu-grid>
+ </odahu-grid>
+ </div>
+</div>
+
diff --git a/services/self-service/src/test/java/com/epam/datalab/backendapi/.gitkeep b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.scss
similarity index 100%
rename from services/self-service/src/test/java/com/epam/datalab/backendapi/.gitkeep
rename to services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.scss
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.ts
new file mode 100644
index 0000000..642b311
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/odahu/odahu.component.ts
@@ -0,0 +1,59 @@
+import { Component, OnInit } from '@angular/core';
+import {OdahuDataService} from './odahu-data.service';
+import {Subscription} from 'rxjs';
+import {MatDialog} from '@angular/material/dialog';
+import {ToastrService} from 'ngx-toastr';
+import {CreateOdahuClusterComponent} from './create-odahu-claster/create-odahu-cluster.component';
+import {HealthStatusService, OdahuDeploymentService} from '../../core/services';
+
+export interface OdahuCluster {
+ name: string;
+ project: string;
+ endpoint: string;
+}
+
+@Component({
+ selector: 'datalab-odahu',
+ templateUrl: './odahu.component.html',
+ styleUrls: ['./odahu.component.scss']
+})
+export class OdahuComponent implements OnInit {
+
+ private odahuList: any[];
+ private subscriptions: Subscription = new Subscription();
+ private healthStatus;
+
+ constructor(
+ private odahuDataService: OdahuDataService,
+ private dialog: MatDialog,
+ public toastr: ToastrService,
+ public odahuDeploymentService: OdahuDeploymentService,
+ private healthStatusService: HealthStatusService,
+ ) { }
+
+ ngOnInit() {
+ this.getEnvironmentHealthStatus();
+ this.subscriptions.add(this.odahuDataService._odahuClasters.subscribe(
+ (value) => {
+ if (value) this.odahuList = value;
+ }));
+ this.refreshGrid();
+ }
+
+ public createOdahuCluster(): void {
+ this.dialog.open(CreateOdahuClusterComponent, { data: this.odahuList, panelClass: 'modal-lg' })
+ .afterClosed().subscribe((result) => {
+ result && this.getEnvironmentHealthStatus();
+ this.refreshGrid();
+ });
+ }
+
+ private getEnvironmentHealthStatus(): void {
+ this.healthStatusService.getEnvironmentHealthStatus()
+ .subscribe((result: any) => this.healthStatus = result);
+ }
+
+ public refreshGrid(): void {
+ this.odahuDataService.updateClasters();
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
index 35c9df7..461c5f7 100644
--- a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
@@ -34,6 +34,7 @@ import { RolesComponent } from './administration/roles/roles.component';
import { SwaggerComponent } from './swagger/swagger.component';
import { AuthorizationGuard, CheckParamsGuard, CloudProviderGuard, AdminGuard, AuditGuard } from './core/services';
import {AuditComponent} from './reports/audit/audit.component';
+import {OdahuComponent} from './administration/odahu/odahu.component';
const routes: Routes = [{
path: 'login',
@@ -59,7 +60,12 @@ const routes: Routes = [{
path: 'projects',
component: ProjectComponent,
canActivate: [AuthorizationGuard, AdminGuard],
- }, {
+ },
+ {
+ // path: 'odahu',
+ // component: OdahuComponent,
+ // canActivate: [AuthorizationGuard, AdminGuard],
+ // }, {
path: 'roles',
component: RolesComponent,
canActivate: [AuthorizationGuard, AdminGuard],
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/core.module.ts b/services/self-service/src/main/resources/webapp/src/app/core/core.module.ts
index 4b1c0f9..ae6221a 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/core.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/core.module.ts
@@ -48,7 +48,7 @@ import { NoCacheInterceptor } from './interceptors/nocache.interceptor';
import { ErrorInterceptor } from './interceptors/error.interceptor';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
-import {AuditGuard} from './services';
+import {AuditGuard, OdahuDeploymentService} from './services';
@NgModule({
imports: [CommonModule],
@@ -85,6 +85,7 @@ export class CoreModule {
ProjectService,
EndpointService,
UserAccessKeyService,
+ OdahuDeploymentService,
{ provide: MatDialogRef, useValue: {} },
{ provide: MAT_DIALOG_DATA, useValue: [] },
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 30882f1..97bbfd4 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
@@ -75,6 +75,7 @@ export class ApplicationServiceFacade {
private static readonly DOWNLOAD_REPORT = 'download_report';
private static readonly SETTINGS = 'settings';
private static readonly PROJECT = 'project';
+ private static readonly ODAHU = 'odahu';
private static readonly ENDPOINT = 'endpoint';
private static readonly ENDPOINT_CONNECTION = 'endpoint_connection';
private static readonly AUDIT = 'audit';
@@ -654,6 +655,24 @@ export class ApplicationServiceFacade {
data);
}
+ public createOdahuCluster(data): Observable<any> {
+ return this.buildRequest(HTTPMethod.POST,
+ this.requestRegistry.Item(ApplicationServiceFacade.ODAHU),
+ data);
+ }
+
+ public getOdahuList(): Observable<any> {
+ return this.buildRequest(HTTPMethod.GET,
+ this.requestRegistry.Item(ApplicationServiceFacade.ODAHU),
+ null);
+ }
+
+ public odahuStartStop(data, params): Observable<any> {
+ return this.buildRequest(HTTPMethod.POST,
+ this.requestRegistry.Item(ApplicationServiceFacade.ODAHU) + `/${params}`,
+ data);
+ }
+
private setupRegistry(): void {
this.requestRegistry = new Dictionary<string>();
@@ -759,4 +778,5 @@ export class ApplicationServiceFacade {
return this.http.get(body ? (url + body) : url, opt);
}
}
+
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/index.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/index.ts
index 2005741..4e9a898 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/services/index.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/index.ts
@@ -39,3 +39,4 @@ export * from './dataengineConfiguration.service';
export * from './storage.service';
export * from './project.service';
export * from './endpoint.service';
+export * from './odahu-deployment.service';
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/odahu-deployment.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/odahu-deployment.service.ts
new file mode 100644
index 0000000..f6fe528
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/odahu-deployment.service.ts
@@ -0,0 +1,37 @@
+import { Injectable } from '@angular/core';
+import {Observable} from 'rxjs';
+import { map, catchError } from 'rxjs/operators';
+import { ApplicationServiceFacade } from './applicationServiceFacade.service';
+import { ErrorUtils } from '../util';
+
+@Injectable({
+ providedIn: 'root'
+})
+
+export class OdahuDeploymentService {
+ constructor(private applicationServiceFacade: ApplicationServiceFacade) { }
+
+ public createOdahuNewCluster(data): Observable<{}> {
+ return this.applicationServiceFacade
+ .createOdahuCluster(data)
+ .pipe(
+ map(response => response),
+ catchError(ErrorUtils.handleServiceError));
+ }
+
+ public getOduhuClustersList(): Observable<{}> {
+ return this.applicationServiceFacade
+ .getOdahuList()
+ .pipe(
+ map(response => response),
+ catchError(ErrorUtils.handleServiceError));
+ }
+
+ public odahuAction(data, action) {
+ return this.applicationServiceFacade
+ .odahuStartStop(data, action)
+ .pipe(
+ map(response => response),
+ catchError(ErrorUtils.handleServiceError));
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/util/errorUtils.ts b/services/self-service/src/main/resources/webapp/src/app/core/util/errorUtils.ts
index c3c9179..5d25db2 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/util/errorUtils.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/util/errorUtils.ts
@@ -20,6 +20,7 @@
import { throwError as observableThrowError } from 'rxjs';
import { CheckUtils } from './checkUtils';
+import {logger} from 'codelyzer/util/logger';
export class ErrorUtils {
@@ -41,7 +42,6 @@ export class ErrorUtils {
public static handleServiceError(errorMessage) {
const error = CheckUtils.isJSON(errorMessage.error) ? JSON.parse(errorMessage.error) : errorMessage.error;
-
return observableThrowError({
status: error.code,
statusText: errorMessage.statusText,
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html
index d73dae3..5d297e6 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html
@@ -23,7 +23,20 @@
<button type="button" class="close" (click)="dialogRef.close()">×</button>
</header>
<div class="dialog-content">
- <div *ngIf="data ">
+ <div *ngIf="data.legion">
+ <table class="detail-header">
+ <tr>
+ <td>{{odahu.name}}</td>
+ <td>
+ <span class="status" ngClass="{{odahu.status || ''}}">
+ {{odahu.status}}
+ </span>
+ </td>
+ <td>{{odahu.shape}}</td>
+ </tr>
+ </table>
+ </div>
+ <div *ngIf="data.notebook">
<table class="detail-header">
<tr>
<td>{{notebook.template_name || notebook.name}}</td>
@@ -258,5 +271,25 @@
</div>
</div>
+ <div class="legion-info" *ngIf="data.odahu">
+ <div class="content-box">
+ <div class="detail-info" *ngIf="!odahu.error_message">
+ <div class="links_block">
+ <div *ngFor="let url of odahu.url" class="odahu-links">
+ <div class="odahu-link">
+ <span class="description">{{url.description }}: </span>
+ <a class="ellipsis" matTooltip="{{ url.url}}" matTooltipPosition="above" href="{{ url.url}}"
+ target="_blank">{{ url.url}}
+ </a>
+ </div>
+ <div class="grafana" *ngIf="url.description === 'Grafana'">
+ <div><span>Gafana user: </span><span class="creds">{{odahu.bucket_name}}</span></div>
+ <div><span>Gafana password: </span><span class="creds">{{odahu.shared_bucket_name}}</span></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.scss
index e91c04b..fed1aa5 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.scss
@@ -27,8 +27,31 @@
.links_block {
- >p {
- display: flex;
+ .odahu-links:not(:last-child){
+ margin-bottom: 20px;
+ }
+
+ .grafana{
+ white-space: nowrap;
+ padding-left: 30px;
+ color: $blue-grey-color;
+
+ div{
+ display: flex;
+
+ span{
+ font-size: 13px;
+ font-weight: 500;
+
+ &.creds{
+ font-weight: 600;
+ }
+ }
+ }
+ }
+
+ >p, .odahu-link {
+ display: flex;
.description {
white-space: nowrap;
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts
index dfda98c..cd1b574 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts
@@ -47,7 +47,7 @@ export class DetailDialogComponent implements OnInit {
bucketStatus: object = {};
isBucketAllowed = true;
isCopyIconVissible: {bucket} = {bucket: false};
-
+ public odahu: any;
public configurationForm: FormGroup;
@ViewChild('configurationNode') configuration;
@@ -61,7 +61,15 @@ export class DetailDialogComponent implements OnInit {
public toastr: ToastrService,
public auditService: AuditService
) {
+ if (data.notebook) {
+ this.notebook = data.notebook;
+ this.PROVIDER = this.data.notebook.cloud_provider;
+ }
+ if (data.odahu) {
+ this.odahu = data.odahu;
+ this.PROVIDER = this.data.odahu.cloud_provider || 'azure';
+ }
}
ngOnInit() {
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 981d56e..2124f24 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
@@ -115,8 +115,9 @@
<!-- [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'" -->
<tr *ngFor="let element of element.exploratory; let i = index" class="element-row mat-row">
- <td class="name-col highlight" (click)="printDetailEnvironmentModal(element)">
- <span matTooltip="{{ element.name }}" matTooltipPosition="above">{{ element.name }}</span>
+ <td class="name-col">
+ <span *ngIf="element.shape !== 'odahu cluster'" matTooltip="{{ element.name }}" matTooltipPosition="above" (click)="printDetailEnvironmentModal(element)">{{ element.name }}</span>
+ <span *ngIf="element.shape === 'odahu cluster'" matTooltip="{{ element.name }}" matTooltipPosition="above" (click)="printDetailOdahuModal(element)">{{ element.name }}</span>
</td>
<td class="status-col status" ngClass="{{ element.status.toLowerCase() || ''}}">
{{element.status | underscoreless }}
@@ -162,7 +163,7 @@
</span>
<bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left">
- <ul class="list-unstyled">
+ <ul class="list-unstyled" *ngIf="element.shape !== 'odahu cluster'">
<div class="active-items" *ngIf="element.status.toLowerCase() !== 'failed'
&& element.status !== 'terminating'
&& element.status !== 'terminated'
@@ -248,6 +249,29 @@
</div>
</li>
</ul>
+ <ul class="list-unstyled" *ngIf="element.shape === 'odahu cluster'">
+ <li class="project-seting-item" *ngIf="element.status === 'stopped'" (click)="odahuAction(element, 'start')">
+ <i class="material-icons">play_circle_outline</i>
+ <a class="action">
+ Start
+ </a>
+ </li>
+ <li class="project-seting-item" *ngIf="element.status === 'running'" (click)="odahuAction(element, 'stop')">
+ <i class="material-icons">pause_circle_outline</i>
+ <a class="action" >
+ Stop
+ </a>
+ </li>
+ <li class="project-seting-item"
+ [ngClass]="{'disabled': element.status === 'stopped' || element.status.toLowerCase() === 'stopping' || element.status.toLowerCase() === 'starting'}"
+ *ngIf="element.status === element.status !== 'terminated' && element.status !== 'terminating'" (click)="odahuAction(element, 'terminate')"
+ >
+ <i class="material-icons">phonelink_off</i>
+ <a class="action">
+ Terminate
+ </a>
+ </li>
+ </ul>
</bubble-up>
</td>
</tr>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss
index 03df6ff..6ef7e50 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.scss
@@ -441,3 +441,16 @@ table.resources {
+.info {
+ padding: 40px;
+ text-align: center;
+}
+
+.odahu-icon{
+ vertical-align: middle;
+ margin-left: 10px;
+}
+
+.content-row{
+ background-clip: padding-box;
+}
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 7bae81b..cdb4407 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
@@ -22,7 +22,7 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { ToastrService } from 'ngx-toastr';
import { MatDialog } from '@angular/material/dialog';
-import {ProjectService, UserResourceService} from '../../core/services';
+import {ProjectService, UserResourceService, OdahuDeploymentService} from '../../core/services';
import { ExploratoryModel, Exploratory } from './resources-grid.model';
import { FilterConfigurationModel } from './filter-configuration.model';
import { GeneralEnvironmentStatus } from '../../administration/management/management.model';
@@ -37,6 +37,7 @@ import { ConfirmationDialogComponent } from '../../shared/modal-dialog/confirmat
import { SchedulerComponent } from '../scheduler';
import { DICTIONARY } from '../../../dictionary/global.dictionary';
import {ProgressBarService} from '../../core/services/progress-bar.service';
+import {OdahuActionDialogComponent} from '../../shared/modal-dialog/odahu-action-dialog';
import {ComputationModel} from '../computational/computational-resource.model';
import {NotebookModel} from '../exploratory/notebook.model';
import {AuditService} from '../../core/services/audit.service';
@@ -132,6 +133,7 @@ export class ResourcesGridComponent implements OnInit {
private progressBarService: ProgressBarService,
private projectService: ProjectService,
private auditService: AuditService,
+ private odahuDeploymentService: OdahuDeploymentService,
) { }
ngOnInit(): void {
@@ -227,6 +229,11 @@ export class ResourcesGridComponent implements OnInit {
.afterClosed().subscribe(() => this.buildGrid());
}
+ public printDetailOdahuModal(data): void {
+ this.dialog.open(DetailDialogComponent, { data: {odahu: 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());
@@ -247,7 +254,8 @@ export class ResourcesGridComponent implements OnInit {
error => this.toastr.error(error.message || 'Exploratory starting failed!', 'Oops!'));
} else if (action === 'stop') {
const compute = data.resources.filter(cluster => cluster.status === 'running');
- this.dialog.open(ConfirmationDialogComponent, { data: { notebook: data, compute, type: ConfirmationDialogType.StopExploratory }, panelClass: 'modal-sm' })
+ this.dialog.open(ConfirmationDialogComponent,
+ { data: { notebook: data, compute, type: ConfirmationDialogType.StopExploratory }, panelClass: 'modal-sm' })
.afterClosed().subscribe((res) => {
res && this.buildGrid();
});
@@ -445,6 +453,17 @@ export class ResourcesGridComponent implements OnInit {
(error) => console.log('UPDATE USER PREFERENCES ERROR ', error));
}
+ private odahuAction(element: any, action: string) {
+ this.dialog.open(OdahuActionDialogComponent, {data: {type: action, item: element}, panelClass: 'modal-sm'})
+ .afterClosed().subscribe(result => {
+ result && this.odahuDeploymentService.odahuAction(element, action).subscribe(v =>
+ this.buildGrid(),
+ error => this.toastr.error(`Odahu cluster ${action} failed!`, 'Oops!')
+ ) ;
+ }, error => this.toastr.error(error.message || `Odahu cluster ${action} failed!`, 'Oops!')
+ );
+ }
+
public logAction(name) {
this.auditService.sendDataToAudit({
resource_name: name, info: `Open terminal, requested for notebook`, type: 'WEB_TERMINAL'
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts
index e1b1360..1465199 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts
@@ -56,6 +56,92 @@ export class ExploratoryModel {
public static loadEnvironments(data: Array<any>) {
if (data) {
+
+
+ // return data.map((value) => {
+ // const exploratory = value.exploratory.map(el => {
+ // let provider;
+ // if (el.cloud_provider) {
+ // provider = el.cloud_provider.toLowerCase();
+ // }
+ // return new ExploratoryModel(
+ // provider,
+ // el.exploratory_name,
+ // el.template_name,
+ // el.image,
+ // el.status,
+ // el.shape,
+ // el.computational_resources,
+ // el.up_time,
+ // el.exploratory_url,
+ // value.shared[el.endpoint].edge_node_ip,
+ // el.private_ip,
+ // el.exploratory_user,
+ // el.exploratory_pass,
+ // value.shared[el.endpoint][DICTIONARY[provider].bucket_name],
+ // value.shared[el.endpoint][DICTIONARY[provider].shared_bucket_name],
+ // el.error_message,
+ // el[DICTIONARY[provider].billing.cost],
+ // el[DICTIONARY[provider].billing.currencyCode],
+ // el.billing,
+ // el.libs,
+ // value.shared[el.endpoint][DICTIONARY[provider].user_storage_account_name],
+ // value.shared[el.endpoint][DICTIONARY[provider].shared_storage_account_name],
+ // value.shared[el.endpoint][DICTIONARY[provider].datalake_name],
+ // value.shared[el.endpoint][DICTIONARY[provider].datalake_user_directory_name],
+ // value.shared[el.endpoint][DICTIONARY[provider].datalake_shared_directory_name],
+ // el.project,
+ // el.endpoint,
+ // el.tags
+ // );
+ // });
+ //
+ // const odahu = value.odahu.map(el => {
+ // let provider;
+ // if (el.cloud_provider) {
+ // provider = el.cloud_provider.toLowerCase();
+ // } else {
+ // provider = 'azure';
+ // }
+ // return new ExploratoryModel(
+ // provider,
+ // el.name,
+ // el.template_name,
+ // el.image,
+ // el.status.toLowerCase(),
+ // 'odahu cluster',
+ // [],
+ // el.up_time,
+ // el.urls,
+ // value.shared[el.endpoint].edge_node_ip,
+ // el.private_ip,
+ // el.exploratory_user,
+ // el.exploratory_pass,
+ // el.grafana_admin,
+ // el.grafana_pass,
+ // el.error_message,
+ // el[DICTIONARY[provider].billing.cost],
+ // el[DICTIONARY[provider].billing.currencyCode],
+ // [],
+ // [],
+ // '',
+ // '',
+ // '',
+ // '',
+ // '',
+ // el.project,
+ // el.endpoint,
+ // el.tags
+ // )});
+ // return {
+ // project: value.project,
+ // exploratory: [...exploratory, ...odahu]
+ // };
+ // });
+ // }
+ // }
+
+
return data.map((value) => {
return {
project: value.project,
diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/modal-dialog/odahu-action-dialog/index.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-dialog/odahu-action-dialog/index.ts
new file mode 100644
index 0000000..bfc5420
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-dialog/odahu-action-dialog/index.ts
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { OdahuActionDialogComponent } from './odahu-action-dialog.component';
+import { MaterialModule } from '../../material.module';
+import {FormsModule} from '@angular/forms';
+
+export * from './odahu-action-dialog.component';
+
+@NgModule({
+ imports: [CommonModule, MaterialModule, FormsModule],
+ declarations: [OdahuActionDialogComponent],
+ entryComponents: [OdahuActionDialogComponent],
+ exports: [OdahuActionDialogComponent]
+})
+export class OdahuActionDialogModule {}
diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/modal-dialog/odahu-action-dialog/odahu-action-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-dialog/odahu-action-dialog/odahu-action-dialog.component.ts
new file mode 100644
index 0000000..921ff99
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-dialog/odahu-action-dialog/odahu-action-dialog.component.ts
@@ -0,0 +1,50 @@
+import { Component, Inject } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+
+
+@Component({
+ selector: 'edge-action-dialog',
+ template: `
+ <div id="dialog-box">
+ <header class="dialog-header">
+ <h4 class="modal-title"><span class="action">{{data.type | titlecase}}</span> Odahu cluster</h4>
+ <button type="button" class="close" (click)="dialogRef.close()">×</button>
+ </header>
+ <div mat-dialog-content class="content message mat-dialog-content">
+ <h3>Odahu cluster <span class="strong">{{data.item.name}} </span>will be {{label[data.type]}}</h3>
+ <p class="m-top-20 action-text"><span class="strong">Do you want to proceed?</span></p>
+
+ <div class="text-center m-top-30 m-bott-30">
+ <button type="button" class="butt" mat-raised-button (click)="dialogRef.close()">No</button>
+ <button type="button" class="butt butt-success" mat-raised-button (click)="dialogRef.close(true)">Yes</button>
+ </div>
+ </div>
+ </div>
+ `,
+ styles: [`
+ .content { color: #718ba6; padding: 20px 50px; font-size: 14px; font-weight: 400; margin: 0; }
+ .info .confirm-dialog { color: #607D8B; }
+ header { display: flex; justify-content: space-between; color: #607D8B; }
+ h3 { font-weight: 300; }
+ header h4 i { vertical-align: bottom; }
+ header a i { font-size: 20px; }
+ header a:hover i { color: #35afd5; cursor: pointer; }
+ .action{text-transform: capitalize}
+ .action-text { text-align: center; }
+ label { font-size: 15px; font-weight: 500; font-family: "Open Sans",sans-serif; cursor: pointer; display: flex; align-items: center;}
+ label input {margin-top: 2px; margin-right: 5px;}
+ `]
+})
+
+export class OdahuActionDialogComponent {
+ public label = {
+ stop: 'stopped',
+ start: 'started',
+ terminate: 'terminated',
+ };
+
+ constructor(
+ public dialogRef: MatDialogRef<OdahuActionDialogComponent>,
+ @Inject(MAT_DIALOG_DATA) public data: any) {
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html
index 9e73f34..89de5e0 100644
--- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html
@@ -88,6 +88,11 @@
<span *ngIf="isExpanded; else projects">Projects</span>
<ng-template #projects><i class="material-icons">dns</i></ng-template>
</a>
+<!-- <a class="sub-nav-item" [style.margin-left.px]="isExpanded ? '30' : '0'" [routerLink]="['/odahu']"-->
+<!-- [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}">-->
+<!-- <span *ngIf="isExpanded; else odahu">Odahu deployment</span>-->
+<!-- <ng-template #odahu><i class="material-icons">get_app</i></ng-template>-->
+<!-- </a>-->
<a class="sub-nav-item" [style.margin-left.px]="isExpanded ? '30' : '0'"
[routerLink]="['/environment_management']" [routerLinkActive]="['active']"
[routerLinkActiveOptions]="{exact:true}">
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datalab.apache.org
For additional commands, e-mail: commits-help@datalab.apache.org