summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator')
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap29
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.html61
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less21
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts478
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts104
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link.model.ts36
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html55
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less45
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts149
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.module.ts25
10 files changed, 1003 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap
new file mode 100644
index 0000000000..094f41bd84
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/__snapshots__/link-row.component.spec.ts.snap
@@ -0,0 +1,29 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`artifact form component should match current snapshot of artifact form component 1`] = `
+<link-row
+ source={[Function Array]}
+ srcCP={[Function Array]}
+ target={[Function Array]}
+ targetCP={[Function Array]}
+>
+ <ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkSrc"
+ /><ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkSrcCP"
+ /><ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkTarget"
+ /><ui-element-dropdown
+ class="cell link-selector"
+ data-tests-id="linkTargetCP"
+ /><div
+ class="cell remove"
+ data-tests-id="removeLnk"
+ >
+
+ </div>
+</link-row>
+`;
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.html
new file mode 100644
index 0000000000..0abdda1cc6
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.html
@@ -0,0 +1,61 @@
+<!--
+ ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ ~
+ ~ Licensed 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.
+ -->
+
+<ui-element-dropdown
+ data-tests-id="linkSrc"
+ [readonly]="!link.isFirst || (link.isFirst && !link.canEdit)"
+ class="cell link-selector"
+ [values]="source"
+ [(value)]="link.fromNode"
+ (valueChange)="onSourceSelected($event)">
+</ui-element-dropdown>
+
+<ui-element-dropdown
+ data-tests-id="linkSrcCP"
+ [readonly]="!link.isFirst || (link.isFirst && !link.canEdit)"
+ class="cell link-selector"
+ [values]="srcCP"
+ [(value)]="link.fromCP"
+ (valueChange)="onSrcCPSelected($event)">
+</ui-element-dropdown>
+
+<ui-element-dropdown
+ data-tests-id="linkTarget"
+ [readonly]="!link.canEdit"
+ class="cell link-selector"
+ [values]="target"
+ [(value)]="link.toNode"
+ (valueChange)="onTargetSelected($event)">
+</ui-element-dropdown>
+
+<ui-element-dropdown
+ data-tests-id="linkTargetCP"
+ [readonly]="!link.canEdit"
+ class="cell link-selector"
+ [values]="targetCP"
+ [(value)]="link.toCP"
+ (valueChange)="onTargetCPSelected($event)">
+</ui-element-dropdown>
+
+<div
+ class="cell remove"
+ data-tests-id="removeLnk">
+ <span
+ *ngIf="link.canRemove"
+ class="sprite-new delete-item-icon"
+ (click)="removeRow()">
+ </span>
+</div>
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less
new file mode 100644
index 0000000000..2a1d0d98c8
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.less
@@ -0,0 +1,21 @@
+@import './../../../../../../../assets/styles/variables.less';
+.remove {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.cell {
+ padding: 0;
+}
+
+/deep/ .link-selector {
+ select {
+ height: 30px;
+ border: none;
+ stroke: none;
+ }
+
+}
+
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts
new file mode 100644
index 0000000000..5cbad6ea5d
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.spec.ts
@@ -0,0 +1,478 @@
+import {async, ComponentFixture} from "@angular/core/testing";
+import {CacheService} from "../../../../../services/cache.service";
+import {ConfigureFn, configureTests} from "../../../../../../../jest/test-config.helper";
+import {NO_ERRORS_SCHEMA} from "@angular/core";
+import {LinkRowComponent} from "./link-row.component";
+import {DropdownValue} from "../../../../../components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {MapItemData, ServicePathMapItem} from "../../../../../../models/graph/nodes-and-links-map";
+
+describe('artifact form component', () => {
+
+ let fixture: ComponentFixture<LinkRowComponent>;
+ let cacheServiceMock: Partial<CacheService>;
+
+ beforeEach(
+ async(() => {
+
+
+ cacheServiceMock = {
+ contains: jest.fn(),
+ remove: jest.fn(),
+ set: jest.fn(),
+ get: jest.fn()
+ }
+
+ const configure: ConfigureFn = testBed => {
+ testBed.configureTestingModule({
+ declarations: [LinkRowComponent],
+ imports: [],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: []
+ ,
+ });
+ };
+
+ configureTests(configure).then(testBed => {
+ fixture = testBed.createComponent(LinkRowComponent);
+ });
+ })
+ );
+
+
+ it('should match current snapshot of artifact form component', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+
+ it('ngOnChanges() -> in case data exist -> call to parseInitialData()' ,() => {
+ // init values / mock functions
+ let data = 'something';
+ fixture.componentInstance.parseInitialData = jest.fn();
+ fixture.componentInstance.data = data;
+
+ // call to the tested function
+ fixture.componentInstance.ngOnChanges();
+
+ // expect that
+ expect(fixture.componentInstance.parseInitialData).toHaveBeenCalledWith(data);
+ });
+
+ it('onSourceSelected() -> in case id -> srcCP, link.fromCP, link.toNode, link.toCP, target, targetCP should be updated accordingly' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let data = 'data';
+ let link = {
+ fromCP:'testVal',
+ toNode:'testVal',
+ toCP:'testVal'
+ }
+ let target = ['val1', 'val2'];
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.data = data;
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.target = target;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onSourceSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.findOptions).toHaveBeenCalledWith(data, id);
+ expect(fixture.componentInstance.srcCP).toBe('dummyConvertedVal');
+ expect(fixture.componentInstance.link.fromCP).toBe('');
+ expect(fixture.componentInstance.link.toNode).toBe('');
+ expect(fixture.componentInstance.link.toCP).toBe('');
+ expect(fixture.componentInstance.target.length).toBe(0);
+ expect(fixture.componentInstance.targetCP.length).toBe(0);
+ });
+
+ it('onSourceSelected() -> in case id undefined -> No Change to srcCP, link.fromCP, link.toNode, link.toCP, target, targetCP' ,() => {
+ // init values / mock functions
+ let id;
+ let data = 'data';
+ let link = {
+ fromCP:'testVal',
+ toNode:'testVal',
+ toCP:'testVal'
+ }
+ let target = ['val1', 'val2'];
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.data = data;
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.target = target;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onSourceSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.link.fromCP).toBe(link.fromCP);
+ expect(fixture.componentInstance.link.toNode).toBe(link.toNode);
+ expect(fixture.componentInstance.link.toCP).toBe(link.toCP);
+ expect(fixture.componentInstance.target.length).toBe(2);
+ expect(fixture.componentInstance.target[0]).toBe('val1')
+ expect(fixture.componentInstance.targetCP.length).toBe(2);
+ expect(fixture.componentInstance.targetCP[1]).toBe('val2');
+ });
+
+ it('onSrcCPSelected() -> in case id -> Verify target, link.fromCPOriginId, link.toNode, link.toCP, targetCP.length' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let link = {
+ fromNode:'testVal',
+ toCPOriginId: 'initValue_ShouldBeChanged'
+ };
+ let option1 = {
+ id: 'something'
+ };
+ let option2 = {
+ id: 'id',
+ data: {"ownerId":1}
+ };
+
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.findOptions = jest.fn(() => [option1, option2]);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+
+ // call to the tested function
+ fixture.componentInstance.onSrcCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.target).toBe('dummyConvertedVal');
+ expect(fixture.componentInstance.link.fromCPOriginId).toBe(option2.data.ownerId);
+ expect(fixture.componentInstance.link.toNode).toBe('');
+ expect(fixture.componentInstance.link.toCP).toBe('');
+ expect(fixture.componentInstance.targetCP.length).toBe(0);
+
+ });
+
+ it('onSrcCPSelected() -> in case id undefined -> Verify target, link.fromCPOriginId, link.toNode, link.toCP, targetCP.length' ,() => {
+ // init values / mock functions
+ let id;
+
+ let targetInput:Array<DropdownValue> = [{value:'Value', label:'Label', hidden:true, selected:true}];
+
+ let linkInput = {
+ fromCPOriginId:'expectedLinkFromCPOriginId',
+ toNode:'expectedLinkToNode',
+ toCP:'expectedLinkToCP',
+ // Link Object
+ canEdit:true,
+ canRemove:true,
+ isFirst:true,
+ // ForwardingPathLink Object
+ ownerId:'',
+ fromNode:'',
+ fromCP:'',
+ toCPOriginId:''
+ }
+
+ fixture.componentInstance.target = targetInput;
+ fixture.componentInstance.link = linkInput;
+ fixture.componentInstance.targetCP = targetInput;
+
+
+ // call to the tested function
+ fixture.componentInstance.onSrcCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.target).toBe(targetInput);
+ expect(fixture.componentInstance.link.fromCPOriginId).toBe('expectedLinkFromCPOriginId');
+ expect(fixture.componentInstance.link.toNode).toBe('expectedLinkToNode');
+ expect(fixture.componentInstance.link.toCP).toBe('expectedLinkToCP');
+ expect(fixture.componentInstance.targetCP.length).toBe(1);
+ });
+
+ it('onTargetSelected() -> in case id -> Verify targetCP & link.toCP' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let link = {
+ toCP:'testVal'
+ }
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onTargetSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.targetCP).toBe('dummyConvertedVal');
+ expect(fixture.componentInstance.link.toCP).toBe('');
+
+ });
+
+ it('onTargetSelected() -> in case id undefined -> Verify targetCP & link.toCP' ,() => {
+ // init values / mock functions
+ let id;
+ let link = {
+ toCP:'toCP_testVal'
+ }
+ let targetCP = ['val1', 'val2'];
+
+ fixture.componentInstance.findOptions = jest.fn();
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => 'dummyConvertedVal');
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.targetCP = targetCP;
+
+ // call to the tested function
+ fixture.componentInstance.onTargetSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.targetCP.length).toBe(2);
+ expect(fixture.componentInstance.targetCP).toEqual(['val1', 'val2']);
+ expect(fixture.componentInstance.link.toCP).toBe('toCP_testVal');
+ });
+
+ it('onTargetCPSelected() -> in case id -> Validate toCPOriginId' ,() => {
+ // init values / mock functions
+ let id = 'id';
+ let link = {
+ toNode:'testVal',
+ toCPOriginId: 'initValue_ShouldBeChanged'
+ };
+ let option1 = {
+ id: 'something'
+ };
+ let option2 = {
+ id: 'id',
+ data: {"ownerId":1}
+ };
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.findOptions = jest.fn(() => [option1, option2]);
+
+ // call to the tested function
+ fixture.componentInstance.onTargetCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.link.toCPOriginId).toBe(option2.data.ownerId);
+ });
+
+ it('onTargetCPSelected() -> in case id undefined -> Validate toCPOriginId' ,() => {
+ // init values / mock functions
+ let id;
+ let link = {
+ toNode:'testVal',
+ toCPOriginId: 'initValue_ShouldRemain'
+ };
+ let option1 = {
+ id: 'something'
+ };
+ let option2 = {
+ id: 'id',
+ data: {"ownerId":1}
+ };
+ fixture.componentInstance.link = link;
+ fixture.componentInstance.findOptions = jest.fn(() => [option1, option2]);
+
+ // call to the tested function
+ fixture.componentInstance.onTargetCPSelected(id);
+
+ // expect that
+ expect(fixture.componentInstance.link.toCPOriginId).toBe('initValue_ShouldRemain');
+ });
+
+
+ it('findOptions() -> in case item.data.options -> Validate return item.data.options' ,() => {
+ // init values / mock functions
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const innerServicePathItem: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ const mapItemData1: MapItemData = { id: 'mapItemData1_id', name: 'mapItemData1_name', options: [innerServicePathItem]};
+
+ const servicePathItem: ServicePathMapItem = { id: 'servicePathItem_id', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem];
+
+ let nodeOrCPId: string = servicePathItem.id;
+
+ // call to the tested function
+ let res = fixture.componentInstance.findOptions(arrServicePathItems, nodeOrCPId);
+
+ // expect that
+ expect(res).toEqual([innerServicePathItem]);
+ });
+
+ it('findOptions() -> in case NOT item || item.data || item.data.options -> Validate return null' ,() => {
+ // init values / mock functions
+ let item = [{
+ // data: {
+ data:{
+ name:'data_name',
+ id: 'data_id'
+ },
+ name:'name',
+ id: 'id'
+ // }
+ }];
+ let items: Array<ServicePathMapItem> = item;
+ let nodeOrCPId: string = 'someString';
+
+ // call to the tested function
+ let res = fixture.componentInstance.findOptions(items, nodeOrCPId);
+
+ // expect that
+ expect(res).toBe(null);
+ });
+
+ it('convertValuesToDropDownOptions() -> Verify that the result is sorted' ,() => {
+ // init values / mock functions
+ const mapItemData1: MapItemData = { id: 'Z_ID', name: 'Z_NAME'};
+ const servicePathItem1: ServicePathMapItem = { id: 'Z_servicePathItem_id', data: mapItemData1 };
+
+ const mapItemData2: MapItemData = { id: 'A_ID', name: 'A_NAME'};
+ const servicePathItem2: ServicePathMapItem = { id: 'A_servicePathItem_id', data: mapItemData2 };
+
+ const mapItemData3: MapItemData = { id: 'M_ID', name: 'M_NAME'};
+ const servicePathItem3: ServicePathMapItem = { id: 'M_servicePathItem_id', data: mapItemData3 };
+
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1, servicePathItem2, servicePathItem3];
+
+ // call to the tested function
+ let res = fixture.componentInstance.convertValuesToDropDownOptions(arrServicePathItems);
+
+ // expect that
+ expect(res.length).toBe(3);
+ expect(res[0].value).toBe("A_servicePathItem_id");
+ expect(res[0].label).toBe("A_NAME");
+ expect(res[1].value).toBe("M_servicePathItem_id");
+ expect(res[1].label).toBe("M_NAME");
+ expect(res[2].value).toBe("Z_servicePathItem_id");
+ expect(res[2].label).toBe("Z_NAME");
+
+ });
+
+ it('parseInitialData() -> link.fromNode Exist => Verify srcCP' ,() => {
+ // init values / mock functions
+
+ //Simulate Array<ServicePathMapItem to pass to the function
+ const mapItemData1: MapItemData = { id: 'mapItemID', name: 'mapItemName'};
+ const servicePathItem1: ServicePathMapItem = { id: 'servicePathItemId', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1];
+
+ //Simulate link
+ let link = {
+ fromNode:'testVal'
+ };
+ fixture.componentInstance.link = link;
+
+ //Simulate the response from convertValuesToDropDownOptions()
+ const value = "expected_id_fromNode";
+ const label = "expected_label_fromNode"
+ let result:Array<DropdownValue> = [];
+ result[0] = new DropdownValue(value, label);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => result);
+
+ //Simulate the response from findOptions()
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const options: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ fixture.componentInstance.findOptions = jest.fn(() => options);
+
+
+ // call to the tested function
+ fixture.componentInstance.parseInitialData(arrServicePathItems);
+
+ // expect that
+ expect(fixture.componentInstance.srcCP.length).toBe(1);
+ expect(fixture.componentInstance.srcCP[0]).toEqual({
+ "value": value,
+ "label": label,
+ "hidden": false,
+ "selected": false
+ });
+ });
+
+ it('parseInitialData() -> link.fromNode & link.fromCP Exist => Verify srcCP' ,() => {
+ // init values / mock functions
+
+ //Simulate Array<ServicePathMapItem to pass to the function
+ const mapItemData1: MapItemData = { id: 'mapItemID', name: 'mapItemName'};
+ const servicePathItem1: ServicePathMapItem = { id: 'servicePathItemId', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1];
+
+ //Simulate link
+ let link = {
+ fromNode:'testVal',
+ fromCP: 'testVal'
+ };
+ fixture.componentInstance.link = link;
+
+ //Simulate the response from convertValuesToDropDownOptions()
+ const value = "expected_id_fromNode_and_fromCP";
+ const label = "expected_label_fromNode_and_fromCP"
+ let result:Array<DropdownValue> = [];
+ result[0] = new DropdownValue(value, label);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => result);
+
+ //Simulate the response from findOptions()
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const options: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ fixture.componentInstance.findOptions = jest.fn(() => options);
+
+
+ // call to the tested function
+ fixture.componentInstance.parseInitialData(arrServicePathItems);
+
+ // expect that
+ expect(fixture.componentInstance.srcCP.length).toBe(1);
+ expect(fixture.componentInstance.srcCP[0]).toEqual({
+ "value": value,
+ "label": label,
+ "hidden": false,
+ "selected": false
+ });
+ });
+
+
+ it('parseInitialData() -> link.fromNode & link.fromCP & link.toNode Exist => Verify srcCP' ,() => {
+ // init values / mock functions
+
+ //Simulate Array<ServicePathMapItem to pass to the function
+ const mapItemData1: MapItemData = { id: 'mapItemID', name: 'mapItemName'};
+ const servicePathItem1: ServicePathMapItem = { id: 'servicePathItemId', data: mapItemData1 };
+ const arrServicePathItems: ServicePathMapItem[] = [servicePathItem1];
+
+ //Simulate link
+ let link = {
+ fromNode:'testVal',
+ fromCP: 'testVal',
+ toNode: 'testVal'
+ };
+ fixture.componentInstance.link = link;
+
+ //Simulate the response from convertValuesToDropDownOptions()
+ const value = "expected_id_fromNode_and_fromCP_and_toNode";
+ const label = "expected_label_fromNode_and_fromCP_and_toNode"
+ let result:Array<DropdownValue> = [];
+ result[0] = new DropdownValue(value, label);
+ fixture.componentInstance.convertValuesToDropDownOptions = jest.fn(() => result);
+
+ //Simulate the response from findOptions()
+ const innerMapItemData1: MapItemData = { id: 'innerMapItemData1_id', name: 'innerMapItemData1_name', options: []};
+ const options: ServicePathMapItem = { id: 'innerServicePathItem_id', data: innerMapItemData1 };
+ fixture.componentInstance.findOptions = jest.fn(() => options);
+
+
+ // call to the tested function
+ fixture.componentInstance.parseInitialData(arrServicePathItems);
+
+ // expect that
+ expect(fixture.componentInstance.srcCP.length).toBe(1);
+ expect(fixture.componentInstance.srcCP[0]).toEqual({
+ "value": value,
+ "label": label,
+ "hidden": false,
+ "selected": false
+ });
+ });
+
+
+
+}); \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts
new file mode 100644
index 0000000000..83c30b1a60
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link-row.component.ts
@@ -0,0 +1,104 @@
+import {Component, Input} from '@angular/core';
+import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component";
+import {Link} from './link.model';
+import {ServicePathMapItem} from "app/models/graph/nodes-and-links-map";
+import * as _ from "lodash";
+
+@Component({
+ selector: 'link-row',
+ templateUrl: './link-row.component.html',
+ styleUrls: ['./link-row.component.less']
+})
+
+
+export class LinkRowComponent {
+ @Input() data:Array<ServicePathMapItem>;
+ @Input() link:Link;
+ @Input() removeRow:Function;
+ source: Array<DropdownValue> = [];
+ target: Array<DropdownValue> = [];
+ srcCP: Array<DropdownValue> = [];
+ targetCP: Array<DropdownValue> = [];
+
+ ngOnChanges() {
+ if (this.data) {
+ this.parseInitialData(this.data);
+ }
+ }
+
+ parseInitialData(data: Array<ServicePathMapItem>) {
+ this.source = this.convertValuesToDropDownOptions(data);
+ if (this.link.fromNode) {
+ let srcCPOptions = this.findOptions(data, this.link.fromNode);
+ if (!srcCPOptions) { return; }
+ this.srcCP = this.convertValuesToDropDownOptions(srcCPOptions);
+ if (this.link.fromCP) {
+ this.target = this.convertValuesToDropDownOptions(data);
+ if (this.link.toNode) {
+ let targetCPOptions = this.findOptions(data, this.link.toNode);
+ if (!targetCPOptions) { return; }
+ this.targetCP = this.convertValuesToDropDownOptions(targetCPOptions);
+ }
+ }
+ }
+ }
+
+ private findOptions(items: Array<ServicePathMapItem>, nodeOrCPId: string) {
+ let item = _.find(items, (dataItem) => nodeOrCPId === dataItem.id);
+ if (item && item.data && item.data.options) {
+ return item.data.options;
+ }
+ console.warn('no option was found to match selection of Node/CP with id:' + nodeOrCPId);
+ return null;
+ }
+
+ private convertValuesToDropDownOptions(values: Array<ServicePathMapItem>): Array<DropdownValue> {
+ let result:Array<DropdownValue> = [];
+ for (let i = 0; i < values.length ; i++) {
+ result[result.length] = new DropdownValue(values[i].id, values[i].data.name);
+ }
+ return result.sort((a, b) => a.label.localeCompare(b.label));
+ }
+
+ onSourceSelected(id) {
+ if (id) {
+ let srcCPOptions = this.findOptions(this.data, id);
+ this.srcCP = this.convertValuesToDropDownOptions(srcCPOptions);
+ this.link.fromCP = '';
+ this.link.toNode = '';
+ this.link.toCP = '';
+ this.target = [];
+ this.targetCP = [];
+ }
+ }
+
+ onSrcCPSelected (id) {
+ if (id) {
+ let srcCPOptions = this.findOptions(this.data, this.link.fromNode);
+ let srcCPData = srcCPOptions.find(option => id === option.id).data;
+ this.target = this.convertValuesToDropDownOptions(this.data);
+ this.link.fromCPOriginId = srcCPData.ownerId;
+ this.link.toNode = '';
+ this.link.toCP = '';
+ this.targetCP = [];
+ }
+
+ }
+
+ onTargetSelected(id) {
+ if (id) {
+ let targetCPOptions = this.findOptions(this.data, id);
+ this.targetCP = this.convertValuesToDropDownOptions(targetCPOptions);
+ this.link.toCP = '';
+ }
+
+ }
+
+ onTargetCPSelected(id) {
+ if (id) {
+ let targetCPOptions = this.findOptions(this.data, this.link.toNode);
+ let targetCPDataObj = targetCPOptions.find(option => id === option.id).data;
+ this.link.toCPOriginId = targetCPDataObj.ownerId;
+ }
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link.model.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link.model.ts
new file mode 100644
index 0000000000..80128eb42e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/link-row/link.model.ts
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+'use strict';
+import {ForwardingPathLink} from "app/models/forwarding-path-link";
+
+export class Link extends ForwardingPathLink {
+ public canEdit:boolean = false;
+ public canRemove:boolean = false;
+ public isFirst:boolean = false;
+
+ constructor(link: ForwardingPathLink, canEdit: boolean, canRemove: boolean, isFirst: boolean) {
+ super(link.fromNode,link.fromCP, link.toNode, link.toCP, link.fromCPOriginId, link.toCPOriginId);
+ this.canEdit = canEdit;
+ this.canRemove = canRemove;
+ this.isFirst = isFirst;
+ }
+}
+
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html
new file mode 100644
index 0000000000..db0d912934
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.html
@@ -0,0 +1,55 @@
+<!--
+ ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ ~
+ ~ Licensed 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="service-path-creator">
+ <form class="w-sdc-form">
+ <div class="i-sdc-form-item" >
+ <label class="i-sdc-form-label required">Flow Name</label>
+ <input type="text" data-tests-id="pathName" name="pathName" [(ngModel)]="forwardingPath.name" [attr.maxLength]="200" />
+ </div>
+
+ <div class="side-by-side">
+ <div class="i-sdc-form-item" >
+ <label class="i-sdc-form-label">Protocol</label>
+ <input type="text" data-tests-id="pathProtocol" name="protocol" [(ngModel)]="forwardingPath.protocol" [attr.maxLength]="200" />
+ </div>
+ <div class="i-sdc-form-item" >
+ <label class="i-sdc-form-label">Destination Port Numbers</label>
+ <input type="text" data-tests-id="pathPortNumbers" name="portNumbers" [(ngModel)]="forwardingPath.destinationPortNumber" pattern="[0-9,]*" />
+ </div>
+ </div>
+
+ <div class="separator-buttons">
+ <span class="based-on-title">Based On</span>
+ <a (click)="addRow()" [ngClass]="{'disabled':!isExtendAllowed()}" data-tests-id="extendPathlnk">Extend Flow</a>
+ </div>
+
+ <div class="generic-table">
+ <div class="header-row">
+ <div class="cell header-cell" *ngFor="let header of headers">
+ {{header}}
+ </div>
+ </div>
+ <div *ngIf="links && links.length === 0" class="no-row-text" >
+ There is no data to display
+ </div>
+ <div>
+ <link-row *ngFor="let link of links" [data]="linksMap" [link]="link" [removeRow]="removeRow" class="data-row" ></link-row>
+ </div>
+ </div>
+
+
+ </form>
+</div> \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less
new file mode 100644
index 0000000000..2a3efbdd3c
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.less
@@ -0,0 +1,45 @@
+@import './../../../../../../assets/styles/variables.less';
+.service-path-creator {
+ font-family: @font-opensans-regular;
+ .separator-buttons {
+ margin: 10px 0;
+ display: flex;
+ justify-content: space-between;
+ }
+ .i-sdc-form-label {
+ font-size: 12px;
+ }
+ .w-sdc-form .i-sdc-form-item {
+ margin-bottom: 15px;
+ }
+
+ .side-by-side {
+ display: flex;
+ .i-sdc-form-item {
+ flex-basis: 100%;
+ &:first-child {
+ margin-right: 10px;
+ }
+ }
+ }
+
+ .generic-table {
+ max-height: 233px;
+ .header-row .header-cell {
+ &:last-child {
+ padding: 0;
+ }
+ }
+ /deep/ .cell {
+ &:last-child {
+ min-width: 30px;
+ }
+ }
+ }
+
+ .based-on-title {
+ text-transform: uppercase;
+ font-size: 18px;
+ font-family: @font-opensans-regular;
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts
new file mode 100644
index 0000000000..17c2081a75
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.component.ts
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+import * as _ from "lodash";
+import { Component, ElementRef, forwardRef, Inject } from '@angular/core';
+import {Link} from './link-row/link.model';
+import {ForwardingPath} from 'app/models/forwarding-path';
+import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service";
+import {ForwardingPathLink} from "app/models/forwarding-path-link";
+import {ServicePathMapItem} from "app/models/graph/nodes-and-links-map";
+import {CompositionService} from "app/ng2/pages/composition/composition.service";
+
+@Component({
+ selector: 'service-path-creator',
+ templateUrl: './service-path-creator.component.html',
+ styleUrls:['./service-path-creator.component.less'],
+ providers: [ServiceServiceNg2]
+})
+
+export class ServicePathCreatorComponent {
+
+ linksMap:Array<ServicePathMapItem>;
+ links:Array<Link> = [];
+ input:any;
+ headers: Array<string> = [];
+ removeRow: Function;
+ forwardingPath:ForwardingPath;
+ //isExtendAllowed:boolean = false;
+
+ constructor(private serviceService: ServiceServiceNg2,
+ private compositionService: CompositionService) {
+ this.forwardingPath = new ForwardingPath();
+ this.links = [new Link(new ForwardingPathLink('', '', '', '', '', ''), true, false, true)];
+ this.headers = ['Source', 'Source Connection Point', 'Target', 'Target Connection Point', ' '];
+ this.removeRow = () => {
+ if (this.links.length === 1) {
+ return;
+ }
+ this.links.splice(this.links.length-1, 1);
+ this.enableCurrentRow();
+ };
+ }
+
+ ngOnInit() {
+ this.serviceService.getNodesAndLinksMap(this.input.serviceId).subscribe((res:any) => {
+ this.linksMap = res;
+ });
+ this.processExistingPath();
+
+ }
+
+ private processExistingPath() {
+ if (this.input.pathId) {
+ let forwardingPath = <ForwardingPath>{...this.compositionService.forwardingPaths[this.input.pathId]};
+ this.forwardingPath.name = forwardingPath.name;
+ this.forwardingPath.destinationPortNumber = forwardingPath.destinationPortNumber;
+ this.forwardingPath.protocol = forwardingPath.protocol;
+ this.forwardingPath.uniqueId = forwardingPath.uniqueId;
+ this.links = [];
+ _.forEach(forwardingPath.pathElements.listToscaDataDefinition, (link:ForwardingPathLink) => {
+ this.links[this.links.length] = new Link(link, false, false, false);
+ });
+ this.links[this.links.length - 1].canEdit = true;
+ this.links[this.links.length - 1].canRemove = true;
+ this.links[0].isFirst = true;
+ }
+ }
+
+ isExtendAllowed():boolean {
+ if (this.links[this.links.length-1].toCP) {
+ return true;
+ }
+ return false;
+ }
+
+ enableCurrentRow() {
+ this.links[this.links.length-1].canEdit = true;
+ if (this.links.length !== 1) {
+ this.links[this.links.length-1].canRemove = true;
+ }
+ }
+
+ addRow() {
+ this.disableRows();
+ this.links[this.links.length] = new Link(
+ new ForwardingPathLink(this.links[this.links.length-1].toNode,
+ this.links[this.links.length-1].toCP,
+ '',
+ '',
+ this.links[this.links.length-1].toCPOriginId,
+ ''
+ ),
+ true,
+ true,
+ false
+ );
+ }
+
+ disableRows() {
+ for (let i = 0 ; i < this.links.length ; i++) {
+ this.links[i].canEdit = false;
+ this.links[i].canRemove = false;
+ }
+ }
+
+ createPathLinksObject() {
+ for (let i = 0 ; i < this.links.length ; i++) {
+ let link = this.links[i];
+ this.forwardingPath.addPathLink(link.fromNode, link.fromCP, link.toNode, link.toCP, link.fromCPOriginId, link.toCPOriginId);
+ }
+ }
+
+ createServicePathData() {
+ this.createPathLinksObject();
+ return this.forwardingPath;
+ }
+
+ checkFormValidForSubmit():boolean {
+ if (this.forwardingPath.name && this.isPathValid() ) {
+ return true;
+ }
+ return false;
+ }
+
+ isPathValid():boolean {
+ let lastLink = this.links[this.links.length -1] ;
+ if (lastLink.toNode && lastLink.toCP && lastLink.fromNode && lastLink.fromCP) {
+ return true;
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.module.ts b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.module.ts
new file mode 100644
index 0000000000..78005317a2
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/service-path-creator/service-path-creator.module.ts
@@ -0,0 +1,25 @@
+import { NgModule } from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {ServicePathCreatorComponent} from "./service-path-creator.component";
+import {FormsModule} from "@angular/forms";
+import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module";
+import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module";
+import {LinkRowComponent} from './link-row/link-row.component'
+@NgModule({
+ declarations: [
+ ServicePathCreatorComponent,
+ LinkRowComponent
+ ],
+ imports: [CommonModule,
+ FormsModule,
+ FormElementsModule,
+ UiElementsModule
+ ],
+ exports: [],
+ entryComponents: [
+ ServicePathCreatorComponent
+ ],
+ providers: []
+})
+export class ServicePathCreatorModule {
+} \ No newline at end of file