blob: d7442de71e9c13069e3661efc4670aa221da9b2d [file] [log] [blame]
/*
* 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, OnDestroy, Inject, ViewChild } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Subscription } from 'rxjs';
import { ToastrService } from 'ngx-toastr';
import { ProjectDataService } from './project-data.service';
import {HealthStatusService, ProjectService, UserResourceService} from '../../core/services';
import { NotificationDialogComponent } from '../../shared/modal-dialog/notification-dialog';
import { ProjectListComponent } from './project-list/project-list.component';
import {ExploratoryModel} from '../../resources/resources-grid/resources-grid.model';
export interface Endpoint {
name: string;
status: string;
edgeInfo: any;
}
export interface Project {
name: string;
endpoints: any;
tag: string;
groups: string[];
shared_image_enabled?: boolean;
}
@Component({
selector: 'dlab-project',
templateUrl: './project.component.html'
})
export class ProjectComponent implements OnInit, OnDestroy {
projectList: Project[] = [];
healthStatus: any;
activeFiltering: boolean = false;
resources: any = [];
private subscriptions: Subscription = new Subscription();
@ViewChild(ProjectListComponent, { static: false }) list: ProjectListComponent;
constructor(
public dialog: MatDialog,
public toastr: ToastrService,
private projectService: ProjectService,
private projectDataService: ProjectDataService,
private healthStatusService: HealthStatusService,
private userResourceService: UserResourceService
) { }
ngOnInit() {
this.getEnvironmentHealthStatus();
this.subscriptions.add(this.projectDataService._projects.subscribe(
(value: Project[]) => {
if (value) this.projectList = value;
}));
this.refreshGrid();
this.getResources();
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
private getResources() {
this.userResourceService.getUserProvisionedResources()
.subscribe((result: any) => {
this.resources = ExploratoryModel.loadEnvironments(result);
});
}
refreshGrid() {
this.projectDataService.updateProjects();
this.activeFiltering = false;
}
createProject() {
if (this.projectList.length)
this.dialog.open(EditProjectComponent, { data: { action: 'create', item: null }, panelClass: 'modal-xl-s' })
.afterClosed().subscribe(() => {
console.log('Create project');
this.getEnvironmentHealthStatus();
});
}
public toggleFiltering(): void {
this.activeFiltering = !this.activeFiltering;
this.activeFiltering ? this.list.showActiveInstances() : this.projectDataService.updateProjects();
}
public editProject($event) {
this.dialog.open(EditProjectComponent, { data: { action: 'edit', item: $event }, panelClass: 'modal-xl-s' })
.afterClosed().subscribe(() => {
this.refreshGrid();
});
}
public toggleStatus($event) {
const data = { 'project_name': $event.project.name, endpoint: $event.endpoint.map(endpoint => endpoint.name)};
this.toggleStatusRequest(data, $event.action);
}
private toggleStatusRequest(data, action) {
if ( action === 'terminate') {
const projectsResources = this.resources.filter(resource => resource.project === data.project_name );
const activeProjectsResources = projectsResources.length ? projectsResources[0].exploratory
.filter(expl => expl.status !== 'terminated' && expl.status !== 'terminating' && expl.status !== 'failed') : [];
let termResources = [];
data.endpoint.forEach(v => {
termResources = [...termResources, ...activeProjectsResources.filter(resource => resource.endpoint === v)];
});
this.dialog.open(NotificationDialogComponent, { data: {
type: 'terminateNode', item: {action: data, resources: termResources.map(resource => resource.name)}
}, panelClass: 'modal-sm' })
.afterClosed().subscribe(result => {
result && this.edgeNodeAction(data, action);
});
} else {
this.edgeNodeAction(data, action);
}
}
private edgeNodeAction(data, action) {
this.projectService.toggleProjectStatus(data, action).subscribe(() => {
this.refreshGrid();
this.toastr.success(`Edge node ${this.toEndpointAction(action)} is in progress!`, 'Processing!');
}, error => this.toastr.error(error.message, 'Oops!'));
}
private getEnvironmentHealthStatus() {
this.healthStatusService.getEnvironmentHealthStatus()
.subscribe((result: any) => this.healthStatus = result);
}
private toEndpointAction(action) {
if (action === 'start') {
return 'starting';
} else if (action === 'stop') {
return 'stopping';
} else if (action === 'terminate') {
return 'terminating';
} else {
return action;
}
}
}
@Component({
selector: 'edit-project',
template: `
<div id="dialog-box" class="edit-form">
<div class="dialog-header">
<h4 class="modal-title">
<span *ngIf="data?.action === 'create'">Create new project</span>
<span *ngIf="data?.action === 'edit'">Edit {{ data.item.name }}</span>
</h4>
<button type="button" class="close" (click)="dialogRef.close()">&times;</button>
</div>
<div mat-dialog-content class="content project-form">
<project-form [item]="data.item" (update)="dialogRef.close(true)"></project-form>
</div>
</div>
`,
styles: [`
.content { color: #718ba6; padding: 0; font-size: 14px; font-weight: 400; margin: 0; overflow: hidden; }
.edit-form { height: 410px; overflow: hidden; }
`]
})
export class EditProjectComponent {
constructor(
public dialogRef: MatDialogRef<EditProjectComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) { }
}