2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 import * as _ from "lodash";
22 import {Component, Inject, ViewChild} from "@angular/core";
23 import {PropertiesService} from "../../services/properties.service";
26 Component as ComponentData,
29 FilterPropertiesAssignmentData,
33 InstanceBePropertiesMap,
34 InstanceFePropertiesMap,
35 InstancePropertiesAPIMap,
42 PropertyDeclareAPIModel
44 import {ResourceType} from "app/utils";
45 import {ComponentServiceNg2} from "../../services/component-services/component.service";
46 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
47 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
48 import {KeysPipe} from 'app/ng2/pipes/keys.pipe';
49 import {EVENTS, PROPERTY_TYPES, WorkspaceMode} from "../../../utils/constants";
50 import {EventListenerService} from "app/services/event-listener-service"
51 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
52 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
53 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
54 import {HierarchyNavService} from "./services/hierarchy-nav.service";
55 import {PropertiesUtils} from "./services/properties.utils";
56 import {ComponentModeService} from "../../services/component-services/component-mode.service";
57 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
58 import {InputsUtils} from "./services/inputs.utils";
59 import {InstanceFeDetails} from "../../../models/instance-fe-details";
60 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
61 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
62 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
63 import {ModalService} from "../../services/modal.service";
64 import {DeclareListComponent} from "./declare-list/declare-list.component";
65 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
66 import {CapabilitiesGroup, Capability} from "../../../models/capability";
67 import {ToscaPresentationData} from "../../../models/tosca-presentation";
68 import {Observable} from "rxjs";
69 import {TranslateService} from "../../shared/translator/translate.service";
70 import {ToscaFunction} from "../../../models/tosca-function";
71 import {SubPropertyToscaFunction} from "../../../models/sub-property-tosca-function";
73 const SERVICE_SELF_TITLE = "SELF";
75 templateUrl: './properties-assignment.page.component.html',
76 styleUrls: ['./properties-assignment.page.component.less']
78 export class PropertiesAssignmentComponent {
79 title = "Properties & Inputs";
81 component: ComponentData;
82 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
83 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
85 propertiesNavigationData = [];
86 instancesNavigationData = [];
88 instanceFePropertiesMap: InstanceFePropertiesMap;
89 inputs: Array<InputFEModel> = [];
90 policies: Array<PolicyInstance> = [];
91 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
93 propertyStructureHeader: string;
95 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
96 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
97 checkedPropertiesCount: number = 0;
98 checkedChildPropertiesCount: number = 0;
100 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
101 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
102 displayClearSearch = false;
103 searchPropertyName: string;
105 isInputsTabSelected: boolean;
106 isPropertiesTabSelected: boolean;
107 isPoliciesTabSelected: boolean;
109 resourceIsReadonly: boolean;
110 loadingInstances: boolean = false;
111 loadingInputs: boolean = false;
112 loadingPolicies: boolean = false;
113 loadingProperties: boolean = false;
114 changedData: Array<PropertyFEModel | InputFEModel>;
115 hasChangedData: boolean;
116 isValidChangedData: boolean;
117 savingChangedData: boolean;
118 stateChangeStartUnregister: Function;
119 serviceBePropertiesMap: InstanceBePropertiesMap;
120 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
121 selectedInstance_FlattenCapabilitiesList: Capability[];
123 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
124 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
125 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
127 constructor(private propertiesService: PropertiesService,
128 private hierarchyNavService: HierarchyNavService,
129 private propertiesUtils: PropertiesUtils,
130 private inputsUtils: InputsUtils,
131 private componentServiceNg2: ComponentServiceNg2,
132 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
133 private propertyCreatorComponent: PropertyCreatorComponent,
134 @Inject("$stateParams") _stateParams,
135 @Inject("$scope") private $scope: ng.IScope,
136 @Inject("$state") private $state: ng.ui.IStateService,
137 @Inject("Notification") private notification: any,
138 private componentModeService: ComponentModeService,
139 private eventListenerService: EventListenerService,
140 private ModalServiceSdcUI: SdcUiServices.ModalService,
141 private modalService: ModalService,
142 private keysPipe: KeysPipe,
143 private topologyTemplateService: TopologyTemplateService,
144 private translateService: TranslateService) {
146 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
147 /* 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
148 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
149 this.component = _stateParams.component;
150 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
151 this.updateViewMode();
152 this.changedData = [];
153 this.updateHasChangedData();
154 this.isValidChangedData = true;
158 console.debug("==>" + this.constructor.name + ": ngOnInit");
159 this.loadingInputs = true;
160 this.loadingPolicies = true;
161 this.loadingInstances = true;
162 this.loadingProperties = true;
163 this.topologyTemplateService
164 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
165 .subscribe(response => {
166 _.forEach(response.inputs, (input: InputBEModel) => {
167 const newInput: InputFEModel = new InputFEModel(input);
168 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
169 this.inputs.push(newInput); //only push items that were declared via SDC
171 this.loadingInputs = false;
175 this.componentServiceNg2
176 .getComponentResourcePropertiesData(this.component)
177 .subscribe(response => {
178 this.loadingPolicies = false;
180 this.instances.push(...response.componentInstances);
181 this.instances.push(...response.groupInstances);
182 this.instances.push(...response.policies);
184 if (response.componentInstances) {
185 response.componentInstances.forEach(instance => {
186 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
188 iconClass: instance.iconClass,
189 originArchived: instance.originArchived
194 _.forEach(response.policies, (policy: any) => {
195 const newPolicy: InputFEModel = new InputFEModel(policy);
196 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
197 this.policies.push(policy);
200 // add the service self instance to the top of the list.
201 const serviceInstance = new ComponentInstance();
202 serviceInstance.name = SERVICE_SELF_TITLE;
203 serviceInstance.uniqueId = this.component.uniqueId;
204 this.instances.unshift(serviceInstance);
206 _.forEach(this.instances, (instance) => {
207 this.instancesNavigationData.push(instance);
208 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
210 iconClass: instance.iconClass,
211 originArchived: instance.originArchived
214 this.loadingInstances = false;
215 if (this.instancesNavigationData[0] == undefined) {
216 this.loadingProperties = false;
218 this.selectFirstInstanceByDefault();
220 this.loadingInstances = false;
223 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
224 // stop if has changed properties
225 if (this.hasChangedData) {
226 event.preventDefault();
227 this.showUnsavedChangesAlert().then(() => {
228 this.$state.go(toState, toParams);
234 this.loadDataTypesByComponentModel(this.component.model);
238 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
239 this.stateChangeStartUnregister();
242 selectFirstInstanceByDefault = () => {
243 if (this.instancesNavigationData[0] !== undefined) {
244 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
248 updateViewMode = () => {
249 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
252 onCheckout = (component: ComponentData) => {
253 this.component = component;
254 this.updateViewMode();
257 isSelf = (): boolean => {
258 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
261 showAddProperties = (): boolean => {
262 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
265 return this.isSelf();
268 getServiceProperties() {
269 this.loadingProperties = true;
270 this.topologyTemplateService
271 .getServiceProperties(this.component.uniqueId)
272 .subscribe((response) => {
273 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
274 this.serviceBePropertiesMap[this.component.uniqueId] = response;
275 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
276 this.loadingProperties = false;
278 this.loadingProperties = false;
282 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
283 // stop if has changed properties
284 if (this.hasChangedData) {
285 this.showUnsavedChangesAlert().then((resolve) => {
286 this.changeSelectedInstance(instance)
291 this.changeSelectedInstance(instance);
294 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
295 this.selectedInstanceData = instance;
296 this.loadingProperties = true;
297 if (instance instanceof ComponentInstance) {
298 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
299 if (this.isInput(instance.originType)) {
300 this.componentInstanceServiceNg2
301 .getComponentInstanceInputs(this.component, instance)
302 .subscribe(response => {
303 instanceBePropertiesMap[instance.uniqueId] = response;
304 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
308 this.loadingProperties = false;
310 } else if (this.isSelf()) {
311 this.getServiceProperties();
313 this.componentInstanceServiceNg2
314 .getComponentInstanceProperties(this.component, instance.uniqueId)
315 .subscribe(response => {
316 instanceBePropertiesMap[instance.uniqueId] = response;
317 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
321 this.loadingProperties = false;
324 this.loadingProperties = false;
325 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
326 } else if (instance instanceof GroupInstance) {
327 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
328 this.componentInstanceServiceNg2
329 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
330 .subscribe((response) => {
331 instanceBePropertiesMap[instance.uniqueId] = response;
332 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
336 this.loadingProperties = false;
338 } else if (instance instanceof PolicyInstance) {
339 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
340 this.componentInstanceServiceNg2
341 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
342 .subscribe((response) => {
343 instanceBePropertiesMap[instance.uniqueId] = response;
344 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
348 this.loadingProperties = false;
351 this.loadingProperties = false;
354 if (this.searchPropertyName) {
357 //clear selected property from the navigation
358 this.selectedFlatProperty = new SimpleFlatProperty();
359 this.propertiesNavigationData = [];
363 * Entry point handling response from server
365 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
366 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
367 this.checkedPropertiesCount = 0;
368 this.checkedChildPropertiesCount = 0;
371 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
372 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
373 let currentUniqueId = this.selectedInstanceData.uniqueId;
374 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
375 let isCapabilityOwnedByInstance: boolean;
376 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
377 this.selectedInstance_FlattenCapabilitiesList,
378 (result, cap: Capability) => {
379 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
380 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
381 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
382 if (cap.properties && isCapabilityOwnedByInstance) {
383 _.forEach(cap.properties, prop => {
384 if (!prop.origName) {
385 prop.origName = prop.name;
386 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
389 return result.concat(cap.properties);
393 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
394 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
395 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
396 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
398 //concatenate capabilitiesProps to all props list
399 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
400 this.checkedPropertiesCount = 0;
403 isCapabilityProperty = (prop: PropertyBEModel) => {
404 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
407 /*** VALUE CHANGE EVENTS ***/
408 dataChanged = (item: PropertyFEModel | InputFEModel) => {
410 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
411 itemHasChanged = item.hasValueObjChanged();
412 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
413 itemHasChanged = item.hasChanged();
414 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
415 itemHasChanged = item.hasDefaultValueChanged();
418 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
419 if (itemHasChanged) {
420 if (dataChangedIdx === -1) {
421 this.changedData.push(item);
424 if (dataChangedIdx !== -1) {
425 this.changedData.splice(dataChangedIdx, 1);
429 if (this.isPropertiesTabSelected) {
430 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
431 } else if (this.isInputsTabSelected) {
432 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
433 } else if (this.isPoliciesTabSelected) {
434 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
436 this.updateHasChangedData();
440 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
443 * Handle select node in navigation area, and select the row in table
445 onPropertySelectedUpdate = ($event) => {
446 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
447 this.selectedFlatProperty = $event;
448 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
449 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
453 * When user select row in table, this will prepare the hirarchy object for the tree.
455 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
456 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
457 let property = propertyRowSelectedEvent.propertyModel;
458 let instanceName = propertyRowSelectedEvent.instanceName;
459 this.propertyStructureHeader = null;
461 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
462 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
463 let simpleFlatProperty: Array<SimpleFlatProperty>;
464 if (property instanceof PropertyFEModel) {
465 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
466 } else if (property instanceof DerivedFEProperty) {
467 // Need to find parent PropertyFEModel
468 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
469 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
471 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
473 this.propertiesNavigationData = simpleFlatProperty;
476 // Update the header in the navigation tree with property name.
477 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
479 // Set selected property in table
480 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
481 this.hierarchyNavTabs.triggerTabChange('Property Structure');
485 selectInstanceRow = ($event) => {//get instance name
486 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
487 return instance.name == $event;
489 this.hierarchyNavTabs.triggerTabChange('Composition');
492 tabChanged = (event) => {
493 // stop if has changed properties
494 if (this.hasChangedData) {
495 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
496 this.showUnsavedChangesAlert().then((proceed) => {
497 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
503 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
504 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
505 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
506 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
507 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
508 this.propertyStructureHeader = null;
509 this.searchQuery = '';
513 * Select Tosca function value from defined values
515 selectToscaFunctionAndValues = (): void => {
516 const selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = this.getSelectedInstance();
517 if (!selectedInstanceData) {
520 this.openToscaGetFunctionModal();
523 private getSelectedInstance(): ComponentInstance | GroupInstance | PolicyInstance {
524 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
525 const instanceId: string = instancesIds[0];
526 return <ComponentInstance | GroupInstance | PolicyInstance> this.instances.find(instance =>
527 instance.uniqueId == instanceId && (instance instanceof ComponentInstance || instance instanceof GroupInstance || instance instanceof PolicyInstance));
530 private buildCheckedInstanceProperty(): PropertyBEModel {
531 return this.buildCheckedInstanceProperties()[0];
534 private buildCheckedInstanceProperties(): PropertyBEModel[] {
535 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
536 const instanceId: string = instancesIds[0];
537 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
540 private openToscaGetFunctionModal() {
541 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
542 const modalButtons = [];
543 let disableSaveButtonFlag = true;
544 const modal = this.modalService.createCustomModal(new ModalModel(
551 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
553 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
554 if (toscaGetFunction) {
555 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
557 this.clearCheckedInstancePropertyValue();
559 this.modalService.closeCurrentModal();
561 (): boolean => { return disableSaveButtonFlag }
563 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
564 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
565 this.modalService.closeCurrentModal();
569 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
570 'property': checkedInstanceProperty,
571 'componentInstanceMap': this.componentInstanceMap
573 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
574 disableSaveButtonFlag = !validationEvent.isValid;
576 modal.instance.open();
579 private clearCheckedInstancePropertyValue() {
580 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
581 checkedInstanceProperty.getInputValues = null;
582 checkedInstanceProperty.value = null;
583 checkedInstanceProperty.toscaFunction = null;
584 if (checkedInstanceProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName){
585 const propertiesNameArray = (<PropertyDeclareAPIModel>checkedInstanceProperty).propertiesName;
586 const parts = propertiesNameArray.split("#");
587 if (propertiesNameArray.length > 1){
588 const index = checkedInstanceProperty.subPropertyToscaFunctions.findIndex(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, parts.slice(1)));
589 checkedInstanceProperty.subPropertyToscaFunctions.splice(index, 1);
592 if (this.selectedInstanceData instanceof ComponentInstance) {
593 this.updateInstanceProperty(checkedInstanceProperty);
594 } else if (this.selectedInstanceData instanceof GroupInstance) {
595 this.updateGroupInstanceProperty(checkedInstanceProperty);
596 } else if (this.selectedInstanceData instanceof PolicyInstance) {
597 this.updatePolicyInstanceProperty(checkedInstanceProperty);
601 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
602 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
603 if (checkedProperty instanceof PropertyDeclareAPIModel && (<PropertyDeclareAPIModel>checkedProperty).propertiesName){
604 const propertiesName = (<PropertyDeclareAPIModel>checkedProperty).propertiesName;
605 const parts = propertiesName.split("#");
607 if (checkedProperty.subPropertyToscaFunctions == null){
608 checkedProperty.subPropertyToscaFunctions = [];
610 let subPropertyToscaFunction = checkedProperty.subPropertyToscaFunctions.find(existingSubPropertyToscaFunction => this.areEqual(existingSubPropertyToscaFunction.subPropertyPath, parts.slice(1)));
611 if (!subPropertyToscaFunction){
612 subPropertyToscaFunction = new SubPropertyToscaFunction();
613 checkedProperty.subPropertyToscaFunctions.push(subPropertyToscaFunction);
615 subPropertyToscaFunction.toscaFunction = toscaFunction;
616 subPropertyToscaFunction.subPropertyPath = parts.slice(1);
619 checkedProperty.subPropertyToscaFunctions = null;
620 checkedProperty.toscaFunction = toscaFunction;
622 if (this.selectedInstanceData instanceof ComponentInstance) {
623 this.updateInstanceProperty(checkedProperty);
624 } else if (this.selectedInstanceData instanceof GroupInstance) {
625 this.updateGroupInstanceProperty(checkedProperty);
626 } else if (this.selectedInstanceData instanceof PolicyInstance) {
627 this.updatePolicyInstanceProperty(checkedProperty);
631 private areEqual(array1: string[], array2: string[]): boolean {
632 return array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
635 updateInstanceProperty(instanceProperty: PropertyBEModel) {
636 this.loadingProperties = true;
637 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
638 this.selectedInstanceData.uniqueId, [instanceProperty])
640 this.changeSelectedInstance(this.getSelectedInstance());
642 this.loadingProperties = false;
643 console.error(error);
645 this.loadingProperties = false;
649 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
650 this.loadingProperties = true;
651 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
652 this.selectedInstanceData.uniqueId, [instanceProperty])
654 this.changeSelectedInstance(this.getSelectedInstance());
656 this.loadingProperties = false;
657 console.error(error);
659 this.loadingProperties = false;
663 updatePolicyInstanceProperty(instanceProperty: PropertyBEModel) {
664 this.loadingProperties = true;
665 this.componentInstanceServiceNg2.updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId,
666 this.selectedInstanceData.uniqueId, [instanceProperty])
668 this.changeSelectedInstance(this.getSelectedInstance());
670 this.loadingProperties = false;
671 console.error(error);
673 this.loadingProperties = false;
677 /*** DECLARE PROPERTIES/INPUTS ***/
678 declareProperties = (): void => {
679 console.debug("==>" + this.constructor.name + ": declareProperties");
681 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
682 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
683 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
684 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
685 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
687 angular.forEach(instancesIds, (instanceId: string): void => {
688 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
689 if (selectedInstanceData instanceof ComponentInstance) {
690 if (!this.isInput(selectedInstanceData.originType)) {
691 // convert Property FE model -> Property BE model, extract only checked
692 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
694 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
696 } else if (selectedInstanceData instanceof GroupInstance) {
697 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
698 } else if (selectedInstanceData instanceof PolicyInstance) {
699 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
703 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
705 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
706 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
707 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
709 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
710 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
713 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
714 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
715 prop => !this.isCapabilityProperty(prop)
717 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
718 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
721 let isCapabilityPropertyChanged = false;
723 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
724 (prop: PropertyBEModel) => {
725 prop.name = prop.origName || prop.name;
726 if (this.isCapabilityProperty(prop)) {
727 isCapabilityPropertyChanged = true;
731 this.topologyTemplateService
732 .createInput(this.component, inputsToCreate, this.isSelf())
733 .subscribe((response) => {
734 this.selectInstanceRow(SERVICE_SELF_TITLE);
735 this.onInstanceSelectedUpdate(this.instances[0]);
736 this.setInputTabIndication(response.length);
737 this.checkedPropertiesCount = 0;
738 this.checkedChildPropertiesCount = 0;
739 _.forEach(response, (input: InputBEModel) => {
740 const newInput: InputFEModel = new InputFEModel(input);
741 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
742 this.inputs.push(newInput);
743 this.updatePropertyValueAfterDeclare(newInput);
745 if (isCapabilityPropertyChanged) {
746 this.reloadInstanceCapabilities();
748 }, error => {}); //ignore error
751 declareListProperties = (): void => {
752 // get selected properties
753 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
754 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
755 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
756 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
757 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
758 let propertyNameList: Array<string> = [];
761 angular.forEach(instancesIds, (instanceId: string): void => {
763 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
764 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
766 if (selectedInstanceData instanceof ComponentInstance) {
767 if (!this.isInput(selectedInstanceData.originType)) {
768 // convert Property FE model -> Property BE model, extract only checked
769 selectedComponentInstancesProperties[instanceId] = checkedProperties;
771 selectedComponentInstancesInputs[instanceId] = checkedProperties;
773 } else if (selectedInstanceData instanceof GroupInstance) {
774 selectedGroupInstancesProperties[instanceId] = checkedProperties;
775 } else if (selectedInstanceData instanceof PolicyInstance) {
776 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
779 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
780 propertyNameList.push(property.name);
784 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
786 let modalTitle = 'Declare Properties as List Input';
787 const modal = this.modalService.createCustomModal(new ModalModel(
789 modalTitle, /* title */
794 'blue', /* css class */
795 () => { /* callback */
796 let content:any = modal.instance.dynamicContent.instance;
799 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
800 let typelist: any = PROPERTY_TYPES.LIST;
801 let uniID: any = insId;
802 let boolfalse: any = false;
803 let required: any = content.propertyModel.required;
807 "type": content.propertyModel.simpleType,
811 let schemaProp :any = {
812 "type": content.propertyModel.simpleType,
816 reglistInput.description = content.propertyModel.description;
817 reglistInput.name = content.propertyModel.name;
818 reglistInput.type = typelist;
819 reglistInput.schemaType = content.propertyModel.simpleType;
820 reglistInput.instanceUniqueId = uniID;
821 reglistInput.uniqueId = uniID;
822 reglistInput.required = required;
823 reglistInput.schema = schem;
824 reglistInput.schemaProperty = schemaProp;
827 componentInstInputsMap: content.inputsToCreate,
828 listInput: reglistInput
831 this.topologyTemplateService
832 .createListInput(this.component, input, this.isSelf())
833 .subscribe(response => {
834 this.setInputTabIndication(response.length);
835 this.checkedPropertiesCount = 0;
836 this.checkedChildPropertiesCount = 0;
837 _.forEach(response, (input: InputBEModel) => {
838 let newInput: InputFEModel = new InputFEModel(input);
839 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
840 this.inputs.push(newInput);
841 // create list input does not return updated properties info, so need to reload
842 //this.updatePropertyValueAfterDeclare(newInput);
843 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
844 this.changeSelectedInstance(this.selectedInstanceData);
846 modal.instance.close();
848 }, error => {}); //ignore error
851 /*, getDisabled: function */
853 new ButtonModel('Cancel', 'outline grey', () => {
854 modal.instance.close();
859 // 3rd arg is passed to DeclareListComponent instance
860 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
861 modal.instance.open();
864 /*** DECLARE PROPERTIES/POLICIES ***/
865 declarePropertiesToPolicies = (): void => {
866 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
867 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
869 angular.forEach(instancesIds, (instanceId: string): void => {
870 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
871 if (selectedInstanceData instanceof ComponentInstance) {
872 if (!this.isInput(selectedInstanceData.originType)) {
873 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
878 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
879 this.loadingPolicies = true;
881 this.topologyTemplateService
882 .createPolicy(this.component, policiesToCreate, this.isSelf())
883 .subscribe(response => {
884 this.setPolicyTabIndication(response.length);
885 this.checkedPropertiesCount = 0;
886 this.displayPoliciesAsDeclared(response);
887 this.loadingPolicies = false;
892 displayPoliciesAsDeclared = (policies) => {
893 _.forEach(policies, (policy: any) => {
894 let newPolicy: InputFEModel = new InputFEModel(policy);
895 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
896 newPolicy.relatedPropertyName = policy.name;
897 newPolicy.relatedPropertyValue = policy.value;
898 this.updatePropertyValueAfterDeclare(newPolicy);
899 this.policies.push(policy);
903 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
904 return new Promise((resolve, reject) => {
905 if (!this.isValidChangedData) {
906 reject('Changed data is invalid - cannot save!');
909 if (!this.changedData.length) {
914 // make request and its handlers
916 let handleSuccess, handleError;
917 let changedInputsProperties = [], changedCapabilitiesProperties = [];
918 if (this.isPropertiesTabSelected) {
919 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
920 changedProp = <PropertyFEModel>changedProp;
921 const propBE = new PropertyBEModel(changedProp);
922 propBE.toscaPresentation = new ToscaPresentationData();
923 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
924 propBE.value = changedProp.getJSONValue();
925 propBE.name = changedProp.origName || changedProp.name;
926 delete propBE.origName;
929 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
931 if (this.selectedInstanceData instanceof ComponentInstance) {
932 if (this.isInput(this.selectedInstanceData.originType)) {
933 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
934 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
935 request = Observable.forkJoin(
936 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
937 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
938 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
941 else if (changedInputsProperties.length) {
942 request = this.componentInstanceServiceNg2
943 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
945 else if (changedCapabilitiesProperties.length) {
946 request = this.componentInstanceServiceNg2
947 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
949 handleSuccess = (response) => {
950 // reset each changed property with new value and remove it from changed properties list
951 response.forEach((resInput) => {
952 const changedProp = <PropertyFEModel>this.changedData.shift();
953 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
958 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
959 delete cp.constraints;
963 request = this.componentInstanceServiceNg2
964 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
966 handleSuccess = (response) => {
967 // reset each changed property with new value and remove it from changed properties list
968 response.forEach((resProp) => {
969 const changedProp = <PropertyFEModel>this.changedData.shift();
970 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
975 } else if (this.selectedInstanceData instanceof GroupInstance) {
976 request = this.componentInstanceServiceNg2
977 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
978 handleSuccess = (response) => {
979 // reset each changed property with new value and remove it from changed properties list
980 response.forEach((resProp) => {
981 const changedProp = <PropertyFEModel>this.changedData.shift();
982 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
986 } else if (this.selectedInstanceData instanceof PolicyInstance) {
987 request = this.componentInstanceServiceNg2
988 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
989 handleSuccess = (response) => {
990 // reset each changed property with new value and remove it from changed properties list
991 response.forEach((resProp) => {
992 const changedProp = <PropertyFEModel>this.changedData.shift();
993 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
998 } else if (this.isInputsTabSelected) {
1000 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
1001 changedInput = <InputFEModel>changedInput;
1002 const inputBE = new InputBEModel(changedInput);
1003 inputBE.defaultValue = changedInput.getJSONDefaultValue();
1006 request = this.componentServiceNg2
1007 .updateComponentInputs(this.component, changedInputs);
1008 handleSuccess = (response) => {
1009 // reset each changed property with new value and remove it from changed properties list
1010 response.forEach((resInput) => {
1011 const changedInput = <InputFEModel>this.changedData.shift();
1012 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
1013 changedInput.required = resInput.required;
1014 changedInput.requiredOrig = resInput.required;
1019 this.savingChangedData = true;
1022 this.savingChangedData = false;
1023 if (changedCapabilitiesProperties.length) {
1024 this.reloadInstanceCapabilities();
1026 handleSuccess && handleSuccess(response);
1027 this.updateHasChangedData();
1031 this.savingChangedData = false;
1032 handleError && handleError(error);
1033 this.updateHasChangedData();
1040 reloadInstanceCapabilities = (): void => {
1041 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
1042 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
1043 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
1044 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
1045 return instance.capabilities;
1048 }, new CapabilitiesGroup());
1049 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1053 reverseChangedData = ():void => {
1054 // make reverse item handler
1055 let handleReverseItem;
1056 if (this.isPropertiesTabSelected) {
1057 handleReverseItem = (changedItem) => {
1058 changedItem = <PropertyFEModel>changedItem;
1059 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1061 } else if (this.isInputsTabSelected) {
1062 handleReverseItem = (changedItem) => {
1063 changedItem = <InputFEModel>changedItem;
1064 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1065 changedItem.resetMetadata();
1066 changedItem.required = changedItem.requiredOrig;
1070 this.changedData.forEach(handleReverseItem);
1071 this.changedData = [];
1072 this.updateHasChangedData();
1075 updateHasChangedData = ():boolean => {
1076 const curHasChangedData:boolean = (this.changedData.length > 0);
1077 if (curHasChangedData !== this.hasChangedData) {
1078 this.hasChangedData = curHasChangedData;
1079 if(this.hasChangedData) {
1080 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1082 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1085 return this.hasChangedData;
1088 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1089 this.saveChangedData().then(
1091 this.notification.success({
1092 message: 'Successfully saved changes',
1095 if(onSuccessFunction) onSuccessFunction();
1098 this.notification.error({
1099 message: 'Failed to save changes!',
1102 if(onError) onError();
1107 showUnsavedChangesAlert = ():Promise<any> => {
1108 let modalTitle:string;
1109 if (this.isPropertiesTabSelected) {
1110 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1111 } else if (this.isInputsTabSelected) {
1112 modalTitle = `Unsaved inputs for ${this.component.name}`;
1115 return new Promise<any>((resolve, reject) => {
1116 const modal = this.ModalServiceSdcUI.openCustomModal(
1120 type: SdcUiCommon.ModalType.custom,
1121 testId: "navigate-modal",
1124 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1125 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1126 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1127 ] as SdcUiCommon.IModalButtonComponent[]
1128 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1133 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1134 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1135 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1136 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1137 return feProperty.name == input.relatedPropertyName &&
1138 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1140 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1141 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1142 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1143 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1147 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1148 updateCheckedPropertyCount = (increment: boolean): void => {
1149 this.checkedPropertiesCount += (increment) ? 1 : -1;
1150 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1153 updateCheckedChildPropertyCount = (increment: boolean): void => {
1154 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1157 setInputTabIndication = (numInputs: number): void => {
1158 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1161 setPolicyTabIndication = (numPolicies: number): void => {
1162 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1165 resetUnsavedChangesForInput = (input:InputFEModel) => {
1166 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1167 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1168 this.updateHasChangedData();
1171 deleteInput = (input: InputFEModel) => {
1172 //reset any unsaved changes to the input before deleting it
1173 this.resetUnsavedChangesForInput(input);
1175 console.debug("==>" + this.constructor.name + ": deleteInput");
1176 let inputToDelete = new InputBEModel(input);
1178 this.componentServiceNg2
1179 .deleteInput(this.component, inputToDelete)
1180 .subscribe(response => {
1181 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1183 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1184 this.changeSelectedInstance(this.selectedInstanceData);
1185 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1187 // if (instanceFeProperties) {
1188 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1189 // return prop.name == input.propertyName;
1192 // if (propToEnable) {
1193 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1194 // propToEnable.setNonDeclared(response.inputPath);
1195 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1196 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1199 }, error => {}); //ignore error
1202 deletePolicy = (policy: PolicyInstance) => {
1203 this.loadingPolicies = true;
1204 this.topologyTemplateService
1205 .deletePolicy(this.component, policy)
1206 .subscribe((response) => {
1207 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1208 this.changeSelectedInstance(this.selectedInstanceData);
1209 this.loadingPolicies = false;
1213 deleteProperty = (property: PropertyFEModel) => {
1214 const propertyToDelete = new PropertyFEModel(property);
1215 this.loadingProperties = true;
1216 const feMap = this.instanceFePropertiesMap;
1217 this.topologyTemplateService
1218 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1219 .subscribe((response) => {
1220 const props = feMap[this.component.uniqueId];
1221 props.splice(props.findIndex(p => p.uniqueId === response),1);
1222 this.loadingProperties = false;
1224 this.loadingProperties = false;
1225 console.error(error);
1229 /*** addProperty ***/
1230 addProperty = (model: string) => {
1231 this.loadDataTypesByComponentModel(model)
1232 let modalTitle = 'Add Property';
1233 let modal = this.modalService.createCustomModal(new ModalModel(
1238 new ButtonModel('Save', 'blue', () => {
1239 modal.instance.dynamicContent.instance.isLoading = true;
1240 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1241 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1242 .subscribe((response) => {
1243 modal.instance.dynamicContent.instance.isLoading = false;
1244 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1245 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1246 modal.instance.close();
1248 modal.instance.dynamicContent.instance.isLoading = false;
1249 this.notification.error({
1250 message: 'Failed to add property:' + error,
1254 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1255 new ButtonModel('Cancel', 'outline grey', () => {
1256 modal.instance.close();
1261 modal.instance.open();
1262 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1267 let modalTitle = 'Add Input';
1268 let modal = this.modalService.createCustomModal(new ModalModel(
1273 new ButtonModel('Save', 'blue', () => {
1274 modal.instance.dynamicContent.instance.isLoading = true;
1275 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1276 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1277 .subscribe((response) => {
1278 modal.instance.dynamicContent.instance.isLoading = false;
1279 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1280 this.inputs.push(newInputProp);
1281 modal.instance.close();
1283 modal.instance.dynamicContent.instance.isLoading = false;
1284 this.notification.error({
1285 message: 'Failed to add input:' + error,
1289 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1290 new ButtonModel('Cancel', 'outline grey', () => {
1291 modal.instance.close();
1296 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1297 modal.instance.open();
1300 /*** SEARCH RELATED FUNCTIONS ***/
1301 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1302 let instanceBePropertiesMap:InstanceBePropertiesMap;
1303 this.componentServiceNg2
1304 .filterComponentInstanceProperties(this.component, filterData)
1305 .subscribe((response) => {
1306 this.processInstancePropertiesResponse(response, false);
1307 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1308 this.searchPropertyName = filterData.propertyName;//mark in table
1309 this.hierarchyNavTabs.triggerTabChange('Composition');
1310 this.propertiesNavigationData = [];
1311 this.displayClearSearch = true;
1312 }, (error) => {}); //ignore error
1316 clearSearch = () => {
1317 this.instancesNavigationData = this.instances;
1318 this.searchPropertyName = "";
1319 this.hierarchyPropertiesDisplayOptions.searchText = "";
1320 this.displayClearSearch = false;
1321 this.advanceSearch.clearAll();
1322 this.searchQuery = '';
1325 clickOnClearSearch = () => {
1327 this.selectFirstInstanceByDefault();
1328 this.hierarchyNavTabs.triggerTabChange('Composition');
1331 private isInput = (instanceType:string):boolean =>{
1332 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1335 loadDataTypesByComponentModel(model:string) {
1336 this.propertyCreatorComponent.filterDataTypesByModel(model);