diff options
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition/deployment')
6 files changed, 256 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.html b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.html new file mode 100644 index 0000000000..4a163ee24b --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.html @@ -0,0 +1 @@ +<div class="sdc-deployment-graph-wrapper"></div> diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.less b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.less new file mode 100644 index 0000000000..9b80fcd651 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.less @@ -0,0 +1,13 @@ +.sdc-deployment-graph-wrapper { + height: 100%; + width: 100%; + + ::ng-deep canvas { + /*canvas z-index is initialized to 999 while top-nav z-Index is 10, which makes top-nav disappear, so z-Index must be overwritten here*/ + z-index: 10 !important; + } + } + +::ng-deep .sdc-workspace-container .w-sdc-main-right-container .w-sdc-main-container-body-content.deploy-body-content{ + padding: 0px; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.spec.ts new file mode 100644 index 0000000000..823086fbbf --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.spec.ts @@ -0,0 +1,92 @@ +import {async, ComponentFixture} from '@angular/core/testing'; +import 'jest-dom/extend-expect'; +import {DeploymentGraphComponent} from "./deployment-graph.component"; +import {DeploymentGraphService} from "./deployment-graph.service"; +import {NO_ERRORS_SCHEMA} from "@angular/core"; +import * as cytoscape from "cytoscape/dist/cytoscape" +import {AngularJSBridge} from "../../../../services/angular-js-bridge-service"; +import {NodesFactory} from "../../../../models/graph/nodes/nodes-factory"; +import {CommonGraphUtils} from "../graph/common/common-graph-utils"; +import {groupsMock} from "../../../../../jest/mocks/groups.mock"; +import {Module} from "../../../../models/modules/base-module"; +import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance"; +import {componentInstancesMock} from "../../../../../jest/mocks/component-instance.mock"; +import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper"; +import {TopologyTemplateService} from "../../../services/component-services/topology-template.service"; +import {WorkspaceService} from "../../workspace/workspace.service"; +import {SdcConfigToken} from "../../../config/sdc-config.config"; +import {CompositionGraphLinkUtils} from "../graph/utils"; + +describe('DeploymentGraphComponent', () => { + + let fixture: ComponentFixture<DeploymentGraphComponent>; + let deploymentGraphServiceMock: Partial<DeploymentGraphService>; + let nodeFactoryServiceMock: Partial<NodesFactory>; + let commonGraphUtilsServiceMock: Partial<CommonGraphUtils>; + let angularJsBridgeServiceMock: Partial<AngularJSBridge>; + let sdcConfigTokenMock: Partial<AngularJSBridge>; + + beforeEach( + async(() => { + + deploymentGraphServiceMock = { + modules: <Array<Module>>groupsMock, + componentInstances: <Array<ComponentInstance>>componentInstancesMock + } + + nodeFactoryServiceMock = { + createModuleNode: jest.fn().mockResolvedValue(() => { + }), + createNode: jest.fn().mockResolvedValue(() => { + }) + } + + commonGraphUtilsServiceMock = { + addNodeToGraph: jest.fn(), + addComponentInstanceNodeToGraph: jest.fn() + } + + sdcConfigTokenMock = { + imagePath: '' + } + + const configure: ConfigureFn = testBed => { + testBed.configureTestingModule({ + declarations: [DeploymentGraphComponent], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + {provide: DeploymentGraphService, useValue: deploymentGraphServiceMock}, + {provide: NodesFactory, useValue: nodeFactoryServiceMock}, + {provide: TopologyTemplateService, useValue: {}}, + {provide: WorkspaceService, useValue: {}}, + {provide: CommonGraphUtils, useValue: commonGraphUtilsServiceMock}, + {provide: CompositionGraphLinkUtils, useValue: {}}, + {provide: AngularJSBridge, useValue: angularJsBridgeServiceMock}, + {provide: SdcConfigToken, useValue: SdcConfigToken} + ] + }); + }; + + configureTests(configure).then(testBed => { + fixture = testBed.createComponent(DeploymentGraphComponent); + }); + }) + ); + + it('expected deployment graph component to be defined', () => { + expect(fixture).toBeDefined(); + }); + + + it('expected to addNodeToGraph to haveBeenCalled 6 times out of 7 cause one of the instances have no parent module', () => { + fixture.componentInstance._cy = cytoscape({ + zoomingEnabled: false, + selectionType: 'single', + }); + jest.spyOn(fixture.componentInstance, 'findInstanceModule'); + fixture.componentInstance.initGraphComponentInstances(); + expect(fixture.componentInstance.findInstanceModule).toHaveBeenCalledTimes(7); + expect(commonGraphUtilsServiceMock.addComponentInstanceNodeToGraph).toHaveBeenCalledTimes(6); + }); + +});
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.ts new file mode 100644 index 0000000000..143a759960 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.component.ts @@ -0,0 +1,127 @@ +import {Component, ElementRef, Inject, OnInit} from "@angular/core"; +import {DeploymentGraphService} from "./deployment-graph.service"; +import '@bardit/cytoscape-expand-collapse'; +import * as _ from "lodash"; +import {TopologyTemplateService} from "../../../services/component-services/topology-template.service"; +import {WorkspaceService} from "../../workspace/workspace.service"; +import {NodesFactory} from "../../../../models/graph/nodes/nodes-factory"; +import {CommonGraphUtils} from "../graph/common/common-graph-utils"; +import {ISdcConfig, SdcConfigToken} from "../../../config/sdc-config.config"; +import {Module} from "../../../../models/modules/base-module"; +import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance"; +import {ComponentGenericResponse} from "../../../services/responses/component-generic-response"; +import {ComponentInstanceFactory} from "../../../../utils/component-instance-factory"; +import {ModulesNodesStyle} from "../graph/common/style/module-node-style"; +import {ComponentInstanceNodesStyle} from "../graph/common/style/component-instances-nodes-style"; +import {CompositionGraphLinkUtils} from "../graph/utils/composition-graph-links-utils"; + +@Component({ + selector: 'deployment-graph', + templateUrl: './deployment-graph.component.html', + styleUrls: ['./deployment-graph.component.less'] +}) + +export class DeploymentGraphComponent implements OnInit { + constructor(private elRef: ElementRef, + private topologyTemplateService: TopologyTemplateService, + private workspaceService: WorkspaceService, + private deploymentService: DeploymentGraphService, + private commonGraphUtils: CommonGraphUtils, + private nodeFactory: NodesFactory, + private commonGraphLinkUtils: CompositionGraphLinkUtils, + @Inject(SdcConfigToken) private sdcConfig: ISdcConfig) { + + } + + public _cy: Cy.Instance; + + ngOnInit(): void { + this.topologyTemplateService.getDeploymentGraphData(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId).subscribe((response: ComponentGenericResponse) => { + this.deploymentService.componentInstances = response.componentInstances; + this.deploymentService.componentInstancesRelations = response.componentInstancesRelations; + this.deploymentService.modules = response.modules; + this.loadGraph(); + }); + } + + public findInstanceModule = (groupsArray: Array<Module>, componentInstanceId: string): string => { + let parentGroup: Module = _.find(groupsArray, (group: Module) => { + return _.find(_.values(group.members), (member: string) => { + return member === componentInstanceId; + }); + }); + return parentGroup ? parentGroup.uniqueId : ""; + }; + + public initGraphModules = () => { + if (this.deploymentService.modules) { // Init module nodes + _.each(this.deploymentService.modules, (groupModule: Module) => { + let moduleNode = this.nodeFactory.createModuleNode(groupModule); + this.commonGraphUtils.addNodeToGraph(this._cy, moduleNode); + }); + } + } + + public initGraphComponentInstances = () => { + _.each(this.deploymentService.componentInstances, (instance: ComponentInstance) => { // Init component instance nodes + let componentInstanceNode = this.nodeFactory.createNode(instance); + componentInstanceNode.parent = this.findInstanceModule(this.deploymentService.modules, instance.uniqueId); + if (componentInstanceNode.parent) { // we are not drawing instances that are not a part of a module + this.commonGraphUtils.addComponentInstanceNodeToGraph(this._cy, componentInstanceNode); + } + }); + } + + public handleEmptyModule = () => { + // This is a special functionality to pass the cytoscape default behavior - we can't create Parent module node without children's + // so we must add an empty dummy child node + _.each(this._cy.nodes('[?isGroup]'), (moduleNode: Cy.CollectionFirstNode) => { + if (!moduleNode.isParent()) { + let dummyInstance = ComponentInstanceFactory.createEmptyComponentInstance(); + let componentInstanceNode = this.nodeFactory.createNode(dummyInstance); + componentInstanceNode.parent = moduleNode.id(); + let dummyNode = this.commonGraphUtils.addNodeToGraph(this._cy, componentInstanceNode, moduleNode.position()); + dummyNode.addClass('dummy-node'); + } + }) + } + + public initGraphNodes = (): void => { + this.initGraphModules(); + this.initGraphComponentInstances(); + this.handleEmptyModule(); + }; + + private loadGraph = () => { + + let graphEl = this.elRef.nativeElement.querySelector('.sdc-deployment-graph-wrapper'); + this._cy = cytoscape({ + container: graphEl, + style: ComponentInstanceNodesStyle.getCompositionGraphStyle().concat(ModulesNodesStyle.getModuleGraphStyle()), + zoomingEnabled: false, + selectionType: 'single', + + }); + + //adding expand collapse extension + this._cy.expandCollapse({ + layoutBy: { + name: "grid", + animate: true, + randomize: false, + fit: true + }, + fisheye: false, + undoable: false, + expandCollapseCueSize: 18, + expandCueImage: this.sdcConfig.imagesPath + '/assets/styles/images/resource-icons/' + 'closeModule.png', + collapseCueImage: this.sdcConfig.imagesPath + '/assets/styles/images/resource-icons/' + 'openModule.png', + expandCollapseCueSensitivity: 2, + cueOffset: -20 + }); + + this.initGraphNodes(); //creating instances nodes + this.commonGraphLinkUtils.initGraphLinks(this._cy, this.deploymentService.componentInstancesRelations); + this._cy.collapseAll(); + }; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.module.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.module.ts new file mode 100644 index 0000000000..91f97db8c3 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.module.ts @@ -0,0 +1,15 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {DeploymentGraphComponent} from "./deployment-graph.component"; + +@NgModule({ + declarations: [DeploymentGraphComponent], + imports: [CommonModule], + exports: [DeploymentGraphComponent], + entryComponents: [DeploymentGraphComponent], + providers: [ + + ] +}) +export class DeploymentGraphModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.service.ts b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.service.ts new file mode 100644 index 0000000000..7ec346c20b --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/deployment/deployment-graph.service.ts @@ -0,0 +1,8 @@ +import {Injectable} from "@angular/core"; +import 'rxjs/add/observable/forkJoin'; +import {CommonGraphDataService} from "../common/common-graph-data.service"; +import {Module} from "../../../../models/modules/base-module"; +@Injectable() +export class DeploymentGraphService extends CommonGraphDataService { + public modules:Array<Module>; +} |