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 let currentValue = 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 ? (<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 delete valueJson[currentKey];
598 checkedInstanceProperty.value = JSON.stringify(valueJson);
601 if (this.selectedInstanceData instanceof ComponentInstance) {
602 this.updateInstanceProperty(checkedInstanceProperty);
603 } else if (this.selectedInstanceData instanceof GroupInstance) {
604 this.updateGroupInstanceProperty(checkedInstanceProperty);
605 } else if (this.selectedInstanceData instanceof PolicyInstance) {
606 this.updatePolicyInstanceProperty(checkedInstanceProperty);
610 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
611 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
612 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
613 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
614 const parts = propertiesName.split("#");
615 const currentKey = checkedProperty.type === PROPERTY_TYPES.MAP ? (<DerivedFEProperty>checkedProperty.input).mapKey : null;
616 if (checkedProperty.subPropertyToscaFunctions == null){
617 checkedProperty.subPropertyToscaFunctions = [];
619 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey != null ? [currentKey] : parts.slice(1)));
620 if (!subPropertyToscaFunction){
621 subPropertyToscaFunction = new SubPropertyToscaFunction();
622 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
624 subPropertyToscaFunction.toscaFunction = toscaFunction;
625 subPropertyToscaFunction.subPropertyPath = currentKey != null ? [currentKey] : parts.slice(1);
628 checkedProperty.subPropertyToscaFunctions = null;
629 checkedProperty.toscaFunction = toscaFunction;
631 if (this.selectedInstanceData instanceof ComponentInstance) {
632 this.updateInstanceProperty(checkedProperty);
633 } else if (this.selectedInstanceData instanceof GroupInstance) {
634 this.updateGroupInstanceProperty(checkedProperty);
635 } else if (this.selectedInstanceData instanceof PolicyInstance) {
636 this.updatePolicyInstanceProperty(checkedProperty);
640 private areEqual(array1: string[], array2: string[]): boolean {
641 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
644 updateInstanceProperty(instanceProperty: PropertyBEModel) {
645 this.loadingProperties = true;
646 this.enableToscaFunction = false;
647 this.checkedToscaCount = 0;
648 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
649 this.selectedInstanceData.uniqueId, [instanceProperty])
651 this.changeSelectedInstance(this.getSelectedInstance());
653 this.loadingProperties = false;
654 console.error(error);
656 this.loadingProperties = false;
660 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
661 this.loadingProperties = true;
662 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
663 this.selectedInstanceData.uniqueId, [instanceProperty])
665 this.changeSelectedInstance(this.getSelectedInstance());
667 this.loadingProperties = false;
668 console.error(error);
670 this.loadingProperties = false;
674 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
675 this.loadingProperties = true;
676 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
677 this.selectedInstanceData.uniqueId, [instanceProperty])
679 this.changeSelectedInstance(this.getSelectedInstance());
681 this.loadingProperties = false;
682 console.error(error);
684 this.loadingProperties = false;
688 /*** DECLARE PROPERTIES/INPUTS ***/
689 declareProperties = (): void => {
690 console.debug("==>" + this.constructor.name + ": declareProperties");
692 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
693 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
694 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
695 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
696 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
698 angular.forEach(instancesIds, (instanceId: string): void => {
699 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
700 if (selectedInstanceData instanceof ComponentInstance) {
701 if (!this.isInput(selectedInstanceData.originType)) {
702 // convert Property FE model -> Property BE model, extract only checked
703 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
705 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
707 } else if (selectedInstanceData instanceof GroupInstance) {
708 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
709 } else if (selectedInstanceData instanceof PolicyInstance) {
710 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
714 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
716 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
717 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
718 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
720 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
721 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
724 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
725 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
726 prop => !this.isCapabilityProperty(prop)
728 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
729 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
732 let isCapabilityPropertyChanged = false;
734 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
735 (prop: PropertyBEModel) => {
736 prop.name = prop.origName || prop.name;
737 if (this.isCapabilityProperty(prop)) {
738 isCapabilityPropertyChanged = true;
742 this.topologyTemplateService
743 .createInput(this.component, inputsToCreate, this.isSelf())
744 .subscribe((response) => {
745 this.selectInstanceRow(SERVICE_SELF_TITLE);
746 this.onInstanceSelectedUpdate(this.instances[0]);
747 this.setInputTabIndication(response.length);
748 this.checkedPropertiesCount = 0;
749 this.checkedChildPropertiesCount = 0;
750 _.forEach(response, (input: InputBEModel) => {
751 const newInput: InputFEModel = new InputFEModel(input);
752 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
753 this.inputs.push(newInput);
754 this.updatePropertyValueAfterDeclare(newInput);
756 if (isCapabilityPropertyChanged) {
757 this.reloadInstanceCapabilities();
759 }, error => {}); //ignore error
762 declareListProperties = (): void => {
763 // get selected properties
764 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
765 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
766 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
767 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
768 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
769 let propertyNameList: Array<string> = [];
772 angular.forEach(instancesIds, (instanceId: string): void => {
774 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
775 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
777 if (selectedInstanceData instanceof ComponentInstance) {
778 if (!this.isInput(selectedInstanceData.originType)) {
779 // convert Property FE model -> Property BE model, extract only checked
780 selectedComponentInstancesProperties[instanceId] = checkedProperties;
782 selectedComponentInstancesInputs[instanceId] = checkedProperties;
784 } else if (selectedInstanceData instanceof GroupInstance) {
785 selectedGroupInstancesProperties[instanceId] = checkedProperties;
786 } else if (selectedInstanceData instanceof PolicyInstance) {
787 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
790 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
791 propertyNameList.push(property.name);
795 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
797 let modalTitle = 'Declare Properties as List Input';
798 const modal = this.modalService.createCustomModal(new ModalModel(
800 modalTitle, /* title */
805 'blue', /* css class */
806 () => { /* callback */
807 let content:any = modal.instance.dynamicContent.instance;
810 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
811 let typelist: any = PROPERTY_TYPES.LIST;
812 let uniID: any = insId;
813 let boolfalse: any = false;
814 let required: any = content.propertyModel.required;
818 "type": content.propertyModel.simpleType,
822 let schemaProp :any = {
823 "type": content.propertyModel.simpleType,
827 reglistInput.description = content.propertyModel.description;
828 reglistInput.name = content.propertyModel.name;
829 reglistInput.type = typelist;
830 reglistInput.schemaType = content.propertyModel.simpleType;
831 reglistInput.instanceUniqueId = uniID;
832 reglistInput.uniqueId = uniID;
833 reglistInput.required = required;
834 reglistInput.schema = schem;
835 reglistInput.schemaProperty = schemaProp;
838 componentInstInputsMap: content.inputsToCreate,
839 listInput: reglistInput
842 this.topologyTemplateService
843 .createListInput(this.component, input, this.isSelf())
844 .subscribe(response => {
845 this.setInputTabIndication(response.length);
846 this.checkedPropertiesCount = 0;
847 this.checkedChildPropertiesCount = 0;
848 _.forEach(response, (input: InputBEModel) => {
849 let newInput: InputFEModel = new InputFEModel(input);
850 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
851 this.inputs.push(newInput);
852 // create list input does not return updated properties info, so need to reload
853 //this.updatePropertyValueAfterDeclare(newInput);
854 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
855 this.changeSelectedInstance(this.selectedInstanceData);
857 modal.instance.close();
859 }, error => {}); //ignore error
862 /*, getDisabled: function */
864 new ButtonModel('Cancel', 'outline grey', () => {
865 modal.instance.close();
870 // 3rd arg is passed to DeclareListComponent instance
871 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
872 modal.instance.open();
875 /*** DECLARE PROPERTIES/POLICIES ***/
876 declarePropertiesToPolicies = (): void => {
877 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
878 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
880 angular.forEach(instancesIds, (instanceId: string): void => {
881 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
882 if (selectedInstanceData instanceof ComponentInstance) {
883 if (!this.isInput(selectedInstanceData.originType)) {
884 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
889 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
890 this.loadingPolicies = true;
892 this.topologyTemplateService
893 .createPolicy(this.component, policiesToCreate, this.isSelf())
894 .subscribe(response => {
895 this.setPolicyTabIndication(response.length);
896 this.checkedPropertiesCount = 0;
897 this.displayPoliciesAsDeclared(response);
898 this.loadingPolicies = false;
903 displayPoliciesAsDeclared = (policies) => {
904 _.forEach(policies, (policy: any) => {
905 let newPolicy: InputFEModel = new InputFEModel(policy);
906 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
907 newPolicy.relatedPropertyName = policy.name;
908 newPolicy.relatedPropertyValue = policy.value;
909 this.updatePropertyValueAfterDeclare(newPolicy);
910 this.policies.push(policy);
914 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
915 return new Promise((resolve, reject) => {
916 if (!this.isValidChangedData) {
917 reject('Changed data is invalid - cannot save!');
920 if (!this.changedData.length) {
925 // make request and its handlers
927 let handleSuccess, handleError;
928 let changedInputsProperties = [], changedCapabilitiesProperties = [];
929 if (this.isPropertiesTabSelected) {
930 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
931 changedProp = <PropertyFEModel>changedProp;
932 const propBE = new PropertyBEModel(changedProp);
933 propBE.toscaPresentation = new ToscaPresentationData();
934 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
935 propBE.value = changedProp.getJSONValue();
936 propBE.name = changedProp.origName || changedProp.name;
937 delete propBE.origName;
940 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
942 if (this.selectedInstanceData instanceof ComponentInstance) {
943 if (this.isInput(this.selectedInstanceData.originType)) {
944 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
945 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
946 request = Observable.forkJoin(
947 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
948 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
949 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
952 else if (changedInputsProperties.length) {
953 request = this.componentInstanceServiceNg2
954 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
956 else if (changedCapabilitiesProperties.length) {
957 request = this.componentInstanceServiceNg2
958 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
960 handleSuccess = (response) => {
961 // reset each changed property with new value and remove it from changed properties list
962 response.forEach((resInput) => {
963 const changedProp = <PropertyFEModel>this.changedData.shift();
964 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
969 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
970 delete cp.constraints;
974 request = this.componentInstanceServiceNg2
975 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
977 handleSuccess = (response) => {
978 // reset each changed property with new value and remove it from changed properties list
979 response.forEach((resProp) => {
980 const changedProp = <PropertyFEModel>this.changedData.shift();
981 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
986 } else if (this.selectedInstanceData instanceof GroupInstance) {
987 request = this.componentInstanceServiceNg2
988 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
989 handleSuccess = (response) => {
990 // reset each changed property with new value and remove it from changed properties list
991 response.forEach((resProp) => {
992 const changedProp = <PropertyFEModel>this.changedData.shift();
993 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
997 } else if (this.selectedInstanceData instanceof PolicyInstance) {
998 request = this.componentInstanceServiceNg2
999 .updateComponentPolicyInstanceProperties(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);
1009 } else if (this.isInputsTabSelected) {
1011 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1012 changedInput = <InputFEModel>changedInput;
1013 const inputBE = new InputBEModel(changedInput);
1014 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1017 request = this.componentServiceNg2
1018 .updateComponentInputs(this.component, changedInputs);
1019 handleSuccess = (response) => {
1020 // reset each changed property with new value and remove it from changed properties list
1021 response.forEach((resInput) => {
1022 const changedInput = <InputFEModel>this.changedData.shift();
1023 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1024 changedInput.required = resInput.required;
1025 changedInput.requiredOrig = resInput.required;
1030 this.savingChangedData = true;
1033 this.savingChangedData = false;
1034 if (changedCapabilitiesProperties.length) {
1035 this.reloadInstanceCapabilities();
1037 handleSuccess && handleSuccess(response);
1038 this.updateHasChangedData();
1042 this.savingChangedData = false;
1043 handleError && handleError(error);
1044 this.updateHasChangedData();
1051 reloadInstanceCapabilities = (): void => {
1052 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1053 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1054 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1055 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1056 return instance.capabilities;
1059 }, new CapabilitiesGroup());
1060 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1064 reverseChangedData = ():void => {
1065 // make reverse item handler
1066 let handleReverseItem;
1067 if (this.isPropertiesTabSelected) {
1068 handleReverseItem = (changedItem) => {
1069 changedItem = <PropertyFEModel>changedItem;
1070 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1072 } else if (this.isInputsTabSelected) {
1073 handleReverseItem = (changedItem) => {
1074 changedItem = <InputFEModel>changedItem;
1075 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1076 changedItem.resetMetadata();
1077 changedItem.required = changedItem.requiredOrig;
1081 this.changedData.forEach(handleReverseItem);
1082 this.changedData = [];
1083 this.updateHasChangedData();
1086 updateHasChangedData = ():boolean => {
1087 const curHasChangedData:boolean = (this.changedData.length > 0);
1088 if (curHasChangedData !== this.hasChangedData) {
1089 this.hasChangedData = curHasChangedData;
1090 if(this.hasChangedData) {
1091 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1093 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1096 return this.hasChangedData;
1099 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1100 this.saveChangedData().then(
1102 this.notification.success({
1103 message: 'Successfully saved changes',
1106 if(onSuccessFunction) onSuccessFunction();
1109 this.notification.error({
1110 message: 'Failed to save changes!',
1113 if(onError) onError();
1118 showUnsavedChangesAlert = ():Promise<any> => {
1119 let modalTitle:string;
1120 if (this.isPropertiesTabSelected) {
1121 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1122 } else if (this.isInputsTabSelected) {
1123 modalTitle = `Unsaved inputs for ${this.component.name}`;
1126 return new Promise<any>((resolve, reject) => {
1127 const modal = this.ModalServiceSdcUI.openCustomModal(
1131 type: SdcUiCommon.ModalType.custom,
1132 testId: "navigate-modal",
1135 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1136 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1137 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1138 ] as SdcUiCommon.IModalButtonComponent[]
1139 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1144 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1145 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1146 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1147 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1148 return feProperty.name == input.relatedPropertyName &&
1149 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1151 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1152 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1153 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1154 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1158 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1159 updateCheckedPropertyCount = (increment: boolean): void => {
1160 this.checkedPropertiesCount += (increment) ? 1 : -1;
1161 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1164 updateCheckedChildPropertyCount = (increment: boolean): void => {
1165 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1168 togggleToscaBtn = (toscaFlag: boolean) : void => {
1169 this.checkedToscaCount += toscaFlag ? 1 : -1;
1170 if(this.checkedToscaCount == 1){
1171 this.enableToscaFunction = true;
1173 this.enableToscaFunction = false;
1177 setInputTabIndication = (numInputs: number): void => {
1178 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1181 setPolicyTabIndication = (numPolicies: number): void => {
1182 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1185 resetUnsavedChangesForInput = (input:InputFEModel) => {
1186 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1187 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1188 this.updateHasChangedData();
1191 deleteInput = (input: InputFEModel) => {
1192 //reset any unsaved changes to the input before deleting it
1193 this.resetUnsavedChangesForInput(input);
1195 console.debug("==>" + this.constructor.name + ": deleteInput");
1196 let inputToDelete = new InputBEModel(input);
1198 this.componentServiceNg2
1199 .deleteInput(this.component, inputToDelete)
1200 .subscribe(response => {
1201 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1203 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1204 this.changeSelectedInstance(this.selectedInstanceData);
1205 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1207 // if (instanceFeProperties) {
1208 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1209 // return prop.name == input.propertyName;
1212 // if (propToEnable) {
1213 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1214 // propToEnable.setNonDeclared(response.inputPath);
1215 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1216 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1219 }, error => {}); //ignore error
1222 deletePolicy = (policy: PolicyInstance) => {
1223 this.loadingPolicies = true;
1224 this.topologyTemplateService
1225 .deletePolicy(this.component, policy)
1226 .subscribe((response) => {
1227 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1228 this.changeSelectedInstance(this.selectedInstanceData);
1229 this.loadingPolicies = false;
1233 deleteProperty = (property: PropertyFEModel) => {
1234 const propertyToDelete = new PropertyFEModel(property);
1235 this.loadingProperties = true;
1236 const feMap = this.instanceFePropertiesMap;
1237 this.topologyTemplateService
1238 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1239 .subscribe((response) => {
1240 const props = feMap[this.component.uniqueId];
1241 props.splice(props.findIndex(p => p.uniqueId === response),1);
1242 this.loadingProperties = false;
1244 this.loadingProperties = false;
1245 console.error(error);
1249 /*** addProperty ***/
1250 addProperty = (model: string) => {
1251 this.loadDataTypesByComponentModel(model)
1252 let modalTitle = 'Add Property';
1253 let modal = this.modalService.createCustomModal(new ModalModel(
1258 new ButtonModel('Save', 'blue', () => {
1259 modal.instance.dynamicContent.instance.isLoading = true;
1260 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1261 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1262 .subscribe((response) => {
1263 modal.instance.dynamicContent.instance.isLoading = false;
1264 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1265 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1266 modal.instance.close();
1268 modal.instance.dynamicContent.instance.isLoading = false;
1269 this.notification.error({
1270 message: 'Failed to add property:' + error,
1274 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1275 new ButtonModel('Cancel', 'outline grey', () => {
1276 modal.instance.close();
1281 modal.instance.open();
1282 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1287 let modalTitle = 'Add Input';
1288 let modal = this.modalService.createCustomModal(new ModalModel(
1293 new ButtonModel('Save', 'blue', () => {
1294 modal.instance.dynamicContent.instance.isLoading = true;
1295 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1296 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1297 .subscribe((response) => {
1298 modal.instance.dynamicContent.instance.isLoading = false;
1299 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1300 this.inputs.push(newInputProp);
1301 modal.instance.close();
1303 modal.instance.dynamicContent.instance.isLoading = false;
1304 this.notification.error({
1305 message: 'Failed to add input:' + error,
1309 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1310 new ButtonModel('Cancel', 'outline grey', () => {
1311 modal.instance.close();
1316 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1317 modal.instance.open();
1320 /*** SEARCH RELATED FUNCTIONS ***/
1321 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1322 let instanceBePropertiesMap:InstanceBePropertiesMap;
1323 this.componentServiceNg2
1324 .filterComponentInstanceProperties(this.component, filterData)
1325 .subscribe((response) => {
1326 this.processInstancePropertiesResponse(response, false);
1327 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1328 this.searchPropertyName = filterData.propertyName;//mark in table
1329 this.hierarchyNavTabs.triggerTabChange('Composition');
1330 this.propertiesNavigationData = [];
1331 this.displayClearSearch = true;
1332 }, (error) => {}); //ignore error
1336 clearSearch = () => {
1337 this.instancesNavigationData = this.instances;
1338 this.searchPropertyName = "";
1339 this.hierarchyPropertiesDisplayOptions.searchText = "";
1340 this.displayClearSearch = false;
1341 this.advanceSearch.clearAll();
1342 this.searchQuery = '';
1345 clickOnClearSearch = () => {
1347 this.selectFirstInstanceByDefault();
1348 this.hierarchyNavTabs.triggerTabChange('Composition');
1351 private isInput = (instanceType:string):boolean =>{
1352 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1355 loadDataTypesByComponentModel(model:string) {
1356 this.propertyCreatorComponent.filterDataTypesByModel(model);