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
44 import {ResourceType} from "app/utils";
45 import {ComponentServiceNg2} from "../../services/component-services/component.service";
46 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
47 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
48 import {KeysPipe} from 'app/ng2/pipes/keys.pipe';
49 import {EVENTS, PROPERTY_TYPES, WorkspaceMode} from "../../../utils/constants";
50 import {EventListenerService} from "app/services/event-listener-service"
51 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
52 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
53 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
54 import {HierarchyNavService} from "./services/hierarchy-nav.service";
55 import {PropertiesUtils} from "./services/properties.utils";
56 import {ComponentModeService} from "../../services/component-services/component-mode.service";
57 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
58 import {InputsUtils} from "./services/inputs.utils";
59 import {InstanceFeDetails} from "../../../models/instance-fe-details";
60 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
61 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
62 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
63 import {ModalService} from "../../services/modal.service";
64 import {DeclareListComponent} from "./declare-list/declare-list.component";
65 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
66 import {CapabilitiesGroup, Capability} from "../../../models/capability";
67 import {ToscaPresentationData} from "../../../models/tosca-presentation";
68 import {Observable} from "rxjs";
69 import {TranslateService} from "../../shared/translator/translate.service";
70 import {ToscaFunction} from "../../../models/tosca-function";
71 import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function";
73 const SERVICE_SELF_TITLE = "SELF";
75 templateUrl: './properties-assignment.page.component.html',
76 styleUrls: ['./properties-assignment.page.component.less']
78 export class PropertiesAssignmentComponent {
79 title = "Properties & Inputs";
81 component: ComponentData;
82 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
83 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
85 propertiesNavigationData = [];
86 instancesNavigationData = [];
88 instanceFePropertiesMap: InstanceFePropertiesMap;
89 inputs: Array<InputFEModel> = [];
90 policies: Array<PolicyInstance> = [];
91 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
93 propertyStructureHeader: string;
95 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
96 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
97 checkedPropertiesCount: number = 0;
98 checkedChildPropertiesCount: number = 0;
99 enableToscaFunction: boolean = false;
100 checkedToscaCount: number = 0;
102 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
103 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
104 displayClearSearch = false;
105 searchPropertyName: string;
107 isInputsTabSelected: boolean;
108 isPropertiesTabSelected: boolean;
109 isPoliciesTabSelected: boolean;
111 resourceIsReadonly: boolean;
112 loadingInstances: boolean = false;
113 loadingInputs: boolean = false;
114 loadingPolicies: boolean = false;
115 loadingProperties: boolean = false;
116 changedData: Array<PropertyFEModel | InputFEModel>;
117 hasChangedData: boolean;
118 isValidChangedData: boolean;
119 savingChangedData: boolean;
120 stateChangeStartUnregister: Function;
121 serviceBePropertiesMap: InstanceBePropertiesMap;
122 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
123 selectedInstance_FlattenCapabilitiesList: Capability[];
125 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
126 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
127 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
129 constructor(private propertiesService: PropertiesService,
130 private hierarchyNavService: HierarchyNavService,
131 private propertiesUtils: PropertiesUtils,
132 private inputsUtils: InputsUtils,
133 private componentServiceNg2: ComponentServiceNg2,
134 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
135 private propertyCreatorComponent: PropertyCreatorComponent,
136 @Inject("$stateParams") _stateParams,
137 @Inject("$scope") private $scope: ng.IScope,
138 @Inject("$state") private $state: ng.ui.IStateService,
139 @Inject("Notification") private notification: any,
140 private componentModeService: ComponentModeService,
141 private eventListenerService: EventListenerService,
142 private ModalServiceSdcUI: SdcUiServices.ModalService,
143 private modalService: ModalService,
144 private keysPipe: KeysPipe,
145 private topologyTemplateService: TopologyTemplateService,
146 private translateService: TranslateService) {
148 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
149 /* 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
150 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
151 this.component = _stateParams.component;
152 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
153 this.updateViewMode();
154 this.changedData = [];
155 this.updateHasChangedData();
156 this.isValidChangedData = true;
160 console.debug("==>" + this.constructor.name + ": ngOnInit");
161 this.loadingInputs = true;
162 this.loadingPolicies = true;
163 this.loadingInstances = true;
164 this.loadingProperties = true;
165 this.topologyTemplateService
166 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
167 .subscribe(response => {
168 _.forEach(response.inputs, (input: InputBEModel) => {
169 const newInput: InputFEModel = new InputFEModel(input);
170 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
171 this.inputs.push(newInput); //only push items that were declared via SDC
173 this.loadingInputs = false;
177 this.componentServiceNg2
178 .getComponentResourcePropertiesData(this.component)
179 .subscribe(response => {
180 this.loadingPolicies = false;
182 this.instances.push(...response.componentInstances);
183 this.instances.push(...response.groupInstances);
184 this.instances.push(...response.policies);
186 if (response.componentInstances) {
187 response.componentInstances.forEach(instance => {
188 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
190 iconClass: instance.iconClass,
191 originArchived: instance.originArchived
196 _.forEach(response.policies, (policy: any) => {
197 const newPolicy: InputFEModel = new InputFEModel(policy);
198 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
199 this.policies.push(policy);
202 // add the service self instance to the top of the list.
203 const serviceInstance = new ComponentInstance();
204 serviceInstance.name = SERVICE_SELF_TITLE;
205 serviceInstance.uniqueId = this.component.uniqueId;
206 this.instances.unshift(serviceInstance);
208 _.forEach(this.instances, (instance) => {
209 this.instancesNavigationData.push(instance);
210 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
212 iconClass: instance.iconClass,
213 originArchived: instance.originArchived
216 this.loadingInstances = false;
217 if (this.instancesNavigationData[0] == undefined) {
218 this.loadingProperties = false;
220 this.selectFirstInstanceByDefault();
222 this.loadingInstances = false;
225 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
226 // stop if has changed properties
227 if (this.hasChangedData) {
228 event.preventDefault();
229 this.showUnsavedChangesAlert().then(() => {
230 this.$state.go(toState, toParams);
236 this.loadDataTypesByComponentModel(this.component.model);
240 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
241 this.stateChangeStartUnregister();
244 selectFirstInstanceByDefault = () => {
245 if (this.instancesNavigationData[0] !== undefined) {
246 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
250 updateViewMode = () => {
251 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
254 onCheckout = (component: ComponentData) => {
255 this.component = component;
256 this.updateViewMode();
259 isSelf = (): boolean => {
260 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
263 showAddProperties = (): boolean => {
264 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
267 return this.isSelf();
270 getServiceProperties() {
271 this.loadingProperties = true;
272 this.topologyTemplateService
273 .getServiceProperties(this.component.uniqueId)
274 .subscribe((response) => {
275 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
276 this.serviceBePropertiesMap[this.component.uniqueId] = response;
277 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
278 this.loadingProperties = false;
280 this.loadingProperties = false;
284 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
285 // stop if has changed properties
286 if (this.hasChangedData) {
287 this.showUnsavedChangesAlert().then((resolve) => {
288 this.changeSelectedInstance(instance)
293 this.changeSelectedInstance(instance);
296 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
297 this.selectedInstanceData = instance;
298 this.loadingProperties = true;
299 if (instance instanceof ComponentInstance) {
300 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
301 if (this.isInput(instance.originType)) {
302 this.componentInstanceServiceNg2
303 .getComponentInstanceInputs(this.component, instance)
304 .subscribe(response => {
305 instanceBePropertiesMap[instance.uniqueId] = response;
306 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
310 this.loadingProperties = false;
312 } else if (this.isSelf()) {
313 this.getServiceProperties();
315 this.componentInstanceServiceNg2
316 .getComponentInstanceProperties(this.component, instance.uniqueId)
317 .subscribe(response => {
318 instanceBePropertiesMap[instance.uniqueId] = response;
319 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
323 this.loadingProperties = false;
326 this.loadingProperties = false;
327 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
328 } else if (instance instanceof GroupInstance) {
329 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
330 this.componentInstanceServiceNg2
331 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
332 .subscribe((response) => {
333 instanceBePropertiesMap[instance.uniqueId] = response;
334 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
338 this.loadingProperties = false;
340 } else if (instance instanceof PolicyInstance) {
341 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
342 this.componentInstanceServiceNg2
343 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
344 .subscribe((response) => {
345 instanceBePropertiesMap[instance.uniqueId] = response;
346 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
350 this.loadingProperties = false;
353 this.loadingProperties = false;
356 if (this.searchPropertyName) {
359 //clear selected property from the navigation
360 this.selectedFlatProperty = new SimpleFlatProperty();
361 this.propertiesNavigationData = [];
365 * Entry point handling response from server
367 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
368 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
369 this.checkedPropertiesCount = 0;
370 this.checkedChildPropertiesCount = 0;
373 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
374 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
375 let currentUniqueId = this.selectedInstanceData.uniqueId;
376 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
377 let isCapabilityOwnedByInstance: boolean;
378 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
379 this.selectedInstance_FlattenCapabilitiesList,
380 (result, cap: Capability) => {
381 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
382 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
383 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
384 if (cap.properties && isCapabilityOwnedByInstance) {
385 _.forEach(cap.properties, prop => {
386 if (!prop.origName) {
387 prop.origName = prop.name;
388 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
391 return result.concat(cap.properties);
395 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
396 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
397 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
398 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
400 //concatenate capabilitiesProps to all props list
401 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
402 this.checkedPropertiesCount = 0;
405 isCapabilityProperty = (prop: PropertyBEModel) => {
406 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
409 /*** VALUE CHANGE EVENTS ***/
410 dataChanged = (item: PropertyFEModel | InputFEModel) => {
412 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
413 itemHasChanged = item.hasValueObjChanged();
414 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
415 itemHasChanged = item.hasChanged();
416 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
417 itemHasChanged = item.hasDefaultValueChanged();
420 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
421 if (itemHasChanged) {
422 if (dataChangedIdx === -1) {
423 this.changedData.push(item);
426 if (dataChangedIdx !== -1) {
427 this.changedData.splice(dataChangedIdx, 1);
431 if (this.isPropertiesTabSelected) {
432 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
433 } else if (this.isInputsTabSelected) {
434 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
435 } else if (this.isPoliciesTabSelected) {
436 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
438 this.updateHasChangedData();
442 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
445 * Handle select node in navigation area, and select the row in table
447 onPropertySelectedUpdate = ($event) => {
448 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
449 this.selectedFlatProperty = $event;
450 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
451 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
455 * When user select row in table, this will prepare the hirarchy object for the tree.
457 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
458 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
459 let property = propertyRowSelectedEvent.propertyModel;
460 let instanceName = propertyRowSelectedEvent.instanceName;
461 this.propertyStructureHeader = null;
463 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
464 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
465 let simpleFlatProperty: Array<SimpleFlatProperty>;
466 if (property instanceof PropertyFEModel) {
467 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
468 } else if (property instanceof DerivedFEProperty) {
469 // Need to find parent PropertyFEModel
470 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
471 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
473 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
475 this.propertiesNavigationData = simpleFlatProperty;
478 // Update the header in the navigation tree with property name.
479 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
481 // Set selected property in table
482 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
483 this.hierarchyNavTabs.triggerTabChange('Property Structure');
487 selectInstanceRow = ($event) => {//get instance name
488 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
489 return instance.name == $event;
491 this.hierarchyNavTabs.triggerTabChange('Composition');
494 tabChanged = (event) => {
495 // stop if has changed properties
496 if (this.hasChangedData) {
497 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
498 this.showUnsavedChangesAlert().then((proceed) => {
499 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
505 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
506 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
507 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
508 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
509 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
510 this.propertyStructureHeader = null;
511 this.searchQuery = '';
515 * Select Tosca function value from defined values
517 selectToscaFunctionAndValues = (): void => {
518 const selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = this.getSelectedInstance();
519 if (!selectedInstanceData) {
522 this.openToscaGetFunctionModal();
525 private getSelectedInstance(): ComponentInstance | GroupInstance | PolicyInstance {
526 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
527 const instanceId: string = instancesIds[0];
528 return <ComponentInstance | GroupInstance | PolicyInstance> this.instances.find(instance =>
529 instance.uniqueId == instanceId && (instance instanceof ComponentInstance || instance instanceof GroupInstance || instance instanceof PolicyInstance));
532 private buildCheckedInstanceProperty(): PropertyBEModel {
533 return this.buildCheckedInstanceProperties()[0];
536 private buildCheckedInstanceProperties(): PropertyBEModel[] {
537 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
538 const instanceId: string = instancesIds[0];
539 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
542 private openToscaGetFunctionModal() {
543 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
544 const modalButtons = [];
545 let disableSaveButtonFlag = true;
546 const modal = this.modalService.createCustomModal(new ModalModel(
553 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
555 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
556 if (toscaGetFunction) {
557 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
559 this.clearCheckedInstancePropertyValue();
561 this.modalService.closeCurrentModal();
563 (): boolean => { return disableSaveButtonFlag }
565 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
566 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
567 this.modalService.closeCurrentModal();
571 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
572 'property': checkedInstanceProperty,
573 'componentInstanceMap': this.componentInstanceMap
575 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
576 disableSaveButtonFlag = !validationEvent.isValid;
578 modal.instance.open();
581 private clearCheckedInstancePropertyValue() {
582 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
583 const currentValue : any = checkedInstanceProperty.value;
584 checkedInstanceProperty.getInputValues = null;
585 checkedInstanceProperty.value = null;
586 checkedInstanceProperty.toscaFunction = null;
587 if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
588 const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
589 const parts = propertiesNameArray.split("#");
590 const currentKey = (checkedInstanceProperty.type == PROPERTY_TYPES.MAP || checkedInstanceProperty.type == PROPERTY_TYPES.LIST) ? (<DerivedFEProperty>checkedInstanceProperty.input).mapKey : null;
591 if (propertiesNameArray.length > 1){
592 const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey != null ? [currentKey] : parts.slice(1)));
593 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
595 if(currentValue !== null && currentKey !== null){
596 let valueJson = JSON.parse(currentValue);
597 let tempValue = valueJson[currentKey];
598 delete valueJson[currentKey];
599 if (checkedInstanceProperty.type == PROPERTY_TYPES.LIST) {
601 valueJson.forEach(item => {
602 if (item != null && item != '' && item != tempValue) {
603 listValue.push(item);
606 checkedInstanceProperty.value = JSON.stringify(listValue);
608 checkedInstanceProperty.value = JSON.stringify(valueJson);
612 if (this.selectedInstanceData instanceof ComponentInstance) {
613 this.updateInstanceProperty(checkedInstanceProperty);
614 } else if (this.selectedInstanceData instanceof GroupInstance) {
615 this.updateGroupInstanceProperty(checkedInstanceProperty);
616 } else if (this.selectedInstanceData instanceof PolicyInstance) {
617 this.updatePolicyInstanceProperty(checkedInstanceProperty);
621 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
622 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
623 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
624 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
625 const parts = propertiesName.split("#");
626 const currentKey = (checkedProperty.type == PROPERTY_TYPES.MAP || checkedProperty.type == PROPERTY_TYPES.LIST) ? (<DerivedFEProperty>checkedProperty.input).mapKey : null;
627 if (checkedProperty.subPropertyToscaFunctions == null){
628 checkedProperty.subPropertyToscaFunctions = [];
630 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey != null ? [currentKey] : parts.slice(1)));
631 if (!subPropertyToscaFunction){
632 subPropertyToscaFunction = new SubPropertyToscaFunction();
633 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
635 subPropertyToscaFunction.toscaFunction = toscaFunction;
636 subPropertyToscaFunction.subPropertyPath = currentKey != null ? [currentKey] : parts.slice(1);
639 checkedProperty.subPropertyToscaFunctions = null;
640 checkedProperty.toscaFunction = toscaFunction;
642 if (this.selectedInstanceData instanceof ComponentInstance) {
643 this.updateInstanceProperty(checkedProperty);
644 } else if (this.selectedInstanceData instanceof GroupInstance) {
645 this.updateGroupInstanceProperty(checkedProperty);
646 } else if (this.selectedInstanceData instanceof PolicyInstance) {
647 this.updatePolicyInstanceProperty(checkedProperty);
651 private areEqual(array1: string[], array2: string[]): boolean {
652 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
655 updateInstanceProperty(instanceProperty: PropertyBEModel) {
656 this.loadingProperties = true;
657 this.enableToscaFunction = false;
658 this.checkedToscaCount = 0;
659 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
660 this.selectedInstanceData.uniqueId, [instanceProperty])
662 this.changeSelectedInstance(this.getSelectedInstance());
664 this.loadingProperties = false;
665 console.error(error);
667 this.loadingProperties = false;
671 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
672 this.loadingProperties = true;
673 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
674 this.selectedInstanceData.uniqueId, [instanceProperty])
676 this.changeSelectedInstance(this.getSelectedInstance());
678 this.loadingProperties = false;
679 console.error(error);
681 this.loadingProperties = false;
685 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
686 this.loadingProperties = true;
687 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
688 this.selectedInstanceData.uniqueId, [instanceProperty])
690 this.changeSelectedInstance(this.getSelectedInstance());
692 this.loadingProperties = false;
693 console.error(error);
695 this.loadingProperties = false;
699 /*** DECLARE PROPERTIES/INPUTS ***/
700 declareProperties = (): void => {
701 console.debug("==>" + this.constructor.name + ": declareProperties");
703 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
704 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
705 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
706 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
707 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
709 angular.forEach(instancesIds, (instanceId: string): void => {
710 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
711 if (selectedInstanceData instanceof ComponentInstance) {
712 if (!this.isInput(selectedInstanceData.originType)) {
713 // convert Property FE model -> Property BE model, extract only checked
714 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
716 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
718 } else if (selectedInstanceData instanceof GroupInstance) {
719 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
720 } else if (selectedInstanceData instanceof PolicyInstance) {
721 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
725 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
727 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
728 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
729 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
731 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
732 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
735 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
736 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
737 prop => !this.isCapabilityProperty(prop)
739 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
740 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
743 let isCapabilityPropertyChanged = false;
745 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
746 (prop: PropertyBEModel) => {
747 prop.name = prop.origName || prop.name;
748 if (this.isCapabilityProperty(prop)) {
749 isCapabilityPropertyChanged = true;
753 this.topologyTemplateService
754 .createInput(this.component, inputsToCreate, this.isSelf())
755 .subscribe((response) => {
756 this.selectInstanceRow(SERVICE_SELF_TITLE);
757 this.onInstanceSelectedUpdate(this.instances[0]);
758 this.setInputTabIndication(response.length);
759 this.checkedPropertiesCount = 0;
760 this.checkedChildPropertiesCount = 0;
761 _.forEach(response, (input: InputBEModel) => {
762 const newInput: InputFEModel = new InputFEModel(input);
763 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
764 this.inputs.push(newInput);
765 this.updatePropertyValueAfterDeclare(newInput);
767 if (isCapabilityPropertyChanged) {
768 this.reloadInstanceCapabilities();
770 }, error => {}); //ignore error
773 declareListProperties = (): void => {
774 // get selected properties
775 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
776 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
777 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
778 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
779 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
780 let propertyNameList: Array<string> = [];
783 angular.forEach(instancesIds, (instanceId: string): void => {
785 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
786 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
788 if (selectedInstanceData instanceof ComponentInstance) {
789 if (!this.isInput(selectedInstanceData.originType)) {
790 // convert Property FE model -> Property BE model, extract only checked
791 selectedComponentInstancesProperties[instanceId] = checkedProperties;
793 selectedComponentInstancesInputs[instanceId] = checkedProperties;
795 } else if (selectedInstanceData instanceof GroupInstance) {
796 selectedGroupInstancesProperties[instanceId] = checkedProperties;
797 } else if (selectedInstanceData instanceof PolicyInstance) {
798 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
801 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
802 propertyNameList.push(property.name);
806 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
808 let modalTitle = 'Declare Properties as List Input';
809 const modal = this.modalService.createCustomModal(new ModalModel(
811 modalTitle, /* title */
816 'blue', /* css class */
817 () => { /* callback */
818 let content:any = modal.instance.dynamicContent.instance;
821 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
822 let typelist: any = PROPERTY_TYPES.LIST;
823 let uniID: any = insId;
824 let boolfalse: any = false;
825 let required: any = content.propertyModel.required;
829 "type": content.propertyModel.simpleType,
833 let schemaProp :any = {
834 "type": content.propertyModel.simpleType,
838 reglistInput.description = content.propertyModel.description;
839 reglistInput.name = content.propertyModel.name;
840 reglistInput.type = typelist;
841 reglistInput.schemaType = content.propertyModel.simpleType;
842 reglistInput.instanceUniqueId = uniID;
843 reglistInput.uniqueId = uniID;
844 reglistInput.required = required;
845 reglistInput.schema = schem;
846 reglistInput.schemaProperty = schemaProp;
849 componentInstInputsMap: content.inputsToCreate,
850 listInput: reglistInput
853 this.topologyTemplateService
854 .createListInput(this.component, input, this.isSelf())
855 .subscribe(response => {
856 this.setInputTabIndication(response.length);
857 this.checkedPropertiesCount = 0;
858 this.checkedChildPropertiesCount = 0;
859 _.forEach(response, (input: InputBEModel) => {
860 let newInput: InputFEModel = new InputFEModel(input);
861 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
862 this.inputs.push(newInput);
863 // create list input does not return updated properties info, so need to reload
864 //this.updatePropertyValueAfterDeclare(newInput);
865 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
866 this.changeSelectedInstance(this.selectedInstanceData);
868 modal.instance.close();
870 }, error => {}); //ignore error
873 /*, getDisabled: function */
875 new ButtonModel('Cancel', 'outline grey', () => {
876 modal.instance.close();
881 // 3rd arg is passed to DeclareListComponent instance
882 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
883 modal.instance.open();
886 /*** DECLARE PROPERTIES/POLICIES ***/
887 declarePropertiesToPolicies = (): void => {
888 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
889 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
891 angular.forEach(instancesIds, (instanceId: string): void => {
892 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
893 if (selectedInstanceData instanceof ComponentInstance) {
894 if (!this.isInput(selectedInstanceData.originType)) {
895 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
900 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
901 this.loadingPolicies = true;
903 this.topologyTemplateService
904 .createPolicy(this.component, policiesToCreate, this.isSelf())
905 .subscribe(response => {
906 this.setPolicyTabIndication(response.length);
907 this.checkedPropertiesCount = 0;
908 this.displayPoliciesAsDeclared(response);
909 this.loadingPolicies = false;
914 displayPoliciesAsDeclared = (policies) => {
915 _.forEach(policies, (policy: any) => {
916 let newPolicy: InputFEModel = new InputFEModel(policy);
917 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
918 newPolicy.relatedPropertyName = policy.name;
919 newPolicy.relatedPropertyValue = policy.value;
920 this.updatePropertyValueAfterDeclare(newPolicy);
921 this.policies.push(policy);
925 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
926 return new Promise((resolve, reject) => {
927 if (!this.isValidChangedData) {
928 reject('Changed data is invalid - cannot save!');
931 if (!this.changedData.length) {
936 // make request and its handlers
938 let handleSuccess, handleError;
939 let changedInputsProperties = [], changedCapabilitiesProperties = [];
940 if (this.isPropertiesTabSelected) {
941 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
942 changedProp = <PropertyFEModel>changedProp;
943 const propBE = new PropertyBEModel(changedProp);
944 propBE.toscaPresentation = new ToscaPresentationData();
945 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
946 propBE.value = changedProp.getJSONValue();
947 propBE.name = changedProp.origName || changedProp.name;
948 delete propBE.origName;
951 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
953 if (this.selectedInstanceData instanceof ComponentInstance) {
954 if (this.isInput(this.selectedInstanceData.originType)) {
955 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
956 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
957 request = Observable.forkJoin(
958 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
959 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
960 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
963 else if (changedInputsProperties.length) {
964 request = this.componentInstanceServiceNg2
965 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
967 else if (changedCapabilitiesProperties.length) {
968 request = this.componentInstanceServiceNg2
969 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
971 handleSuccess = (response) => {
972 // reset each changed property with new value and remove it from changed properties list
973 response.forEach((resInput) => {
974 const changedProp = <PropertyFEModel>this.changedData.shift();
975 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
980 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
981 delete cp.constraints;
985 request = this.componentInstanceServiceNg2
986 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
988 handleSuccess = (response) => {
989 // reset each changed property with new value and remove it from changed properties list
990 response.forEach((resProp) => {
991 const changedProp = <PropertyFEModel>this.changedData.shift();
992 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
997 } else if (this.selectedInstanceData instanceof GroupInstance) {
998 request = this.componentInstanceServiceNg2
999 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1000 handleSuccess = (response) => {
1001 // reset each changed property with new value and remove it from changed properties list
1002 response.forEach((resProp) => {
1003 const changedProp = <PropertyFEModel>this.changedData.shift();
1004 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1008 } else if (this.selectedInstanceData instanceof PolicyInstance) {
1009 request = this.componentInstanceServiceNg2
1010 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1011 handleSuccess = (response) => {
1012 // reset each changed property with new value and remove it from changed properties list
1013 response.forEach((resProp) => {
1014 const changedProp = <PropertyFEModel>this.changedData.shift();
1015 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1020 } else if (this.isInputsTabSelected) {
1022 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1023 changedInput = <InputFEModel>changedInput;
1024 const inputBE = new InputBEModel(changedInput);
1025 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1028 request = this.componentServiceNg2
1029 .updateComponentInputs(this.component, changedInputs);
1030 handleSuccess = (response) => {
1031 // reset each changed property with new value and remove it from changed properties list
1032 response.forEach((resInput) => {
1033 const changedInput = <InputFEModel>this.changedData.shift();
1034 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1035 changedInput.required = resInput.required;
1036 changedInput.requiredOrig = resInput.required;
1041 this.savingChangedData = true;
1044 this.savingChangedData = false;
1045 if (changedCapabilitiesProperties.length) {
1046 this.reloadInstanceCapabilities();
1048 handleSuccess && handleSuccess(response);
1049 this.updateHasChangedData();
1053 this.savingChangedData = false;
1054 handleError && handleError(error);
1055 this.updateHasChangedData();
1062 reloadInstanceCapabilities = (): void => {
1063 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1064 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1065 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1066 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1067 return instance.capabilities;
1070 }, new CapabilitiesGroup());
1071 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1075 reverseChangedData = ():void => {
1076 // make reverse item handler
1077 let handleReverseItem;
1078 if (this.isPropertiesTabSelected) {
1079 handleReverseItem = (changedItem) => {
1080 changedItem = <PropertyFEModel>changedItem;
1081 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1083 } else if (this.isInputsTabSelected) {
1084 handleReverseItem = (changedItem) => {
1085 changedItem = <InputFEModel>changedItem;
1086 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1087 changedItem.resetMetadata();
1088 changedItem.required = changedItem.requiredOrig;
1092 this.changedData.forEach(handleReverseItem);
1093 this.changedData = [];
1094 this.updateHasChangedData();
1097 updateHasChangedData = ():boolean => {
1098 const curHasChangedData:boolean = (this.changedData.length > 0);
1099 if (curHasChangedData !== this.hasChangedData) {
1100 this.hasChangedData = curHasChangedData;
1101 if(this.hasChangedData) {
1102 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1104 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1107 return this.hasChangedData;
1110 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1111 this.saveChangedData().then(
1113 this.notification.success({
1114 message: 'Successfully saved changes',
1117 if(onSuccessFunction) onSuccessFunction();
1120 this.notification.error({
1121 message: 'Failed to save changes!',
1124 if(onError) onError();
1129 showUnsavedChangesAlert = ():Promise<any> => {
1130 let modalTitle:string;
1131 if (this.isPropertiesTabSelected) {
1132 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1133 } else if (this.isInputsTabSelected) {
1134 modalTitle = `Unsaved inputs for ${this.component.name}`;
1137 return new Promise<any>((resolve, reject) => {
1138 const modal = this.ModalServiceSdcUI.openCustomModal(
1142 type: SdcUiCommon.ModalType.custom,
1143 testId: "navigate-modal",
1146 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1147 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1148 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1149 ] as SdcUiCommon.IModalButtonComponent[]
1150 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1155 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1156 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1157 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1158 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1159 return feProperty.name == input.relatedPropertyName &&
1160 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1162 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1163 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1164 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1165 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1169 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1170 updateCheckedPropertyCount = (increment: boolean): void => {
1171 this.checkedPropertiesCount += (increment) ? 1 : -1;
1172 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1175 updateCheckedChildPropertyCount = (increment: boolean): void => {
1176 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1179 togggleToscaBtn = (toscaFlag: boolean) : void => {
1180 this.checkedToscaCount += toscaFlag ? 1 : -1;
1181 if(this.checkedToscaCount == 1){
1182 this.enableToscaFunction = true;
1184 this.enableToscaFunction = false;
1188 setInputTabIndication = (numInputs: number): void => {
1189 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1192 setPolicyTabIndication = (numPolicies: number): void => {
1193 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1196 resetUnsavedChangesForInput = (input:InputFEModel) => {
1197 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1198 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1199 this.updateHasChangedData();
1202 deleteInput = (input: InputFEModel) => {
1203 //reset any unsaved changes to the input before deleting it
1204 this.resetUnsavedChangesForInput(input);
1206 console.debug("==>" + this.constructor.name + ": deleteInput");
1207 let inputToDelete = new InputBEModel(input);
1209 this.componentServiceNg2
1210 .deleteInput(this.component, inputToDelete)
1211 .subscribe(response => {
1212 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1214 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1215 this.changeSelectedInstance(this.selectedInstanceData);
1216 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1218 // if (instanceFeProperties) {
1219 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1220 // return prop.name == input.propertyName;
1223 // if (propToEnable) {
1224 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1225 // propToEnable.setNonDeclared(response.inputPath);
1226 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1227 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1230 }, error => {}); //ignore error
1233 deletePolicy = (policy: PolicyInstance) => {
1234 this.loadingPolicies = true;
1235 this.topologyTemplateService
1236 .deletePolicy(this.component, policy)
1237 .subscribe((response) => {
1238 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1239 this.changeSelectedInstance(this.selectedInstanceData);
1240 this.loadingPolicies = false;
1244 deleteProperty = (property: PropertyFEModel) => {
1245 const propertyToDelete = new PropertyFEModel(property);
1246 this.loadingProperties = true;
1247 const feMap = this.instanceFePropertiesMap;
1248 this.topologyTemplateService
1249 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1250 .subscribe((response) => {
1251 const props = feMap[this.component.uniqueId];
1252 props.splice(props.findIndex(p => p.uniqueId === response),1);
1253 this.loadingProperties = false;
1255 this.loadingProperties = false;
1256 console.error(error);
1260 /*** addProperty ***/
1261 addProperty = (model: string) => {
1262 this.loadDataTypesByComponentModel(model)
1263 let modalTitle = 'Add Property';
1264 let modal = this.modalService.createCustomModal(new ModalModel(
1269 new ButtonModel('Save', 'blue', () => {
1270 modal.instance.dynamicContent.instance.isLoading = true;
1271 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1272 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1273 .subscribe((response) => {
1274 modal.instance.dynamicContent.instance.isLoading = false;
1275 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1276 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1277 modal.instance.close();
1279 modal.instance.dynamicContent.instance.isLoading = false;
1280 this.notification.error({
1281 message: 'Failed to add property:' + error,
1285 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1286 new ButtonModel('Cancel', 'outline grey', () => {
1287 modal.instance.close();
1292 modal.instance.open();
1293 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1298 let modalTitle = 'Add Input';
1299 let modal = this.modalService.createCustomModal(new ModalModel(
1304 new ButtonModel('Save', 'blue', () => {
1305 modal.instance.dynamicContent.instance.isLoading = true;
1306 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1307 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1308 .subscribe((response) => {
1309 modal.instance.dynamicContent.instance.isLoading = false;
1310 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1311 this.inputs.push(newInputProp);
1312 modal.instance.close();
1314 modal.instance.dynamicContent.instance.isLoading = false;
1315 this.notification.error({
1316 message: 'Failed to add input:' + error,
1320 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1321 new ButtonModel('Cancel', 'outline grey', () => {
1322 modal.instance.close();
1327 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1328 modal.instance.open();
1331 /*** SEARCH RELATED FUNCTIONS ***/
1332 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1333 let instanceBePropertiesMap:InstanceBePropertiesMap;
1334 this.componentServiceNg2
1335 .filterComponentInstanceProperties(this.component, filterData)
1336 .subscribe((response) => {
1337 this.processInstancePropertiesResponse(response, false);
1338 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1339 this.searchPropertyName = filterData.propertyName;//mark in table
1340 this.hierarchyNavTabs.triggerTabChange('Composition');
1341 this.propertiesNavigationData = [];
1342 this.displayClearSearch = true;
1343 }, (error) => {}); //ignore error
1347 clearSearch = () => {
1348 this.instancesNavigationData = this.instances;
1349 this.searchPropertyName = "";
1350 this.hierarchyPropertiesDisplayOptions.searchText = "";
1351 this.displayClearSearch = false;
1352 this.advanceSearch.clearAll();
1353 this.searchQuery = '';
1356 clickOnClearSearch = () => {
1358 this.selectFirstInstanceByDefault();
1359 this.hierarchyNavTabs.triggerTabChange('Composition');
1362 private isInput = (instanceType:string):boolean =>{
1363 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1366 loadDataTypesByComponentModel(model:string) {
1367 this.propertyCreatorComponent.filterDataTypesByModel(model);