From 091343aa4bbf1bd6b882e08113d90685c1c84ffe Mon Sep 17 00:00:00 2001 From: Yoav Schneiderman Date: Wed, 20 Nov 2019 16:50:45 +0200 Subject: Allow platform multi-selection for VNF in modern UI Issue-ID: VID-722 Change-Id: Id87f59fff128e277d9158b83f3908754375c8b01 Signed-off-by: Yoav Schneiderman Signed-off-by: Einat Vinouze --- .../multiselect.formControl.component.html | 40 +++++++----- .../multiselect.formControl.component.spec.ts | 74 ---------------------- .../multiselect.formControl.component.ts | 45 ++++++++++++- .../multiselect/multiselect.formControl.service.ts | 50 +++++++++++++++ .../component/multiselect/multiselect.model.ts | 11 ++++ .../vnfGenerator/vnf.control.generator.spec.ts | 30 +++++++++ .../vnfGenerator/vnf.control.generator.ts | 52 +++++++++++++-- .../genericForm/generic-form.component.html | 5 ++ .../multiselectFormControl.model.ts | 10 ++- vid-webpack-master/src/app/shared/shared.module.ts | 2 + 10 files changed, 221 insertions(+), 98 deletions(-) delete mode 100644 vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts create mode 100644 vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts create mode 100644 vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts (limited to 'vid-webpack-master/src/app/shared') diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html index f7c4894b2..f205259e4 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.html @@ -1,16 +1,26 @@ -
-
- - - -
-
+
+ + + > + + + + + + + + +
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts deleted file mode 100644 index 81c8d4679..000000000 --- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core' -import {CommonModule} from "@angular/common"; -import {FormBuilder, FormControl, ReactiveFormsModule, Validators} from "@angular/forms"; -import { - ValidatorModel, - ValidatorOptions -} from "../../../../models/formControlModels/formControl.model"; -import {FormControlMessageErrorComponent} from "../../errorMessage/formControlMessageError.component"; -import {BrowserModule} from "@angular/platform-browser"; -import {MultiselectFormControlComponent} from "./multiselect.formControl.component"; -import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; -import { of } from "rxjs"; -describe('Dropdown Form Control Component', () => { - let component: MultiselectFormControlComponent; - let fixture: ComponentFixture; - let fb: FormBuilder; - - beforeAll(done => (async () => { - TestBed.configureTestingModule({ - imports: [CommonModule, BrowserModule, ReactiveFormsModule], - providers: [FormBuilder], - declarations: [MultiselectFormControlComponent, FormControlMessageErrorComponent], - schemas: [CUSTOM_ELEMENTS_SCHEMA] - }); - await TestBed.compileComponents(); - - fixture = TestBed.createComponent(MultiselectFormControlComponent); - component = fixture.componentInstance; - fb = TestBed.get(FormBuilder); - - })().then(done).catch(done.fail)); - - test('component should initialize basic parameters', () => { - component.data = new MultiselectFormControl({ - displayName: "display Name", - validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], - dataTestId: "data-test-id", - placeHolder: "place holder", - controlName: 'testDropdown', - options: of([ - 'option1', - 'option2', - 'option3', - 'onBlur' - ]) - }); - - component.data.hasErrors = function () { - return this.formGroup.controls[this.controlName].touched && this.formGroup.controls[this.controlName].errors ? ['error-style'] : []; - }; - - component.data.onBlur = function () { - component.form.controls['testDropdown'].setValue('onBlur'); - }; - - component.form = fb.group({ - 'testDropdown': new FormControl({ - value: component.data.value, - disabled: false - }, Validators.compose(component.data.validations.map(item => item.validator))) - }); - - component.form.controls['testDropdown'].setValue(''); - expect(component.form.controls['testDropdown'].errors.required).toBeTruthy(); - component.form.controls['testDropdown'].setValue('option2'); - expect(component.form.controls['testDropdown'].errors).toBeFalsy(); - component.data.onBlur(); - expect(component.form.controls['testDropdown'].value).toEqual('onBlur'); - expect(component.form.controls['testDropdown'].errors).toBeFalsy(); - } - ) -}); - diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts index 4b98c7e26..9b900dedf 100644 --- a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.component.ts @@ -1,6 +1,8 @@ import {Component, Input, OnChanges, SimpleChanges} from "@angular/core"; import {FormGroup} from "@angular/forms"; import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiselectFormControlService} from "./multiselect.formControl.service"; +import {MultiSelectItem} from "./multiselect.model"; @Component({ selector: 'multiselect-form-control', @@ -8,13 +10,52 @@ import {MultiselectFormControl} from "../../../../models/formControlModels/multi }) export class MultiselectFormControlComponent implements OnChanges{ @Input() data: MultiselectFormControl = null; + @Input() multiselectOptions: [] = null; + @Input() selectedItems = []; @Input() form: FormGroup = null; - ngOnChanges(changes: SimpleChanges): void { + + multiselectFormControlService : MultiselectFormControlService; + constructor(private _multiselectFormControlService : MultiselectFormControlService){ + this.multiselectFormControlService = _multiselectFormControlService; + } + dropdownSettings = { + singleSelection : false + }; + + options : MultiSelectItem[]; + + + + async ngOnChanges(changes: SimpleChanges) { + if(this.data.options$){ + this._multiselectFormControlService.convertOriginalItems(this.data).then((options)=>{ + this.options = options; + this._multiselectFormControlService.convertSelectedItems(this.data).then((res)=> { + this.selectedItems = res; + this.form.controls[this.data.controlName].setValue(this.selectedItems); + }) + }); + + } if (changes["data"] !== undefined && changes["data"].currentValue !== changes["data"].previousValue && changes["data"].firstChange) { - if(this.data.onInit){ + if (this.data.onInit) { this.data.onInit(this.data, this.form); } } } + + onItemSelect(item:any){ + this.data.onChange(this.selectedItems ,this.form); + } + OnItemDeSelect(item:any){ + this.data.onChange(this.selectedItems ,this.form); + } + onSelectAll(items: any){ + this.data.onChange(this.selectedItems ,this.form); + } + onDeSelectAll(items: any){ + this.data.onChange(this.selectedItems ,this.form); + } } + diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts new file mode 100644 index 000000000..4a9580563 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.formControl.service.ts @@ -0,0 +1,50 @@ +import {Injectable} from "@angular/core"; +import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiSelectItem} from "./multiselect.model"; +import * as _ from "lodash"; + + +@Injectable() +export class MultiselectFormControlService { + + convertOriginalItems = (data : MultiselectFormControl) : Promise => { + return new Promise((resolve) =>{ + let result: MultiSelectItem[] = []; + if(data.options$) { + let index: number = 1; + data.options$.map((originalItems: any) => { + result.push(new MultiSelectItem(index, originalItems[data.ngValue], originalItems[data.selectedFieldName])); + index++; + }); + } + resolve(result); + }) + }; + + + convertOptionsToHashMap = (config : MultiselectFormControl) => { + let index = 1; + return _.reduce(config.options$ , (obj, param: any ) => { + param.index = index; + index++; + obj[param[config.ngValue]] = param; + return obj; + }, {}); + }; + + convertSelectedItems(data : MultiselectFormControl) : Promise{ + return new Promise((resolve) =>{ + let result: MultiSelectItem[] = []; + const hashMap = this.convertOptionsToHashMap(data); + + if(data.options$ && data.value) { + const convertArray = data.convertOriginalDataToArray ? data.convertOriginalDataToArray(data.value) : data.value; + convertArray.map((itemId) => { + const uniqueIdentifier = itemId.trim(); + result.push(new MultiSelectItem(hashMap[uniqueIdentifier].index, hashMap[uniqueIdentifier][data.ngValue], hashMap[uniqueIdentifier][data.selectedFieldName])); + }); + } + resolve(result); + }); + } +} diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts new file mode 100644 index 000000000..a495211d4 --- /dev/null +++ b/vid-webpack-master/src/app/shared/components/formControls/component/multiselect/multiselect.model.ts @@ -0,0 +1,11 @@ +export class MultiSelectItem { + id : number; + itemId : number; + itemName : string; + + constructor(genericId: number, itemId : number, itemName : string){ + this.id = genericId; + this.itemId = itemId; + this.itemName = itemName; + } +} diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts index 5c6e25c6b..9230ccfa7 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts @@ -16,6 +16,7 @@ import {VnfControlGenerator} from "./vnf.control.generator"; import {Observable} from "rxjs"; import {SelectOption} from "../../../../models/selectOption"; import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service"; +import {FormControlType} from "../../../../models/formControlModels/formControlTypes.enum"; class MockAppStore { getState(){ @@ -939,6 +940,35 @@ describe('VNF Control Generator', () => { })().then(done).catch(done.fail)); + + test('should call platform dropdown control', ()=>{ + spyOn(service, 'getPlatformDropdownControl'); + + service.getPlatformControl(null, [], false); + + expect(service.getPlatformDropdownControl).toBeCalledWith(null, []); + }); + + test('should call platform multi select control', ()=>{ + spyOn(service, 'getPlatformMultiselectControl'); + + service.getPlatformControl(null, [], true); + + expect(service.getPlatformMultiselectControl).toBeCalledWith(null, []); + }); + + test('should generate platform multi select control', ()=>{ + const control = service.getPlatformMultiselectControl(null, []); + expect(control.type).toEqual(FormControlType.MULTI_SELECT); + expect(control.controlName).toEqual('platformName'); + expect(control.displayName).toEqual('Platform'); + expect(control.dataTestId).toEqual('multi-selectPlatform'); + expect(control.selectedFieldName).toEqual('name'); + expect(control.value).toEqual(''); + expect(control.onChange).toBeDefined(); + expect(control.convertOriginalDataToArray).toBeDefined(); + }); + test('getMacroFormControls check for mandatory controls', () => { const serviceId : string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44"; const vnfName : string = "VF_vGeraldine 0"; diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts index 7760ba8ad..55177aaac 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts +++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts @@ -20,6 +20,8 @@ import {Observable, of} from "rxjs"; import {SelectOption} from "../../../../models/selectOption"; import * as _ from 'lodash'; import {Constants} from "../../../../utils/constants"; +import {MultiselectFormControl} from "../../../../models/formControlModels/multiselectFormControl.model"; +import {MultiSelectItem} from "../../../formControls/component/multiselect/multiselect.model"; export enum FormControlNames { INSTANCE_NAME = 'instanceName', @@ -101,12 +103,13 @@ export class VnfControlGenerator { const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfName]); if (!_.isNil(vnfModel)) { + const flags = this.store.getState().global.flags; result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming)); result.push(this._basicControlGenerator.getProductFamilyControl(vnfInstance, result, false)); result.push(this.getLcpRegionControl(serviceId, vnfInstance, result)); result.push(this._basicControlGenerator.getLegacyRegion(vnfInstance)); result.push(this.getTenantControl(serviceId, vnfInstance, result)); - result.push(this.getPlatformControl(vnfInstance, result)); + result.push(this.getPlatformControl(vnfInstance, result, flags['FLAG_2002_VNF_PLATFORM_MULTI_SELECT'])); result.push(this.getLineOfBusinessControl(vnfInstance, result)); result.push(this.getRollbackOnFailureControl(vnfInstance, result)); } @@ -139,20 +142,59 @@ export class VnfControlGenerator { }) }; - getPlatformControl = (instance: any, controls: FormControlModel[]): DropdownFormControl => { + + + getPlatformDropdownControl = (instance: any, controls: FormControlModel[]) : DropdownFormControl => { return new DropdownFormControl({ - type: FormControlType.DROPDOWN, + type: FormControlType.DROPDOWN , controlName: 'platformName', displayName: 'Platform', dataTestId: 'platform', + selectedFieldName : null , + ngValue : null, placeHolder: 'Select Platform', isDisabled: false, name: "platform", value: instance ? instance.platformName : null, validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], onInitSelectedField: ['platformList'], - onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters) - }) + onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters), + }); + }; + + getPlatformMultiselectControl = (instance: any, controls: FormControlModel[]) : MultiselectFormControl => { + return new MultiselectFormControl({ + type: FormControlType.MULTI_SELECT , + controlName: 'platformName', + displayName: 'Platform', + dataTestId: 'multi-selectPlatform', + selectedFieldName : 'name' , + ngValue : 'name', + placeHolder: 'Select Platform', + isDisabled: false, + name: "platform", + value: instance ? instance.platformName : '', + validations: [new ValidatorModel(ValidatorOptions.required, 'is required')], + onInitSelectedField: ['platformList'], + onInit: this._basicControlGenerator.getSubscribeInitResult.bind(null, this._aaiService.getCategoryParameters), + onChange : (param: MultiSelectItem[], form: FormGroup) => { + form.controls['platformName'].setValue(param.map((multiSelectItem: MultiSelectItem)=>{ + return multiSelectItem.itemName + }).join(',')); + }, + convertOriginalDataToArray : (value?: string) => { + if(_.isNil(value)) return []; + return value.split(','); + } + }); + }; + + getPlatformControl = (instance: any, controls: FormControlModel[], isMultiSelect?: boolean): MultiselectFormControl | DropdownFormControl => { + const shouldGenerateDropdown = isMultiSelect === undefined || isMultiSelect === false; + if(shouldGenerateDropdown){ + return this.getPlatformDropdownControl(instance, controls); + } + return this.getPlatformMultiselectControl(instance, controls); }; getTenantControl = (serviceId: string, instance: any, controls: FormControlModel[]): DropdownFormControl => { diff --git a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html index d4c5118b3..edf86823c 100644 --- a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html +++ b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html @@ -6,6 +6,11 @@ +
diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts index b13745104..09fc1d250 100644 --- a/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts +++ b/vid-webpack-master/src/app/shared/models/formControlModels/multiselectFormControl.model.ts @@ -7,10 +7,13 @@ export class MultiselectFormControl extends FormControlModel{ options$ : Observable; args : string[]; onInit: (data : MultiselectFormControl, form: FormGroup) => Observable; - selectedItems : string; + selectedItems : any[]; onInitSelectedItems : string[]; + selectedFieldName : string; ngValue : string; settings: {}; + onInitSelectedField?: string[]; + convertOriginalDataToArray? : (values)=> void; constructor(data) { @@ -18,10 +21,13 @@ export class MultiselectFormControl extends FormControlModel{ this.type = FormControlType.MULTI_SELECT; this.options$ = data.options; this.onInit = data.onInit; - this.selectedItems = data.selectedItems; + this.selectedItems = data.selectedItems || []; this.onInitSelectedItems = data.onInitSelectedItems ? data.onInitSelectedItems : null; this.ngValue = data.selectedField ? data.selectedField : 'id'; + this.selectedFieldName = data.selectedFieldName; this.settings = data.settings || {}; + this.onInitSelectedField = data.onInitSelectedField ? data.onInitSelectedField : null; + this.convertOriginalDataToArray = data.convertOriginalDataToArray ? data.convertOriginalDataToArray : null } } diff --git a/vid-webpack-master/src/app/shared/shared.module.ts b/vid-webpack-master/src/app/shared/shared.module.ts index d486f2975..d246771af 100644 --- a/vid-webpack-master/src/app/shared/shared.module.ts +++ b/vid-webpack-master/src/app/shared/shared.module.ts @@ -73,6 +73,7 @@ import {ClickOutsideDirective} from "./directives/clickOutside/clickOutside.dire import {DynamicInputsComponent} from "./components/dynamic-inputs/dynamic-inputs.component"; import {DynamicInputLabelPipe} from "./pipes/dynamicInputLabel/dynamic-input-label.pipe"; import {ModelInformationService} from "./components/model-information/model-information.service"; +import {MultiselectFormControlService} from "./components/formControls/component/multiselect/multiselect.formControl.service"; @NgModule({ @@ -196,6 +197,7 @@ import {ModelInformationService} from "./components/model-information/model-info ErrorMsgService, DataFilterPipe, ModelInformationService, + MultiselectFormControlService ] }) export class SharedModule { -- cgit 1.2.3-korg