summaryrefslogtreecommitdiffstats
path: root/vid-webpack-master/src/app/shared/components/searchMembersModal
diff options
context:
space:
mode:
Diffstat (limited to 'vid-webpack-master/src/app/shared/components/searchMembersModal')
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/member-table-row.model.ts6
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.html75
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.scss91
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.ts57
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.spec.ts270
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.ts153
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.html35
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.scss89
-rw-r--r--vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.ts82
9 files changed, 858 insertions, 0 deletions
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/member-table-row.model.ts b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/member-table-row.model.ts
new file mode 100644
index 000000000..c5f1a7a07
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/member-table-row.model.ts
@@ -0,0 +1,6 @@
+import {VnfMember} from "../../../models/VnfMember";
+
+export class MemberTableRowModel extends VnfMember{
+ isSelected : boolean = false;
+}
+
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.html b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.html
new file mode 100644
index 000000000..3a29ed824
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.html
@@ -0,0 +1,75 @@
+<div class="table-header">
+ <div class="left-header">
+ <span class="title-header">{{description}}</span>
+ <div class="sub-title-header">
+ <span class="vnf-match-your-criteria" class="total" [attr.data-tests-id]="'total-amount'" style="margin-right: 5px;"><span
+ [attr.data-tests-id]="'numberOfNotHideVnfMembers'">{{membersTableService.numberOfNotHideVnfMembers}}</span> VNFs match your criteria</span>
+ <span class="vnf-selected" class="total" [attr.data-tests-id]="'total-selected'"><span
+ [attr.data-tests-id]="'numberOfSelectedVnfMembers'">{{membersTableService.numberOfSelectedVnfMembers}}</span> VNF{{membersTableService.numberOfSelectedVnfMembers>1?'s':'' }} selected</span>
+ </div>
+ </div>
+
+ <div class="search-container">
+ <sdc-filter-bar
+ [placeHolder]="'Search...'"
+ [debounceTime]="250"
+ [testId]="'vnf-members-search'"
+ (valueChange)="search($event)">
+ </sdc-filter-bar>
+ </div>
+</div>
+<table id="member-table" class="table table-bordered" *ngIf="data?.length > 0">
+ <thead class="thead-dark">
+ <tr>
+ <th class="allCheckboxAreSelected" style="position: relative;">
+ <sdc-checkbox
+ [(checked)]="membersTableService.allCheckboxAreSelected"
+ [testId]="'all-checkbox-selected'"
+ (checkedChange)="changeAllCheckboxStatus($event)"
+ ></sdc-checkbox>
+ </th>
+ <th class="header-title" *ngFor="let header of headers">{{header.displayName}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="member-table-row" *ngFor="let vnf of membersTableService.filteredMembers">
+ <td class="sdcCheckboxMember" style="position: relative;" [attr.data-tests-id]="vnf?.instanceId">
+ <sdc-checkbox
+ [checked]="membersTableService.allMemberStatusMap[vnf.instanceId]?.isSelected"
+ [testId]="vnf?.instanceId"
+ (checkedChange)="changeCheckboxStatus(vnf.instanceId)"
+ ></sdc-checkbox></td>
+ <td id="vnfName">
+ <custom-ellipsis [id]="vnf?.instanceName" [value]="vnf?.instanceName"
+ [hightlight]="filterValue"></custom-ellipsis>
+ <custom-ellipsis class="second-line" [id]="vnf?.instanceId" [value]="'UUID: '+ vnf?.instanceId"
+ [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ <td id="version">
+ <custom-ellipsis [id]="vnf?.modelInfo?.modelVersion" [value]="vnf?.modelInfo?.modelVersion" [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ <td id="modelName">
+ <custom-ellipsis [id]="vnf?.modelInfo?.modelName" [value]="vnf?.modelInfo?.modelName" [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ <td id="provStatus">
+ <custom-ellipsis [id]="vnf?.provStatus" [value]="vnf?.provStatus" [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ <td id="serviceInstance">
+ <custom-ellipsis [id]="vnf?.serviceInstanceName" [value]="vnf?.serviceInstanceName"
+ [hightlight]="filterValue"></custom-ellipsis>
+ <custom-ellipsis class="second-line" [id]="vnf?.serviceInstanceId" [value]="'UUID: '+ vnf?.serviceInstanceId"
+ [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ <td id="cloudRegion">
+ <custom-ellipsis [id]="vnf?.lcpCloudRegionId" [value]="vnf?.lcpCloudRegionId" [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ <td id="tenantName">
+ <custom-ellipsis [id]="vnf?.tenantName" [value]="vnf?.tenantName" [hightlight]="filterValue"></custom-ellipsis>
+ </td>
+ </tr>
+
+ </tbody>
+</table>
+<div class="no-result" *ngIf="data?.length == 0">No VNFs were found that can belong to this group.</div>
+
+
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.scss b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.scss
new file mode 100644
index 000000000..3be975222
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.scss
@@ -0,0 +1,91 @@
+.table-header {
+ display: flex;
+ margin-bottom: 5px;
+ .left-header{
+ .title-header{
+ font-family: OpenSans-SemiBold;
+ color: #191919;
+ font-size: 15px;
+ margin-bottom: 5px;
+ display: block;
+ }
+
+ .sub-title-header{
+
+ .vnf-selected{
+ margin-left: 25px;
+ }
+
+ .vnf-match-your-criteria{
+ }
+ }
+ .total{
+ font-family: OpenSans-Regular;
+ color: #191919;
+ font-size: 15px;
+ margin-right: 10px;
+ }
+
+ }
+
+ .search-container{
+ flex-basis: 300px;
+ margin-left: auto;
+ }
+}
+
+#member-table>tbody+tbody {
+ border-top: 1px solid #ddd;
+}
+
+
+
+#member-table {
+ border: 1px solid #D2D2D2;
+ thead {
+ background: #F8F8F8;
+ th.allCheckboxAreSelected {
+ vertical-align: middle !important;
+ width: 48px;
+ max-width: 48px;
+ min-width: 48px;
+ height: 48px;
+ }
+ th.header-title {
+ font-family: OpenSans-SemiBold;
+ vertical-align: middle !important;
+ height: 48px;
+ font-size: 12px;
+ }
+ }
+ tbody {
+ td{
+ text-align: center;
+ height: 60px;
+ padding-top: 0;
+ padding-bottom: 0;
+ max-height: 60px;
+ vertical-align: middle;
+ .second-line {
+ font-size: 12px;
+ }
+ }
+ }
+
+
+ //font-size: 12px;
+
+ th.allCheckboxAreSelected {
+ text-align: center;
+ }
+}
+
+.no-result {
+ font-family: OpenSans-Regular;
+ width: 100%;
+ height: 100%;
+ border: 1px solid #d2d2d2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.ts b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.ts
new file mode 100644
index 000000000..9736563af
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.component.ts
@@ -0,0 +1,57 @@
+import {Component, Input, OnChanges, Output, SimpleChanges, EventEmitter} from '@angular/core';
+import {VnfMember} from "../../../models/VnfMember";
+import {MembersTableService} from "./members-table.service";
+import * as _ from 'lodash';
+
+export class CustomTableColumnDefinition {
+ public displayName = '';
+ public key : any = '';
+ public type? = 'text';
+ public filter? = '';
+}
+
+@Component({
+ selector: 'app-members-table',
+ templateUrl: './members-table.component.html',
+ styleUrls: ['./members-table.component.scss']
+})
+
+export class MembersTableComponent implements OnChanges{
+ filterValue: string = null;
+ allMemberStatusMap = null;
+ membersTableService : MembersTableService;
+ headers: CustomTableColumnDefinition[] = MembersTableService.getHeaders();
+ @Input() data: VnfMember[];
+ @Input() description: string;
+ @Output() selectedMembersAmountChange : EventEmitter<number> = new EventEmitter();
+ constructor(private _membersTableService : MembersTableService){
+ this.membersTableService = this._membersTableService;
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if(_.isNil(this.data)){
+ this._membersTableService.resetAll();
+ }else {
+ this._membersTableService.allMemberStatusMap = MembersTableService.generateAllMembersStatus(this.data);
+ this._membersTableService.filteredMembers = MembersTableService.sortVnfMembersByName(this.data, "instanceName");
+ this._membersTableService.updateAmountsAndCheckAll();
+ }
+ }
+
+ search(searchStr: string): void {
+ this.filterValue = searchStr;
+ this._membersTableService.filterMembers(this.filterValue);
+ }
+
+ changeAllCheckboxStatus(status: boolean) : void {
+ this._membersTableService.changeAllCheckboxStatus(status);
+ this.selectedMembersAmountChange.emit(this._membersTableService.numberOfSelectedVnfMembers);
+ }
+
+
+ changeCheckboxStatus(vnfInstanceId: string) : void {
+ this._membersTableService.changeCheckboxStatus(vnfInstanceId);
+ this.selectedMembersAmountChange.emit(this._membersTableService.numberOfSelectedVnfMembers);
+ }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.spec.ts b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.spec.ts
new file mode 100644
index 000000000..e53c63be1
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.spec.ts
@@ -0,0 +1,270 @@
+import {MembersTableService} from "./members-table.service";
+import {TestBed, getTestBed} from "@angular/core/testing";
+import {NgRedux} from "@angular-redux/store";
+import {CustomTableColumnDefinition} from "./members-table.component";
+import {AppState} from "../../../store/reducers";
+import {createRelatedVnfMemberInstance} from "../../../storeUtil/utils/relatedVnfMember/relatedVnfMember.actions";
+import {DataFilterPipe} from "../../../pipes/dataFilter/data-filter.pipe";
+import {VnfMember} from "../../../models/VnfMember";
+
+
+
+class MockAppStore<T> {
+ dispatch() {
+ }
+ getState() {
+ return {
+ service : {
+ serviceHierarchy: {
+ },
+ serviceInstance : {
+ "serviceModelId" : {
+ vnfGroups:{
+ "aa1":{
+ vnfs:{
+ "VNF1_INSTANCE_ID":{
+ "action": "None",
+ "instanceName": "VNF1_INSTANCE_NAME",
+ "instanceId": "VNF1_INSTANCE_ID",
+ "orchStatus": null,
+ "lcpCloudRegionId": "mtn23b",
+ "tenantId": "3e9a20a3e89e45f884e09df0cc2d2d2a",
+ "tenantName": "APPC-24595-T-IST-02C",
+ "modelInfo": {
+ "modelInvariantId": "vnf-instance-model-invariant-id",
+ "modelVersionId": "7a6ee536-f052-46fa-aa7e-2fca9d674c44",
+ "modelVersion": "2.0",
+ "modelName": "vf_vEPDG",
+ "modelType": "vnf"
+ },
+ "instanceType": "VNF1_INSTANCE_TYPE",
+ "provStatus": null,
+ "inMaint": false,
+ "uuid": "7a6ee536-f052-46fa-aa7e-2fca9d674c44",
+ "trackById": "7a6ee536-f052-46fa-aa7e-2fca9d674c44:002",
+ "serviceInstanceId": "service-instance-id1",
+ "serviceInstanceName": "service-instance-name"
+
+ },
+ "aa1-vnf1":{
+ vnfName: "",
+ instanceId:"",
+ serviceInstanceId:""
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+}
+
+describe('MembersTableService view member count', () => {
+ let injector;
+ let service: MembersTableService;
+ let store: NgRedux<AppState>;
+ let data = loadMockMembers();
+
+ beforeAll(done => (async () => {
+
+ TestBed.configureTestingModule(
+ {
+ providers: [
+ MembersTableService,
+ {provide: NgRedux, useClass: MockAppStore},
+ DataFilterPipe
+
+ ],
+ declarations: [DataFilterPipe]
+ });
+ await TestBed.compileComponents();
+
+ injector = getTestBed();
+ service = injector.get(MembersTableService);
+ store = injector.get(NgRedux)
+
+ })().then(done).catch(done.fail));
+
+
+ test('should return number of displayed members', () => {
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>data);
+ service.filteredMembers = <any>data;
+ expect(service.calculateNotHideVnfMembers()).toEqual(2);
+ });
+
+ test('should return number of selected members', () => {
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>data);
+ service.allMemberStatusMap['VNF1_INSTANCE_ID'].isSelected = true;
+ service.allMemberStatusMap['VNF2_INSTANCE_ID'].isSelected = true;
+ expect(service.calculateSelectedVnfMembers()).toEqual(2);
+ });
+
+ test('should return number of selected members', () => {
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>data);
+ service.filteredMembers = <any>data;
+ service.allMemberStatusMap['VNF1_INSTANCE_ID'].isSelected = true;
+ service.filterMembers('VNF2');
+ service.allMemberStatusMap['VNF2_INSTANCE_ID'].isSelected = true;
+ expect(service.calculateNotHideVnfMembers()).toEqual(1);
+ });
+
+ test('getHeader should return labels with array of keys', () => {
+ const headers: CustomTableColumnDefinition[] = MembersTableService.getHeaders();
+ expect(headers).toEqual([
+ {displayName: 'VNF instance name', key: ['instanceName']},
+ {displayName: 'VNF version', key: ['modelInfo', 'modelVersion']},
+ {displayName: 'VNF model name', key: ['modelInfo', 'modelName']},
+ {displayName: 'Prov Status', key: ['provStatus']},
+ {displayName: 'Service instance name', key: ['serviceInstanceName']},
+ {displayName: 'Cloud Region', key: ['lcpCloudRegionId']},
+ {displayName: 'Tenant Name', key: ['tenantName']}
+ ]);
+ });
+
+
+ test('setMembers should dispatch action only on selected members', () => {
+ const vnfGroupStoreKey: string = 'vnfGroupStoreKey';
+ const serviceId: string = 'serviceId';
+
+ jest.spyOn(store, 'dispatch');
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>data);
+ service.allMemberStatusMap['VNF1_INSTANCE_ID'].isSelected = true;
+ service.setMembers({serviceId: serviceId, vnfGroupStoreKey: vnfGroupStoreKey});
+ expect(store.dispatch).toHaveBeenCalledTimes(1);
+ expect(store.dispatch).toHaveBeenCalledWith(createRelatedVnfMemberInstance(vnfGroupStoreKey, serviceId, service.allMemberStatusMap['VNF1_INSTANCE_ID']));
+ });
+
+ test('generateAllMembersStatus should add to each instance isHide and isSelected and convert to map', () => {
+
+ let allMemberStatusMapMock = MembersTableService.generateAllMembersStatus(<any>data);
+ for (const key in allMemberStatusMapMock) {
+ expect(allMemberStatusMapMock[key].isSelected).toBeFalsy();
+ }
+ });
+
+ test('changeAllCheckboxStatus', () => {
+ let data = loadMockMembers();
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>data);
+ service.filteredMembers = <any>data;
+ service.changeAllCheckboxStatus(true);
+ for (let key in service.allMemberStatusMap) {
+ expect(service.allMemberStatusMap[key].isSelected).toEqual(true);
+ }
+ });
+
+ test('should reset all numbers and lists', () => {
+ let data = loadMockMembers();
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>data);
+ service.filteredMembers = <any>data;
+ service.changeAllCheckboxStatus(true);
+ service.resetAll();
+ expect(service.numberOfNotHideVnfMembers).toEqual(0);
+ expect(service.numberOfSelectedAndNotHideVnfMembers).toEqual(0);
+ expect(service.numberOfSelectedVnfMembers).toEqual(0);
+ expect(service.allMemberStatusMap).toEqual({});
+ expect(service.filteredMembers.length).toEqual(0);
+ });
+
+ test('checkAllCheckboxStatus should be false if not all are selected', () => {
+ service.allMemberStatusMap = MembersTableService.generateAllMembersStatus(<any>loadMockMembers());
+ service.updateAmountsAndCheckAll();
+
+ expect(service.allCheckboxAreSelected).toEqual(false);
+ });
+
+
+ test('sortVnfMembersByName should sort list by vnf name', () => {
+ let data = <any>loadMockMembers();
+ let sortedList = MembersTableService.sortVnfMembersByName(data, "instanceName");
+
+ expect(sortedList[0].instanceName).toEqual("VNF1_INSTANCE_NAME");
+ expect(sortedList[1].instanceName).toEqual("VNF2_INSTANCE_NAME");
+
+ let tmp = data[0];
+ data[0] = data[1];
+ data[1] = tmp;
+
+ sortedList = MembersTableService.sortVnfMembersByName(data, "instanceName");
+
+ expect(sortedList[1].instanceName).toEqual("VNF1_INSTANCE_NAME");
+ expect(sortedList[0].instanceName).toEqual("VNF2_INSTANCE_NAME");
+ sortedList = MembersTableService.sortVnfMembersByName(null, "instanceName");
+ expect(sortedList).toEqual([]);
+ sortedList = MembersTableService.sortVnfMembersByName(data, undefined);
+ expect(sortedList).toEqual([]);
+ });
+
+ test('should return only vnf members not associated to any vnf group', ()=>{
+ const result: VnfMember[] = service.filterUsedVnfMembers("serviceModelId",loadMockMembers());
+ expect(result.length).toEqual(1);
+ expect(result[0].instanceId).toEqual("VNF2_INSTANCE_ID");
+ });
+
+});
+
+
+function loadMockMembers(): any[] {
+ return [
+ {
+ "action": "None",
+ "instanceName": "VNF1_INSTANCE_NAME",
+ "instanceId": "VNF1_INSTANCE_ID",
+ "orchStatus": null,
+ "productFamilyId": null,
+ "lcpCloudRegionId": "mtn23b",
+ "tenantId": "3e9a20a3e89e45f884e09df0cc2d2d2a",
+ "tenantName": "APPC-24595-T-IST-02C",
+ "modelInfo": {
+ "modelInvariantId": "vnf-instance-model-invariant-id",
+ "modelVersionId": "7a6ee536-f052-46fa-aa7e-2fca9d674c44",
+ "modelVersion": "2.0",
+ "modelName": "vf_vEPDG",
+ "modelType": "vnf"
+ },
+ "instanceType": "VNF1_INSTANCE_TYPE",
+ "provStatus": null,
+ "inMaint": false,
+ "uuid": "7a6ee536-f052-46fa-aa7e-2fca9d674c44",
+ "originalName": null,
+ "legacyRegion": null,
+ "lineOfBusiness": null,
+ "platformName": null,
+ "trackById": "7a6ee536-f052-46fa-aa7e-2fca9d674c44:002",
+ "serviceInstanceId": "service-instance-id1",
+ "serviceInstanceName": "service-instance-name"
+ },
+ {
+ "action": "None",
+ "instanceName": "VNF2_INSTANCE_NAME",
+ "instanceId": "VNF2_INSTANCE_ID",
+ "orchStatus": null,
+ "productFamilyId": null,
+ "lcpCloudRegionId": "mtn23b",
+ "tenantId": "3e9a20a3e89e45f884e09df0cc2d2d2a",
+ "tenantName": "APPC-24595-T-IST-02C",
+ "modelInfo": {
+ "modelInvariantId": "vnf-instance-model-invariant-id",
+ "modelVersionId": "eb5f56bf-5855-4e61-bd00-3e19a953bf02",
+ "modelVersion": "1.0",
+ "modelName": "vf_vEPDG",
+ "modelType": "vnf"
+ },
+ "instanceType": "VNF2_INSTANCE_TYPE",
+ "provStatus": null,
+ "inMaint": true,
+ "uuid": "eb5f56bf-5855-4e61-bd00-3e19a953bf02",
+ "originalName": null,
+ "legacyRegion": null,
+ "lineOfBusiness": null,
+ "platformName": null,
+ "trackById": "eb5f56bf-5855-4e61-bd00-3e19a953bf02:003",
+ "serviceInstanceId": "service-instance-id2",
+ "serviceInstanceName": "service-instance-name"
+ }
+ ];
+}
+
+
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.ts b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.ts
new file mode 100644
index 000000000..5b9cd39a2
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/members-table/members-table.service.ts
@@ -0,0 +1,153 @@
+import {Injectable} from "@angular/core";
+import {VnfMember} from "../../../models/VnfMember";
+import {CustomTableColumnDefinition} from "./members-table.component";
+import {NgRedux} from "@angular-redux/store";
+import {AppState} from "../../../store/reducers";
+import {createRelatedVnfMemberInstance} from "../../../storeUtil/utils/relatedVnfMember/relatedVnfMember.actions";
+import * as _ from 'lodash';
+import {DataFilterPipe} from "../../../pipes/dataFilter/data-filter.pipe";
+import {MemberTableRowModel} from "./member-table-row.model";
+
+@Injectable()
+export class MembersTableService {
+ allMemberStatusMap : { [key:string]: MemberTableRowModel; };
+ filteredMembers : VnfMember[];
+ allCheckboxAreSelected : boolean;
+ numberOfNotHideVnfMembers : number;
+ numberOfSelectedVnfMembers : number;
+ numberOfSelectedAndNotHideVnfMembers : number;
+
+ constructor(private _store: NgRedux<AppState>, private dataFilter: DataFilterPipe){
+ this.resetAll();
+ }
+
+ filterUsedVnfMembers = (serviceModelId: string, result: VnfMember[]): VnfMember[] => {
+ const allMembersMap = _.keyBy(result as VnfMember[], 'instanceId');
+ const vnfGroupsData = this._store.getState().service.serviceInstance[serviceModelId].vnfGroups;
+ const vnfMembersArr = _.flatMap(vnfGroupsData).map((vnfGroup) =>vnfGroup.vnfs );
+ for( let vnf of vnfMembersArr ){
+ for(let member in vnf){
+ delete allMembersMap[member];
+ }
+ }
+ return _.flatMap(allMembersMap);
+ };
+
+ updateAmountsAndCheckAll = () : void => {
+ this.numberOfSelectedVnfMembers = this.calculateSelectedVnfMembers();
+ this.numberOfNotHideVnfMembers = this.calculateNotHideVnfMembers();
+ this.numberOfSelectedAndNotHideVnfMembers = this.calculateSelectedAndNotHide();
+ this.allCheckboxAreSelected = this.numberOfNotHideVnfMembers > 0 && this.numberOfNotHideVnfMembers === this.numberOfSelectedAndNotHideVnfMembers;
+ };
+
+ resetAll = () : void => {
+ this.allMemberStatusMap = {};
+ this.filteredMembers = [];
+ this.numberOfSelectedVnfMembers = 0;
+ this.numberOfNotHideVnfMembers = 0;
+ this.numberOfSelectedAndNotHideVnfMembers = 0;
+ this.allCheckboxAreSelected = false;
+ };
+
+ changeAllCheckboxStatus = (status : boolean) : void =>{
+ for(const member of this.filteredMembers){
+ this.allMemberStatusMap[member.instanceId].isSelected = status;
+ }
+ this.updateAmountsAndCheckAll();
+ };
+
+ changeCheckboxStatus = (vnfInstanceId : string ) : void =>{
+ this.allMemberStatusMap[vnfInstanceId].isSelected = !this.allMemberStatusMap[vnfInstanceId].isSelected;
+ this.updateAmountsAndCheckAll();
+ };
+
+ /************************************************
+ iterate over all current vnf members:
+ 1) if vnf member is selected then update REDUX store
+ 2) if vnf member is not selected then delete member
+ @allMemberStatusMap: current vnf member status
+ @vnfGroupStoreKey: vnf group store key
+ @serviceId: service model id
+ ************************************************/
+ setMembers = (data : {serviceId : string, vnfGroupStoreKey : string}) : void =>{
+ let tmpMembers = this.allMemberStatusMap;
+ for(let key in tmpMembers){
+ if(tmpMembers[key].isSelected){
+ this._store.dispatch(createRelatedVnfMemberInstance( data.vnfGroupStoreKey, data.serviceId, tmpMembers[key]));
+ }
+ }
+ };
+
+ filterMembers(searchStr: string): void {
+ const keys: string[][] = MembersTableService.getDataKeys();
+ this.filteredMembers = this.dataFilter.transform(_.values(this.allMemberStatusMap), searchStr || '', keys);
+ this.updateAmountsAndCheckAll();
+ }
+
+ /************************************
+ generate vnf member data for select/ unselect rows
+ ************************************/
+ static generateAllMembersStatus(tableData : VnfMember[]) : { [key:string]: MemberTableRowModel; }{
+
+ tableData.map((vnf) => {
+ vnf['isSelected'] = false
+ });
+ return _.keyBy(tableData as MemberTableRowModel[], 'instanceId');
+ }
+
+
+ static sortVnfMembersByName(list : VnfMember[], keyName : string) :VnfMember[]{
+ if(!_.isNil(list) && !_.isNil(keyName)) {
+ return list.sort(function(itemA, itemB) { return itemA[keyName]- itemB[keyName];})
+ }
+ return [];
+
+ }
+
+ /********************************
+ table columns headers and key's
+ ********************************/
+ static getHeaders() : CustomTableColumnDefinition[] {
+ return [
+ {displayName: 'VNF instance name', key: ['instanceName']},
+ {displayName: 'VNF version', key: ['modelInfo', 'modelVersion']},
+ {displayName: 'VNF model name', key: ['modelInfo', 'modelName']},
+ {displayName: 'Prov Status', key: ['provStatus']},
+ {displayName: 'Service instance name', key: ['serviceInstanceName']},
+ {displayName: 'Cloud Region', key: ['lcpCloudRegionId']},
+ {displayName: 'Tenant Name', key: ['tenantName']}
+ ];
+ }
+
+ static getDataKeys(): string[][]{
+ const headers = MembersTableService.getHeaders();
+ return headers.map((header)=> header.key).concat([['instanceId']],[['serviceInstanceId']]);
+ }
+
+ /*************************************************************************************
+ calculate the number of selected vnf members - include not visible and visible rows
+ @allMemberStatusMap: current vnf member status
+ *************************************************************************************/
+ calculateSelectedVnfMembers() : number {
+ const flatObject = _.values(this.allMemberStatusMap);
+ return _.filter(flatObject, (item) => { if (item.isSelected) return item }).length;
+ }
+
+ /************************************************
+ calculate the number of display vnf members
+ @allMemberStatusMap: current vnf member status
+ ************************************************/
+ calculateNotHideVnfMembers() : number {
+ return this.filteredMembers.length;
+ }
+
+ /************************************************
+ calculate the number of display vnf members
+ @allMemberStatusMap: current vnf member status
+ ************************************************/
+ calculateSelectedAndNotHide() : number {
+ return _.filter(this.filteredMembers, (item) => { if ( this.allMemberStatusMap[item.instanceId].isSelected) return item }).length;
+ }
+
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.html b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.html
new file mode 100644
index 000000000..899bc9889
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.html
@@ -0,0 +1,35 @@
+<div class="modal-search-member-content">
+ <div class="header">
+ <vid-svg-icon
+ [attr.data-tests-id]="'cancelBtn'"
+ (click)="closeDialog()"
+ class="navigation-arrow-back"
+ [mode]="'primary'"
+ [size]="'large'"
+ [name]="'navigation-arrow-back'"
+ [clickable]="true"
+ [fill]="'#FFFFFF'"
+ [widthViewBox]="'24'"
+ [heightViewBox]="'24'">
+ </vid-svg-icon>
+
+ <span class="title">
+ {{title}}
+ </span>
+ <button type="submit" data-tests-id="setMembersBtn" [disabled]="disableSetMembers" (click)="setMembers()" class="sdc-button sdc-button__primary">SET MEMBERS</button>
+ </div>
+ <div class="content-wrapper">
+ <div class="sidebar-left">
+ <div class="search-criteria-wrapper">
+ <div class="search-criteria-title">SEARCH CRITERIA</div>
+ <div class="search-item" *ngFor="let searchFieldItem of searchFields">
+ <span class="label-item">{{searchFieldItem.title}}</span>
+ <span attr.data-tests-id="{{searchFieldItem.dataTestId}}" class="text-item">{{searchFieldItem.value}}</span>
+ </div>
+ </div>
+ </div>
+ <div class="sidebar-right">
+ <app-members-table [data]="membersData" [description]="description" (selectedMembersAmountChange)="selectedMembersAmountChange($event)"></app-members-table>
+ </div>
+ </div>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.scss b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.scss
new file mode 100644
index 000000000..d49653934
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.scss
@@ -0,0 +1,89 @@
+.modal-search-member-content {
+ height: 100vh;
+ width: 100vw;
+ position: relative;
+ background: white;
+ .header {
+ height: 60px;
+ font-family: OpenSans-Regular;
+ display: -webkit-box;
+ display: flex;
+ font-size: 14px;
+ box-shadow: 2px 2px 6px #D2D2D2;
+ color: white;
+ background: #009fdb;
+ z-index: 1;
+ position: relative;
+ .navigation-arrow-back {
+ border-right: 1px solid #1eb9f3;
+ width: 60px;
+ height: 60px;
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+ .title {
+ font-size: 18px;
+ line-height: 60px;
+ margin-left: 20px;
+ }
+ button {
+ width: 125px;
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ margin-left: auto;
+ margin-right: 20px;
+ margin-top: 12px;
+ border: 1px solid white;
+ &:disabled {
+ opacity: 0.5;
+ background: none;
+ }
+ }
+ }
+
+ .content-wrapper {
+ display: flex;
+
+ .sidebar-left {
+ flex-basis: 285px;
+ border-right: 1px solid #D2D2D2;
+ height: calc(100vh - 60px);
+
+ .search-criteria-wrapper{
+
+ .search-criteria-title{
+ font-family: OpenSans-SemiBold;
+ font-size: 14px;
+ color: #191919;
+ border-bottom: 1px solid #D2D2D2;
+ line-height: 50px;
+ padding-left: 30px;
+ }
+ .search-item{
+ color: #191919;
+ display: flex;
+ flex-direction: column;
+ margin: 25px 30px;
+ .label-item {
+ font-family: OpenSans-SemiBold;
+ font-size: 12px;
+ }
+ .text-item{
+ font-family: OpenSans-Regular;
+ font-size: 14px;
+ color: #5a5a5a;
+ word-break: break-all;
+ }
+
+ }
+ }
+ }
+
+ .sidebar-right {
+ flex: 1;
+ margin: 80px 50px;
+ }
+ }
+}
diff --git a/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.ts b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.ts
new file mode 100644
index 000000000..9c65d222d
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/searchMembersModal/search-members-modal.component.ts
@@ -0,0 +1,82 @@
+import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
+import {DialogComponent, DialogService} from "ng2-bootstrap-modal";
+import {IframeService} from "../../utils/iframe.service";
+import {AaiService} from "../../services/aaiService/aai.service";
+import {VnfMember} from "../../models/VnfMember";
+import {VnfGroupModel} from "../../models/vnfGroupModel";
+import {MembersTableService} from "./members-table/members-table.service";
+import {VnfGroupInstance} from "../../models/vnfGroupInstance";
+
+
+export interface PopupModel {
+ title: string;
+ serviceModelId : string;
+ searchFields: ISearchField[];
+ description : string;
+ subscriberId: string,
+ serviceType: string,
+ node: VnfGroupInstance,
+ vnfGroupModel: VnfGroupModel;
+
+}
+
+export interface ISearchField {
+ title: string;
+ value: any;
+ dataTestId: string;
+}
+
+@Component({
+ selector : 'search-members-modal',
+ templateUrl : 'search-members-modal.component.html',
+ styleUrls : ['search-members-modal.component.scss']
+})
+
+export class SearchMembersModalComponent extends DialogComponent<PopupModel, boolean> implements OnInit, OnDestroy {
+ title: string;
+ serviceModelId : string;
+ parentElementClassName = 'content';
+ membersData: VnfMember[];
+ description : string;
+ searchFields: ISearchField[];
+ vnfGroupModel: VnfGroupModel;
+ subscriberId: string;
+ serviceType: string;
+ node: VnfGroupInstance;
+ disableSetMembers: boolean = true;
+ constructor(dialogService: DialogService ,
+ private _iframeService : IframeService,
+ private _aaiService : AaiService,
+ private _membersTableService: MembersTableService){
+ super(dialogService);
+
+ }
+ @ViewChild('MembersTableComponent') membersTable;
+
+ ngOnInit() : void{
+ this._aaiService.getOptionalGroupMembers(this.serviceModelId, this.subscriberId, this.serviceType, (Object.values(this.vnfGroupModel.members))[0].sourceModelInvariant, this.vnfGroupModel.properties.type, this.vnfGroupModel.properties.role)
+ .subscribe((result: VnfMember[])=>{
+ this.membersData = this._membersTableService.filterUsedVnfMembers(this.serviceModelId, result);
+ });
+ };
+
+
+ closeDialog() : void{
+ this._iframeService.removeClassCloseModal(this.parentElementClassName);
+ this.dialogService.removeDialog(this);
+ setTimeout(() => {
+ window.parent.postMessage("closeIframe", "*");
+ }, 15);
+ }
+ selectedMembersAmountChange(selectedMembersAmount: number) : void {
+ this.disableSetMembers = selectedMembersAmount==0;
+ }
+
+
+ setMembers() : void {
+ this._membersTableService.setMembers({serviceId : this.serviceModelId, vnfGroupStoreKey : this.node.vnfGroupStoreKey});
+ this.closeDialog();
+ }
+}
+
+