Skip to content

Commit

Permalink
Merge pull request #62 from tillias/dev
Browse files Browse the repository at this point in the history
Delete dependency from dashboard screen #53
  • Loading branch information
tillias authored Oct 23, 2020
2 parents c1681cf + ea4c5ac commit b8f2cf8
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 151 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Injectable } from '@angular/core';
import { NgbModal, NgbModalOptions, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { DependencyDeleteDialogComponent } from '../../entities/dependency/dependency-delete-dialog.component';
import { IDependency } from '../../shared/model/dependency.model';
import { IMicroservice } from '../../shared/model/microservice.model';
import { MicroserviceDeleteDialogComponent } from '../../entities/microservice/microservice-delete-dialog.component';

@Injectable({
providedIn: 'root',
})
export class DeleteDialogService {
private isDependencyOpen = false;
private isMicroserviceOpen = false;

constructor(private modalService: NgbModal) {}

openForDependency(dependency?: IDependency): void {
if (this.isDependencyOpen) {
return;
}
this.isDependencyOpen = true;

const modalRef: NgbModalRef = this.modalService.open(DependencyDeleteDialogComponent, this.getOptions());
modalRef.componentInstance.dependency = dependency;
modalRef.result.finally(() => (this.isDependencyOpen = false));
}

openForMicroservice(microservice?: IMicroservice): void {
if (this.isMicroserviceOpen) {
return;
}
this.isMicroserviceOpen = true;

const modalRef: NgbModalRef = this.modalService.open(MicroserviceDeleteDialogComponent, this.getOptions());
modalRef.componentInstance.microservice = microservice;
modalRef.result.finally(() => (this.isMicroserviceOpen = false));
}

getOptions(): NgbModalOptions {
return {
centered: true,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,50 +1,53 @@
<div class="row">
<div class="col-2">
<ngb-accordion [closeOthers]="true" [destroyOnHide]="false" activeIds="search">
<ngb-panel title="Search" id="search">
<div class="col-3">
<ngb-accordion [closeOthers]="true" [destroyOnHide]="false" activeIds="general">
<ngb-panel title="General" id="general">
<ng-template ngbPanelContent>
<jhi-microservice-search (itemSelected)="onMicroserviceSelected($event)">
</jhi-microservice-search>
<div class="form-check p-0 pt-4">
<div class="form-check p-0 pt-4 pl-1">
<label class="form-check-label">
<input type="checkbox" [(ngModel)]="onlyIncomingFilter" (ngModelChange)="onFilterChange()">
<span jhiTranslate="microcatalogApp.dashboard.dependency.filter.incoming"></span>
</label>
</div>
<div class="form-check p-0 pt-1">
<div class="form-check p-0 pt-1 pl-1">
<label class="form-check-label">
<input type="checkbox" [(ngModel)]="onlyOutgoingFilter" (ngModelChange)="onFilterChange()">
<span jhiTranslate="microcatalogApp.dashboard.dependency.filter.outgoing"></span>
</label>
</div>
</ng-template>
</ngb-panel>
<ngb-panel title="Management" id="dependency">
<ng-template ngbPanelContent>
<div class="p-1">
<div class="pt-4">
<button class="btn btn-block btn-success btn-sm" [routerLink]="['/microservice','', 'edit']">
Create microservice
</button>
</div>
<div class="p-1">
<div class="pt-2">
<button class="btn btn-block btn-success btn-sm" (click)="createDependency()">Create
dependency
</button>
</div>
<div class="p-1">
<button class="btn btn-block btn-warning btn-sm" [disabled]="!selection">Delete microservice
<div class="pt-2">
<button class="btn btn-block btn-warning btn-sm" [disabled]="!nodeSelection?.hasNodes()"
(click)="deleteMicroservice()">Delete microservice
</button>
</div>
<div class="pt-1">
<button class="btn btn-block btn-warning btn-sm" [disabled]="!selection">Delete dependency
<div class="pt-2">
<button class="btn btn-block btn-warning btn-sm" [disabled]="!edgeSelection?.hasEdges()"
(click)="deleteDependency()">Delete dependency
</button>
</div>
</ng-template>
</ngb-panel>
<ngb-panel title="DDD" id="dependency">
<ng-template ngbPanelContent>
<p>DDD is coming soon!</p>
</ng-template>
</ngb-panel>
<ngb-panel title="Analysis">
<ng-template ngbPanelContent>
<div class="p-1">
<button class="btn btn-block btn-success btn-sm" [disabled]="!selection"
<button class="btn btn-block btn-success btn-sm" [disabled]="!nodeSelection"
(click)="buildDeploymentPath()">Build deployment path
</button>
</div>
Expand All @@ -53,10 +56,10 @@
</ngb-accordion>

</div>
<div class="col-7">
<div class="col-6">
<div class="p3 vis-network-full-height" #visNetwork></div>
</div>
<div class="col-3">
<jhi-node-legend [selection]="selection"></jhi-node-legend>
<jhi-node-legend [nodeSelection]="nodeSelection" [edgeSelection]="edgeSelection"></jhi-node-legend>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { DataSet } from 'vis-data/peer';
import { Network } from 'vis-network/peer';
import { DependencyService } from '../../entities/dependency/dependency.service';
import { IDependency } from '../../shared/model/dependency.model';
import { IMicroservice } from '../../shared/model/microservice.model';
import { ISelectPayload } from '../../shared/vis/events/VisEvents';
import { EXPERIMENTAL_FEATURE } from '../../app.constants';
import { CreateDependencyDialogService } from './create-dependency-dialog/create-dependency-dialog.service';
import { JhiEventManager } from 'ng-jhipster';
import { forkJoin, Subscription } from 'rxjs';
import { Subscription } from 'rxjs';
import { MicroserviceService } from '../../entities/microservice/microservice.service';
import { map } from 'rxjs/operators';
import { ISelectPayload, SelectPayload } from '../../shared/vis/events/VisEvents';
import { DeleteDialogService } from './delete-dialog.service';
import { FilterContext, GraphBuilderService } from './graph-builder.service';

@Component({
selector: 'jhi-dependency-dashboard',
Expand All @@ -27,49 +26,32 @@ export class DependencyDashboardComponent implements OnInit, AfterViewInit, OnDe
searchValue?: IMicroservice;
onlyIncomingFilter = true;
onlyOutgoingFilter = true;
selection?: ISelectPayload;
nodeSelection?: ISelectPayload;
edgeSelection?: ISelectPayload;
experimentalFeatures = EXPERIMENTAL_FEATURE;

constructor(
protected eventManager: JhiEventManager,
protected dependencyService: DependencyService,
protected microserviceService: MicroserviceService,
protected createDependencyDialogService: CreateDependencyDialogService
protected graphBuilderService: GraphBuilderService,
protected createDependencyDialogService: CreateDependencyDialogService,
protected deleteDialogService: DeleteDialogService
) {}

ngOnInit(): void {
this.registerChangeInDependencies();
}

registerChangeInDependencies(): void {
this.subscription = this.eventManager.subscribe('dependencyListModification', () => this.loadAll());
this.subscription.add(this.eventManager.subscribe('microserviceListModification', () => this.loadAll()));
this.subscription = this.eventManager.subscribe('dependencyListModification', () => this.refreshGraph());
this.subscription.add(this.eventManager.subscribe('microserviceListModification', () => this.refreshGraph()));
}

ngAfterViewInit(): void {
const container = this.visNetwork;

const data = {};
this.networkInstance = new Network(container.nativeElement, data, {
height: '100%',
width: '100%',
nodes: {
shape: 'hexagon',
font: {
color: 'white',
},
},
clickToUse: false,
edges: {
smooth: false,
arrows: {
to: {
enabled: true,
type: 'vee',
},
},
},
});
this.networkInstance = this.graphBuilderService.createNetwork(container);

// See Network.d.ts -> NetworkEvents
this.networkInstance.on('selectNode', (params: any) => {
Expand All @@ -78,132 +60,100 @@ export class DependencyDashboardComponent implements OnInit, AfterViewInit, OnDe
this.networkInstance.on('deselectNode', () => {
this.handleDeselectNode();
});
this.networkInstance.on('selectEdge', (params: any) => {
this.handleSelectEdge(params);
});
this.networkInstance.on('deselectEdge', () => {
this.handleDeselectEdge();
});

this.loadAll();
this.refreshGraph();
}

ngOnDestroy(): void {
this.networkInstance.off('selectNode');
this.networkInstance.off('deselectNode');
this.networkInstance.off('selectEdge');
this.networkInstance.off('deselectEdge');

if (this.subscription) {
this.eventManager.destroy(this.subscription);
}
}

handleSelectNode(payload: ISelectPayload): void {
this.selection = payload;
handleSelectNode(payload: any): void {
this.nodeSelection = new SelectPayload(payload);
}

handleDeselectNode(): void {
this.selection = undefined;
handleSelectEdge(payload: any): void {
this.edgeSelection = new SelectPayload(payload);
}

onFilterChange(): any {
// Only makes sense to refresh if filter for particular microservice is active
if (this.searchValue) {
this.loadAll();
}
handleDeselectNode(): void {
this.nodeSelection = undefined;
}

loadAll(): void {
const dependencies$ = this.dependencyService.query();
const microservices$ = this.microserviceService.query();

forkJoin({ dependencies$, microservices$ })
.pipe(
map(result => {
return {
dependencies: result.dependencies$.body || [],
microservices: result.microservices$.body || [],
};
})
)
.subscribe(results => {
this.refreshGraph(results.dependencies, results.microservices);
});
handleDeselectEdge(): void {
this.edgeSelection = undefined;
}

refreshGraph(dependencies: IDependency[], microservices: IMicroservice[]): void {
let filteredDependencies = dependencies;

if (this.searchValue) {
const searchID = this.searchValue.id;
filteredDependencies = dependencies.filter(d => {
if (this.onlyIncomingFilter && !this.onlyOutgoingFilter) {
return d.target?.id === searchID;
}

if (this.onlyOutgoingFilter && !this.onlyIncomingFilter) {
return d.source?.id === searchID;
}

if (this.onlyIncomingFilter && this.onlyOutgoingFilter) {
return d.source?.id === searchID || d.target?.id === searchID;
}

return false;
});
}

const edges = new DataSet<any>();
const nodeIds = new Set();

filteredDependencies.forEach(d => {
if (d.source != null && d.target != null) {
const sourceID = d.source.id;
const targetID = d.target.id;

edges.add({
from: sourceID,
to: targetID,
});

nodeIds.add(sourceID);
nodeIds.add(targetID);
}
});

let filteredMicroservices = microservices;
onFilterChange(): any {
// Only makes sense to refresh if filter for particular microservice is active
if (this.searchValue) {
filteredMicroservices = microservices.filter(m => nodeIds.has(m.id));
this.refreshGraph();
}

const nodes = new DataSet<any>(filteredMicroservices.map(m => this.convertToGraphNode(m)));

const data = { nodes, edges };

this.networkInstance.setData(data);
}

convertToGraphNode(microservice: IMicroservice): any {
return {
id: microservice.id,
label: microservice.name,
};
refreshGraph(): void {
const filterContext = new FilterContext(this.onlyIncomingFilter, this.onlyOutgoingFilter, this.searchValue);
this.graphBuilderService.refreshGraph(this.networkInstance, filterContext);
}

onMicroserviceSelected(microservice?: IMicroservice): any {
this.searchValue = microservice;
this.loadAll();
this.refreshGraph();
}

buildDeploymentPath(): void {}

createDependency(): void {
// Use selected microservice as dependency's start
if (this.selection) {
const id = this.selection.nodes[0];
if (this.nodeSelection && this.nodeSelection.hasNodes()) {
const id = this.nodeSelection.firstNode();
this.microserviceService
.find(id)
.pipe(map(r => r.body || undefined))
.subscribe(r => this.openDialog(r));
.subscribe(r => this.openCreateDependencyDialog(r));
} else {
this.openDialog(this.searchValue);
this.openCreateDependencyDialog(this.searchValue);
}
}

openDialog(initialSource?: IMicroservice): void {
openCreateDependencyDialog(initialSource?: IMicroservice): void {
this.createDependencyDialogService.open(initialSource);
}

deleteDependency(): void {
if (this.edgeSelection && this.edgeSelection.hasEdges()) {
const id = this.edgeSelection.firstEdge();
this.dependencyService
.find(id)
.pipe(map(r => r.body || undefined))
.subscribe(d => {
this.deleteDialogService.openForDependency(d);
});
}
}

deleteMicroservice(): void {
if (this.nodeSelection && this.nodeSelection.hasNodes()) {
const id = this.nodeSelection.firstNode();
this.microserviceService
.find(id)
.pipe(map(r => r.body || undefined))
.subscribe(m => {
this.deleteDialogService.openForMicroservice(m);
});
}
}
}
Loading

0 comments on commit b8f2cf8

Please sign in to comment.