2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 import * as _ from "lodash";
22 import {Component, Inject, ViewChild} from "@angular/core";
23 import {PropertiesService} from "../../services/properties.service";
26 Component as ComponentData,
29 FilterPropertiesAssignmentData,
33 InstanceBePropertiesMap,
34 InstanceFePropertiesMap,
35 InstancePropertiesAPIMap,
42 PropertyDeclareAPIModel,
45 import {ResourceType} from "app/utils";
46 import {ComponentServiceNg2} from "../../services/component-services/component.service";
47 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
48 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
49 import {KeysPipe} from 'app/ng2/pipes/keys.pipe';
50 import {EVENTS, PROPERTY_TYPES, WorkspaceMode, PROPERTY_DATA} from "../../../utils/constants";
51 import {EventListenerService} from "app/services/event-listener-service"
52 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
53 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
54 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
55 import {HierarchyNavService} from "./services/hierarchy-nav.service";
56 import {PropertiesUtils} from "./services/properties.utils";
57 import {ComponentModeService} from "../../services/component-services/component-mode.service";
58 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
59 import {InputsUtils} from "./services/inputs.utils";
60 import {InstanceFeDetails} from "../../../models/instance-fe-details";
61 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
62 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
63 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
64 import {ModalService} from "../../services/modal.service";
65 import {DeclareListComponent} from "./declare-list/declare-list.component";
66 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
67 import {CapabilitiesGroup, Capability} from "../../../models/capability";
68 import {ToscaPresentationData} from "../../../models/tosca-presentation";
69 import {Observable} from "rxjs";
70 import {TranslateService} from "../../shared/translator/translate.service";
71 import {ToscaFunction} from "../../../models/tosca-function";
72 import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function";
73 import {DeclareInputComponent} from "./declare-input/declare-input.component";
75 const SERVICE_SELF_TITLE = "SELF";
77 templateUrl: './properties-assignment.page.component.html',
78 styleUrls: ['./properties-assignment.page.component.less']
80 export class PropertiesAssignmentComponent {
81 title = "Properties & Inputs";
83 component: ComponentData;
84 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
85 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
87 propertiesNavigationData = [];
88 instancesNavigationData = [];
90 instanceFePropertiesMap: InstanceFePropertiesMap;
91 inputs: Array<InputFEModel> = [];
92 policies: Array<PolicyInstance> = [];
93 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
95 propertyStructureHeader: string;
97 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
98 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
99 checkedPropertiesCount: number = 0;
100 checkedChildPropertiesCount: number = 0;
101 enableToscaFunction: boolean = false;
102 checkedToscaCount: number = 0;
104 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
105 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
106 displayClearSearch = false;
107 searchPropertyName: string;
109 isInputsTabSelected: boolean;
110 isPropertiesTabSelected: boolean;
111 isPoliciesTabSelected: boolean;
113 resourceIsReadonly: boolean;
114 loadingInstances: boolean = false;
115 loadingInputs: boolean = false;
116 loadingPolicies: boolean = false;
117 loadingProperties: boolean = false;
118 changedData: Array<PropertyFEModel | InputFEModel>;
119 hasChangedData: boolean;
120 isValidChangedData: boolean;
121 savingChangedData: boolean;
122 stateChangeStartUnregister: Function;
123 serviceBePropertiesMap: InstanceBePropertiesMap;
124 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
125 selectedInstance_FlattenCapabilitiesList: Capability[];
126 componentInstancePropertyMap : PropertiesGroup;
127 defaultInputName: string;
129 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
130 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
131 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
133 constructor(private propertiesService: PropertiesService,
134 private hierarchyNavService: HierarchyNavService,
135 private propertiesUtils: PropertiesUtils,
136 private inputsUtils: InputsUtils,
137 private componentServiceNg2: ComponentServiceNg2,
138 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
139 private propertyCreatorComponent: PropertyCreatorComponent,
140 @Inject("$stateParams") _stateParams,
141 @Inject("$scope") private $scope: ng.IScope,
142 @Inject("$state") private $state: ng.ui.IStateService,
143 @Inject("Notification") private notification: any,
144 private componentModeService: ComponentModeService,
145 private eventListenerService: EventListenerService,
146 private ModalServiceSdcUI: SdcUiServices.ModalService,
147 private modalService: ModalService,
148 private keysPipe: KeysPipe,
149 private topologyTemplateService: TopologyTemplateService,
150 private translateService: TranslateService) {
152 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
153 /* This is the way you can access the component data, please do not use any data except metadata, all other data should be received from the new api calls on the first time
154 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
155 this.component = _stateParams.component;
156 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
157 this.updateViewMode();
158 this.changedData = [];
159 this.updateHasChangedData();
160 this.isValidChangedData = true;
164 console.debug("==>" + this.constructor.name + ": ngOnInit");
165 this.loadingInputs = true;
166 this.loadingPolicies = true;
167 this.loadingInstances = true;
168 this.loadingProperties = true;
169 this.topologyTemplateService
170 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
171 .subscribe(response => {
172 _.forEach(response.inputs, (input: InputBEModel) => {
173 const newInput: InputFEModel = new InputFEModel(input);
174 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
175 this.inputs.push(newInput); //only push items that were declared via SDC
177 this.componentInstancePropertyMap = response.componentInstancesProperties;
178 this.loadingInputs = false;
182 this.componentServiceNg2
183 .getComponentResourcePropertiesData(this.component)
184 .subscribe(response => {
185 this.loadingPolicies = false;
187 this.instances.push(...response.componentInstances);
188 this.instances.push(...response.groupInstances);
189 this.instances.push(...response.policies);
191 if (response.componentInstances) {
192 response.componentInstances.forEach(instance => {
193 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
195 iconClass: instance.iconClass,
196 originArchived: instance.originArchived
201 _.forEach(response.policies, (policy: any) => {
202 const newPolicy: InputFEModel = new InputFEModel(policy);
203 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
204 this.policies.push(policy);
207 // add the service self instance to the top of the list.
208 const serviceInstance = new ComponentInstance();
209 serviceInstance.name = SERVICE_SELF_TITLE;
210 serviceInstance.uniqueId = this.component.uniqueId;
211 this.instances.unshift(serviceInstance);
213 _.forEach(this.instances, (instance) => {
214 this.instancesNavigationData.push(instance);
215 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
217 iconClass: instance.iconClass,
218 originArchived: instance.originArchived
221 this.loadingInstances = false;
222 if (this.instancesNavigationData[0] == undefined) {
223 this.loadingProperties = false;
225 this.selectFirstInstanceByDefault();
227 this.loadingInstances = false;
230 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
231 // stop if has changed properties
232 if (this.hasChangedData) {
233 event.preventDefault();
234 this.showUnsavedChangesAlert().then(() => {
235 this.$state.go(toState, toParams);
241 this.loadDataTypesByComponentModel(this.component.model);
245 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
246 this.stateChangeStartUnregister();
249 selectFirstInstanceByDefault = () => {
250 if (this.instancesNavigationData[0] !== undefined) {
251 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
255 updateViewMode = () => {
256 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
259 onCheckout = (component: ComponentData) => {
260 this.component = component;
261 this.updateViewMode();
264 isSelf = (): boolean => {
265 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
268 showAddProperties = (): boolean => {
269 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
272 return this.isSelf();
275 getServiceProperties() {
276 this.loadingProperties = true;
277 this.topologyTemplateService
278 .getServiceProperties(this.component.uniqueId)
279 .subscribe((response) => {
280 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
281 this.serviceBePropertiesMap[this.component.uniqueId] = response;
282 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
283 this.loadingProperties = false;
285 this.loadingProperties = false;
289 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
290 // stop if has changed properties
291 if (this.hasChangedData) {
292 this.showUnsavedChangesAlert().then((resolve) => {
293 this.changeSelectedInstance(instance)
298 this.changeSelectedInstance(instance);
301 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
302 this.selectedInstanceData = instance;
303 this.loadingProperties = true;
304 if (instance instanceof ComponentInstance) {
305 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
306 if (this.isInput(instance.originType)) {
307 this.componentInstanceServiceNg2
308 .getComponentInstanceInputs(this.component, instance)
309 .subscribe(response => {
310 instanceBePropertiesMap[instance.uniqueId] = response;
311 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
315 this.loadingProperties = false;
317 } else if (this.isSelf()) {
318 this.getServiceProperties();
320 this.componentInstanceServiceNg2
321 .getComponentInstanceProperties(this.component, instance.uniqueId)
322 .subscribe(response => {
323 instanceBePropertiesMap[instance.uniqueId] = response;
324 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
328 this.loadingProperties = false;
331 this.loadingProperties = false;
332 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
333 } else if (instance instanceof GroupInstance) {
334 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
335 this.componentInstanceServiceNg2
336 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
337 .subscribe((response) => {
338 instanceBePropertiesMap[instance.uniqueId] = response;
339 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
343 this.loadingProperties = false;
345 } else if (instance instanceof PolicyInstance) {
346 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
347 this.componentInstanceServiceNg2
348 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
349 .subscribe((response) => {
350 instanceBePropertiesMap[instance.uniqueId] = response;
351 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
355 this.loadingProperties = false;
358 this.loadingProperties = false;
361 if (this.searchPropertyName) {
364 //clear selected property from the navigation
365 this.selectedFlatProperty = new SimpleFlatProperty();
366 this.propertiesNavigationData = [];
367 this.checkedToscaCount = 0;
368 this.enableToscaFunction = false;
372 * Entry point handling response from server
374 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
375 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
376 this.checkedPropertiesCount = 0;
377 this.checkedChildPropertiesCount = 0;
380 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
381 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
382 let currentUniqueId = this.selectedInstanceData.uniqueId;
383 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
384 let isCapabilityOwnedByInstance: boolean;
385 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
386 this.selectedInstance_FlattenCapabilitiesList,
387 (result, cap: Capability) => {
388 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
389 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
390 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
391 if (cap.properties && isCapabilityOwnedByInstance) {
392 _.forEach(cap.properties, prop => {
393 if (!prop.origName) {
394 prop.origName = prop.name;
395 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
398 return result.concat(cap.properties);
402 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
403 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
404 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
405 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
407 //concatenate capabilitiesProps to all props list
408 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
409 this.checkedPropertiesCount = 0;
412 isCapabilityProperty = (prop: PropertyBEModel) => {
413 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
416 /*** VALUE CHANGE EVENTS ***/
417 dataChanged = (item: PropertyFEModel | InputFEModel) => {
419 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
420 itemHasChanged = item.hasValueObjChanged();
421 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
422 itemHasChanged = item.hasChanged();
423 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
424 itemHasChanged = item.hasDefaultValueChanged();
427 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
428 if (itemHasChanged) {
429 if (dataChangedIdx === -1) {
430 this.changedData.push(item);
433 if (dataChangedIdx !== -1) {
434 this.changedData.splice(dataChangedIdx, 1);
438 if (this.isPropertiesTabSelected) {
439 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
440 } else if (this.isInputsTabSelected) {
441 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
442 } else if (this.isPoliciesTabSelected) {
443 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
445 this.updateHasChangedData();
449 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
452 * Handle select node in navigation area, and select the row in table
454 onPropertySelectedUpdate = ($event) => {
455 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
456 this.selectedFlatProperty = $event;
457 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
458 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
462 * When user select row in table, this will prepare the hirarchy object for the tree.
464 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
465 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
466 let property = propertyRowSelectedEvent.propertyModel;
467 let instanceName = propertyRowSelectedEvent.instanceName;
468 this.propertyStructureHeader = null;
470 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
471 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
472 let simpleFlatProperty: Array<SimpleFlatProperty>;
473 if (property instanceof PropertyFEModel) {
474 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
475 } else if (property instanceof DerivedFEProperty) {
476 // Need to find parent PropertyFEModel
477 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
478 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
480 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
482 this.propertiesNavigationData = simpleFlatProperty;
485 // Update the header in the navigation tree with property name.
486 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
488 // Set selected property in table
489 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
490 this.hierarchyNavTabs.triggerTabChange('Property Structure');
494 selectInstanceRow = ($event) => {//get instance name
495 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
496 return instance.name == $event;
498 this.hierarchyNavTabs.triggerTabChange('Composition');
501 tabChanged = (event) => {
502 // stop if has changed properties
503 if (this.hasChangedData) {
504 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
505 this.showUnsavedChangesAlert().then((proceed) => {
506 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
512 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
513 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
514 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
515 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
516 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
517 this.propertyStructureHeader = null;
518 this.searchQuery = '';
522 * Select Tosca function value from defined values
524 selectToscaFunctionAndValues = (): void => {
525 const selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = this.getSelectedInstance();
526 if (!selectedInstanceData) {
529 this.openToscaGetFunctionModal();
532 private getSelectedInstance(): ComponentInstance | GroupInstance | PolicyInstance {
533 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
534 const instanceId: string = instancesIds[0];
535 return <ComponentInstance | GroupInstance | PolicyInstance> this.instances.find(instance =>
536 instance.uniqueId == instanceId && (instance instanceof ComponentInstance || instance instanceof GroupInstance || instance instanceof PolicyInstance));
539 private buildCheckedInstanceProperty(): PropertyBEModel {
540 return this.buildCheckedInstanceProperties()[0];
543 private buildCheckedInstanceProperties(): PropertyBEModel[] {
544 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
545 const instanceId: string = instancesIds[0];
546 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
549 private openToscaGetFunctionModal() {
550 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
551 const modalButtons = [];
552 let disableSaveButtonFlag = true;
553 const modal = this.modalService.createCustomModal(new ModalModel(
560 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
562 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
563 if (toscaGetFunction) {
564 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
566 this.clearCheckedInstancePropertyValue();
568 this.modalService.closeCurrentModal();
570 (): boolean => { return disableSaveButtonFlag }
572 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
573 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
574 this.modalService.closeCurrentModal();
578 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
579 'property': checkedInstanceProperty,
580 'componentInstanceMap': this.componentInstanceMap
582 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
583 disableSaveButtonFlag = !validationEvent.isValid;
585 modal.instance.open();
588 private clearCheckedInstancePropertyValue() {
589 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
590 const currentValue : any = checkedInstanceProperty.value;
591 checkedInstanceProperty.getInputValues = null;
592 checkedInstanceProperty.value = null;
593 checkedInstanceProperty.toscaFunction = null;
594 if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
595 const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
596 const parts = propertiesNameArray.split("#");
598 if (this.isListOrMap(checkedInstanceProperty.type)) {
599 if (checkedInstanceProperty.schemaType == PROPERTY_TYPES.MAP) {
600 currentKey.push((<DerivedFEProperty>checkedInstanceProperty.input).parentMapKey);
602 currentKey.push((<DerivedFEProperty>checkedInstanceProperty.input).mapKey);
603 if (checkedInstanceProperty.schemaType != PROPERTY_TYPES.MAP && this.isComplexSchemaType(checkedInstanceProperty.schemaType)) {
604 currentKey.push(parts.reverse()[0]);
607 if (propertiesNameArray.length > 1){
608 const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
609 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
611 if(currentValue !== null && currentKey.length > 0){
612 let valueJson = JSON.parse(currentValue);
613 if(currentKey.length >1){
614 let innerObj = valueJson[currentKey[0]];
615 delete innerObj[currentKey[1]];
616 valueJson[currentKey[0]] = innerObj;
618 delete valueJson[currentKey[0]];
620 if (checkedInstanceProperty.type == PROPERTY_TYPES.LIST && currentKey.length == 1) {
621 let listValue = valueJson.filter(function (item) {
622 return item != null && item != '';
624 checkedInstanceProperty.value = JSON.stringify(listValue);
626 checkedInstanceProperty.value = JSON.stringify(valueJson);
630 if (this.selectedInstanceData instanceof ComponentInstance) {
631 var toRemove = this.changedData.filter(obj => {
632 return obj.name == checkedInstanceProperty.name && obj.type == checkedInstanceProperty.type && obj.value == null;
634 const index: number = this.changedData.indexOf(toRemove[0]);
636 this.changedData.splice(index, 1);
638 this.updateInstanceProperty(checkedInstanceProperty);
639 } else if (this.selectedInstanceData instanceof GroupInstance) {
640 this.updateGroupInstanceProperty(checkedInstanceProperty);
641 } else if (this.selectedInstanceData instanceof PolicyInstance) {
642 this.updatePolicyInstanceProperty(checkedInstanceProperty);
646 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
647 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
648 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
649 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
650 const parts = propertiesName.split("#");
652 if (this.isListOrMap(checkedProperty.type)) {
653 if (checkedProperty.schemaType == PROPERTY_TYPES.MAP) {
654 currentKey.push((<DerivedFEProperty>checkedProperty.input).parentMapKey);
656 currentKey.push((<DerivedFEProperty>checkedProperty.input).mapKey);
657 if (checkedProperty.schemaType != PROPERTY_TYPES.MAP && this.isComplexSchemaType(checkedProperty.schemaType)) {
658 currentKey.push(parts.reverse()[0]);
661 if (checkedProperty.subPropertyToscaFunctions == null){
662 checkedProperty.subPropertyToscaFunctions = [];
664 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
665 if (!subPropertyToscaFunction){
666 subPropertyToscaFunction = new SubPropertyToscaFunction();
667 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
669 subPropertyToscaFunction.toscaFunction = toscaFunction;
670 subPropertyToscaFunction.subPropertyPath = currentKey.length > 0 ? currentKey : parts.slice(1);
673 checkedProperty.subPropertyToscaFunctions = null;
674 checkedProperty.toscaFunction = toscaFunction;
676 if (this.selectedInstanceData instanceof ComponentInstance) {
677 this.updateInstanceProperty(checkedProperty);
678 } else if (this.selectedInstanceData instanceof GroupInstance) {
679 this.updateGroupInstanceProperty(checkedProperty);
680 } else if (this.selectedInstanceData instanceof PolicyInstance) {
681 this.updatePolicyInstanceProperty(checkedProperty);
685 private isComplexSchemaType(propertyType: string): boolean {
686 return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
689 private isListOrMap(propertyType: string): boolean {
690 return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
693 private areEqual(array1: string[], array2: string[]): boolean {
694 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
697 updateInstanceProperty(instanceProperty: PropertyBEModel) {
698 this.loadingProperties = true;
699 this.enableToscaFunction = false;
700 this.checkedToscaCount = 0;
702 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
703 this.selectedInstanceData.uniqueId, [instanceProperty])
705 this.changeSelectedInstance(this.getSelectedInstance());
707 this.loadingProperties = false;
708 console.error(error);
710 this.loadingProperties = false;
714 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
715 this.loadingProperties = true;
716 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
717 this.selectedInstanceData.uniqueId, [instanceProperty])
719 this.changeSelectedInstance(this.getSelectedInstance());
721 this.loadingProperties = false;
722 console.error(error);
724 this.loadingProperties = false;
728 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
729 this.loadingProperties = true;
730 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
731 this.selectedInstanceData.uniqueId, [instanceProperty])
733 this.changeSelectedInstance(this.getSelectedInstance());
735 this.loadingProperties = false;
736 console.error(error);
738 this.loadingProperties = false;
742 /*** DECLARE PROPERTIES/INPUTS ***/
743 declareInputFromProperties = (inputName:string): void => {
744 console.debug("==>" + this.constructor.name + ": declareProperties");
746 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
747 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
748 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
749 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
750 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
752 angular.forEach(instancesIds, (instanceId: string): void => {
753 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
754 if (selectedInstanceData instanceof ComponentInstance) {
755 if (!this.isInput(selectedInstanceData.originType)) {
756 // convert Property FE model -> Property BE model, extract only checked
757 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
759 selectedComponentInstancesProperties[instanceId][0].inputName = inputName;
762 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
764 } else if (selectedInstanceData instanceof GroupInstance) {
765 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
766 } else if (selectedInstanceData instanceof PolicyInstance) {
767 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
771 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
773 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
774 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
775 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
777 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
778 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
781 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
782 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
783 prop => !this.isCapabilityProperty(prop)
785 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
786 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
789 let isCapabilityPropertyChanged = false;
791 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
792 (prop: PropertyBEModel) => {
793 prop.name = prop.origName || prop.name;
794 if (this.isCapabilityProperty(prop)) {
795 isCapabilityPropertyChanged = true;
799 this.topologyTemplateService
800 .createInput(this.component, inputsToCreate, this.isSelf())
801 .subscribe((response) => {
802 this.selectInstanceRow(SERVICE_SELF_TITLE);
803 this.onInstanceSelectedUpdate(this.instances[0]);
804 this.setInputTabIndication(response.length);
805 this.checkedPropertiesCount = 0;
806 this.checkedChildPropertiesCount = 0;
807 _.forEach(response, (input: InputBEModel) => {
808 const newInput: InputFEModel = new InputFEModel(input);
809 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
810 this.inputs.push(newInput);
811 this.updatePropertyValueAfterDeclare(newInput);
813 if (isCapabilityPropertyChanged) {
814 this.reloadInstanceCapabilities();
816 }, error => {}); //ignore error
819 generateDefaultInputName = (): string => {
820 let defaultInputName: string;
821 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
822 angular.forEach(instancesIds, (instanceId: string) => {
823 let selectedProperty: PropertyBEModel = new PropertyBEModel(this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId])[0]);
824 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
825 defaultInputName = this.generateInputName(selectedInstanceData.invariantName, selectedProperty.name);
827 return defaultInputName;
830 private generateInputName = (componentName: string, propertyName: string): string => {
831 let inputName: string;
833 if (propertyName.includes("::")) {
834 propertyName = propertyName.replace("::", "_");
837 inputName = componentName + "_" + propertyName;
839 inputName = propertyName;
845 private openAddInputNameAndDeclareInputModal = (): void => {
846 const modalTitle = this.translateService.translate('ADD_INPUT_NAME_TO_DECLARE');
847 const modalButtons = [];
848 const modal = this.modalService.createCustomModal(new ModalModel(
855 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
857 const inputName: string = modal.instance.dynamicContent.instance.inputNameForm.value;
859 this.declareInputFromProperties(inputName);
861 this.notification.warning({
862 message: 'Failed to set input name',
866 this.modalService.closeCurrentModal();
869 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
870 this.modalService.closeCurrentModal();
872 this.modalService.addDynamicContentToModal(modal, DeclareInputComponent, {defaultInputName: this.generateDefaultInputName()});
873 modal.instance.open();
876 declareListProperties = (): void => {
877 // get selected properties
878 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
879 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
880 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
881 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
882 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
883 let propertyNameList: Array<string> = [];
886 angular.forEach(instancesIds, (instanceId: string): void => {
888 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
889 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
891 if (selectedInstanceData instanceof ComponentInstance) {
892 if (!this.isInput(selectedInstanceData.originType)) {
893 // convert Property FE model -> Property BE model, extract only checked
894 selectedComponentInstancesProperties[instanceId] = checkedProperties;
896 selectedComponentInstancesInputs[instanceId] = checkedProperties;
898 } else if (selectedInstanceData instanceof GroupInstance) {
899 selectedGroupInstancesProperties[instanceId] = checkedProperties;
900 } else if (selectedInstanceData instanceof PolicyInstance) {
901 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
904 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
905 propertyNameList.push(property.name);
909 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
911 let modalTitle = 'Declare Properties as List Input';
912 const modal = this.modalService.createCustomModal(new ModalModel(
914 modalTitle, /* title */
919 'blue', /* css class */
920 () => { /* callback */
921 let content:any = modal.instance.dynamicContent.instance;
924 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
925 let typelist: any = PROPERTY_TYPES.LIST;
926 let uniID: any = insId;
927 let boolfalse: any = false;
928 let required: any = content.propertyModel.required;
932 "type": content.propertyModel.simpleType,
936 let schemaProp :any = {
937 "type": content.propertyModel.simpleType,
941 reglistInput.description = content.propertyModel.description;
942 reglistInput.name = content.propertyModel.name;
943 reglistInput.type = typelist;
944 reglistInput.schemaType = content.propertyModel.simpleType;
945 reglistInput.instanceUniqueId = uniID;
946 reglistInput.uniqueId = uniID;
947 reglistInput.required = required;
948 reglistInput.schema = schem;
949 reglistInput.schemaProperty = schemaProp;
952 componentInstInputsMap: content.inputsToCreate,
953 listInput: reglistInput
956 this.topologyTemplateService
957 .createListInput(this.component, input, this.isSelf())
958 .subscribe(response => {
959 this.setInputTabIndication(response.length);
960 this.checkedPropertiesCount = 0;
961 this.checkedChildPropertiesCount = 0;
962 _.forEach(response, (input: InputBEModel) => {
963 let newInput: InputFEModel = new InputFEModel(input);
964 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
965 this.inputs.push(newInput);
966 // create list input does not return updated properties info, so need to reload
967 //this.updatePropertyValueAfterDeclare(newInput);
968 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
969 this.changeSelectedInstance(this.selectedInstanceData);
971 modal.instance.close();
973 }, error => {}); //ignore error
976 /*, getDisabled: function */
978 new ButtonModel('Cancel', 'outline grey', () => {
979 modal.instance.close();
984 // 3rd arg is passed to DeclareListComponent instance
985 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
986 modal.instance.open();
989 /*** DECLARE PROPERTIES/POLICIES ***/
990 declarePropertiesToPolicies = (): void => {
991 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
992 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
994 angular.forEach(instancesIds, (instanceId: string): void => {
995 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
996 if (selectedInstanceData instanceof ComponentInstance) {
997 if (!this.isInput(selectedInstanceData.originType)) {
998 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
1003 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
1004 this.loadingPolicies = true;
1006 this.topologyTemplateService
1007 .createPolicy(this.component, policiesToCreate, this.isSelf())
1008 .subscribe(response => {
1009 this.setPolicyTabIndication(response.length);
1010 this.checkedPropertiesCount = 0;
1011 this.displayPoliciesAsDeclared(response);
1012 this.loadingPolicies = false;
1017 displayPoliciesAsDeclared = (policies) => {
1018 _.forEach(policies, (policy: any) => {
1019 let newPolicy: InputFEModel = new InputFEModel(policy);
1020 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
1021 newPolicy.relatedPropertyName = policy.name;
1022 newPolicy.relatedPropertyValue = policy.value;
1023 this.updatePropertyValueAfterDeclare(newPolicy);
1024 this.policies.push(policy);
1028 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
1029 return new Promise((resolve, reject) => {
1030 if (!this.isValidChangedData) {
1031 reject('Changed data is invalid - cannot save!');
1034 if (!this.changedData.length) {
1039 // make request and its handlers
1041 let handleSuccess, handleError;
1042 let changedInputsProperties = [], changedCapabilitiesProperties = [];
1043 if (this.isPropertiesTabSelected) {
1044 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
1045 changedProp = <PropertyFEModel>changedProp;
1046 const propBE = new PropertyBEModel(changedProp);
1047 propBE.toscaPresentation = new ToscaPresentationData();
1048 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
1049 propBE.value = changedProp.getJSONValue();
1050 propBE.name = changedProp.origName || changedProp.name;
1051 delete propBE.origName;
1054 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
1056 if (this.selectedInstanceData instanceof ComponentInstance) {
1057 if (this.isInput(this.selectedInstanceData.originType)) {
1058 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
1059 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
1060 request = Observable.forkJoin(
1061 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
1062 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
1063 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
1066 else if (changedInputsProperties.length) {
1067 request = this.componentInstanceServiceNg2
1068 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
1070 else if (changedCapabilitiesProperties.length) {
1071 request = this.componentInstanceServiceNg2
1072 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
1074 handleSuccess = (response) => {
1075 // reset each changed property with new value and remove it from changed properties list
1076 response.forEach((resInput) => {
1077 const changedProp = <PropertyFEModel>this.changedData.shift();
1078 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
1082 if (this.isSelf()) {
1083 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
1084 delete cp.constraints;
1088 request = this.componentInstanceServiceNg2
1089 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1091 handleSuccess = (response) => {
1092 // reset each changed property with new value and remove it from changed properties list
1093 response.forEach((resProp) => {
1094 const changedProp = <PropertyFEModel>this.changedData.shift();
1095 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1100 } else if (this.selectedInstanceData instanceof GroupInstance) {
1101 request = this.componentInstanceServiceNg2
1102 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1103 handleSuccess = (response) => {
1104 // reset each changed property with new value and remove it from changed properties list
1105 response.forEach((resProp) => {
1106 const changedProp = <PropertyFEModel>this.changedData.shift();
1107 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1111 } else if (this.selectedInstanceData instanceof PolicyInstance) {
1112 request = this.componentInstanceServiceNg2
1113 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1114 handleSuccess = (response) => {
1115 // reset each changed property with new value and remove it from changed properties list
1116 response.forEach((resProp) => {
1117 const changedProp = <PropertyFEModel>this.changedData.shift();
1118 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1123 } else if (this.isInputsTabSelected) {
1125 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1126 changedInput = <InputFEModel>changedInput;
1127 const inputBE = new InputBEModel(changedInput);
1128 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1131 request = this.componentServiceNg2
1132 .updateComponentInputs(this.component, changedInputs);
1133 handleSuccess = (response) => {
1134 // reset each changed property with new value and remove it from changed properties list
1135 response.forEach((resInput) => {
1136 const changedInput = <InputFEModel>this.changedData.shift();
1137 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1138 changedInput.required = resInput.required;
1139 changedInput.requiredOrig = resInput.required;
1144 this.savingChangedData = true;
1147 this.savingChangedData = false;
1148 if (changedCapabilitiesProperties.length) {
1149 this.reloadInstanceCapabilities();
1151 handleSuccess && handleSuccess(response);
1152 this.updateHasChangedData();
1156 this.savingChangedData = false;
1157 handleError && handleError(error);
1158 this.updateHasChangedData();
1165 reloadInstanceCapabilities = (): void => {
1166 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1167 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1168 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1169 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1170 return instance.capabilities;
1173 }, new CapabilitiesGroup());
1174 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1178 reverseChangedData = ():void => {
1179 // make reverse item handler
1180 let handleReverseItem;
1181 if (this.isPropertiesTabSelected) {
1182 handleReverseItem = (changedItem) => {
1183 changedItem = <PropertyFEModel>changedItem;
1184 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1186 } else if (this.isInputsTabSelected) {
1187 handleReverseItem = (changedItem) => {
1188 changedItem = <InputFEModel>changedItem;
1189 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1190 changedItem.resetMetadata();
1191 changedItem.required = changedItem.requiredOrig;
1195 this.changedData.forEach(handleReverseItem);
1196 this.changedData = [];
1197 this.updateHasChangedData();
1200 updateHasChangedData = ():boolean => {
1201 const curHasChangedData:boolean = (this.changedData.length > 0);
1202 if (curHasChangedData !== this.hasChangedData) {
1203 this.hasChangedData = curHasChangedData;
1204 if(this.hasChangedData) {
1205 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1207 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1210 return this.hasChangedData;
1213 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1214 this.saveChangedData().then(
1216 this.notification.success({
1217 message: 'Successfully saved changes',
1220 if(onSuccessFunction) onSuccessFunction();
1223 this.notification.error({
1224 message: 'Failed to save changes!',
1227 if(onError) onError();
1232 showUnsavedChangesAlert = ():Promise<any> => {
1233 let modalTitle:string;
1234 if (this.isPropertiesTabSelected) {
1235 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1236 } else if (this.isInputsTabSelected) {
1237 modalTitle = `Unsaved inputs for ${this.component.name}`;
1240 return new Promise<any>((resolve, reject) => {
1241 const modal = this.ModalServiceSdcUI.openCustomModal(
1245 type: SdcUiCommon.ModalType.custom,
1246 testId: "navigate-modal",
1249 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1250 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1251 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1252 ] as SdcUiCommon.IModalButtonComponent[]
1253 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1258 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1259 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1260 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1261 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1262 return feProperty.name == input.relatedPropertyName &&
1263 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1265 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1266 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1267 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1268 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1272 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1273 updateCheckedPropertyCount = (increment: boolean): void => {
1274 this.checkedPropertiesCount += (increment) ? 1 : -1;
1275 this.checkedToscaCount = 0;
1276 this.enableToscaFunction = false;
1277 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1280 updateCheckedChildPropertyCount = (increment: boolean): void => {
1281 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1284 togggleToscaBtn = (toscaFlag: boolean) : void => {
1285 this.checkedToscaCount += toscaFlag ? 1 : -1;
1286 if(this.checkedToscaCount == 1){
1287 this.enableToscaFunction = true;
1289 this.enableToscaFunction = false;
1293 setInputTabIndication = (numInputs: number): void => {
1294 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1297 setPolicyTabIndication = (numPolicies: number): void => {
1298 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1301 resetUnsavedChangesForInput = (input:InputFEModel) => {
1302 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1303 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1304 this.updateHasChangedData();
1307 deleteInput = (input: InputFEModel) => {
1308 //reset any unsaved changes to the input before deleting it
1309 this.resetUnsavedChangesForInput(input);
1311 console.debug("==>" + this.constructor.name + ": deleteInput");
1312 let inputToDelete = new InputBEModel(input);
1314 this.componentServiceNg2
1315 .deleteInput(this.component, inputToDelete)
1316 .subscribe(response => {
1317 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1319 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1320 this.changeSelectedInstance(this.selectedInstanceData);
1321 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1323 // if (instanceFeProperties) {
1324 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1325 // return prop.name == input.propertyName;
1328 // if (propToEnable) {
1329 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1330 // propToEnable.setNonDeclared(response.inputPath);
1331 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1332 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1335 }, error => {}); //ignore error
1338 deletePolicy = (policy: PolicyInstance) => {
1339 this.loadingPolicies = true;
1340 this.topologyTemplateService
1341 .deletePolicy(this.component, policy)
1342 .subscribe((response) => {
1343 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1344 this.changeSelectedInstance(this.selectedInstanceData);
1345 this.loadingPolicies = false;
1349 deleteProperty = (property: PropertyFEModel) => {
1350 const propertyToDelete = new PropertyFEModel(property);
1351 this.loadingProperties = true;
1352 const feMap = this.instanceFePropertiesMap;
1353 this.topologyTemplateService
1354 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1355 .subscribe((response) => {
1356 const props = feMap[this.component.uniqueId];
1357 props.splice(props.findIndex(p => p.uniqueId === response),1);
1358 this.loadingProperties = false;
1360 this.loadingProperties = false;
1361 console.error(error);
1365 /*** addProperty ***/
1366 addProperty = (model: string) => {
1367 this.loadDataTypesByComponentModel(model)
1368 let modalTitle = 'Add Property';
1369 let modal = this.modalService.createCustomModal(new ModalModel(
1374 new ButtonModel('Save', 'blue', () => {
1375 modal.instance.dynamicContent.instance.isLoading = true;
1376 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1377 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1378 .subscribe((response) => {
1379 modal.instance.dynamicContent.instance.isLoading = false;
1380 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1381 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1382 modal.instance.close();
1384 modal.instance.dynamicContent.instance.isLoading = false;
1385 this.notification.error({
1386 message: 'Failed to add property:' + error,
1390 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1391 new ButtonModel('Cancel', 'outline grey', () => {
1392 modal.instance.close();
1397 modal.instance.open();
1398 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1403 let modalTitle = 'Add Input';
1404 let modal = this.modalService.createCustomModal(new ModalModel(
1409 new ButtonModel('Save', 'blue', () => {
1410 modal.instance.dynamicContent.instance.isLoading = true;
1411 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1412 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1413 .subscribe((response) => {
1414 modal.instance.dynamicContent.instance.isLoading = false;
1415 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1416 this.inputs.push(newInputProp);
1417 modal.instance.close();
1419 modal.instance.dynamicContent.instance.isLoading = false;
1420 this.notification.error({
1421 message: 'Failed to add input:' + error,
1425 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1426 new ButtonModel('Cancel', 'outline grey', () => {
1427 modal.instance.close();
1432 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1433 modal.instance.open();
1436 /*** SEARCH RELATED FUNCTIONS ***/
1437 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1438 let instanceBePropertiesMap:InstanceBePropertiesMap;
1439 this.componentServiceNg2
1440 .filterComponentInstanceProperties(this.component, filterData)
1441 .subscribe((response) => {
1442 this.processInstancePropertiesResponse(response, false);
1443 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1444 this.searchPropertyName = filterData.propertyName;//mark in table
1445 this.hierarchyNavTabs.triggerTabChange('Composition');
1446 this.propertiesNavigationData = [];
1447 this.displayClearSearch = true;
1448 }, (error) => {}); //ignore error
1452 clearSearch = () => {
1453 this.instancesNavigationData = this.instances;
1454 this.searchPropertyName = "";
1455 this.hierarchyPropertiesDisplayOptions.searchText = "";
1456 this.displayClearSearch = false;
1457 this.advanceSearch.clearAll();
1458 this.searchQuery = '';
1461 clickOnClearSearch = () => {
1463 this.selectFirstInstanceByDefault();
1464 this.hierarchyNavTabs.triggerTabChange('Composition');
1467 private isInput = (instanceType:string):boolean =>{
1468 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1471 loadDataTypesByComponentModel(model:string) {
1472 this.propertyCreatorComponent.filterDataTypesByModel(model);