2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 import * as _ from "lodash";
22 import {Component, Inject, ViewChild} from "@angular/core";
23 import {PropertiesService} from "../../services/properties.service";
26 Component as ComponentData,
29 FilterPropertiesAssignmentData,
33 InstanceBePropertiesMap,
34 InstanceFePropertiesMap,
35 InstancePropertiesAPIMap,
42 PropertyDeclareAPIModel,
45 import {ResourceType} from "app/utils";
46 import {ComponentServiceNg2} from "../../services/component-services/component.service";
47 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
48 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
49 import {KeysPipe} from 'app/ng2/pipes/keys.pipe';
50 import {EVENTS, PROPERTY_TYPES, WorkspaceMode, PROPERTY_DATA} from "../../../utils/constants";
51 import {EventListenerService} from "app/services/event-listener-service"
52 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
53 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
54 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
55 import {HierarchyNavService} from "./services/hierarchy-nav.service";
56 import {PropertiesUtils} from "./services/properties.utils";
57 import {ComponentModeService} from "../../services/component-services/component-mode.service";
58 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
59 import {InputsUtils} from "./services/inputs.utils";
60 import {InstanceFeDetails} from "../../../models/instance-fe-details";
61 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
62 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
63 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
64 import {ModalService} from "../../services/modal.service";
65 import {DeclareListComponent} from "./declare-list/declare-list.component";
66 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
67 import {CapabilitiesGroup, Capability} from "../../../models/capability";
68 import {ToscaPresentationData} from "../../../models/tosca-presentation";
69 import {Observable} from "rxjs";
70 import {TranslateService} from "../../shared/translator/translate.service";
71 import {ToscaFunction} from "../../../models/tosca-function";
72 import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function";
73 import {DeclareInputComponent} from "./declare-input/declare-input.component";
75 const SERVICE_SELF_TITLE = "SELF";
77 templateUrl: './properties-assignment.page.component.html',
78 styleUrls: ['./properties-assignment.page.component.less']
80 export class PropertiesAssignmentComponent {
81 title = "Properties & Inputs";
83 component: ComponentData;
84 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
85 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
87 propertiesNavigationData = [];
88 instancesNavigationData = [];
90 instanceFePropertiesMap: InstanceFePropertiesMap;
91 inputs: Array<InputFEModel> = [];
92 policies: Array<PolicyInstance> = [];
93 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
95 propertyStructureHeader: string;
97 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
98 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
99 checkedPropertiesCount: number = 0;
100 checkedChildPropertiesCount: number = 0;
101 enableToscaFunction: boolean = false;
102 checkedToscaCount: number = 0;
104 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
105 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
106 displayClearSearch = false;
107 searchPropertyName: string;
109 isInputsTabSelected: boolean;
110 isPropertiesTabSelected: boolean;
111 isPoliciesTabSelected: boolean;
113 resourceIsReadonly: boolean;
114 loadingInstances: boolean = false;
115 loadingInputs: boolean = false;
116 loadingPolicies: boolean = false;
117 loadingProperties: boolean = false;
118 changedData: Array<PropertyFEModel | InputFEModel>;
119 hasChangedData: boolean;
120 isValidChangedData: boolean;
121 savingChangedData: boolean;
122 stateChangeStartUnregister: Function;
123 serviceBePropertiesMap: InstanceBePropertiesMap;
124 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
125 selectedInstance_FlattenCapabilitiesList: Capability[];
126 componentInstancePropertyMap : PropertiesGroup;
127 defaultInputName: string;
129 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
130 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
131 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
133 constructor(private propertiesService: PropertiesService,
134 private hierarchyNavService: HierarchyNavService,
135 private propertiesUtils: PropertiesUtils,
136 private inputsUtils: InputsUtils,
137 private componentServiceNg2: ComponentServiceNg2,
138 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
139 private propertyCreatorComponent: PropertyCreatorComponent,
140 @Inject("$stateParams") _stateParams,
141 @Inject("$scope") private $scope: ng.IScope,
142 @Inject("$state") private $state: ng.ui.IStateService,
143 @Inject("Notification") private notification: any,
144 private componentModeService: ComponentModeService,
145 private eventListenerService: EventListenerService,
146 private ModalServiceSdcUI: SdcUiServices.ModalService,
147 private modalService: ModalService,
148 private keysPipe: KeysPipe,
149 private topologyTemplateService: TopologyTemplateService,
150 private translateService: TranslateService) {
152 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
153 /* This is the way you can access the component data, please do not use any data except metadata, all other data should be received from the new api calls on the first time
154 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
155 this.component = _stateParams.component;
156 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
157 this.updateViewMode();
158 this.changedData = [];
159 this.updateHasChangedData();
160 this.isValidChangedData = true;
164 console.debug("==>" + this.constructor.name + ": ngOnInit");
165 this.loadingInputs = true;
166 this.loadingPolicies = true;
167 this.loadingInstances = true;
168 this.loadingProperties = true;
169 this.topologyTemplateService
170 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
171 .subscribe(response => {
172 _.forEach(response.inputs, (input: InputBEModel) => {
173 const newInput: InputFEModel = new InputFEModel(input);
174 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
175 this.inputs.push(newInput); //only push items that were declared via SDC
177 this.componentInstancePropertyMap = response.componentInstancesProperties;
178 this.loadingInputs = false;
182 this.componentServiceNg2
183 .getComponentResourcePropertiesData(this.component)
184 .subscribe(response => {
185 this.loadingPolicies = false;
187 this.instances.push(...response.componentInstances);
188 this.instances.push(...response.groupInstances);
189 this.instances.push(...response.policies);
191 if (response.componentInstances) {
192 response.componentInstances.forEach(instance => {
193 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
195 iconClass: instance.iconClass,
196 originArchived: instance.originArchived
201 _.forEach(response.policies, (policy: any) => {
202 const newPolicy: InputFEModel = new InputFEModel(policy);
203 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
204 this.policies.push(policy);
207 // add the service self instance to the top of the list.
208 const serviceInstance = new ComponentInstance();
209 serviceInstance.name = SERVICE_SELF_TITLE;
210 serviceInstance.uniqueId = this.component.uniqueId;
211 this.instances.unshift(serviceInstance);
213 _.forEach(this.instances, (instance) => {
214 this.instancesNavigationData.push(instance);
215 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
217 iconClass: instance.iconClass,
218 originArchived: instance.originArchived
221 this.loadingInstances = false;
222 if (this.instancesNavigationData[0] == undefined) {
223 this.loadingProperties = false;
225 this.selectFirstInstanceByDefault();
227 this.loadingInstances = false;
230 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
231 // stop if has changed properties
232 if (this.hasChangedData) {
233 event.preventDefault();
234 this.showUnsavedChangesAlert().then(() => {
235 this.$state.go(toState, toParams);
241 this.loadDataTypesByComponentModel(this.component.model);
245 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
246 this.stateChangeStartUnregister();
249 selectFirstInstanceByDefault = () => {
250 if (this.instancesNavigationData[0] !== undefined) {
251 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
255 updateViewMode = () => {
256 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
259 onCheckout = (component: ComponentData) => {
260 this.component = component;
261 this.updateViewMode();
264 isSelf = (): boolean => {
265 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
268 showAddProperties = (): boolean => {
269 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
272 return this.isSelf();
275 getServiceProperties() {
276 this.loadingProperties = true;
277 this.topologyTemplateService
278 .getServiceProperties(this.component.uniqueId)
279 .subscribe((response) => {
280 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
281 this.serviceBePropertiesMap[this.component.uniqueId] = response;
282 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
283 this.loadingProperties = false;
285 this.loadingProperties = false;
289 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
290 // stop if has changed properties
291 if (this.hasChangedData) {
292 this.showUnsavedChangesAlert().then((resolve) => {
293 this.changeSelectedInstance(instance)
298 this.changeSelectedInstance(instance);
301 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
302 this.selectedInstanceData = instance;
303 this.loadingProperties = true;
304 if (instance instanceof ComponentInstance) {
305 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
306 if (this.isInput(instance.originType)) {
307 this.componentInstanceServiceNg2
308 .getComponentInstanceInputs(this.component, instance)
309 .subscribe(response => {
310 instanceBePropertiesMap[instance.uniqueId] = response;
311 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
315 this.loadingProperties = false;
317 } else if (this.isSelf()) {
318 this.getServiceProperties();
320 this.componentInstanceServiceNg2
321 .getComponentInstanceProperties(this.component, instance.uniqueId)
322 .subscribe(response => {
323 instanceBePropertiesMap[instance.uniqueId] = response;
324 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
328 this.loadingProperties = false;
331 this.loadingProperties = false;
332 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
333 } else if (instance instanceof GroupInstance) {
334 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
335 this.componentInstanceServiceNg2
336 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
337 .subscribe((response) => {
338 instanceBePropertiesMap[instance.uniqueId] = response;
339 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
343 this.loadingProperties = false;
345 } else if (instance instanceof PolicyInstance) {
346 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
347 this.componentInstanceServiceNg2
348 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
349 .subscribe((response) => {
350 instanceBePropertiesMap[instance.uniqueId] = response;
351 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
355 this.loadingProperties = false;
358 this.loadingProperties = false;
361 if (this.searchPropertyName) {
364 //clear selected property from the navigation
365 this.selectedFlatProperty = new SimpleFlatProperty();
366 this.propertiesNavigationData = [];
367 this.checkedToscaCount = 0;
368 this.enableToscaFunction = false;
372 * Entry point handling response from server
374 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
375 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
376 this.checkedPropertiesCount = 0;
377 this.checkedChildPropertiesCount = 0;
380 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
381 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
382 let currentUniqueId = this.selectedInstanceData.uniqueId;
383 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
384 let isCapabilityOwnedByInstance: boolean;
385 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
386 this.selectedInstance_FlattenCapabilitiesList,
387 (result, cap: Capability) => {
388 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
389 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
390 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
391 if (cap.properties && isCapabilityOwnedByInstance) {
392 _.forEach(cap.properties, prop => {
393 if (!prop.origName) {
394 prop.origName = prop.name;
395 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
398 return result.concat(cap.properties);
402 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
403 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
404 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
405 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
407 //concatenate capabilitiesProps to all props list
408 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
409 this.checkedPropertiesCount = 0;
412 isCapabilityProperty = (prop: PropertyBEModel) => {
413 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
416 /*** VALUE CHANGE EVENTS ***/
417 dataChanged = (item: PropertyFEModel | InputFEModel) => {
419 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
420 itemHasChanged = item.hasValueObjChanged();
421 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
422 itemHasChanged = item.hasChanged();
423 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
424 itemHasChanged = item.hasDefaultValueChanged();
427 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
428 if (itemHasChanged) {
429 if (dataChangedIdx === -1) {
430 this.changedData.push(item);
433 if (dataChangedIdx !== -1) {
434 this.changedData.splice(dataChangedIdx, 1);
438 if (this.isPropertiesTabSelected) {
439 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
440 } else if (this.isInputsTabSelected) {
441 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
442 } else if (this.isPoliciesTabSelected) {
443 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
445 this.updateHasChangedData();
449 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
452 * Handle select node in navigation area, and select the row in table
454 onPropertySelectedUpdate = ($event) => {
455 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
456 this.selectedFlatProperty = $event;
457 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
458 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
462 * When user select row in table, this will prepare the hirarchy object for the tree.
464 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
465 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
466 let property = propertyRowSelectedEvent.propertyModel;
467 let instanceName = propertyRowSelectedEvent.instanceName;
468 this.propertyStructureHeader = null;
470 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
471 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
472 let simpleFlatProperty: Array<SimpleFlatProperty>;
473 if (property instanceof PropertyFEModel) {
474 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
475 } else if (property instanceof DerivedFEProperty) {
476 // Need to find parent PropertyFEModel
477 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
478 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
480 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
482 this.propertiesNavigationData = simpleFlatProperty;
485 // Update the header in the navigation tree with property name.
486 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
488 // Set selected property in table
489 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
490 this.hierarchyNavTabs.triggerTabChange('Property Structure');
494 selectInstanceRow = ($event) => {//get instance name
495 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
496 return instance.name == $event;
498 this.hierarchyNavTabs.triggerTabChange('Composition');
501 tabChanged = (event) => {
502 // stop if has changed properties
503 if (this.hasChangedData) {
504 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
505 this.showUnsavedChangesAlert().then((proceed) => {
506 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
512 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
513 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
514 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
515 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
516 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
517 this.propertyStructureHeader = null;
518 this.searchQuery = '';
522 * Select Tosca function value from defined values
524 selectToscaFunctionAndValues = (): void => {
525 const selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = this.getSelectedInstance();
526 if (!selectedInstanceData) {
529 this.openToscaGetFunctionModal();
532 private getSelectedInstance(): ComponentInstance | GroupInstance | PolicyInstance {
533 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
534 const instanceId: string = instancesIds[0];
535 return <ComponentInstance | GroupInstance | PolicyInstance> this.instances.find(instance =>
536 instance.uniqueId == instanceId && (instance instanceof ComponentInstance || instance instanceof GroupInstance || instance instanceof PolicyInstance));
539 private buildCheckedInstanceProperty(): PropertyBEModel {
540 return this.buildCheckedInstanceProperties()[0];
543 private buildCheckedInstanceProperties(): PropertyBEModel[] {
544 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
545 const instanceId: string = instancesIds[0];
546 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
549 private openToscaGetFunctionModal() {
550 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
551 const modalButtons = [];
552 let disableSaveButtonFlag = true;
553 const modal = this.modalService.createCustomModal(new ModalModel(
560 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
562 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
563 if (toscaGetFunction) {
564 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
566 this.clearCheckedInstancePropertyValue();
568 this.modalService.closeCurrentModal();
570 (): boolean => { return disableSaveButtonFlag }
572 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
573 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
574 this.modalService.closeCurrentModal();
578 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
579 'property': checkedInstanceProperty,
580 'componentInstanceMap': this.componentInstanceMap
582 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
583 disableSaveButtonFlag = !validationEvent.isValid;
585 modal.instance.open();
588 private deleteToscaValue(valueJson : any, currentKey: string[]) {
589 if(currentKey.length == 1) {
590 if (Array.isArray(valueJson) && !isNaN(Number(currentKey[0]))) {
591 valueJson.splice(Number(currentKey[0]),1);
593 delete valueJson[currentKey[0]];
596 this.deleteToscaValue(valueJson[currentKey[0]],currentKey.splice(1,currentKey.length -1));
600 private clearCheckedInstancePropertyValue() {
601 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
602 const currentValue : any = checkedInstanceProperty.value;
603 checkedInstanceProperty.getInputValues = null;
604 checkedInstanceProperty.value = null;
605 checkedInstanceProperty.toscaFunction = null;
606 if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
607 const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
608 const parts = propertiesNameArray.split("#");
609 let currentKey = (<DerivedFEProperty>checkedInstanceProperty.input).toscaPath;
610 if (propertiesNameArray.length > 1){
611 const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
612 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
614 if(currentValue !== null && currentKey.length > 0){
615 let valueJson = JSON.parse(currentValue);
616 this.deleteToscaValue(valueJson, currentKey);
617 checkedInstanceProperty.value = JSON.stringify(valueJson);
620 if (this.selectedInstanceData instanceof ComponentInstance) {
621 var toRemove = this.changedData.filter(obj => {
622 return obj.name == checkedInstanceProperty.name && obj.type == checkedInstanceProperty.type && obj.value == null;
624 const index: number = this.changedData.indexOf(toRemove[0]);
626 this.changedData.splice(index, 1);
628 this.updateInstanceProperty(checkedInstanceProperty);
629 } else if (this.selectedInstanceData instanceof GroupInstance) {
630 this.updateGroupInstanceProperty(checkedInstanceProperty);
631 } else if (this.selectedInstanceData instanceof PolicyInstance) {
632 this.updatePolicyInstanceProperty(checkedInstanceProperty);
636 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
637 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
638 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
639 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
640 const parts = propertiesName.split("#");
641 let currentKey = (<DerivedFEProperty>checkedProperty.input).toscaPath;
642 if (checkedProperty.subPropertyToscaFunctions == null){
643 checkedProperty.subPropertyToscaFunctions = [];
645 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, currentKey.length > 0 ? currentKey : parts.slice(1)));
646 if (!subPropertyToscaFunction){
647 subPropertyToscaFunction = new SubPropertyToscaFunction();
648 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
650 subPropertyToscaFunction.toscaFunction = toscaFunction;
651 subPropertyToscaFunction.subPropertyPath = currentKey.length > 0 ? currentKey : parts.slice(1);
654 checkedProperty.subPropertyToscaFunctions = null;
655 checkedProperty.toscaFunction = toscaFunction;
657 if (this.selectedInstanceData instanceof ComponentInstance) {
658 this.updateInstanceProperty(checkedProperty);
659 } else if (this.selectedInstanceData instanceof GroupInstance) {
660 this.updateGroupInstanceProperty(checkedProperty);
661 } else if (this.selectedInstanceData instanceof PolicyInstance) {
662 this.updatePolicyInstanceProperty(checkedProperty);
666 private isComplexSchemaType(propertyType: string): boolean {
667 return PROPERTY_DATA.SIMPLE_TYPES.indexOf(propertyType) === -1;
670 private isListOrMap(propertyType: string): boolean {
671 return PROPERTY_TYPES.MAP === propertyType || PROPERTY_TYPES.LIST === propertyType;
674 private areEqual(array1: string[], array2: string[]): boolean {
675 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
678 updateInstanceProperty(instanceProperty: PropertyBEModel) {
679 this.loadingProperties = true;
680 this.enableToscaFunction = false;
681 this.checkedToscaCount = 0;
683 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
684 this.selectedInstanceData.uniqueId, [instanceProperty])
686 this.changeSelectedInstance(this.getSelectedInstance());
688 this.loadingProperties = false;
689 console.error(error);
691 this.loadingProperties = false;
695 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
696 this.loadingProperties = true;
697 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
698 this.selectedInstanceData.uniqueId, [instanceProperty])
700 this.changeSelectedInstance(this.getSelectedInstance());
702 this.loadingProperties = false;
703 console.error(error);
705 this.loadingProperties = false;
709 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
710 this.loadingProperties = true;
711 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
712 this.selectedInstanceData.uniqueId, [instanceProperty])
714 this.changeSelectedInstance(this.getSelectedInstance());
716 this.loadingProperties = false;
717 console.error(error);
719 this.loadingProperties = false;
723 declareInput = (): void => {
724 if (this.checkedPropertiesCount == 1) {
725 this.openAddInputNameAndDeclareInputModal();
726 } else if (this.checkedPropertiesCount > 1) {
727 this.declareInputFromProperties();
731 /*** DECLARE PROPERTIES/INPUTS ***/
732 declareInputFromProperties = (inputName?: string): void => {
733 console.debug("==>" + this.constructor.name + ": declareProperties");
735 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
736 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
737 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
738 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
739 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
741 angular.forEach(instancesIds, (instanceId: string): void => {
742 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
743 if (selectedInstanceData instanceof ComponentInstance) {
744 if (!this.isInput(selectedInstanceData.originType)) {
745 // convert Property FE model -> Property BE model, extract only checked
746 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
748 selectedComponentInstancesProperties[instanceId][0].inputName = inputName;
751 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
753 } else if (selectedInstanceData instanceof GroupInstance) {
754 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
755 } else if (selectedInstanceData instanceof PolicyInstance) {
756 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
760 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
762 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
763 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
764 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
766 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
767 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
770 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
771 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
772 prop => !this.isCapabilityProperty(prop)
774 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
775 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
778 let isCapabilityPropertyChanged = false;
780 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
781 (prop: PropertyBEModel) => {
782 prop.name = prop.origName || prop.name;
783 if (this.isCapabilityProperty(prop)) {
784 isCapabilityPropertyChanged = true;
788 this.topologyTemplateService
789 .createInput(this.component, inputsToCreate, this.isSelf())
790 .subscribe((response) => {
791 this.selectInstanceRow(SERVICE_SELF_TITLE);
792 this.onInstanceSelectedUpdate(this.instances[0]);
793 this.setInputTabIndication(response.length);
794 this.checkedPropertiesCount = 0;
795 this.checkedChildPropertiesCount = 0;
796 _.forEach(response, (input: InputBEModel) => {
797 const newInput: InputFEModel = new InputFEModel(input);
798 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
799 this.inputs.push(newInput);
800 this.updatePropertyValueAfterDeclare(newInput);
802 if (isCapabilityPropertyChanged) {
803 this.reloadInstanceCapabilities();
805 }, error => {}); //ignore error
808 generateDefaultInputName = (): string => {
809 let defaultInputName: string;
810 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
811 angular.forEach(instancesIds, (instanceId: string) => {
812 let selectedProperty: PropertyBEModel = new PropertyBEModel(this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId])[0]);
813 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
814 defaultInputName = this.generateInputName(selectedInstanceData.invariantName, selectedProperty.name);
816 return defaultInputName;
819 private generateInputName = (componentName: string, propertyName: string): string => {
820 let inputName: string;
822 if (propertyName.includes("::")) {
823 propertyName = propertyName.replace(/::/g, "_");
826 inputName = componentName + "_" + propertyName;
828 inputName = propertyName;
834 private openAddInputNameAndDeclareInputModal = (): void => {
835 const modalTitle = this.translateService.translate('ADD_INPUT_NAME_TO_DECLARE');
836 const modalButtons = [];
837 const modal = this.modalService.createCustomModal(new ModalModel(
844 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
846 const inputName: string = modal.instance.dynamicContent.instance.inputNameForm.value;
848 this.declareInputFromProperties(inputName);
850 this.notification.warning({
851 message: 'Failed to set input name',
855 this.modalService.closeCurrentModal();
858 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
859 this.modalService.closeCurrentModal();
861 this.modalService.addDynamicContentToModal(modal, DeclareInputComponent, {defaultInputName: this.generateDefaultInputName()});
862 modal.instance.open();
865 declareListProperties = (): void => {
866 // get selected properties
867 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
868 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
869 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
870 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
871 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
872 let propertyNameList: Array<string> = [];
875 angular.forEach(instancesIds, (instanceId: string): void => {
877 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
878 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
880 if (selectedInstanceData instanceof ComponentInstance) {
881 if (!this.isInput(selectedInstanceData.originType)) {
882 // convert Property FE model -> Property BE model, extract only checked
883 selectedComponentInstancesProperties[instanceId] = checkedProperties;
885 selectedComponentInstancesInputs[instanceId] = checkedProperties;
887 } else if (selectedInstanceData instanceof GroupInstance) {
888 selectedGroupInstancesProperties[instanceId] = checkedProperties;
889 } else if (selectedInstanceData instanceof PolicyInstance) {
890 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
893 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
894 propertyNameList.push(property.name);
898 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
900 let modalTitle = 'Declare Properties as List Input';
901 const modal = this.modalService.createCustomModal(new ModalModel(
903 modalTitle, /* title */
908 'blue', /* css class */
909 () => { /* callback */
910 let content:any = modal.instance.dynamicContent.instance;
913 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
914 let typelist: any = PROPERTY_TYPES.LIST;
915 let uniID: any = insId;
916 let boolfalse: any = false;
917 let required: any = content.propertyModel.required;
921 "type": content.propertyModel.simpleType,
925 let schemaProp :any = {
926 "type": content.propertyModel.simpleType,
930 reglistInput.description = content.propertyModel.description;
931 reglistInput.name = content.propertyModel.name;
932 reglistInput.type = typelist;
933 reglistInput.schemaType = content.propertyModel.simpleType;
934 reglistInput.instanceUniqueId = uniID;
935 reglistInput.uniqueId = uniID;
936 reglistInput.required = required;
937 reglistInput.schema = schem;
938 reglistInput.schemaProperty = schemaProp;
941 componentInstInputsMap: content.inputsToCreate,
942 listInput: reglistInput
945 this.topologyTemplateService
946 .createListInput(this.component, input, this.isSelf())
947 .subscribe(response => {
948 this.setInputTabIndication(response.length);
949 this.checkedPropertiesCount = 0;
950 this.checkedChildPropertiesCount = 0;
951 _.forEach(response, (input: InputBEModel) => {
952 let newInput: InputFEModel = new InputFEModel(input);
953 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
954 this.inputs.push(newInput);
955 // create list input does not return updated properties info, so need to reload
956 //this.updatePropertyValueAfterDeclare(newInput);
957 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
958 this.changeSelectedInstance(this.selectedInstanceData);
960 modal.instance.close();
962 }, error => {}); //ignore error
965 /*, getDisabled: function */
967 new ButtonModel('Cancel', 'outline grey', () => {
968 modal.instance.close();
973 // 3rd arg is passed to DeclareListComponent instance
974 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
975 modal.instance.open();
978 /*** DECLARE PROPERTIES/POLICIES ***/
979 declarePropertiesToPolicies = (): void => {
980 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
981 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
983 angular.forEach(instancesIds, (instanceId: string): void => {
984 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
985 if (selectedInstanceData instanceof ComponentInstance) {
986 if (!this.isInput(selectedInstanceData.originType)) {
987 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
992 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
993 this.loadingPolicies = true;
995 this.topologyTemplateService
996 .createPolicy(this.component, policiesToCreate, this.isSelf())
997 .subscribe(response => {
998 this.setPolicyTabIndication(response.length);
999 this.checkedPropertiesCount = 0;
1000 this.displayPoliciesAsDeclared(response);
1001 this.loadingPolicies = false;
1006 displayPoliciesAsDeclared = (policies) => {
1007 _.forEach(policies, (policy: any) => {
1008 let newPolicy: InputFEModel = new InputFEModel(policy);
1009 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
1010 newPolicy.relatedPropertyName = policy.name;
1011 newPolicy.relatedPropertyValue = policy.value;
1012 this.updatePropertyValueAfterDeclare(newPolicy);
1013 this.policies.push(policy);
1017 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
1018 return new Promise((resolve, reject) => {
1019 if (!this.isValidChangedData) {
1020 reject('Changed data is invalid - cannot save!');
1023 if (!this.changedData.length) {
1028 // make request and its handlers
1030 let handleSuccess, handleError;
1031 let changedInputsProperties = [], changedCapabilitiesProperties = [];
1032 if (this.isPropertiesTabSelected) {
1033 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
1034 changedProp = <PropertyFEModel>changedProp;
1035 const propBE = new PropertyBEModel(changedProp);
1036 propBE.toscaPresentation = new ToscaPresentationData();
1037 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
1038 propBE.value = changedProp.getJSONValue();
1039 propBE.name = changedProp.origName || changedProp.name;
1040 delete propBE.origName;
1043 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
1045 if (this.selectedInstanceData instanceof ComponentInstance) {
1046 if (this.isInput(this.selectedInstanceData.originType)) {
1047 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
1048 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
1049 request = Observable.forkJoin(
1050 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
1051 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
1052 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
1055 else if (changedInputsProperties.length) {
1056 request = this.componentInstanceServiceNg2
1057 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
1059 else if (changedCapabilitiesProperties.length) {
1060 request = this.componentInstanceServiceNg2
1061 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
1063 handleSuccess = (response) => {
1064 // reset each changed property with new value and remove it from changed properties list
1065 response.forEach((resInput) => {
1066 const changedProp = <PropertyFEModel>this.changedData.shift();
1067 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
1071 if (this.isSelf()) {
1072 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
1073 delete cp.constraints;
1077 request = this.componentInstanceServiceNg2
1078 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1080 handleSuccess = (response) => {
1081 // reset each changed property with new value and remove it from changed properties list
1082 response.forEach((resProp) => {
1083 const changedProp = <PropertyFEModel>this.changedData.shift();
1084 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1089 } else if (this.selectedInstanceData instanceof GroupInstance) {
1090 request = this.componentInstanceServiceNg2
1091 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1092 handleSuccess = (response) => {
1093 // reset each changed property with new value and remove it from changed properties list
1094 response.forEach((resProp) => {
1095 const changedProp = <PropertyFEModel>this.changedData.shift();
1096 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1100 } else if (this.selectedInstanceData instanceof PolicyInstance) {
1101 request = this.componentInstanceServiceNg2
1102 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
1103 handleSuccess = (response) => {
1104 // reset each changed property with new value and remove it from changed properties list
1105 response.forEach((resProp) => {
1106 const changedProp = <PropertyFEModel>this.changedData.shift();
1107 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
1112 } else if (this.isInputsTabSelected) {
1114 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1115 changedInput = <InputFEModel>changedInput;
1116 const inputBE = new InputBEModel(changedInput);
1117 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1120 request = this.componentServiceNg2
1121 .updateComponentInputs(this.component, changedInputs);
1122 handleSuccess = (response) => {
1123 // reset each changed property with new value and remove it from changed properties list
1124 response.forEach((resInput) => {
1125 const changedInput = <InputFEModel>this.changedData.shift();
1126 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1127 changedInput.required = resInput.required;
1128 changedInput.requiredOrig = resInput.required;
1133 this.savingChangedData = true;
1136 this.savingChangedData = false;
1137 if (changedCapabilitiesProperties.length) {
1138 this.reloadInstanceCapabilities();
1140 handleSuccess && handleSuccess(response);
1141 this.updateHasChangedData();
1145 this.savingChangedData = false;
1146 handleError && handleError(error);
1147 this.updateHasChangedData();
1154 reloadInstanceCapabilities = (): void => {
1155 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1156 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1157 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1158 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1159 return instance.capabilities;
1162 }, new CapabilitiesGroup());
1163 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1167 reverseChangedData = ():void => {
1168 // make reverse item handler
1169 let handleReverseItem;
1170 if (this.isPropertiesTabSelected) {
1171 handleReverseItem = (changedItem) => {
1172 changedItem = <PropertyFEModel>changedItem;
1173 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1175 } else if (this.isInputsTabSelected) {
1176 handleReverseItem = (changedItem) => {
1177 changedItem = <InputFEModel>changedItem;
1178 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1179 changedItem.resetMetadata();
1180 changedItem.required = changedItem.requiredOrig;
1184 this.changedData.forEach(handleReverseItem);
1185 this.changedData = [];
1186 this.updateHasChangedData();
1189 updateHasChangedData = ():boolean => {
1190 const curHasChangedData:boolean = (this.changedData.length > 0);
1191 if (curHasChangedData !== this.hasChangedData) {
1192 this.hasChangedData = curHasChangedData;
1193 if(this.hasChangedData) {
1194 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1196 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1199 return this.hasChangedData;
1202 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1203 this.saveChangedData().then(
1205 this.notification.success({
1206 message: 'Successfully saved changes',
1209 if(onSuccessFunction) onSuccessFunction();
1212 this.notification.error({
1213 message: 'Failed to save changes!',
1216 if(onError) onError();
1221 showUnsavedChangesAlert = ():Promise<any> => {
1222 let modalTitle:string;
1223 if (this.isPropertiesTabSelected) {
1224 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1225 } else if (this.isInputsTabSelected) {
1226 modalTitle = `Unsaved inputs for ${this.component.name}`;
1229 return new Promise<any>((resolve, reject) => {
1230 const modal = this.ModalServiceSdcUI.openCustomModal(
1234 type: SdcUiCommon.ModalType.custom,
1235 testId: "navigate-modal",
1238 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1239 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1240 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1241 ] as SdcUiCommon.IModalButtonComponent[]
1242 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1247 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1248 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1249 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1250 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1251 return feProperty.name == input.relatedPropertyName &&
1252 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1254 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1255 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1256 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1257 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1261 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1262 updateCheckedPropertyCount = (increment: boolean): void => {
1263 this.checkedPropertiesCount += (increment) ? 1 : -1;
1264 this.checkedToscaCount = 0;
1265 this.enableToscaFunction = false;
1266 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1269 updateCheckedChildPropertyCount = (increment: boolean): void => {
1270 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1273 togggleToscaBtn = (toscaFlag: boolean) : void => {
1274 this.checkedToscaCount += toscaFlag ? 1 : -1;
1275 if(this.checkedToscaCount == 1){
1276 this.enableToscaFunction = true;
1278 this.enableToscaFunction = false;
1282 setInputTabIndication = (numInputs: number): void => {
1283 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1286 setPolicyTabIndication = (numPolicies: number): void => {
1287 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1290 resetUnsavedChangesForInput = (input:InputFEModel) => {
1291 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1292 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1293 this.updateHasChangedData();
1296 deleteInput = (input: InputFEModel) => {
1297 //reset any unsaved changes to the input before deleting it
1298 this.resetUnsavedChangesForInput(input);
1300 console.debug("==>" + this.constructor.name + ": deleteInput");
1301 let inputToDelete = new InputBEModel(input);
1303 this.componentServiceNg2
1304 .deleteInput(this.component, inputToDelete)
1305 .subscribe(response => {
1306 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1308 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1309 this.changeSelectedInstance(this.selectedInstanceData);
1310 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1312 // if (instanceFeProperties) {
1313 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1314 // return prop.name == input.propertyName;
1317 // if (propToEnable) {
1318 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1319 // propToEnable.setNonDeclared(response.inputPath);
1320 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1321 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1324 }, error => {}); //ignore error
1327 deletePolicy = (policy: PolicyInstance) => {
1328 this.loadingPolicies = true;
1329 this.topologyTemplateService
1330 .deletePolicy(this.component, policy)
1331 .subscribe((response) => {
1332 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1333 this.changeSelectedInstance(this.selectedInstanceData);
1334 this.loadingPolicies = false;
1338 deleteProperty = (property: PropertyFEModel) => {
1339 const propertyToDelete = new PropertyFEModel(property);
1340 this.loadingProperties = true;
1341 const feMap = this.instanceFePropertiesMap;
1342 this.topologyTemplateService
1343 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1344 .subscribe((response) => {
1345 const props = feMap[this.component.uniqueId];
1346 props.splice(props.findIndex(p => p.uniqueId === response),1);
1347 this.loadingProperties = false;
1349 this.loadingProperties = false;
1350 console.error(error);
1354 /*** addProperty ***/
1355 addProperty = (model: string) => {
1356 this.loadDataTypesByComponentModel(model)
1357 let modalTitle = 'Add Property';
1358 let modal = this.modalService.createCustomModal(new ModalModel(
1363 new ButtonModel('Save', 'blue', () => {
1364 modal.instance.dynamicContent.instance.isLoading = true;
1365 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1366 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1367 .subscribe((response) => {
1368 modal.instance.dynamicContent.instance.isLoading = false;
1369 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1370 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1371 modal.instance.close();
1373 modal.instance.dynamicContent.instance.isLoading = false;
1374 this.notification.error({
1375 message: 'Failed to add property:' + error,
1379 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1380 new ButtonModel('Cancel', 'outline grey', () => {
1381 modal.instance.close();
1386 modal.instance.open();
1387 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1392 let modalTitle = 'Add Input';
1393 let modal = this.modalService.createCustomModal(new ModalModel(
1398 new ButtonModel('Save', 'blue', () => {
1399 modal.instance.dynamicContent.instance.isLoading = true;
1400 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1401 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1402 .subscribe((response) => {
1403 modal.instance.dynamicContent.instance.isLoading = false;
1404 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1405 this.inputs.push(newInputProp);
1406 modal.instance.close();
1408 modal.instance.dynamicContent.instance.isLoading = false;
1409 this.notification.error({
1410 message: 'Failed to add input:' + error,
1414 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1415 new ButtonModel('Cancel', 'outline grey', () => {
1416 modal.instance.close();
1421 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1422 modal.instance.open();
1425 /*** SEARCH RELATED FUNCTIONS ***/
1426 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1427 let instanceBePropertiesMap:InstanceBePropertiesMap;
1428 this.componentServiceNg2
1429 .filterComponentInstanceProperties(this.component, filterData)
1430 .subscribe((response) => {
1431 this.processInstancePropertiesResponse(response, false);
1432 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1433 this.searchPropertyName = filterData.propertyName;//mark in table
1434 this.hierarchyNavTabs.triggerTabChange('Composition');
1435 this.propertiesNavigationData = [];
1436 this.displayClearSearch = true;
1437 }, (error) => {}); //ignore error
1441 clearSearch = () => {
1442 this.instancesNavigationData = this.instances;
1443 this.searchPropertyName = "";
1444 this.hierarchyPropertiesDisplayOptions.searchText = "";
1445 this.displayClearSearch = false;
1446 this.advanceSearch.clearAll();
1447 this.searchQuery = '';
1450 clickOnClearSearch = () => {
1452 this.selectFirstInstanceByDefault();
1453 this.hierarchyNavTabs.triggerTabChange('Composition');
1456 private isInput = (instanceType:string):boolean =>{
1457 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1460 loadDataTypesByComponentModel(model:string) {
1461 this.propertyCreatorComponent.filterDataTypesByModel(model);