diff options
author | Ittay Stern <ittay.stern@att.com> | 2018-08-29 17:01:32 +0300 |
---|---|---|
committer | Ittay Stern <ittay.stern@att.com> | 2019-02-18 18:35:30 +0200 |
commit | 6f900cc45d7dd7f97430812b86b5c1d1693c8ae3 (patch) | |
tree | 936005c364dc5a7264d6304d4777c3d83494db22 /vid-webpack-master/src/app/shared/components/searchMembersModal | |
parent | 67d99f816cc583643c35193197594cf78d8ce60a (diff) |
merge from ecomp a88f0072 - Modern UI
Issue-ID: VID-378
Change-Id: Ibcb23dd27f550cf32ce2fe0239f0f496ae014ff6
Signed-off-by: Ittay Stern <ittay.stern@att.com>
Diffstat (limited to 'vid-webpack-master/src/app/shared/components/searchMembersModal')
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(); + } +} + + |