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,
43 import {ResourceType} from "app/utils";
44 import {ComponentServiceNg2} from "../../services/component-services/component.service";
45 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
46 import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service"
47 import {KeysPipe} from 'app/ng2/pipes/keys.pipe';
48 import {EVENTS, PROPERTY_TYPES, WorkspaceMode} from "../../../utils/constants";
49 import {EventListenerService} from "app/services/event-listener-service"
50 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
51 import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component";
52 import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component";
53 import {HierarchyNavService} from "./services/hierarchy-nav.service";
54 import {PropertiesUtils} from "./services/properties.utils";
55 import {ComponentModeService} from "../../services/component-services/component-mode.service";
56 import {Tab, Tabs} from "../../components/ui/tabs/tabs.component";
57 import {InputsUtils} from "./services/inputs.utils";
58 import {InstanceFeDetails} from "../../../models/instance-fe-details";
59 import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
60 import {UnsavedChangesComponent} from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component";
61 import {PropertyCreatorComponent} from "./property-creator/property-creator.component";
62 import {ModalService} from "../../services/modal.service";
63 import {DeclareListComponent} from "./declare-list/declare-list.component";
64 import {ToscaFunctionComponent, ToscaFunctionValidationEvent} from "./tosca-function/tosca-function.component";
65 import {CapabilitiesGroup, Capability} from "../../../models/capability";
66 import {ToscaPresentationData} from "../../../models/tosca-presentation";
67 import {Observable} from "rxjs";
68 import {TranslateService} from "../../shared/translator/translate.service";
69 import {ToscaFunction} from "../../../models/tosca-function";
71 const SERVICE_SELF_TITLE = "SELF";
73 templateUrl: './properties-assignment.page.component.html',
74 styleUrls: ['./properties-assignment.page.component.less']
76 export class PropertiesAssignmentComponent {
77 title = "Properties & Inputs";
79 component: ComponentData;
80 componentInstanceNamesMap: { [key: string]: InstanceFeDetails } = {}; //key is the instance uniqueId
81 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>(); //key is the instance uniqueId
83 propertiesNavigationData = [];
84 instancesNavigationData = [];
86 instanceFePropertiesMap: InstanceFePropertiesMap;
87 inputs: Array<InputFEModel> = [];
88 policies: Array<PolicyInstance> = [];
89 instances: Array<ComponentInstance | GroupInstance | PolicyInstance> = [];
91 propertyStructureHeader: string;
93 selectedFlatProperty: SimpleFlatProperty = new SimpleFlatProperty();
94 selectedInstanceData: ComponentInstance | GroupInstance | PolicyInstance = null;
95 checkedPropertiesCount: number = 0;
96 checkedChildPropertiesCount: number = 0;
98 hierarchyPropertiesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('path', 'name', 'childrens');
99 hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
100 displayClearSearch = false;
101 searchPropertyName: string;
103 isInputsTabSelected: boolean;
104 isPropertiesTabSelected: boolean;
105 isPoliciesTabSelected: boolean;
107 resourceIsReadonly: boolean;
108 loadingInstances: boolean = false;
109 loadingInputs: boolean = false;
110 loadingPolicies: boolean = false;
111 loadingProperties: boolean = false;
112 changedData: Array<PropertyFEModel | InputFEModel>;
113 hasChangedData: boolean;
114 isValidChangedData: boolean;
115 savingChangedData: boolean;
116 stateChangeStartUnregister: Function;
117 serviceBePropertiesMap: InstanceBePropertiesMap;
118 serviceBeCapabilitiesPropertiesMap: InstanceBePropertiesMap;
119 selectedInstance_FlattenCapabilitiesList: Capability[];
121 @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs;
122 @ViewChild('propertyInputTabs') propertyInputTabs: Tabs;
123 @ViewChild('advanceSearch') advanceSearch: FilterPropertiesAssignmentComponent;
125 constructor(private propertiesService: PropertiesService,
126 private hierarchyNavService: HierarchyNavService,
127 private propertiesUtils: PropertiesUtils,
128 private inputsUtils: InputsUtils,
129 private componentServiceNg2: ComponentServiceNg2,
130 private componentInstanceServiceNg2: ComponentInstanceServiceNg2,
131 private propertyCreatorComponent: PropertyCreatorComponent,
132 @Inject("$stateParams") _stateParams,
133 @Inject("$scope") private $scope: ng.IScope,
134 @Inject("$state") private $state: ng.ui.IStateService,
135 @Inject("Notification") private notification: any,
136 private componentModeService: ComponentModeService,
137 private eventListenerService: EventListenerService,
138 private ModalServiceSdcUI: SdcUiServices.ModalService,
139 private modalService: ModalService,
140 private keysPipe: KeysPipe,
141 private topologyTemplateService: TopologyTemplateService,
142 private translateService: TranslateService) {
144 this.instanceFePropertiesMap = new InstanceFePropertiesMap();
145 /* 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
146 than if the data is already exist, no need to call the api again - Ask orit if you have any questions*/
147 this.component = _stateParams.component;
148 this.eventListenerService.registerObserverCallback(EVENTS.ON_LIFECYCLE_CHANGE, this.onCheckout);
149 this.updateViewMode();
150 this.changedData = [];
151 this.updateHasChangedData();
152 this.isValidChangedData = true;
156 console.debug("==>" + this.constructor.name + ": ngOnInit");
157 this.loadingInputs = true;
158 this.loadingPolicies = true;
159 this.loadingInstances = true;
160 this.loadingProperties = true;
161 this.topologyTemplateService
162 .getComponentInputsWithProperties(this.component.componentType, this.component.uniqueId)
163 .subscribe(response => {
164 _.forEach(response.inputs, (input: InputBEModel) => {
165 const newInput: InputFEModel = new InputFEModel(input);
166 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
167 this.inputs.push(newInput); //only push items that were declared via SDC
169 this.loadingInputs = false;
173 this.componentServiceNg2
174 .getComponentResourcePropertiesData(this.component)
175 .subscribe(response => {
176 this.loadingPolicies = false;
178 this.instances.push(...response.componentInstances);
179 this.instances.push(...response.groupInstances);
180 this.instances.push(...response.policies);
182 if (response.componentInstances) {
183 response.componentInstances.forEach(instance => {
184 this.componentInstanceMap.set(instance.uniqueId, <InstanceFeDetails>{
186 iconClass: instance.iconClass,
187 originArchived: instance.originArchived
192 _.forEach(response.policies, (policy: any) => {
193 const newPolicy: InputFEModel = new InputFEModel(policy);
194 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
195 this.policies.push(policy);
198 // add the service self instance to the top of the list.
199 const serviceInstance = new ComponentInstance();
200 serviceInstance.name = SERVICE_SELF_TITLE;
201 serviceInstance.uniqueId = this.component.uniqueId;
202 this.instances.unshift(serviceInstance);
204 _.forEach(this.instances, (instance) => {
205 this.instancesNavigationData.push(instance);
206 this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{
208 iconClass: instance.iconClass,
209 originArchived: instance.originArchived
212 this.loadingInstances = false;
213 if (this.instancesNavigationData[0] == undefined) {
214 this.loadingProperties = false;
216 this.selectFirstInstanceByDefault();
218 this.loadingInstances = false;
221 this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => {
222 // stop if has changed properties
223 if (this.hasChangedData) {
224 event.preventDefault();
225 this.showUnsavedChangesAlert().then(() => {
226 this.$state.go(toState, toParams);
232 this.loadDataTypesByComponentModel(this.component.model);
236 this.eventListenerService.unRegisterObserver(EVENTS.ON_LIFECYCLE_CHANGE);
237 this.stateChangeStartUnregister();
240 selectFirstInstanceByDefault = () => {
241 if (this.instancesNavigationData[0] !== undefined) {
242 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
246 updateViewMode = () => {
247 this.isReadonly = this.componentModeService.getComponentMode(this.component) === WorkspaceMode.VIEW;
250 onCheckout = (component: ComponentData) => {
251 this.component = component;
252 this.updateViewMode();
255 isSelf = (): boolean => {
256 return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId;
259 showAddProperties = (): boolean => {
260 if (this.component.isService() && !(<Service>this.component).isSubstituteCandidate()) {
263 return this.isSelf();
266 getServiceProperties() {
267 this.loadingProperties = true;
268 this.topologyTemplateService
269 .getServiceProperties(this.component.uniqueId)
270 .subscribe((response) => {
271 this.serviceBePropertiesMap = new InstanceBePropertiesMap();
272 this.serviceBePropertiesMap[this.component.uniqueId] = response;
273 this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false);
274 this.loadingProperties = false;
276 this.loadingProperties = false;
280 onInstanceSelectedUpdate = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
281 // stop if has changed properties
282 if (this.hasChangedData) {
283 this.showUnsavedChangesAlert().then((resolve) => {
284 this.changeSelectedInstance(instance)
289 this.changeSelectedInstance(instance);
292 changeSelectedInstance = (instance: ComponentInstance | GroupInstance | PolicyInstance) => {
293 this.selectedInstanceData = instance;
294 this.loadingProperties = true;
295 if (instance instanceof ComponentInstance) {
296 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
297 if (this.isInput(instance.originType)) {
298 this.componentInstanceServiceNg2
299 .getComponentInstanceInputs(this.component, instance)
300 .subscribe(response => {
301 instanceBePropertiesMap[instance.uniqueId] = response;
302 this.processInstancePropertiesResponse(instanceBePropertiesMap, true);
306 this.loadingProperties = false;
308 } else if (this.isSelf()) {
309 this.getServiceProperties();
311 this.componentInstanceServiceNg2
312 .getComponentInstanceProperties(this.component, instance.uniqueId)
313 .subscribe(response => {
314 instanceBePropertiesMap[instance.uniqueId] = response;
315 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
319 this.loadingProperties = false;
322 this.loadingProperties = false;
323 this.resourceIsReadonly = (instance.componentName === "vnfConfiguration");
324 } else if (instance instanceof GroupInstance) {
325 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
326 this.componentInstanceServiceNg2
327 .getComponentGroupInstanceProperties(this.component, this.selectedInstanceData.uniqueId)
328 .subscribe((response) => {
329 instanceBePropertiesMap[instance.uniqueId] = response;
330 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
334 this.loadingProperties = false;
336 } else if (instance instanceof PolicyInstance) {
337 let instanceBePropertiesMap: InstanceBePropertiesMap = new InstanceBePropertiesMap();
338 this.componentInstanceServiceNg2
339 .getComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId)
340 .subscribe((response) => {
341 instanceBePropertiesMap[instance.uniqueId] = response;
342 this.processInstancePropertiesResponse(instanceBePropertiesMap, false);
346 this.loadingProperties = false;
349 this.loadingProperties = false;
352 if (this.searchPropertyName) {
355 //clear selected property from the navigation
356 this.selectedFlatProperty = new SimpleFlatProperty();
357 this.propertiesNavigationData = [];
361 * Entry point handling response from server
363 processInstancePropertiesResponse = (instanceBePropertiesMap: InstanceBePropertiesMap, originTypeIsVF: boolean) => {
364 this.instanceFePropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(instanceBePropertiesMap, originTypeIsVF, this.inputs, this.component.model); //create flattened children, disable declared props, and init values
365 this.checkedPropertiesCount = 0;
366 this.checkedChildPropertiesCount = 0;
369 processInstanceCapabilitiesPropertiesResponse = (originTypeIsVF: boolean) => {
370 let selectedComponentInstanceData = <ComponentInstance>(this.selectedInstanceData);
371 let currentUniqueId = this.selectedInstanceData.uniqueId;
372 this.serviceBeCapabilitiesPropertiesMap = new InstanceBePropertiesMap();
373 let isCapabilityOwnedByInstance: boolean;
374 this.serviceBeCapabilitiesPropertiesMap[currentUniqueId] = _.reduce(
375 this.selectedInstance_FlattenCapabilitiesList,
376 (result, cap: Capability) => {
377 isCapabilityOwnedByInstance = cap.ownerId === currentUniqueId ||
378 selectedComponentInstanceData.isServiceProxy() || selectedComponentInstanceData.isServiceSubstitution() &&
379 cap.ownerId === selectedComponentInstanceData.sourceModelUid;
380 if (cap.properties && isCapabilityOwnedByInstance) {
381 _.forEach(cap.properties, prop => {
382 if (!prop.origName) {
383 prop.origName = prop.name;
384 prop.name = cap.name + '_' + prop.name;//for display. (before save - the name returns to its orig value: prop.name)
387 return result.concat(cap.properties);
391 let instanceFECapabilitiesPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren(this.serviceBeCapabilitiesPropertiesMap, originTypeIsVF, this.inputs); //create flattened children, disable declared props, and init values
392 //update FECapabilitiesProperties with their origName according to BeCapabilitiesProperties
393 _.forEach(instanceFECapabilitiesPropertiesMap[currentUniqueId], prop => {
394 prop.origName = _.find(this.serviceBeCapabilitiesPropertiesMap[currentUniqueId], p => p.uniqueId === prop.uniqueId).origName;
396 //concatenate capabilitiesProps to all props list
397 this.instanceFePropertiesMap[currentUniqueId] = (this.instanceFePropertiesMap[currentUniqueId] || []).concat(instanceFECapabilitiesPropertiesMap[currentUniqueId]);
398 this.checkedPropertiesCount = 0;
401 isCapabilityProperty = (prop: PropertyBEModel) => {
402 return _.find(this.selectedInstance_FlattenCapabilitiesList, cap => cap.uniqueId === prop.parentUniqueId);
405 /*** VALUE CHANGE EVENTS ***/
406 dataChanged = (item: PropertyFEModel | InputFEModel) => {
408 if (this.isPropertiesTabSelected && item instanceof PropertyFEModel) {
409 itemHasChanged = item.hasValueObjChanged();
410 } else if (this.isInputsTabSelected && item instanceof InputFEModel) {
411 itemHasChanged = item.hasChanged();
412 } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) {
413 itemHasChanged = item.hasDefaultValueChanged();
416 const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item);
417 if (itemHasChanged) {
418 if (dataChangedIdx === -1) {
419 this.changedData.push(item);
422 if (dataChangedIdx !== -1) {
423 this.changedData.splice(dataChangedIdx, 1);
427 if (this.isPropertiesTabSelected) {
428 this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid);
429 } else if (this.isInputsTabSelected) {
430 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid && (<InputFEModel>changedItem).metadataIsValid);
431 } else if (this.isPoliciesTabSelected) {
432 this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid);
434 this.updateHasChangedData();
438 /*** HEIRARCHY/NAV RELATED FUNCTIONS ***/
441 * Handle select node in navigation area, and select the row in table
443 onPropertySelectedUpdate = ($event) => {
444 console.debug("==>" + this.constructor.name + ": onPropertySelectedUpdate");
445 this.selectedFlatProperty = $event;
446 let parentProperty: PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path);
447 parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path;
451 * When user select row in table, this will prepare the hirarchy object for the tree.
453 selectPropertyRow = (propertyRowSelectedEvent: PropertyRowSelectedEvent) => {
454 console.debug("==>" + this.constructor.name + ": selectPropertyRow " + propertyRowSelectedEvent.propertyModel.name);
455 let property = propertyRowSelectedEvent.propertyModel;
456 let instanceName = propertyRowSelectedEvent.instanceName;
457 this.propertyStructureHeader = null;
459 // Build hirarchy tree for the navigation and update propertiesNavigationData with it.
460 if (!(this.selectedInstanceData instanceof ComponentInstance) || this.selectedInstanceData.originType !== ResourceType.VF) {
461 let simpleFlatProperty: Array<SimpleFlatProperty>;
462 if (property instanceof PropertyFEModel) {
463 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(property, instanceName);
464 } else if (property instanceof DerivedFEProperty) {
465 // Need to find parent PropertyFEModel
466 let parentPropertyFEModel: PropertyFEModel = _.find(this.instanceFePropertiesMap[instanceName], (tmpFeProperty): boolean => {
467 return property.propertiesName.indexOf(tmpFeProperty.name) === 0;
469 simpleFlatProperty = this.hierarchyNavService.getSimplePropertiesTree(parentPropertyFEModel, instanceName);
471 this.propertiesNavigationData = simpleFlatProperty;
474 // Update the header in the navigation tree with property name.
475 this.propertyStructureHeader = (property.propertiesName.split('#'))[0];
477 // Set selected property in table
478 this.selectedFlatProperty = this.hierarchyNavService.createSimpleFlatProperty(property, instanceName);
479 this.hierarchyNavTabs.triggerTabChange('Property Structure');
483 selectInstanceRow = ($event) => {//get instance name
484 this.selectedInstanceData = _.find(this.instancesNavigationData, (instance: ComponentInstance) => {
485 return instance.name == $event;
487 this.hierarchyNavTabs.triggerTabChange('Composition');
490 tabChanged = (event) => {
491 // stop if has changed properties
492 if (this.hasChangedData) {
493 this.propertyInputTabs.triggerTabChange(this.currentMainTab.title);
494 this.showUnsavedChangesAlert().then((proceed) => {
495 this.propertyInputTabs.selectTab(this.propertyInputTabs.tabs.find((tab) => tab.title === event.title));
501 console.debug("==>" + this.constructor.name + ": tabChanged " + event);
502 this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title);
503 this.isPropertiesTabSelected = this.currentMainTab.title === "Properties";
504 this.isInputsTabSelected = this.currentMainTab.title === "Inputs";
505 this.isPoliciesTabSelected = this.currentMainTab.title === "Policies";
506 this.propertyStructureHeader = null;
507 this.searchQuery = '';
511 * Select Tosca function value from defined values
513 selectToscaFunctionAndValues = (): void => {
514 const selectedInstanceData: ComponentInstance | GroupInstance = this.getSelectedInstance();
515 if (!selectedInstanceData) {
518 this.openToscaGetFunctionModal();
521 private getSelectedInstance(): ComponentInstance | GroupInstance {
522 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
523 const instanceId: string = instancesIds[0];
524 return <ComponentInstance | GroupInstance> this.instances.find(instance => instance.uniqueId == instanceId && instance instanceof ComponentInstance || instance instanceof GroupInstance);
527 private buildCheckedInstanceProperty(): PropertyBEModel {
528 return this.buildCheckedInstanceProperties()[0];
531 private buildCheckedInstanceProperties(): PropertyBEModel[] {
532 const instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
533 const instanceId: string = instancesIds[0];
534 return this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
537 private openToscaGetFunctionModal() {
538 const modalTitle = this.translateService.translate('TOSCA_FUNCTION_MODAL_TITLE');
539 const modalButtons = [];
540 let disableSaveButtonFlag = true;
541 const modal = this.modalService.createCustomModal(new ModalModel(
548 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_SAVE'), 'blue',
550 const toscaGetFunction: ToscaFunction = modal.instance.dynamicContent.instance.toscaFunctionForm.value;
551 if (toscaGetFunction) {
552 this.updateCheckedInstancePropertyFunctionValue(toscaGetFunction);
554 this.clearCheckedInstancePropertyValue();
556 this.modalService.closeCurrentModal();
558 (): boolean => { return disableSaveButtonFlag }
560 const checkedInstanceProperty = this.buildCheckedInstanceProperty();
561 modalButtons.push(new ButtonModel(this.translateService.translate('MODAL_CANCEL'), 'outline grey', () => {
562 this.modalService.closeCurrentModal();
566 this.modalService.addDynamicContentToModalAndBindInputs(modal, ToscaFunctionComponent, {
567 'property': checkedInstanceProperty,
568 'componentInstanceMap': this.componentInstanceMap
570 modal.instance.dynamicContent.instance.onValidityChange.subscribe((validationEvent: ToscaFunctionValidationEvent) => {
571 disableSaveButtonFlag = !validationEvent.isValid;
573 modal.instance.open();
576 private clearCheckedInstancePropertyValue() {
577 const checkedInstanceProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
578 checkedInstanceProperty.getInputValues = null;
579 checkedInstanceProperty.value = null;
580 checkedInstanceProperty.toscaFunction = null;
581 if (this.selectedInstanceData instanceof ComponentInstance) {
582 this.updateInstanceProperty(checkedInstanceProperty);
583 } else if (this.selectedInstanceData instanceof GroupInstance) {
584 this.updateGroupInstanceProperty(checkedInstanceProperty);
588 private updateCheckedInstancePropertyFunctionValue(toscaFunction: ToscaFunction) {
589 const checkedProperty: PropertyBEModel = this.buildCheckedInstanceProperty();
590 checkedProperty.toscaFunction = toscaFunction;
591 if (this.selectedInstanceData instanceof ComponentInstance) {
592 this.updateInstanceProperty(checkedProperty);
593 } else if (this.selectedInstanceData instanceof GroupInstance) {
594 this.updateGroupInstanceProperty(checkedProperty);
598 updateInstanceProperty(instanceProperty: PropertyBEModel) {
599 this.loadingProperties = true;
600 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
601 this.selectedInstanceData.uniqueId, [instanceProperty])
603 this.changeSelectedInstance(this.getSelectedInstance());
605 this.loadingProperties = false;
606 console.error(error);
608 this.loadingProperties = false;
612 updateGroupInstanceProperty(instanceProperty: PropertyBEModel) {
613 this.loadingProperties = true;
614 this.componentInstanceServiceNg2.updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId,
615 this.selectedInstanceData.uniqueId, [instanceProperty])
617 this.changeSelectedInstance(this.getSelectedInstance());
619 this.loadingProperties = false;
620 console.error(error);
622 this.loadingProperties = false;
626 /*** DECLARE PROPERTIES/INPUTS ***/
627 declareProperties = (): void => {
628 console.debug("==>" + this.constructor.name + ": declareProperties");
630 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
631 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
632 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
633 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
634 let instancesIds = this.keysPipe.transform(this.instanceFePropertiesMap, []);
636 angular.forEach(instancesIds, (instanceId: string): void => {
637 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
638 if (selectedInstanceData instanceof ComponentInstance) {
639 if (!this.isInput(selectedInstanceData.originType)) {
640 // convert Property FE model -> Property BE model, extract only checked
641 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
643 selectedComponentInstancesInputs[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
645 } else if (selectedInstanceData instanceof GroupInstance) {
646 selectedGroupInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
647 } else if (selectedInstanceData instanceof PolicyInstance) {
648 selectedPolicyInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
652 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
654 //move changed capabilities properties from componentInstanceInputsMap obj to componentInstanceProperties
655 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] =
656 (inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId] || []).concat(
658 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
659 (prop: PropertyBEModel) => this.isCapabilityProperty(prop)
662 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId] = _.filter(
663 inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId],
664 prop => !this.isCapabilityProperty(prop)
666 if (inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId].length === 0) {
667 delete inputsToCreate.componentInstanceInputsMap[this.selectedInstanceData.uniqueId];
670 let isCapabilityPropertyChanged = false;
672 inputsToCreate.componentInstanceProperties[this.selectedInstanceData.uniqueId],
673 (prop: PropertyBEModel) => {
674 prop.name = prop.origName || prop.name;
675 if (this.isCapabilityProperty(prop)) {
676 isCapabilityPropertyChanged = true;
680 this.topologyTemplateService
681 .createInput(this.component, inputsToCreate, this.isSelf())
682 .subscribe((response) => {
683 this.selectInstanceRow(SERVICE_SELF_TITLE);
684 this.onInstanceSelectedUpdate(this.instances[0]);
685 this.setInputTabIndication(response.length);
686 this.checkedPropertiesCount = 0;
687 this.checkedChildPropertiesCount = 0;
688 _.forEach(response, (input: InputBEModel) => {
689 const newInput: InputFEModel = new InputFEModel(input);
690 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
691 this.inputs.push(newInput);
692 this.updatePropertyValueAfterDeclare(newInput);
694 if (isCapabilityPropertyChanged) {
695 this.reloadInstanceCapabilities();
697 }, error => {}); //ignore error
700 declareListProperties = (): void => {
701 // get selected properties
702 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
703 let selectedGroupInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
704 let selectedPolicyInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
705 let selectedComponentInstancesInputs: InstanceBePropertiesMap = new InstanceBePropertiesMap();
706 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
707 let propertyNameList: Array<string> = [];
710 angular.forEach(instancesIds, (instanceId: string): void => {
712 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
713 let checkedProperties: PropertyBEModel[] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
715 if (selectedInstanceData instanceof ComponentInstance) {
716 if (!this.isInput(selectedInstanceData.originType)) {
717 // convert Property FE model -> Property BE model, extract only checked
718 selectedComponentInstancesProperties[instanceId] = checkedProperties;
720 selectedComponentInstancesInputs[instanceId] = checkedProperties;
722 } else if (selectedInstanceData instanceof GroupInstance) {
723 selectedGroupInstancesProperties[instanceId] = checkedProperties;
724 } else if (selectedInstanceData instanceof PolicyInstance) {
725 selectedPolicyInstancesProperties[instanceId] = checkedProperties;
728 angular.forEach(checkedProperties, (property: PropertyBEModel) => {
729 propertyNameList.push(property.name);
733 let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties);
735 let modalTitle = 'Declare Properties as List Input';
736 const modal = this.modalService.createCustomModal(new ModalModel(
738 modalTitle, /* title */
743 'blue', /* css class */
744 () => { /* callback */
745 let content:any = modal.instance.dynamicContent.instance;
748 let reglistInput: InstanceBePropertiesMap = new InstanceBePropertiesMap();
749 let typelist: any = PROPERTY_TYPES.LIST;
750 let uniID: any = insId;
751 let boolfalse: any = false;
752 let required: any = content.propertyModel.required;
756 "type": content.propertyModel.simpleType,
760 let schemaProp :any = {
761 "type": content.propertyModel.simpleType,
765 reglistInput.description = content.propertyModel.description;
766 reglistInput.name = content.propertyModel.name;
767 reglistInput.type = typelist;
768 reglistInput.schemaType = content.propertyModel.simpleType;
769 reglistInput.instanceUniqueId = uniID;
770 reglistInput.uniqueId = uniID;
771 reglistInput.required = required;
772 reglistInput.schema = schem;
773 reglistInput.schemaProperty = schemaProp;
776 componentInstInputsMap: content.inputsToCreate,
777 listInput: reglistInput
780 this.topologyTemplateService
781 .createListInput(this.component, input, this.isSelf())
782 .subscribe(response => {
783 this.setInputTabIndication(response.length);
784 this.checkedPropertiesCount = 0;
785 this.checkedChildPropertiesCount = 0;
786 _.forEach(response, (input: InputBEModel) => {
787 let newInput: InputFEModel = new InputFEModel(input);
788 this.inputsUtils.resetInputDefaultValue(newInput, input.defaultValue);
789 this.inputs.push(newInput);
790 // create list input does not return updated properties info, so need to reload
791 //this.updatePropertyValueAfterDeclare(newInput);
792 // Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
793 this.changeSelectedInstance(this.selectedInstanceData);
795 modal.instance.close();
797 }, error => {}); //ignore error
800 /*, getDisabled: function */
802 new ButtonModel('Cancel', 'outline grey', () => {
803 modal.instance.close();
808 // 3rd arg is passed to DeclareListComponent instance
809 this.modalService.addDynamicContentToModal(modal, DeclareListComponent, {properties: inputsToCreate, propertyNameList: propertyNameList});
810 modal.instance.open();
813 /*** DECLARE PROPERTIES/POLICIES ***/
814 declarePropertiesToPolicies = (): void => {
815 let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap();
816 let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []);
818 angular.forEach(instancesIds, (instanceId: string): void => {
819 let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId);
820 if (selectedInstanceData instanceof ComponentInstance) {
821 if (!this.isInput(selectedInstanceData.originType)) {
822 selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]);
827 let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null);
828 this.loadingPolicies = true;
830 this.topologyTemplateService
831 .createPolicy(this.component, policiesToCreate, this.isSelf())
832 .subscribe(response => {
833 this.setPolicyTabIndication(response.length);
834 this.checkedPropertiesCount = 0;
835 this.displayPoliciesAsDeclared(response);
836 this.loadingPolicies = false;
841 displayPoliciesAsDeclared = (policies) => {
842 _.forEach(policies, (policy: any) => {
843 let newPolicy: InputFEModel = new InputFEModel(policy);
844 this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue);
845 newPolicy.relatedPropertyName = policy.name;
846 newPolicy.relatedPropertyValue = policy.value;
847 this.updatePropertyValueAfterDeclare(newPolicy);
848 this.policies.push(policy);
852 saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => {
853 return new Promise((resolve, reject) => {
854 if (!this.isValidChangedData) {
855 reject('Changed data is invalid - cannot save!');
858 if (!this.changedData.length) {
863 // make request and its handlers
865 let handleSuccess, handleError;
866 let changedInputsProperties = [], changedCapabilitiesProperties = [];
867 if (this.isPropertiesTabSelected) {
868 const changedProperties: PropertyBEModel[] = this.changedData.map((changedProp) => {
869 changedProp = <PropertyFEModel>changedProp;
870 const propBE = new PropertyBEModel(changedProp);
871 propBE.toscaPresentation = new ToscaPresentationData();
872 propBE.toscaPresentation.ownerId = changedProp.parentUniqueId;
873 propBE.value = changedProp.getJSONValue();
874 propBE.name = changedProp.origName || changedProp.name;
875 delete propBE.origName;
878 changedCapabilitiesProperties = _.filter(changedProperties, prop => this.isCapabilityProperty(prop));
880 if (this.selectedInstanceData instanceof ComponentInstance) {
881 if (this.isInput(this.selectedInstanceData.originType)) {
882 changedInputsProperties = _.filter(changedProperties, prop => !this.isCapabilityProperty(prop));
883 if (changedInputsProperties.length && changedCapabilitiesProperties.length) {
884 request = Observable.forkJoin(
885 this.componentInstanceServiceNg2.updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties),
886 this.componentInstanceServiceNg2.updateInstanceProperties(this.component.componentType, this.component.uniqueId,
887 this.selectedInstanceData.uniqueId, changedCapabilitiesProperties)
890 else if (changedInputsProperties.length) {
891 request = this.componentInstanceServiceNg2
892 .updateInstanceInputs(this.component, this.selectedInstanceData.uniqueId, changedInputsProperties);
894 else if (changedCapabilitiesProperties.length) {
895 request = this.componentInstanceServiceNg2
896 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedCapabilitiesProperties);
898 handleSuccess = (response) => {
899 // reset each changed property with new value and remove it from changed properties list
900 response.forEach((resInput) => {
901 const changedProp = <PropertyFEModel>this.changedData.shift();
902 this.propertiesUtils.resetPropertyValue(changedProp, resInput.value);
907 request = this.topologyTemplateService.updateServiceProperties(this.component.uniqueId, _.map(changedProperties, cp => {
908 delete cp.constraints;
912 request = this.componentInstanceServiceNg2
913 .updateInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
915 handleSuccess = (response) => {
916 // reset each changed property with new value and remove it from changed properties list
917 response.forEach((resProp) => {
918 const changedProp = <PropertyFEModel>this.changedData.shift();
919 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
924 } else if (this.selectedInstanceData instanceof GroupInstance) {
925 request = this.componentInstanceServiceNg2
926 .updateComponentGroupInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
927 handleSuccess = (response) => {
928 // reset each changed property with new value and remove it from changed properties list
929 response.forEach((resProp) => {
930 const changedProp = <PropertyFEModel>this.changedData.shift();
931 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
935 } else if (this.selectedInstanceData instanceof PolicyInstance) {
936 request = this.componentInstanceServiceNg2
937 .updateComponentPolicyInstanceProperties(this.component.componentType, this.component.uniqueId, this.selectedInstanceData.uniqueId, changedProperties);
938 handleSuccess = (response) => {
939 // reset each changed property with new value and remove it from changed properties list
940 response.forEach((resProp) => {
941 const changedProp = <PropertyFEModel>this.changedData.shift();
942 this.propertiesUtils.resetPropertyValue(changedProp, resProp.value);
947 } else if (this.isInputsTabSelected) {
949 const changedInputs: InputBEModel[] = this.changedData.map((changedInput) => {
950 changedInput = <InputFEModel>changedInput;
951 const inputBE = new InputBEModel(changedInput);
952 inputBE.defaultValue = changedInput.getJSONDefaultValue();
955 request = this.componentServiceNg2
956 .updateComponentInputs(this.component, changedInputs);
957 handleSuccess = (response) => {
958 // reset each changed property with new value and remove it from changed properties list
959 response.forEach((resInput) => {
960 const changedInput = <InputFEModel>this.changedData.shift();
961 this.inputsUtils.resetInputDefaultValue(changedInput, resInput.defaultValue);
962 changedInput.required = resInput.required;
963 changedInput.requiredOrig = resInput.required;
968 this.savingChangedData = true;
971 this.savingChangedData = false;
972 if (changedCapabilitiesProperties.length) {
973 this.reloadInstanceCapabilities();
975 handleSuccess && handleSuccess(response);
976 this.updateHasChangedData();
980 this.savingChangedData = false;
981 handleError && handleError(error);
982 this.updateHasChangedData();
989 reloadInstanceCapabilities = (): void => {
990 let currentInstanceIndex = _.findIndex(this.instances, instance => instance.uniqueId == this.selectedInstanceData.uniqueId);
991 this.componentServiceNg2.getComponentResourceInstances(this.component).subscribe(result => {
992 let instanceCapabilitiesData: CapabilitiesGroup = _.reduce(result.componentInstances, (res, instance) => {
993 if (instance.uniqueId === this.selectedInstanceData.uniqueId) {
994 return instance.capabilities;
997 }, new CapabilitiesGroup());
998 (<ComponentInstance>this.instances[currentInstanceIndex]).capabilities = instanceCapabilitiesData;
1002 reverseChangedData = ():void => {
1003 // make reverse item handler
1004 let handleReverseItem;
1005 if (this.isPropertiesTabSelected) {
1006 handleReverseItem = (changedItem) => {
1007 changedItem = <PropertyFEModel>changedItem;
1008 this.propertiesUtils.resetPropertyValue(changedItem, changedItem.value);
1010 } else if (this.isInputsTabSelected) {
1011 handleReverseItem = (changedItem) => {
1012 changedItem = <InputFEModel>changedItem;
1013 this.inputsUtils.resetInputDefaultValue(changedItem, changedItem.defaultValue);
1014 changedItem.resetMetadata();
1015 changedItem.required = changedItem.requiredOrig;
1019 this.changedData.forEach(handleReverseItem);
1020 this.changedData = [];
1021 this.updateHasChangedData();
1024 updateHasChangedData = ():boolean => {
1025 const curHasChangedData:boolean = (this.changedData.length > 0);
1026 if (curHasChangedData !== this.hasChangedData) {
1027 this.hasChangedData = curHasChangedData;
1028 if(this.hasChangedData) {
1029 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.hasChangedData, this.showUnsavedChangesAlert);
1031 this.eventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, false);
1034 return this.hasChangedData;
1037 doSaveChangedData = (onSuccessFunction?:Function, onError?:Function):void => {
1038 this.saveChangedData().then(
1040 this.notification.success({
1041 message: 'Successfully saved changes',
1044 if(onSuccessFunction) onSuccessFunction();
1047 this.notification.error({
1048 message: 'Failed to save changes!',
1051 if(onError) onError();
1056 showUnsavedChangesAlert = ():Promise<any> => {
1057 let modalTitle:string;
1058 if (this.isPropertiesTabSelected) {
1059 modalTitle = `Unsaved properties for ${this.selectedInstanceData.name}`;
1060 } else if (this.isInputsTabSelected) {
1061 modalTitle = `Unsaved inputs for ${this.component.name}`;
1064 return new Promise<any>((resolve, reject) => {
1065 const modal = this.ModalServiceSdcUI.openCustomModal(
1069 type: SdcUiCommon.ModalType.custom,
1070 testId: "navigate-modal",
1073 {id: 'cancelButton', text: 'Cancel', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => reject()},
1074 {id: 'discardButton', text: 'Discard', type: SdcUiCommon.ButtonType.secondary, size: 'xsm', closeModal: true, callback: () => { this.reverseChangedData(); resolve()}},
1075 {id: 'saveButton', text: 'Save', type: SdcUiCommon.ButtonType.primary, size: 'xsm', closeModal: true, disabled: !this.isValidChangedData, callback: () => this.doSaveChangedData(resolve, reject)}
1076 ] as SdcUiCommon.IModalButtonComponent[]
1077 } as SdcUiCommon.IModalConfig, UnsavedChangesComponent, {isValidChangedData: this.isValidChangedData});
1082 updatePropertyValueAfterDeclare = (input: InputFEModel) => {
1083 if (this.instanceFePropertiesMap[input.instanceUniqueId]) {
1084 const instanceName = input.instanceUniqueId.slice(input.instanceUniqueId.lastIndexOf('.') + 1);
1085 const propertyForUpdatindVal = _.find(this.instanceFePropertiesMap[input.instanceUniqueId], (feProperty: PropertyFEModel) => {
1086 return feProperty.name == input.relatedPropertyName &&
1087 (feProperty.name == input.relatedPropertyName || input.name === instanceName.concat('_').concat(feProperty.name.replace(/[.]/g, '_')));
1089 const inputPath = (input.inputPath && input.inputPath != propertyForUpdatindVal.name) ? input.inputPath : undefined;
1090 propertyForUpdatindVal.setAsDeclared(inputPath); //set prop as declared before assigning value
1091 this.propertiesService.disableRelatedProperties(propertyForUpdatindVal, inputPath);
1092 this.propertiesUtils.resetPropertyValue(propertyForUpdatindVal, input.relatedPropertyValue, inputPath);
1096 //used for declare button, to keep count of newly checked properties (and ignore declared properties)
1097 updateCheckedPropertyCount = (increment: boolean): void => {
1098 this.checkedPropertiesCount += (increment) ? 1 : -1;
1099 console.debug("CheckedProperties count is now.... " + this.checkedPropertiesCount);
1102 updateCheckedChildPropertyCount = (increment: boolean): void => {
1103 this.checkedChildPropertiesCount += (increment) ? 1 : -1;
1106 setInputTabIndication = (numInputs: number): void => {
1107 this.propertyInputTabs.setTabIndication('Inputs', numInputs);
1110 setPolicyTabIndication = (numPolicies: number): void => {
1111 this.propertyInputTabs.setTabIndication('Policies', numPolicies);
1114 resetUnsavedChangesForInput = (input:InputFEModel) => {
1115 this.inputsUtils.resetInputDefaultValue(input, input.defaultValue);
1116 this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId);
1117 this.updateHasChangedData();
1120 deleteInput = (input: InputFEModel) => {
1121 //reset any unsaved changes to the input before deleting it
1122 this.resetUnsavedChangesForInput(input);
1124 console.debug("==>" + this.constructor.name + ": deleteInput");
1125 let inputToDelete = new InputBEModel(input);
1127 this.componentServiceNg2
1128 .deleteInput(this.component, inputToDelete)
1129 .subscribe(response => {
1130 this.inputs = this.inputs.filter(input => input.uniqueId !== response.uniqueId);
1132 //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead!
1133 this.changeSelectedInstance(this.selectedInstanceData);
1134 // let instanceFeProperties = this.instanceFePropertiesMap[this.getInstanceUniqueId(input.instanceName)];
1136 // if (instanceFeProperties) {
1137 // let propToEnable: PropertyFEModel = instanceFeProperties.find((prop) => {
1138 // return prop.name == input.propertyName;
1141 // if (propToEnable) {
1142 // if (propToEnable.name == response.inputPath) response.inputPath = null;
1143 // propToEnable.setNonDeclared(response.inputPath);
1144 // //this.propertiesUtils.resetPropertyValue(propToEnable, newValue, response.inputPath);
1145 // this.propertiesService.undoDisableRelatedProperties(propToEnable, response.inputPath);
1148 }, error => {}); //ignore error
1151 deletePolicy = (policy: PolicyInstance) => {
1152 this.loadingPolicies = true;
1153 this.topologyTemplateService
1154 .deletePolicy(this.component, policy)
1155 .subscribe((response) => {
1156 this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId);
1157 this.changeSelectedInstance(this.selectedInstanceData);
1158 this.loadingPolicies = false;
1162 deleteProperty = (property: PropertyFEModel) => {
1163 const propertyToDelete = new PropertyFEModel(property);
1164 this.loadingProperties = true;
1165 const feMap = this.instanceFePropertiesMap;
1166 this.topologyTemplateService
1167 .deleteServiceProperty(this.component.uniqueId, propertyToDelete)
1168 .subscribe((response) => {
1169 const props = feMap[this.component.uniqueId];
1170 props.splice(props.findIndex(p => p.uniqueId === response),1);
1171 this.loadingProperties = false;
1173 this.loadingProperties = false;
1174 console.error(error);
1178 /*** addProperty ***/
1179 addProperty = (model: string) => {
1180 this.loadDataTypesByComponentModel(model)
1181 let modalTitle = 'Add Property';
1182 let modal = this.modalService.createCustomModal(new ModalModel(
1187 new ButtonModel('Save', 'blue', () => {
1188 modal.instance.dynamicContent.instance.isLoading = true;
1189 const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel;
1190 this.topologyTemplateService.createServiceProperty(this.component.uniqueId, newProperty)
1191 .subscribe((response) => {
1192 modal.instance.dynamicContent.instance.isLoading = false;
1193 const newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response);
1194 this.instanceFePropertiesMap[this.component.uniqueId].push(newProp);
1195 modal.instance.close();
1197 modal.instance.dynamicContent.instance.isLoading = false;
1198 this.notification.error({
1199 message: 'Failed to add property:' + error,
1203 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1204 new ButtonModel('Cancel', 'outline grey', () => {
1205 modal.instance.close();
1210 modal.instance.open();
1211 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1216 let modalTitle = 'Add Input';
1217 let modal = this.modalService.createCustomModal(new ModalModel(
1222 new ButtonModel('Save', 'blue', () => {
1223 modal.instance.dynamicContent.instance.isLoading = true;
1224 const newInput: InputBEModel = modal.instance.dynamicContent.instance.propertyModel;
1225 this.topologyTemplateService.createServiceInput(this.component.uniqueId, newInput)
1226 .subscribe((response) => {
1227 modal.instance.dynamicContent.instance.isLoading = false;
1228 const newInputProp: InputFEModel = this.inputsUtils.convertInputBEToInputFE(response);
1229 this.inputs.push(newInputProp);
1230 modal.instance.close();
1232 modal.instance.dynamicContent.instance.isLoading = false;
1233 this.notification.error({
1234 message: 'Failed to add input:' + error,
1238 }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()),
1239 new ButtonModel('Cancel', 'outline grey', () => {
1240 modal.instance.close();
1245 this.modalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {});
1246 modal.instance.open();
1249 /*** SEARCH RELATED FUNCTIONS ***/
1250 searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => {
1251 let instanceBePropertiesMap:InstanceBePropertiesMap;
1252 this.componentServiceNg2
1253 .filterComponentInstanceProperties(this.component, filterData)
1254 .subscribe((response) => {
1255 this.processInstancePropertiesResponse(response, false);
1256 this.hierarchyPropertiesDisplayOptions.searchText = filterData.propertyName;//mark results in tree
1257 this.searchPropertyName = filterData.propertyName;//mark in table
1258 this.hierarchyNavTabs.triggerTabChange('Composition');
1259 this.propertiesNavigationData = [];
1260 this.displayClearSearch = true;
1261 }, (error) => {}); //ignore error
1265 clearSearch = () => {
1266 this.instancesNavigationData = this.instances;
1267 this.searchPropertyName = "";
1268 this.hierarchyPropertiesDisplayOptions.searchText = "";
1269 this.displayClearSearch = false;
1270 this.advanceSearch.clearAll();
1271 this.searchQuery = '';
1274 clickOnClearSearch = () => {
1276 this.selectFirstInstanceByDefault();
1277 this.hierarchyNavTabs.triggerTabChange('Composition');
1280 private isInput = (instanceType:string):boolean =>{
1281 return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC || instanceType === ResourceType.CR;
1284 loadDataTypesByComponentModel(model:string) {
1285 this.propertyCreatorComponent.filterDataTypesByModel(model);