2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 import * as _ from "lodash";
22 import {Component, Inject, ViewChild} from "@angular/core";
23 import {PropertiesService} from "../../services/properties.service";
26 Component as ComponentData,
29 FilterPropertiesAssignmentData,
33 InstanceBePropertiesMap,
34 InstanceFePropertiesMap,
35 InstancePropertiesAPIMap,
42 PropertyDeclareAPIModel,
45 import {ResourceType} from "app/utils";
46 import {ComponentServiceNg2} from "../../services/component-services/component.service";
47 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
48 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
49 import {KeysPipe} from 'app/ng2/pipes/keys.pipe';
50 import {EVENTS, PROPERTY_TYPES, WorkspaceMode, PROPERTY_DATA} from "../../../utils/constants";
51 import {EventListenerService} from "app/services/event-listener-service"
52 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
53 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
54 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
55 import {HierarchyNavService} from "./services/hierarchy-nav.service";
56 import {PropertiesUtils} from "./services/properties.utils";
57 import {ComponentModeService} from "../../services/component-services/component-mode.service";
58 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
59 import {InputsUtils} from "./services/inputs.utils";
60 import {InstanceFeDetails} from "../../../models/instance-fe-details";
61 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
62 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
63 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
64 import {ModalService} from "../../services/modal.service";
65 import {DeclareListComponent} from "./declare-list/declare-list.component";
66 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
67 import {CapabilitiesGroup, Capability} from "../../../models/capability";
68 import {ToscaPresentationData} from "../../../models/tosca-presentation";
69 import {Observable} from "rxjs";
70 import {TranslateService} from "../../shared/translator/translate.service";
71 import {ToscaFunction} from "../../../models/tosca-function";
72 import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function";
74 const SERVICE_SELF_TITLE = "SELF";
76 templateUrl: './properties-assignment.page.component.html',
77 styleUrls: ['./properties-assignment.page.component.less']
79 export class PropertiesAssignmentComponent {
80 title = "Properties & Inputs";
82 component: ComponentData;
83 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
84 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
86 propertiesNavigationData = [];
87 instancesNavigationData = [];
89 instanceFePropertiesMap: InstanceFePropertiesMap;
90 inputs: Array<InputFEModel> = [];
91 policies: Array<PolicyInstance> = [];
92 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
94 propertyStructureHeader: string;
96 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
97 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
98 checkedPropertiesCount: number = 0;
99 checkedChildPropertiesCount: number = 0;
100 enableToscaFunction: boolean = false;
101 checkedToscaCount: number = 0;
103 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
104 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
105 displayClearSearch = false;
106 searchPropertyName: string;
108 isInputsTabSelected: boolean;
109 isPropertiesTabSelected: boolean;
110 isPoliciesTabSelected: boolean;
112 resourceIsReadonly: boolean;
113 loadingInstances: boolean = false;
114 loadingInputs: boolean = false;
115 loadingPolicies: boolean = false;
116 loadingProperties: boolean = false;
117 changedData: Array<PropertyFEModel | InputFEModel>;
118 hasChangedData: boolean;
119 isValidChangedData: boolean;
120 savingChangedData: boolean;
121 stateChangeStartUnregister: Function;
122 serviceBePropertiesMap: InstanceBePropertiesMap;
123 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
124 selectedInstance_FlattenCapabilitiesList: Capability[];
125 componentInstancePropertyMap : PropertiesGroup;
127 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
128 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
129 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
131 constructor(private propertiesService: PropertiesService,
132 private hierarchyNavService: HierarchyNavService,
133 private propertiesUtils: PropertiesUtils,
134 private inputsUtils: InputsUtils,
135 private componentServiceNg2: ComponentServiceNg2,
136 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
137 private propertyCreatorComponent: PropertyCreatorComponent,
138 @Inject("$stateParams") _stateParams,
139 @Inject("$scope") private $scope: ng.IScope,
140 @Inject("$state") private $state: ng.ui.IStateService,
141 @Inject("Notification") private notification: any,
142 private componentModeService: ComponentModeService,
143 private eventListenerService: EventListenerService,
144 private ModalServiceSdcUI: SdcUiServices.ModalService,
145 private modalService: ModalService,
146 private keysPipe: KeysPipe,
147 private topologyTemplateService: TopologyTemplateService,
148 private translateService: TranslateService) {
150 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
151 /* 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
152 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
153 this.component = _stateParams.component;
154 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
155 this.updateViewMode();
156 this.changedData = [];
157 this.updateHasChangedData();
158 this.isValidChangedData = true;
162 console.debug("==>" + this.constructor.name + ": ngOnInit");
163 this.loadingInputs = true;
164 this.loadingPolicies = true;
165 this.loadingInstances = true;
166 this.loadingProperties = true;
167 this.topologyTemplateService
168 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
169 .subscribe(response => {
170 _.forEach(response.inputs, (input: InputBEModel) => {
171 const newInput: InputFEModel = new InputFEModel(input);
172 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
173 this.inputs.push(newInput); //only push items that were declared via SDC
175 this.componentInstancePropertyMap = response.componentInstancesProperties;
176 this.loadingInputs = false;
180 this.componentServiceNg2
181 .getComponentResourcePropertiesData(this.component)
182 .subscribe(response => {
183 this.loadingPolicies = false;
185 this.instances.push(...response.componentInstances);
186 this.instances.push(...response.groupInstances);
187 this.instances.push(...response.policies);
189 if (response.componentInstances) {
190 response.componentInstances.forEach(instance => {
191 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
193 iconClass: instance.iconClass,
194 originArchived: instance.originArchived
199 _.forEach(response.policies, (policy: any) => {
200 const newPolicy: InputFEModel = new InputFEModel(policy);
201 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
202 this.policies.push(policy);
205 // add the service self instance to the top of the list.
206 const serviceInstance = new ComponentInstance();
207 serviceInstance.name = SERVICE_SELF_TITLE;
208 serviceInstance.uniqueId = this.component.uniqueId;
209 this.instances.unshift(serviceInstance);
211 _.forEach(this.instances, (instance) => {
212 this.instancesNavigationData.push(instance);
213 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
215 iconClass: instance.iconClass,
216 originArchived: instance.originArchived
219 this.loadingInstances = false;
220 if (this.instancesNavigationData[0] == undefined) {
221 this.loadingProperties = false;
223 this.selectFirstInstanceByDefault();
225 this.loadingInstances = false;
228 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
229 // stop if has changed properties
230 if (this.hasChangedData) {
231 event.preventDefault();
232 this.showUnsavedChangesAlert().then(() => {
233 this.$state.go(toState, toParams);
239 this.loadDataTypesByComponentModel(this.component.model);
243 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
244 this.stateChangeStartUnregister();
247 selectFirstInstanceByDefault = () => {
248 if (this.instancesNavigationData[0] !== undefined) {
249 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
253 updateViewMode = () => {
254 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
257 onCheckout = (component: ComponentData) => {
258 this.component = component;
259 this.updateViewMode();
262 isSelf = (): boolean => {
263 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
266 showAddProperties = (): boolean => {
267 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
270 return this.isSelf();
273 getServiceProperties() {
274 this.loadingProperties = true;
275 this.topologyTemplateService
276 .getServiceProperties(this.component.uniqueId)
277 .subscribe((response) => {
278 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
279 this.serviceBePropertiesMap[this.component.uniqueId] = response;
280 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
281 this.loadingProperties = false;
283 this.loadingProperties = false;
287 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
288 // stop if has changed properties
289 if (this.hasChangedData) {
290 this.showUnsavedChangesAlert().then((resolve) => {
291 this.changeSelectedInstance(instance)
296 this.changeSelectedInstance(instance);
299 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
300 this.selectedInstanceData = instance;
301 this.loadingProperties = true;
302 if (instance instanceof ComponentInstance) {
303 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
304 if (this.isInput(instance.originType)) {
305 this.componentInstanceServiceNg2
306 .getComponentInstanceInputs(this.component, instance)
307 .subscribe(response => {
308 instanceBePropertiesMap[instance.uniqueId] = response;
309 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
313 this.loadingProperties = false;
315 } else if (this.isSelf()) {
316 this.getServiceProperties();
318 this.componentInstanceServiceNg2
319 .getComponentInstanceProperties(this.component, instance.uniqueId)
320 .subscribe(response => {
321 instanceBePropertiesMap[instance.uniqueId] = response;
322 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
326 this.loadingProperties = false;
329 this.loadingProperties = false;
330 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
331 } else if (instance instanceof GroupInstance) {
332 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
333 this.componentInstanceServiceNg2
334 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
335 .subscribe((response) => {
336 instanceBePropertiesMap[instance.uniqueId] = response;
337 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
341 this.loadingProperties = false;
343 } else if (instance instanceof PolicyInstance) {
344 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
345 this.componentInstanceServiceNg2
346 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
347 .subscribe((response) => {
348 instanceBePropertiesMap[instance.uniqueId] = response;
349 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
353 this.loadingProperties = false;
356 this.loadingProperties = false;
359 if (this.searchPropertyName) {
362 //clear selected property from the navigation
363 this.selectedFlatProperty = new SimpleFlatProperty();
364 this.propertiesNavigationData = [];
368 * Entry point handling response from server
370 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
371 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
372 this.checkedPropertiesCount = 0;
373 this.checkedChildPropertiesCount = 0;
376 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
377 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
378 let currentUniqueId = this.selectedInstanceData.uniqueId;
379 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
380 let isCapabilityOwnedByInstance: boolean;
381 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
382 this.selectedInstance_FlattenCapabilitiesList,
383 (result, cap: Capability) => {
384 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
385 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
386 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
387 if (cap.properties && isCapabilityOwnedByInstance) {
388 _.forEach(cap.properties, prop => {
389 if (!prop.origName) {
390 prop.origName = prop.name;
391 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
394 return result.concat(cap.properties);
398 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
399 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
400 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
401 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
403 //concatenate capabilitiesProps to all props list
404 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
405 this.checkedPropertiesCount = 0;
408 isCapabilityProperty = (prop: PropertyBEModel) => {
409 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
412 /*** VALUE CHANGE EVENTS ***/
413 dataChanged = (item: PropertyFEModel | InputFEModel) => {
415 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
416 itemHasChanged = item.hasValueObjChanged();
417 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
418 itemHasChanged = item.hasChanged();
419 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
420 itemHasChanged = item.hasDefaultValueChanged();
423 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
424 if (itemHasChanged) {
425 if (dataChangedIdx === -1) {
426 this.changedData.push(item);
429 if (dataChangedIdx !== -1) {
430 this.changedData.splice(dataChangedIdx, 1);
434 if (this.isPropertiesTabSelected) {
435 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
436 } else if (this.isInputsTabSelected) {
437 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
438 } else if (this.isPoliciesTabSelected) {
439 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
441 this.updateHasChangedData();
445 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
448 * Handle select node in navigation area, and select the row in table
450 onPropertySelectedUpdate = ($event) => {
451 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
452 this.selectedFlatProperty = $event;
453 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
454 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
458 * When user select row in table, this will prepare the hirarchy object for the tree.
460 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
461 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
462 let property = propertyRowSelectedEvent.propertyModel;
463 let instanceName = propertyRowSelectedEvent.instanceName;
464 this.propertyStructureHeader = null;
466 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
467 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
468 let simpleFlatProperty: Array<SimpleFlatProperty>;
469 if (property instanceof PropertyFEModel) {
470 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
471 } else if (property instanceof DerivedFEProperty) {
472 // Need to find parent PropertyFEModel
473 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
474 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
476 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
478 this.propertiesNavigationData = simpleFlatProperty;
481 // Update the header in the navigation tree with property name.
482 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
484 // Set selected property in table
485 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
486 this.hierarchyNavTabs.triggerTabChange('Property Structure');
490 selectInstanceRow = ($event) => {//get instance name
491 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
492 return instance.name == $event;
494 this.hierarchyNavTabs.triggerTabChange('Composition');
497 tabChanged = (event) => {
498 // stop if has changed properties
499 if (this.hasChangedData) {
500 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
501 this.showUnsavedChangesAlert().then((proceed) => {
502 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
508 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
509 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
510 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
511 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
512 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
513 this.propertyStructureHeader = null;
514 this.searchQuery = '';
518 * Select Tosca function value from defined values
520 selectToscaFunctionAndValues = (): void => {
521 const selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = this.getSelectedInstance();
522 if (!selectedInstanceData) {
525 this.openToscaGetFunctionModal();
528 private getSelectedInstance(): ComponentInstance | GroupInstance | PolicyInstance {
529 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
530 const instanceId: string = instancesIds[0];
531 return <ComponentInstance | GroupInstance | PolicyInstance> this.instances.find(instance =>
532 instance.uniqueId == instanceId && (instance instanceof ComponentInstance || instance instanceof GroupInstance || instance instanceof PolicyInstance));
535 private buildCheckedInstanceProperty(): PropertyBEModel {
536 return this.buildCheckedInstanceProperties()[0];
539 private buildCheckedInstanceProperties(): PropertyBEModel[] {
540 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
541 const instanceId: string = instancesIds[0];
542 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
545 private openToscaGetFunctionModal() {
546 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
547 const modalButtons = [];
548 let disableSaveButtonFlag = true;
549 const modal = this.modalService.createCustomModal(new ModalModel(
556 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
558 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
559 if (toscaGetFunction) {
560 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
562 this.clearCheckedInstancePropertyValue();
564 this.modalService.closeCurrentModal();
566 (): boolean => { return disableSaveButtonFlag }
568 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
569 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
570 this.modalService.closeCurrentModal();
574 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
575 'property': checkedInstanceProperty,
576 'componentInstanceMap': this.componentInstanceMap
578 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
579 disableSaveButtonFlag = !validationEvent.isValid;
581 modal.instance.open();
584 private clearCheckedInstancePropertyValue() {
585 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
586 const currentValue : any = checkedInstanceProperty.value;
587 checkedInstanceProperty.getInputValues = null;
588 checkedInstanceProperty.value = null;
589 checkedInstanceProperty.toscaFunction = null;
590 if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
591 const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
592 const parts = propertiesNameArray.split("#");
594 if (this.isListOrMap(checkedInstanceProperty.type)) {
595 if (checkedInstanceProperty.schemaType == PROPERTY_TYPES.MAP) {
596 currentKey.push((<DerivedFEProperty>checkedInstanceProperty.input).parentMapKey);
598 currentKey.push((<DerivedFEProperty>checkedInstanceProperty.input).mapKey);
599 if (checkedInstanceProperty.schemaType != PROPERTY_TYPES.MAP && this.isComplexSchemaType(checkedInstanceProperty.schemaType)) {
600 currentKey.push(parts.reverse()[0]);
603 if (propertiesNameArray.length > 1){
604 const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
605 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
607 if(currentValue !== null && currentKey.length > 0){
608 let valueJson = JSON.parse(currentValue);
609 if(currentKey.length >1){
610 let innerObj = valueJson[currentKey[0]];
611 delete innerObj[currentKey[1]];
612 valueJson[currentKey[0]] = innerObj;
614 delete valueJson[currentKey[0]];
616 if (checkedInstanceProperty.type == PROPERTY_TYPES.LIST && currentKey.length == 1) {
617 let listValue = valueJson.filter(function (item) {
618 return item != null && item != '';
620 checkedInstanceProperty.value = JSON.stringify(listValue);
622 checkedInstanceProperty.value = JSON.stringify(valueJson);
626 if (this.selectedInstanceData instanceof ComponentInstance) {
627 this.updateInstanceProperty(checkedInstanceProperty);
628 } else if (this.selectedInstanceData instanceof GroupInstance) {
629 this.updateGroupInstanceProperty(checkedInstanceProperty);
630 } else if (this.selectedInstanceData instanceof PolicyInstance) {
631 this.updatePolicyInstanceProperty(checkedInstanceProperty);
635 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
636 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
637 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
638 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
639 const parts = propertiesName.split("#");
641 if (this.isListOrMap(checkedProperty.type)) {
642 if (checkedProperty.schemaType == PROPERTY_TYPES.MAP) {
643 currentKey.push((<DerivedFEProperty>checkedProperty.input).parentMapKey);
645 currentKey.push((<DerivedFEProperty>checkedProperty.input).mapKey);
646 if (checkedProperty.schemaType != PROPERTY_TYPES.MAP && this.isComplexSchemaType(checkedProperty.schemaType)) {
647 currentKey.push(parts.reverse()[0]);
650 if (checkedProperty.subPropertyToscaFunctions == null){
651 checkedProperty.subPropertyToscaFunctions = [];
653 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
654 if (!subPropertyToscaFunction){
655 subPropertyToscaFunction = new SubPropertyToscaFunction();
656 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
658 subPropertyToscaFunction.toscaFunction = toscaFunction;
659 subPropertyToscaFunction.subPropertyPath = currentKey.length > 0 ? currentKey : parts.slice(1);
662 checkedProperty.subPropertyToscaFunctions = null;
663 checkedProperty.toscaFunction = toscaFunction;
665 if (this.selectedInstanceData instanceof ComponentInstance) {
666 this.updateInstanceProperty(checkedProperty);
667 } else if (this.selectedInstanceData instanceof GroupInstance) {
668 this.updateGroupInstanceProperty(checkedProperty);
669 } else if (this.selectedInstanceData instanceof PolicyInstance) {
670 this.updatePolicyInstanceProperty(checkedProperty);
674 private isComplexSchemaType(propertyType: string): boolean {
675 return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
678 private isListOrMap(propertyType: string): boolean {
679 return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
682 private areEqual(array1: string[], array2: string[]): boolean {
683 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
686 updateInstanceProperty(instanceProperty: PropertyBEModel) {
687 this.loadingProperties = true;
688 this.enableToscaFunction = false;
689 this.checkedToscaCount = 0;
690 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
691 this.selectedInstanceData.uniqueId, [instanceProperty])
693 this.changeSelectedInstance(this.getSelectedInstance());
695 this.loadingProperties = false;
696 console.error(error);
698 this.loadingProperties = false;
702 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
703 this.loadingProperties = true;
704 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
705 this.selectedInstanceData.uniqueId, [instanceProperty])
707 this.changeSelectedInstance(this.getSelectedInstance());
709 this.loadingProperties = false;
710 console.error(error);
712 this.loadingProperties = false;
716 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
717 this.loadingProperties = true;
718 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
719 this.selectedInstanceData.uniqueId, [instanceProperty])
721 this.changeSelectedInstance(this.getSelectedInstance());
723 this.loadingProperties = false;
724 console.error(error);
726 this.loadingProperties = false;
730 /*** DECLARE PROPERTIES/INPUTS ***/
731 declareProperties = (): void => {
732 console.debug("==>" + this.constructor.name + ": declareProperties");
734 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
735 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
736 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
737 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
738 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
740 angular.forEach(instancesIds, (instanceId: string): void => {
741 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
742 if (selectedInstanceData instanceof ComponentInstance) {
743 if (!this.isInput(selectedInstanceData.originType)) {
744 // convert Property FE model -> Property BE model, extract only checked
745 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
747 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
749 } else if (selectedInstanceData instanceof GroupInstance) {
750 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
751 } else if (selectedInstanceData instanceof PolicyInstance) {
752 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
756 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
758 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
759 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
760 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
762 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
763 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
766 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
767 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
768 prop => !this.isCapabilityProperty(prop)
770 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
771 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
774 let isCapabilityPropertyChanged = false;
776 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
777 (prop: PropertyBEModel) => {
778 prop.name = prop.origName || prop.name;
779 if (this.isCapabilityProperty(prop)) {
780 isCapabilityPropertyChanged = true;
784 this.topologyTemplateService
785 .createInput(this.component, inputsToCreate, this.isSelf())
786 .subscribe((response) => {
787 this.selectInstanceRow(SERVICE_SELF_TITLE);
788 this.onInstanceSelectedUpdate(this.instances[0]);
789 this.setInputTabIndication(response.length);
790 this.checkedPropertiesCount = 0;
791 this.checkedChildPropertiesCount = 0;
792 _.forEach(response, (input: InputBEModel) => {
793 const newInput: InputFEModel = new InputFEModel(input);
794 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
795 this.inputs.push(newInput);
796 this.updatePropertyValueAfterDeclare(newInput);
798 if (isCapabilityPropertyChanged) {
799 this.reloadInstanceCapabilities();
801 }, error => {}); //ignore error
804 declareListProperties = (): void => {
805 // get selected properties
806 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
807 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
808 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
809 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
810 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
811 let propertyNameList: Array<string> = [];
814 angular.forEach(instancesIds, (instanceId: string): void => {
816 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
817 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
819 if (selectedInstanceData instanceof ComponentInstance) {
820 if (!this.isInput(selectedInstanceData.originType)) {
821 // convert Property FE model -> Property BE model, extract only checked
822 selectedComponentInstancesProperties[instanceId] = checkedProperties;
824 selectedComponentInstancesInputs[instanceId] = checkedProperties;
826 } else if (selectedInstanceData instanceof GroupInstance) {
827 selectedGroupInstancesProperties[instanceId] = checkedProperties;
828 } else if (selectedInstanceData instanceof PolicyInstance) {
829 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
832 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
833 propertyNameList.push(property.name);
837 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
839 let modalTitle = 'Declare Properties as List Input';
840 const modal = this.modalService.createCustomModal(new ModalModel(
842 modalTitle, /* title */
847 'blue', /* css class */
848 () => { /* callback */
849 let content:any = modal.instance.dynamicContent.instance;
852 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
853 let typelist: any = PROPERTY_TYPES.LIST;
854 let uniID: any = insId;
855 let boolfalse: any = false;
856 let required: any = content.propertyModel.required;
860 "type": content.propertyModel.simpleType,
864 let schemaProp :any = {
865 "type": content.propertyModel.simpleType,
869 reglistInput.description = content.propertyModel.description;
870 reglistInput.name = content.propertyModel.name;
871 reglistInput.type = typelist;
872 reglistInput.schemaType = content.propertyModel.simpleType;
873 reglistInput.instanceUniqueId = uniID;
874 reglistInput.uniqueId = uniID;
875 reglistInput.required = required;
876 reglistInput.schema = schem;
877 reglistInput.schemaProperty = schemaProp;
880 componentInstInputsMap: content.inputsToCreate,
881 listInput: reglistInput
884 this.topologyTemplateService
885 .createListInput(this.component, input, this.isSelf())
886 .subscribe(response => {
887 this.setInputTabIndication(response.length);
888 this.checkedPropertiesCount = 0;
889 this.checkedChildPropertiesCount = 0;
890 _.forEach(response, (input: InputBEModel) => {
891 let newInput: InputFEModel = new InputFEModel(input);
892 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
893 this.inputs.push(newInput);
894 // create list input does not return updated properties info, so need to reload
895 //this.updatePropertyValueAfterDeclare(newInput);
896 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
897 this.changeSelectedInstance(this.selectedInstanceData);
899 modal.instance.close();
901 }, error => {}); //ignore error
904 /*, getDisabled: function */
906 new ButtonModel('Cancel', 'outline grey', () => {
907 modal.instance.close();
912 // 3rd arg is passed to DeclareListComponent instance
913 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
914 modal.instance.open();
917 /*** DECLARE PROPERTIES/POLICIES ***/
918 declarePropertiesToPolicies = (): void => {
919 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
920 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
922 angular.forEach(instancesIds, (instanceId: string): void => {
923 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
924 if (selectedInstanceData instanceof ComponentInstance) {
925 if (!this.isInput(selectedInstanceData.originType)) {
926 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
931 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
932 this.loadingPolicies = true;
934 this.topologyTemplateService
935 .createPolicy(this.component, policiesToCreate, this.isSelf())
936 .subscribe(response => {
937 this.setPolicyTabIndication(response.length);
938 this.checkedPropertiesCount = 0;
939 this.displayPoliciesAsDeclared(response);
940 this.loadingPolicies = false;
945 displayPoliciesAsDeclared = (policies) => {
946 _.forEach(policies, (policy: any) => {
947 let newPolicy: InputFEModel = new InputFEModel(policy);
948 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
949 newPolicy.relatedPropertyName = policy.name;
950 newPolicy.relatedPropertyValue = policy.value;
951 this.updatePropertyValueAfterDeclare(newPolicy);
952 this.policies.push(policy);
956 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
957 return new Promise((resolve, reject) => {
958 if (!this.isValidChangedData) {
959 reject('Changed data is invalid - cannot save!');
962 if (!this.changedData.length) {
967 // make request and its handlers
969 let handleSuccess, handleError;
970 let changedInputsProperties = [], changedCapabilitiesProperties = [];
971 if (this.isPropertiesTabSelected) {
972 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
973 changedProp = <PropertyFEModel>changedProp;
974 const propBE = new PropertyBEModel(changedProp);
975 propBE.toscaPresentation = new ToscaPresentationData();
976 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
977 propBE.value = changedProp.getJSONValue();
978 propBE.name = changedProp.origName || changedProp.name;
979 delete propBE.origName;
982 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
984 if (this.selectedInstanceData instanceof ComponentInstance) {
985 if (this.isInput(this.selectedInstanceData.originType)) {
986 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
987 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
988 request = Observable.forkJoin(
989 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
990 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
991 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
994 else if (changedInputsProperties.length) {
995 request = this.componentInstanceServiceNg2
996 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
998 else if (changedCapabilitiesProperties.length) {
999 request = this.componentInstanceServiceNg2
1000 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
1002 handleSuccess = (response) => {
1003 // reset each changed property with new value and remove it from changed properties list
1004 response.forEach((resInput) => {
1005 const changedProp = <PropertyFEModel>this.changedData.shift();
1006 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
1010 if (this.isSelf()) {
1011 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
1012 delete cp.constraints;
1016 request = this.componentInstanceServiceNg2
1017 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1019 handleSuccess = (response) => {
1020 // reset each changed property with new value and remove it from changed properties list
1021 response.forEach((resProp) => {
1022 const changedProp = <PropertyFEModel>this.changedData.shift();
1023 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1028 } else if (this.selectedInstanceData instanceof GroupInstance) {
1029 request = this.componentInstanceServiceNg2
1030 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1031 handleSuccess = (response) => {
1032 // reset each changed property with new value and remove it from changed properties list
1033 response.forEach((resProp) => {
1034 const changedProp = <PropertyFEModel>this.changedData.shift();
1035 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1039 } else if (this.selectedInstanceData instanceof PolicyInstance) {
1040 request = this.componentInstanceServiceNg2
1041 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1042 handleSuccess = (response) => {
1043 // reset each changed property with new value and remove it from changed properties list
1044 response.forEach((resProp) => {
1045 const changedProp = <PropertyFEModel>this.changedData.shift();
1046 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1051 } else if (this.isInputsTabSelected) {
1053 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1054 changedInput = <InputFEModel>changedInput;
1055 const inputBE = new InputBEModel(changedInput);
1056 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1059 request = this.componentServiceNg2
1060 .updateComponentInputs(this.component, changedInputs);
1061 handleSuccess = (response) => {
1062 // reset each changed property with new value and remove it from changed properties list
1063 response.forEach((resInput) => {
1064 const changedInput = <InputFEModel>this.changedData.shift();
1065 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1066 changedInput.required = resInput.required;
1067 changedInput.requiredOrig = resInput.required;
1072 this.savingChangedData = true;
1075 this.savingChangedData = false;
1076 if (changedCapabilitiesProperties.length) {
1077 this.reloadInstanceCapabilities();
1079 handleSuccess && handleSuccess(response);
1080 this.updateHasChangedData();
1084 this.savingChangedData = false;
1085 handleError && handleError(error);
1086 this.updateHasChangedData();
1093 reloadInstanceCapabilities = (): void => {
1094 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1095 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1096 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1097 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1098 return instance.capabilities;
1101 }, new CapabilitiesGroup());
1102 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1106 reverseChangedData = ():void => {
1107 // make reverse item handler
1108 let handleReverseItem;
1109 if (this.isPropertiesTabSelected) {
1110 handleReverseItem = (changedItem) => {
1111 changedItem = <PropertyFEModel>changedItem;
1112 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1114 } else if (this.isInputsTabSelected) {
1115 handleReverseItem = (changedItem) => {
1116 changedItem = <InputFEModel>changedItem;
1117 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1118 changedItem.resetMetadata();
1119 changedItem.required = changedItem.requiredOrig;
1123 this.changedData.forEach(handleReverseItem);
1124 this.changedData = [];
1125 this.updateHasChangedData();
1128 updateHasChangedData = ():boolean => {
1129 const curHasChangedData:boolean = (this.changedData.length > 0);
1130 if (curHasChangedData !== this.hasChangedData) {
1131 this.hasChangedData = curHasChangedData;
1132 if(this.hasChangedData) {
1133 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1135 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1138 return this.hasChangedData;
1141 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1142 this.saveChangedData().then(
1144 this.notification.success({
1145 message: 'Successfully saved changes',
1148 if(onSuccessFunction) onSuccessFunction();
1151 this.notification.error({
1152 message: 'Failed to save changes!',
1155 if(onError) onError();
1160 showUnsavedChangesAlert = ():Promise<any> => {
1161 let modalTitle:string;
1162 if (this.isPropertiesTabSelected) {
1163 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1164 } else if (this.isInputsTabSelected) {
1165 modalTitle = `Unsaved inputs for ${this.component.name}`;
1168 return new Promise<any>((resolve, reject) => {
1169 const modal = this.ModalServiceSdcUI.openCustomModal(
1173 type: SdcUiCommon.ModalType.custom,
1174 testId: "navigate-modal",
1177 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1178 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1179 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1180 ] as SdcUiCommon.IModalButtonComponent[]
1181 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1186 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1187 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1188 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1189 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1190 return feProperty.name == input.relatedPropertyName &&
1191 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1193 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1194 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1195 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1196 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1200 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1201 updateCheckedPropertyCount = (increment: boolean): void => {
1202 this.checkedPropertiesCount += (increment) ? 1 : -1;
1203 this.checkedToscaCount = 0;
1204 this.enableToscaFunction = false;
1205 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1208 updateCheckedChildPropertyCount = (increment: boolean): void => {
1209 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1212 togggleToscaBtn = (toscaFlag: boolean) : void => {
1213 this.checkedToscaCount += toscaFlag ? 1 : -1;
1214 if(this.checkedToscaCount == 1){
1215 this.enableToscaFunction = true;
1217 this.enableToscaFunction = false;
1221 setInputTabIndication = (numInputs: number): void => {
1222 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1225 setPolicyTabIndication = (numPolicies: number): void => {
1226 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1229 resetUnsavedChangesForInput = (input:InputFEModel) => {
1230 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1231 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1232 this.updateHasChangedData();
1235 deleteInput = (input: InputFEModel) => {
1236 //reset any unsaved changes to the input before deleting it
1237 this.resetUnsavedChangesForInput(input);
1239 console.debug("==>" + this.constructor.name + ": deleteInput");
1240 let inputToDelete = new InputBEModel(input);
1242 this.componentServiceNg2
1243 .deleteInput(this.component, inputToDelete)
1244 .subscribe(response => {
1245 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1247 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1248 this.changeSelectedInstance(this.selectedInstanceData);
1249 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1251 // if (instanceFeProperties) {
1252 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1253 // return prop.name == input.propertyName;
1256 // if (propToEnable) {
1257 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1258 // propToEnable.setNonDeclared(response.inputPath);
1259 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1260 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1263 }, error => {}); //ignore error
1266 deletePolicy = (policy: PolicyInstance) => {
1267 this.loadingPolicies = true;
1268 this.topologyTemplateService
1269 .deletePolicy(this.component, policy)
1270 .subscribe((response) => {
1271 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1272 this.changeSelectedInstance(this.selectedInstanceData);
1273 this.loadingPolicies = false;
1277 deleteProperty = (property: PropertyFEModel) => {
1278 const propertyToDelete = new PropertyFEModel(property);
1279 this.loadingProperties = true;
1280 const feMap = this.instanceFePropertiesMap;
1281 this.topologyTemplateService
1282 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1283 .subscribe((response) => {
1284 const props = feMap[this.component.uniqueId];
1285 props.splice(props.findIndex(p => p.uniqueId === response),1);
1286 this.loadingProperties = false;
1288 this.loadingProperties = false;
1289 console.error(error);
1293 /*** addProperty ***/
1294 addProperty = (model: string) => {
1295 this.loadDataTypesByComponentModel(model)
1296 let modalTitle = 'Add Property';
1297 let modal = this.modalService.createCustomModal(new ModalModel(
1302 new ButtonModel('Save', 'blue', () => {
1303 modal.instance.dynamicContent.instance.isLoading = true;
1304 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1305 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1306 .subscribe((response) => {
1307 modal.instance.dynamicContent.instance.isLoading = false;
1308 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1309 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1310 modal.instance.close();
1312 modal.instance.dynamicContent.instance.isLoading = false;
1313 this.notification.error({
1314 message: 'Failed to add property:' + error,
1318 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1319 new ButtonModel('Cancel', 'outline grey', () => {
1320 modal.instance.close();
1325 modal.instance.open();
1326 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1331 let modalTitle = 'Add Input';
1332 let modal = this.modalService.createCustomModal(new ModalModel(
1337 new ButtonModel('Save', 'blue', () => {
1338 modal.instance.dynamicContent.instance.isLoading = true;
1339 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1340 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1341 .subscribe((response) => {
1342 modal.instance.dynamicContent.instance.isLoading = false;
1343 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1344 this.inputs.push(newInputProp);
1345 modal.instance.close();
1347 modal.instance.dynamicContent.instance.isLoading = false;
1348 this.notification.error({
1349 message: 'Failed to add input:' + error,
1353 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1354 new ButtonModel('Cancel', 'outline grey', () => {
1355 modal.instance.close();
1360 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1361 modal.instance.open();
1364 /*** SEARCH RELATED FUNCTIONS ***/
1365 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1366 let instanceBePropertiesMap:InstanceBePropertiesMap;
1367 this.componentServiceNg2
1368 .filterComponentInstanceProperties(this.component, filterData)
1369 .subscribe((response) => {
1370 this.processInstancePropertiesResponse(response, false);
1371 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1372 this.searchPropertyName = filterData.propertyName;//mark in table
1373 this.hierarchyNavTabs.triggerTabChange('Composition');
1374 this.propertiesNavigationData = [];
1375 this.displayClearSearch = true;
1376 }, (error) => {}); //ignore error
1380 clearSearch = () => {
1381 this.instancesNavigationData = this.instances;
1382 this.searchPropertyName = "";
1383 this.hierarchyPropertiesDisplayOptions.searchText = "";
1384 this.displayClearSearch = false;
1385 this.advanceSearch.clearAll();
1386 this.searchQuery = '';
1389 clickOnClearSearch = () => {
1391 this.selectFirstInstanceByDefault();
1392 this.hierarchyNavTabs.triggerTabChange('Composition');
1395 private isInput = (instanceType:string):boolean =>{
1396 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1399 loadDataTypesByComponentModel(model:string) {
1400 this.propertyCreatorComponent.filterDataTypesByModel(model);