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, PROPERTY_DATA} from "../../../utils/constants";
50 import {EventListenerService} from "app/services/event-listener-service"
51 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
52 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
53 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
54 import {HierarchyNavService} from "./services/hierarchy-nav.service";
55 import {PropertiesUtils} from "./services/properties.utils";
56 import {ComponentModeService} from "../../services/component-services/component-mode.service";
57 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
58 import {InputsUtils} from "./services/inputs.utils";
59 import {InstanceFeDetails} from "../../../models/instance-fe-details";
60 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
61 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
62 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
63 import {ModalService} from "../../services/modal.service";
64 import {DeclareListComponent} from "./declare-list/declare-list.component";
65 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
66 import {CapabilitiesGroup, Capability} from "../../../models/capability";
67 import {ToscaPresentationData} from "../../../models/tosca-presentation";
68 import {Observable} from "rxjs";
69 import {TranslateService} from "../../shared/translator/translate.service";
70 import {ToscaFunction} from "../../../models/tosca-function";
71 import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function";
73 const SERVICE_SELF_TITLE = "SELF";
75 templateUrl: './properties-assignment.page.component.html',
76 styleUrls: ['./properties-assignment.page.component.less']
78 export class PropertiesAssignmentComponent {
79 title = "Properties & Inputs";
81 component: ComponentData;
82 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
83 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
85 propertiesNavigationData = [];
86 instancesNavigationData = [];
88 instanceFePropertiesMap: InstanceFePropertiesMap;
89 inputs: Array<InputFEModel> = [];
90 policies: Array<PolicyInstance> = [];
91 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
93 propertyStructureHeader: string;
95 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
96 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
97 checkedPropertiesCount: number = 0;
98 checkedChildPropertiesCount: number = 0;
99 enableToscaFunction: boolean = false;
100 checkedToscaCount: number = 0;
102 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
103 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
104 displayClearSearch = false;
105 searchPropertyName: string;
107 isInputsTabSelected: boolean;
108 isPropertiesTabSelected: boolean;
109 isPoliciesTabSelected: boolean;
111 resourceIsReadonly: boolean;
112 loadingInstances: boolean = false;
113 loadingInputs: boolean = false;
114 loadingPolicies: boolean = false;
115 loadingProperties: boolean = false;
116 changedData: Array<PropertyFEModel | InputFEModel>;
117 hasChangedData: boolean;
118 isValidChangedData: boolean;
119 savingChangedData: boolean;
120 stateChangeStartUnregister: Function;
121 serviceBePropertiesMap: InstanceBePropertiesMap;
122 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
123 selectedInstance_FlattenCapabilitiesList: Capability[];
125 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
126 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
127 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
129 constructor(private propertiesService: PropertiesService,
130 private hierarchyNavService: HierarchyNavService,
131 private propertiesUtils: PropertiesUtils,
132 private inputsUtils: InputsUtils,
133 private componentServiceNg2: ComponentServiceNg2,
134 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
135 private propertyCreatorComponent: PropertyCreatorComponent,
136 @Inject("$stateParams") _stateParams,
137 @Inject("$scope") private $scope: ng.IScope,
138 @Inject("$state") private $state: ng.ui.IStateService,
139 @Inject("Notification") private notification: any,
140 private componentModeService: ComponentModeService,
141 private eventListenerService: EventListenerService,
142 private ModalServiceSdcUI: SdcUiServices.ModalService,
143 private modalService: ModalService,
144 private keysPipe: KeysPipe,
145 private topologyTemplateService: TopologyTemplateService,
146 private translateService: TranslateService) {
148 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
149 /* This is the way you can access the component data, please do not use any data except metadata, all other data should be received from the new api calls on the first time
150 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
151 this.component = _stateParams.component;
152 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
153 this.updateViewMode();
154 this.changedData = [];
155 this.updateHasChangedData();
156 this.isValidChangedData = true;
160 console.debug("==>" + this.constructor.name + ": ngOnInit");
161 this.loadingInputs = true;
162 this.loadingPolicies = true;
163 this.loadingInstances = true;
164 this.loadingProperties = true;
165 this.topologyTemplateService
166 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
167 .subscribe(response => {
168 _.forEach(response.inputs, (input: InputBEModel) => {
169 const newInput: InputFEModel = new InputFEModel(input);
170 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
171 this.inputs.push(newInput); //only push items that were declared via SDC
173 this.loadingInputs = false;
177 this.componentServiceNg2
178 .getComponentResourcePropertiesData(this.component)
179 .subscribe(response => {
180 this.loadingPolicies = false;
182 this.instances.push(...response.componentInstances);
183 this.instances.push(...response.groupInstances);
184 this.instances.push(...response.policies);
186 if (response.componentInstances) {
187 response.componentInstances.forEach(instance => {
188 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
190 iconClass: instance.iconClass,
191 originArchived: instance.originArchived
196 _.forEach(response.policies, (policy: any) => {
197 const newPolicy: InputFEModel = new InputFEModel(policy);
198 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
199 this.policies.push(policy);
202 // add the service self instance to the top of the list.
203 const serviceInstance = new ComponentInstance();
204 serviceInstance.name = SERVICE_SELF_TITLE;
205 serviceInstance.uniqueId = this.component.uniqueId;
206 this.instances.unshift(serviceInstance);
208 _.forEach(this.instances, (instance) => {
209 this.instancesNavigationData.push(instance);
210 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
212 iconClass: instance.iconClass,
213 originArchived: instance.originArchived
216 this.loadingInstances = false;
217 if (this.instancesNavigationData[0] == undefined) {
218 this.loadingProperties = false;
220 this.selectFirstInstanceByDefault();
222 this.loadingInstances = false;
225 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
226 // stop if has changed properties
227 if (this.hasChangedData) {
228 event.preventDefault();
229 this.showUnsavedChangesAlert().then(() => {
230 this.$state.go(toState, toParams);
236 this.loadDataTypesByComponentModel(this.component.model);
240 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
241 this.stateChangeStartUnregister();
244 selectFirstInstanceByDefault = () => {
245 if (this.instancesNavigationData[0] !== undefined) {
246 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
250 updateViewMode = () => {
251 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
254 onCheckout = (component: ComponentData) => {
255 this.component = component;
256 this.updateViewMode();
259 isSelf = (): boolean => {
260 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
263 showAddProperties = (): boolean => {
264 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
267 return this.isSelf();
270 getServiceProperties() {
271 this.loadingProperties = true;
272 this.topologyTemplateService
273 .getServiceProperties(this.component.uniqueId)
274 .subscribe((response) => {
275 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
276 this.serviceBePropertiesMap[this.component.uniqueId] = response;
277 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
278 this.loadingProperties = false;
280 this.loadingProperties = false;
284 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
285 // stop if has changed properties
286 if (this.hasChangedData) {
287 this.showUnsavedChangesAlert().then((resolve) => {
288 this.changeSelectedInstance(instance)
293 this.changeSelectedInstance(instance);
296 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
297 this.selectedInstanceData = instance;
298 this.loadingProperties = true;
299 if (instance instanceof ComponentInstance) {
300 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
301 if (this.isInput(instance.originType)) {
302 this.componentInstanceServiceNg2
303 .getComponentInstanceInputs(this.component, instance)
304 .subscribe(response => {
305 instanceBePropertiesMap[instance.uniqueId] = response;
306 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
310 this.loadingProperties = false;
312 } else if (this.isSelf()) {
313 this.getServiceProperties();
315 this.componentInstanceServiceNg2
316 .getComponentInstanceProperties(this.component, instance.uniqueId)
317 .subscribe(response => {
318 instanceBePropertiesMap[instance.uniqueId] = response;
319 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
323 this.loadingProperties = false;
326 this.loadingProperties = false;
327 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
328 } else if (instance instanceof GroupInstance) {
329 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
330 this.componentInstanceServiceNg2
331 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
332 .subscribe((response) => {
333 instanceBePropertiesMap[instance.uniqueId] = response;
334 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
338 this.loadingProperties = false;
340 } else if (instance instanceof PolicyInstance) {
341 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
342 this.componentInstanceServiceNg2
343 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
344 .subscribe((response) => {
345 instanceBePropertiesMap[instance.uniqueId] = response;
346 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
350 this.loadingProperties = false;
353 this.loadingProperties = false;
356 if (this.searchPropertyName) {
359 //clear selected property from the navigation
360 this.selectedFlatProperty = new SimpleFlatProperty();
361 this.propertiesNavigationData = [];
365 * Entry point handling response from server
367 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
368 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
369 this.checkedPropertiesCount = 0;
370 this.checkedChildPropertiesCount = 0;
373 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
374 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
375 let currentUniqueId = this.selectedInstanceData.uniqueId;
376 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
377 let isCapabilityOwnedByInstance: boolean;
378 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
379 this.selectedInstance_FlattenCapabilitiesList,
380 (result, cap: Capability) => {
381 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
382 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
383 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
384 if (cap.properties && isCapabilityOwnedByInstance) {
385 _.forEach(cap.properties, prop => {
386 if (!prop.origName) {
387 prop.origName = prop.name;
388 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
391 return result.concat(cap.properties);
395 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
396 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
397 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
398 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
400 //concatenate capabilitiesProps to all props list
401 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
402 this.checkedPropertiesCount = 0;
405 isCapabilityProperty = (prop: PropertyBEModel) => {
406 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
409 /*** VALUE CHANGE EVENTS ***/
410 dataChanged = (item: PropertyFEModel | InputFEModel) => {
412 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
413 itemHasChanged = item.hasValueObjChanged();
414 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
415 itemHasChanged = item.hasChanged();
416 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
417 itemHasChanged = item.hasDefaultValueChanged();
420 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
421 if (itemHasChanged) {
422 if (dataChangedIdx === -1) {
423 this.changedData.push(item);
426 if (dataChangedIdx !== -1) {
427 this.changedData.splice(dataChangedIdx, 1);
431 if (this.isPropertiesTabSelected) {
432 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
433 } else if (this.isInputsTabSelected) {
434 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
435 } else if (this.isPoliciesTabSelected) {
436 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
438 this.updateHasChangedData();
442 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
445 * Handle select node in navigation area, and select the row in table
447 onPropertySelectedUpdate = ($event) => {
448 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
449 this.selectedFlatProperty = $event;
450 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
451 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
455 * When user select row in table, this will prepare the hirarchy object for the tree.
457 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
458 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
459 let property = propertyRowSelectedEvent.propertyModel;
460 let instanceName = propertyRowSelectedEvent.instanceName;
461 this.propertyStructureHeader = null;
463 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
464 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
465 let simpleFlatProperty: Array<SimpleFlatProperty>;
466 if (property instanceof PropertyFEModel) {
467 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
468 } else if (property instanceof DerivedFEProperty) {
469 // Need to find parent PropertyFEModel
470 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
471 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
473 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
475 this.propertiesNavigationData = simpleFlatProperty;
478 // Update the header in the navigation tree with property name.
479 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
481 // Set selected property in table
482 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
483 this.hierarchyNavTabs.triggerTabChange('Property Structure');
487 selectInstanceRow = ($event) => {//get instance name
488 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
489 return instance.name == $event;
491 this.hierarchyNavTabs.triggerTabChange('Composition');
494 tabChanged = (event) => {
495 // stop if has changed properties
496 if (this.hasChangedData) {
497 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
498 this.showUnsavedChangesAlert().then((proceed) => {
499 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
505 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
506 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
507 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
508 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
509 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
510 this.propertyStructureHeader = null;
511 this.searchQuery = '';
515 * Select Tosca function value from defined values
517 selectToscaFunctionAndValues = (): void => {
518 const selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = this.getSelectedInstance();
519 if (!selectedInstanceData) {
522 this.openToscaGetFunctionModal();
525 private getSelectedInstance(): ComponentInstance | GroupInstance | PolicyInstance {
526 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
527 const instanceId: string = instancesIds[0];
528 return <ComponentInstance | GroupInstance | PolicyInstance> this.instances.find(instance =>
529 instance.uniqueId == instanceId && (instance instanceof ComponentInstance || instance instanceof GroupInstance || instance instanceof PolicyInstance));
532 private buildCheckedInstanceProperty(): PropertyBEModel {
533 return this.buildCheckedInstanceProperties()[0];
536 private buildCheckedInstanceProperties(): PropertyBEModel[] {
537 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
538 const instanceId: string = instancesIds[0];
539 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
542 private openToscaGetFunctionModal() {
543 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
544 const modalButtons = [];
545 let disableSaveButtonFlag = true;
546 const modal = this.modalService.createCustomModal(new ModalModel(
553 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
555 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
556 if (toscaGetFunction) {
557 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
559 this.clearCheckedInstancePropertyValue();
561 this.modalService.closeCurrentModal();
563 (): boolean => { return disableSaveButtonFlag }
565 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
566 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
567 this.modalService.closeCurrentModal();
571 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
572 'property': checkedInstanceProperty,
573 'componentInstanceMap': this.componentInstanceMap
575 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
576 disableSaveButtonFlag = !validationEvent.isValid;
578 modal.instance.open();
581 private clearCheckedInstancePropertyValue() {
582 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
583 const currentValue : any = checkedInstanceProperty.value;
584 checkedInstanceProperty.getInputValues = null;
585 checkedInstanceProperty.value = null;
586 checkedInstanceProperty.toscaFunction = null;
587 if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
588 const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
589 const parts = propertiesNameArray.split("#");
591 if (this.isListOrMap(checkedInstanceProperty.type)) {
592 currentKey.push((<DerivedFEProperty>checkedInstanceProperty.input).mapKey);
593 if (this.isComplexSchemaType(checkedInstanceProperty.schemaType)) {
594 currentKey.push(parts.reverse()[0]);
597 if (propertiesNameArray.length > 1){
598 const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
599 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
601 if(currentValue !== null && currentKey.length > 0){
602 let valueJson = JSON.parse(currentValue);
603 if(currentKey.length >1){
604 let innerObj = valueJson[currentKey[0]];
605 delete innerObj[currentKey[1]];
606 valueJson[currentKey[0]] = innerObj;
608 delete valueJson[currentKey[0]];
610 if (checkedInstanceProperty.type == PROPERTY_TYPES.LIST && currentKey.length == 1) {
611 let listValue = valueJson.filter(function (item) {
612 return item != null && item != '';
614 checkedInstanceProperty.value = JSON.stringify(listValue);
616 checkedInstanceProperty.value = JSON.stringify(valueJson);
620 if (this.selectedInstanceData instanceof ComponentInstance) {
621 this.updateInstanceProperty(checkedInstanceProperty);
622 } else if (this.selectedInstanceData instanceof GroupInstance) {
623 this.updateGroupInstanceProperty(checkedInstanceProperty);
624 } else if (this.selectedInstanceData instanceof PolicyInstance) {
625 this.updatePolicyInstanceProperty(checkedInstanceProperty);
629 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
630 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
631 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
632 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
633 const parts = propertiesName.split("#");
635 if (this.isListOrMap(checkedProperty.type)) {
636 currentKey.push((<DerivedFEProperty>checkedProperty.input).mapKey);
637 if (this.isComplexSchemaType(checkedProperty.schemaType)) {
638 currentKey.push(parts.reverse()[0]);
641 if (checkedProperty.subPropertyToscaFunctions == null){
642 checkedProperty.subPropertyToscaFunctions = [];
644 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
645 if (!subPropertyToscaFunction){
646 subPropertyToscaFunction = new SubPropertyToscaFunction();
647 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
649 subPropertyToscaFunction.toscaFunction = toscaFunction;
650 subPropertyToscaFunction.subPropertyPath = currentKey.length > 0 ? currentKey : parts.slice(1);
653 checkedProperty.subPropertyToscaFunctions = null;
654 checkedProperty.toscaFunction = toscaFunction;
656 if (this.selectedInstanceData instanceof ComponentInstance) {
657 this.updateInstanceProperty(checkedProperty);
658 } else if (this.selectedInstanceData instanceof GroupInstance) {
659 this.updateGroupInstanceProperty(checkedProperty);
660 } else if (this.selectedInstanceData instanceof PolicyInstance) {
661 this.updatePolicyInstanceProperty(checkedProperty);
665 private isComplexSchemaType(propertyType: string): boolean {
666 return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
669 private isListOrMap(propertyType: string): boolean {
670 return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
673 private areEqual(array1: string[], array2: string[]): boolean {
674 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
677 updateInstanceProperty(instanceProperty: PropertyBEModel) {
678 this.loadingProperties = true;
679 this.enableToscaFunction = false;
680 this.checkedToscaCount = 0;
681 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
682 this.selectedInstanceData.uniqueId, [instanceProperty])
684 this.changeSelectedInstance(this.getSelectedInstance());
686 this.loadingProperties = false;
687 console.error(error);
689 this.loadingProperties = false;
693 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
694 this.loadingProperties = true;
695 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
696 this.selectedInstanceData.uniqueId, [instanceProperty])
698 this.changeSelectedInstance(this.getSelectedInstance());
700 this.loadingProperties = false;
701 console.error(error);
703 this.loadingProperties = false;
707 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
708 this.loadingProperties = true;
709 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
710 this.selectedInstanceData.uniqueId, [instanceProperty])
712 this.changeSelectedInstance(this.getSelectedInstance());
714 this.loadingProperties = false;
715 console.error(error);
717 this.loadingProperties = false;
721 /*** DECLARE PROPERTIES/INPUTS ***/
722 declareProperties = (): void => {
723 console.debug("==>" + this.constructor.name + ": declareProperties");
725 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
726 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
727 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
728 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
729 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
731 angular.forEach(instancesIds, (instanceId: string): void => {
732 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
733 if (selectedInstanceData instanceof ComponentInstance) {
734 if (!this.isInput(selectedInstanceData.originType)) {
735 // convert Property FE model -> Property BE model, extract only checked
736 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
738 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
740 } else if (selectedInstanceData instanceof GroupInstance) {
741 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
742 } else if (selectedInstanceData instanceof PolicyInstance) {
743 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
747 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
749 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
750 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
751 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
753 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
754 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
757 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
758 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
759 prop => !this.isCapabilityProperty(prop)
761 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
762 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
765 let isCapabilityPropertyChanged = false;
767 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
768 (prop: PropertyBEModel) => {
769 prop.name = prop.origName || prop.name;
770 if (this.isCapabilityProperty(prop)) {
771 isCapabilityPropertyChanged = true;
775 this.topologyTemplateService
776 .createInput(this.component, inputsToCreate, this.isSelf())
777 .subscribe((response) => {
778 this.selectInstanceRow(SERVICE_SELF_TITLE);
779 this.onInstanceSelectedUpdate(this.instances[0]);
780 this.setInputTabIndication(response.length);
781 this.checkedPropertiesCount = 0;
782 this.checkedChildPropertiesCount = 0;
783 _.forEach(response, (input: InputBEModel) => {
784 const newInput: InputFEModel = new InputFEModel(input);
785 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
786 this.inputs.push(newInput);
787 this.updatePropertyValueAfterDeclare(newInput);
789 if (isCapabilityPropertyChanged) {
790 this.reloadInstanceCapabilities();
792 }, error => {}); //ignore error
795 declareListProperties = (): void => {
796 // get selected properties
797 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
798 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
799 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
800 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
801 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
802 let propertyNameList: Array<string> = [];
805 angular.forEach(instancesIds, (instanceId: string): void => {
807 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
808 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
810 if (selectedInstanceData instanceof ComponentInstance) {
811 if (!this.isInput(selectedInstanceData.originType)) {
812 // convert Property FE model -> Property BE model, extract only checked
813 selectedComponentInstancesProperties[instanceId] = checkedProperties;
815 selectedComponentInstancesInputs[instanceId] = checkedProperties;
817 } else if (selectedInstanceData instanceof GroupInstance) {
818 selectedGroupInstancesProperties[instanceId] = checkedProperties;
819 } else if (selectedInstanceData instanceof PolicyInstance) {
820 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
823 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
824 propertyNameList.push(property.name);
828 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
830 let modalTitle = 'Declare Properties as List Input';
831 const modal = this.modalService.createCustomModal(new ModalModel(
833 modalTitle, /* title */
838 'blue', /* css class */
839 () => { /* callback */
840 let content:any = modal.instance.dynamicContent.instance;
843 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
844 let typelist: any = PROPERTY_TYPES.LIST;
845 let uniID: any = insId;
846 let boolfalse: any = false;
847 let required: any = content.propertyModel.required;
851 "type": content.propertyModel.simpleType,
855 let schemaProp :any = {
856 "type": content.propertyModel.simpleType,
860 reglistInput.description = content.propertyModel.description;
861 reglistInput.name = content.propertyModel.name;
862 reglistInput.type = typelist;
863 reglistInput.schemaType = content.propertyModel.simpleType;
864 reglistInput.instanceUniqueId = uniID;
865 reglistInput.uniqueId = uniID;
866 reglistInput.required = required;
867 reglistInput.schema = schem;
868 reglistInput.schemaProperty = schemaProp;
871 componentInstInputsMap: content.inputsToCreate,
872 listInput: reglistInput
875 this.topologyTemplateService
876 .createListInput(this.component, input, this.isSelf())
877 .subscribe(response => {
878 this.setInputTabIndication(response.length);
879 this.checkedPropertiesCount = 0;
880 this.checkedChildPropertiesCount = 0;
881 _.forEach(response, (input: InputBEModel) => {
882 let newInput: InputFEModel = new InputFEModel(input);
883 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
884 this.inputs.push(newInput);
885 // create list input does not return updated properties info, so need to reload
886 //this.updatePropertyValueAfterDeclare(newInput);
887 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
888 this.changeSelectedInstance(this.selectedInstanceData);
890 modal.instance.close();
892 }, error => {}); //ignore error
895 /*, getDisabled: function */
897 new ButtonModel('Cancel', 'outline grey', () => {
898 modal.instance.close();
903 // 3rd arg is passed to DeclareListComponent instance
904 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
905 modal.instance.open();
908 /*** DECLARE PROPERTIES/POLICIES ***/
909 declarePropertiesToPolicies = (): void => {
910 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
911 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
913 angular.forEach(instancesIds, (instanceId: string): void => {
914 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
915 if (selectedInstanceData instanceof ComponentInstance) {
916 if (!this.isInput(selectedInstanceData.originType)) {
917 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
922 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
923 this.loadingPolicies = true;
925 this.topologyTemplateService
926 .createPolicy(this.component, policiesToCreate, this.isSelf())
927 .subscribe(response => {
928 this.setPolicyTabIndication(response.length);
929 this.checkedPropertiesCount = 0;
930 this.displayPoliciesAsDeclared(response);
931 this.loadingPolicies = false;
936 displayPoliciesAsDeclared = (policies) => {
937 _.forEach(policies, (policy: any) => {
938 let newPolicy: InputFEModel = new InputFEModel(policy);
939 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
940 newPolicy.relatedPropertyName = policy.name;
941 newPolicy.relatedPropertyValue = policy.value;
942 this.updatePropertyValueAfterDeclare(newPolicy);
943 this.policies.push(policy);
947 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
948 return new Promise((resolve, reject) => {
949 if (!this.isValidChangedData) {
950 reject('Changed data is invalid - cannot save!');
953 if (!this.changedData.length) {
958 // make request and its handlers
960 let handleSuccess, handleError;
961 let changedInputsProperties = [], changedCapabilitiesProperties = [];
962 if (this.isPropertiesTabSelected) {
963 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
964 changedProp = <PropertyFEModel>changedProp;
965 const propBE = new PropertyBEModel(changedProp);
966 propBE.toscaPresentation = new ToscaPresentationData();
967 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
968 propBE.value = changedProp.getJSONValue();
969 propBE.name = changedProp.origName || changedProp.name;
970 delete propBE.origName;
973 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
975 if (this.selectedInstanceData instanceof ComponentInstance) {
976 if (this.isInput(this.selectedInstanceData.originType)) {
977 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
978 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
979 request = Observable.forkJoin(
980 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
981 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
982 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
985 else if (changedInputsProperties.length) {
986 request = this.componentInstanceServiceNg2
987 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
989 else if (changedCapabilitiesProperties.length) {
990 request = this.componentInstanceServiceNg2
991 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
993 handleSuccess = (response) => {
994 // reset each changed property with new value and remove it from changed properties list
995 response.forEach((resInput) => {
996 const changedProp = <PropertyFEModel>this.changedData.shift();
997 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
1001 if (this.isSelf()) {
1002 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
1003 delete cp.constraints;
1007 request = this.componentInstanceServiceNg2
1008 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1010 handleSuccess = (response) => {
1011 // reset each changed property with new value and remove it from changed properties list
1012 response.forEach((resProp) => {
1013 const changedProp = <PropertyFEModel>this.changedData.shift();
1014 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1019 } else if (this.selectedInstanceData instanceof GroupInstance) {
1020 request = this.componentInstanceServiceNg2
1021 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1022 handleSuccess = (response) => {
1023 // reset each changed property with new value and remove it from changed properties list
1024 response.forEach((resProp) => {
1025 const changedProp = <PropertyFEModel>this.changedData.shift();
1026 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1030 } else if (this.selectedInstanceData instanceof PolicyInstance) {
1031 request = this.componentInstanceServiceNg2
1032 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1033 handleSuccess = (response) => {
1034 // reset each changed property with new value and remove it from changed properties list
1035 response.forEach((resProp) => {
1036 const changedProp = <PropertyFEModel>this.changedData.shift();
1037 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1042 } else if (this.isInputsTabSelected) {
1044 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1045 changedInput = <InputFEModel>changedInput;
1046 const inputBE = new InputBEModel(changedInput);
1047 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1050 request = this.componentServiceNg2
1051 .updateComponentInputs(this.component, changedInputs);
1052 handleSuccess = (response) => {
1053 // reset each changed property with new value and remove it from changed properties list
1054 response.forEach((resInput) => {
1055 const changedInput = <InputFEModel>this.changedData.shift();
1056 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1057 changedInput.required = resInput.required;
1058 changedInput.requiredOrig = resInput.required;
1063 this.savingChangedData = true;
1066 this.savingChangedData = false;
1067 if (changedCapabilitiesProperties.length) {
1068 this.reloadInstanceCapabilities();
1070 handleSuccess && handleSuccess(response);
1071 this.updateHasChangedData();
1075 this.savingChangedData = false;
1076 handleError && handleError(error);
1077 this.updateHasChangedData();
1084 reloadInstanceCapabilities = (): void => {
1085 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1086 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1087 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1088 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1089 return instance.capabilities;
1092 }, new CapabilitiesGroup());
1093 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1097 reverseChangedData = ():void => {
1098 // make reverse item handler
1099 let handleReverseItem;
1100 if (this.isPropertiesTabSelected) {
1101 handleReverseItem = (changedItem) => {
1102 changedItem = <PropertyFEModel>changedItem;
1103 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1105 } else if (this.isInputsTabSelected) {
1106 handleReverseItem = (changedItem) => {
1107 changedItem = <InputFEModel>changedItem;
1108 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1109 changedItem.resetMetadata();
1110 changedItem.required = changedItem.requiredOrig;
1114 this.changedData.forEach(handleReverseItem);
1115 this.changedData = [];
1116 this.updateHasChangedData();
1119 updateHasChangedData = ():boolean => {
1120 const curHasChangedData:boolean = (this.changedData.length > 0);
1121 if (curHasChangedData !== this.hasChangedData) {
1122 this.hasChangedData = curHasChangedData;
1123 if(this.hasChangedData) {
1124 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1126 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1129 return this.hasChangedData;
1132 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1133 this.saveChangedData().then(
1135 this.notification.success({
1136 message: 'Successfully saved changes',
1139 if(onSuccessFunction) onSuccessFunction();
1142 this.notification.error({
1143 message: 'Failed to save changes!',
1146 if(onError) onError();
1151 showUnsavedChangesAlert = ():Promise<any> => {
1152 let modalTitle:string;
1153 if (this.isPropertiesTabSelected) {
1154 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1155 } else if (this.isInputsTabSelected) {
1156 modalTitle = `Unsaved inputs for ${this.component.name}`;
1159 return new Promise<any>((resolve, reject) => {
1160 const modal = this.ModalServiceSdcUI.openCustomModal(
1164 type: SdcUiCommon.ModalType.custom,
1165 testId: "navigate-modal",
1168 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1169 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1170 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1171 ] as SdcUiCommon.IModalButtonComponent[]
1172 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1177 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1178 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1179 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1180 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1181 return feProperty.name == input.relatedPropertyName &&
1182 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1184 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1185 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1186 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1187 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1191 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1192 updateCheckedPropertyCount = (increment: boolean): void => {
1193 this.checkedPropertiesCount += (increment) ? 1 : -1;
1194 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1197 updateCheckedChildPropertyCount = (increment: boolean): void => {
1198 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1201 togggleToscaBtn = (toscaFlag: boolean) : void => {
1202 this.checkedToscaCount += toscaFlag ? 1 : -1;
1203 if(this.checkedToscaCount == 1){
1204 this.enableToscaFunction = true;
1206 this.enableToscaFunction = false;
1210 setInputTabIndication = (numInputs: number): void => {
1211 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1214 setPolicyTabIndication = (numPolicies: number): void => {
1215 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1218 resetUnsavedChangesForInput = (input:InputFEModel) => {
1219 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1220 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1221 this.updateHasChangedData();
1224 deleteInput = (input: InputFEModel) => {
1225 //reset any unsaved changes to the input before deleting it
1226 this.resetUnsavedChangesForInput(input);
1228 console.debug("==>" + this.constructor.name + ": deleteInput");
1229 let inputToDelete = new InputBEModel(input);
1231 this.componentServiceNg2
1232 .deleteInput(this.component, inputToDelete)
1233 .subscribe(response => {
1234 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1236 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1237 this.changeSelectedInstance(this.selectedInstanceData);
1238 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1240 // if (instanceFeProperties) {
1241 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1242 // return prop.name == input.propertyName;
1245 // if (propToEnable) {
1246 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1247 // propToEnable.setNonDeclared(response.inputPath);
1248 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1249 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1252 }, error => {}); //ignore error
1255 deletePolicy = (policy: PolicyInstance) => {
1256 this.loadingPolicies = true;
1257 this.topologyTemplateService
1258 .deletePolicy(this.component, policy)
1259 .subscribe((response) => {
1260 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1261 this.changeSelectedInstance(this.selectedInstanceData);
1262 this.loadingPolicies = false;
1266 deleteProperty = (property: PropertyFEModel) => {
1267 const propertyToDelete = new PropertyFEModel(property);
1268 this.loadingProperties = true;
1269 const feMap = this.instanceFePropertiesMap;
1270 this.topologyTemplateService
1271 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1272 .subscribe((response) => {
1273 const props = feMap[this.component.uniqueId];
1274 props.splice(props.findIndex(p => p.uniqueId === response),1);
1275 this.loadingProperties = false;
1277 this.loadingProperties = false;
1278 console.error(error);
1282 /*** addProperty ***/
1283 addProperty = (model: string) => {
1284 this.loadDataTypesByComponentModel(model)
1285 let modalTitle = 'Add Property';
1286 let modal = this.modalService.createCustomModal(new ModalModel(
1291 new ButtonModel('Save', 'blue', () => {
1292 modal.instance.dynamicContent.instance.isLoading = true;
1293 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1294 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1295 .subscribe((response) => {
1296 modal.instance.dynamicContent.instance.isLoading = false;
1297 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1298 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1299 modal.instance.close();
1301 modal.instance.dynamicContent.instance.isLoading = false;
1302 this.notification.error({
1303 message: 'Failed to add property:' + error,
1307 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1308 new ButtonModel('Cancel', 'outline grey', () => {
1309 modal.instance.close();
1314 modal.instance.open();
1315 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1320 let modalTitle = 'Add Input';
1321 let modal = this.modalService.createCustomModal(new ModalModel(
1326 new ButtonModel('Save', 'blue', () => {
1327 modal.instance.dynamicContent.instance.isLoading = true;
1328 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1329 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1330 .subscribe((response) => {
1331 modal.instance.dynamicContent.instance.isLoading = false;
1332 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1333 this.inputs.push(newInputProp);
1334 modal.instance.close();
1336 modal.instance.dynamicContent.instance.isLoading = false;
1337 this.notification.error({
1338 message: 'Failed to add input:' + error,
1342 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1343 new ButtonModel('Cancel', 'outline grey', () => {
1344 modal.instance.close();
1349 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1350 modal.instance.open();
1353 /*** SEARCH RELATED FUNCTIONS ***/
1354 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1355 let instanceBePropertiesMap:InstanceBePropertiesMap;
1356 this.componentServiceNg2
1357 .filterComponentInstanceProperties(this.component, filterData)
1358 .subscribe((response) => {
1359 this.processInstancePropertiesResponse(response, false);
1360 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1361 this.searchPropertyName = filterData.propertyName;//mark in table
1362 this.hierarchyNavTabs.triggerTabChange('Composition');
1363 this.propertiesNavigationData = [];
1364 this.displayClearSearch = true;
1365 }, (error) => {}); //ignore error
1369 clearSearch = () => {
1370 this.instancesNavigationData = this.instances;
1371 this.searchPropertyName = "";
1372 this.hierarchyPropertiesDisplayOptions.searchText = "";
1373 this.displayClearSearch = false;
1374 this.advanceSearch.clearAll();
1375 this.searchQuery = '';
1378 clickOnClearSearch = () => {
1380 this.selectFirstInstanceByDefault();
1381 this.hierarchyNavTabs.triggerTabChange('Composition');
1384 private isInput = (instanceType:string):boolean =>{
1385 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1388 loadDataTypesByComponentModel(model:string) {
1389 this.propertyCreatorComponent.filterDataTypesByModel(model);