2 * Copyright © 2016-2018 European Support Limited
3 * Modification Copyright (C) 2022 Nordix Foundation.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing
15 * permissions and limitations under the License.
18 import {Component, ComponentRef, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
19 import {ButtonModel, ComponentInstance, InputBEModel, ModalModel, PropertyBEModel, PropertyModel,} from 'app/models';
20 import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
21 import {FilterType, ServiceDependenciesEditorComponent} from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component';
22 import {ModalService} from 'app/ng2/services/modal.service';
23 import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response';
24 import {TranslateService} from 'app/ng2/shared/translator/translate.service';
25 import {ComponentMetadata} from '../../../../models/component-metadata';
26 import {ServiceInstanceObject} from '../../../../models/service-instance-properties-and-interfaces';
27 import {TopologyTemplateService} from '../../../services/component-services/topology-template.service';
28 import {ToscaFilterConstraintType} from "../../../../models/tosca-filter-constraint-type.enum";
29 import {CompositionService} from "../../../pages/composition/composition.service";
30 import {FilterConstraint} from "app/models/filter-constraint";
31 import {PropertyFilterConstraintUi} from "../../../../models/ui-models/property-filter-constraint-ui";
32 import {ConstraintOperatorType, FilterConstraintHelper} from "../../../../utils/filter-constraint-helper";
33 import {CustomToscaFunction} from "../../../../models/default-custom-functions";
35 export enum SourceType {
38 TOSCA_FUNCTION = 'tosca_function',
39 TOSCA_FUNCTION_LIST = 'tosca_function_list'
43 static removeDirectiveModalTitle: string;
44 static removeDirectiveModalText: string;
45 static updateDirectiveModalTitle: string;
46 static updateDirectiveModalText: string;
47 static modalApprove: string;
48 static modalCancel: string;
49 static modalCreate: string;
50 static modalSave: string;
51 static modalDelete: string;
52 static addNodeFilterTxt: string;
53 static updateNodeFilterTxt: string;
54 static deleteNodeFilterTxt: string;
55 static deleteNodeFilterMsg: string;
56 static validateCapabilitiesTxt: string
57 static validateCapabilitiesMsg: string
58 static validateNodePropertiesTxt: string
59 static validateNodePropertiesMsg: string
61 public static translateTexts(translateService) {
62 I18nTexts.removeDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TITLE');
63 I18nTexts.removeDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TEXT');
64 I18nTexts.updateDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TITLE');
65 I18nTexts.updateDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TEXT');
66 I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE');
67 I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
68 I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
69 I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
70 I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
71 I18nTexts.addNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_ADD_NODE_FILTER');
72 I18nTexts.updateNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_NODE_FILTER');
73 I18nTexts.deleteNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER');
74 I18nTexts.deleteNodeFilterMsg = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER_MSG');
75 I18nTexts.validateCapabilitiesTxt = translateService.translate('VALIDATE_CAPABILITIES_TXT');
76 I18nTexts.validateCapabilitiesMsg = translateService.translate('VALIDATE_CAPABILITIES_MSG');
77 I18nTexts.validateNodePropertiesTxt = translateService.translate('VALIDATE_NODE_PROPERTIES_TXT');
78 I18nTexts.validateNodePropertiesMsg = translateService.translate('VALIDATE_NODE_PROPERTIES_MSG');
83 selector: 'service-dependencies',
84 templateUrl: './service-dependencies.component.html',
85 styleUrls: ['service-dependencies.component.less'],
86 providers: [ModalService, TranslateService]
89 export class ServiceDependenciesComponent implements OnInit, OnChanges {
90 modalInstance: ComponentRef<ModalComponent>;
93 parentServiceInputs: InputBEModel[] = [];
94 parentServiceProperties: PropertyBEModel[] = [];
95 constraintProperties: FilterConstraint[] = [];
96 constraintPropertyLabels: string[] = [];
97 constraintCapabilities: PropertyFilterConstraintUi[] = [];
98 constraintCapabilityLabels: string[] = [];
100 capabilities: string = ToscaFilterConstraintType.CAPABILITIES;
101 properties: string = ToscaFilterConstraintType.PROPERTIES;
102 private componentInstancesConstraints: FilterConstraint[] = [];
104 customToscaFunctions: Array<CustomToscaFunction>;
106 @Input() readonly: boolean;
107 @Input() compositeService: ComponentMetadata;
108 @Input() currentServiceInstance: ComponentInstance;
109 @Input() selectedInstanceSiblings: ServiceInstanceObject[];
110 @Input() selectedInstanceConstraints: FilterConstraint[] = [];
111 @Input() selectedInstanceProperties: PropertyBEModel[] = [];
112 @Input() componentInstanceCapabilitiesMap: Map<string, PropertyModel[]>;
113 @Output() updateRulesListEvent: EventEmitter<FilterConstraint[]> = new EventEmitter<FilterConstraint[]>();
114 @Output() updateNodeFilterProperties: EventEmitter<FilterConstraint[]> = new EventEmitter<FilterConstraint[]>();
115 @Output() updateNodeFilterCapabilities: EventEmitter<PropertyFilterConstraintUi[]> = new EventEmitter<PropertyFilterConstraintUi[]>();
116 @Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter();
117 @Output() dependencyStatus = new EventEmitter<boolean>();
119 constructor(private topologyTemplateService: TopologyTemplateService,
120 private modalServiceNg2: ModalService,
121 private translateService: TranslateService,
122 private compositionService: CompositionService) {
126 this.isLoading = false;
127 this.operatorTypes = [
128 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.GREATER_THAN), value: ConstraintOperatorType.GREATER_THAN},
129 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.LESS_THAN), value: ConstraintOperatorType.LESS_THAN},
130 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.EQUAL), value: ConstraintOperatorType.EQUAL},
131 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.GREATER_OR_EQUAL), value: ConstraintOperatorType.GREATER_OR_EQUAL},
132 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.LESS_OR_EQUAL), value: ConstraintOperatorType.LESS_OR_EQUAL},
133 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.LENGTH), value: ConstraintOperatorType.LENGTH},
134 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.IN_RANGE), value: ConstraintOperatorType.IN_RANGE},
135 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.MIN_LENGTH), value: ConstraintOperatorType.MIN_LENGTH},
136 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.MAX_LENGTH), value: ConstraintOperatorType.MAX_LENGTH},
137 {label: FilterConstraintHelper.convertToSymbol(ConstraintOperatorType.PATTERN), value: ConstraintOperatorType.PATTERN}
139 this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId)
140 .subscribe((result: ComponentGenericResponse) => {
141 this.parentServiceInputs = result.inputs;
142 this.parentServiceProperties = result.properties;
144 this.initCustomToscaFunctions();
145 this.loadNodeFilter();
146 this.translateService.languageChangedObservable.subscribe((lang) => {
147 I18nTexts.translateTexts(this.translateService);
151 private initCustomToscaFunctions() {
152 if (!this.customToscaFunctions) {
153 this.customToscaFunctions = [];
154 this.topologyTemplateService.getDefaultCustomFunction().toPromise().then((data) => {
155 for (let customFunction of data) {
156 this.customToscaFunctions.push(new CustomToscaFunction(customFunction));
162 ngOnChanges(changes): void {
163 if (changes.currentServiceInstance) {
164 this.currentServiceInstance = changes.currentServiceInstance.currentValue;
165 this.isDependent = this.currentServiceInstance.isDependent();
167 if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
168 this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
169 this.loadNodeFilter();
173 private getActualDirectiveValue = (): string[] => {
174 return this.currentServiceInstance.directives.length > 0 ? this.currentServiceInstance.directives : [];
177 public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => {
178 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
179 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
180 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.removeDirectiveModalTitle,
181 I18nTexts.removeDirectiveModalText, [actionButton, cancelButton]);
182 this.loadNodeFilter();
183 return this.modalServiceNg2.createCustomModal(modalModel);
186 private loadNodeFilter = (): void => {
187 this.topologyTemplateService.getServiceFilterConstraints(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((response) => {
188 if (response.nodeFilterforNode && response.nodeFilterforNode[this.currentServiceInstance.uniqueId]) {
189 this.componentInstancesConstraints = response.nodeFilterforNode;
190 this.constraintProperties = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].properties;
191 this.buildConstraintPropertyLabels();
192 this.constraintCapabilities = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].capabilities;
193 this.buildCapabilityFilterConstraintLabels();
198 onUncheckDependency = (): void => {
199 this.modalServiceNg2.closeCurrentModal();
200 this.isLoading = true;
201 const isDepOrig = this.isDependent;
202 const rulesListOrig = this.componentInstancesConstraints;
203 this.currentServiceInstance.unmarkAsDependent(this.getActualDirectiveValue());
204 this.updateComponentInstance(isDepOrig, rulesListOrig);
207 onCloseRemoveDependencyModal = (): void => {
208 this.isDependent = true;
209 this.modalServiceNg2.closeCurrentModal();
212 onAddDirectives(directives: string[]): void {
213 this.isEditable = false;
214 this.setDirectiveValue(directives);
215 const rulesListOrig = this.componentInstancesConstraints;
216 this.constraintProperties = [];
217 this.constraintPropertyLabels = [];
218 this.constraintCapabilities = [];
219 this.constraintCapabilityLabels = [];
220 this.loadNodeFilter();
221 this.updateComponentInstance(this.isDependent, rulesListOrig);
224 private onRemoveDirective(): void {
225 this.openRemoveDependencyModal().instance.open();
226 this.constraintProperties = [];
227 this.constraintPropertyLabels = [];
228 this.constraintCapabilities = [];
229 this.constraintCapabilityLabels = [];
232 private onEditDirectives(): void {
233 this.isEditable = true;
236 private setDirectiveValue(newDirectiveValues: string[]): void {
237 this.currentServiceInstance.setDirectiveValue(newDirectiveValues);
240 updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: FilterConstraint[]): void {
241 this.isLoading = true;
242 this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId,
243 this.compositeService.componentType,
244 this.currentServiceInstance)
245 .subscribe((updatedServiceIns: ComponentInstance) => {
246 const selectedComponentInstance = this.compositionService.getComponentInstances()
247 .find(componentInstance => componentInstance.uniqueId == this.currentServiceInstance.uniqueId);
248 selectedComponentInstance.directives = updatedServiceIns.directives;
249 this.currentServiceInstance = new ComponentInstance(updatedServiceIns);
250 this.isDependent = this.currentServiceInstance.isDependent();
251 this.dependencyStatus.emit(this.isDependent);
252 if (this.isDependent) {
253 this.loadRulesListEvent.emit();
255 this.isLoading = false;
257 this.isDependent = isDependentOrigVal;
258 this.componentInstancesConstraints = rulesListOrig;
259 this.isLoading = false;
260 console.error('An error has occurred.', err);
264 onAddNodeFilter = (): void => {
265 if (!this.selectedInstanceProperties) {
266 this.modalServiceNg2.openAlertModal(I18nTexts.validateNodePropertiesTxt, I18nTexts.validateNodePropertiesMsg);
268 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
269 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilter(this.properties), this.getDisabled);
270 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
271 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
272 this.modalServiceNg2.addDynamicContentToModalAndBindInputs(
274 ServiceDependenciesEditorComponent,
276 'currentServiceName': this.currentServiceInstance.name,
277 'operatorTypes': this.operatorTypes,
278 'compositeServiceName': this.compositeService.name,
279 'parentServiceInputs': this.parentServiceInputs,
280 'parentServiceProperties': this.parentServiceProperties,
281 'selectedInstanceProperties': this.selectedInstanceProperties,
282 'customToscaFunctions': this.customToscaFunctions,
283 'filterType': FilterType.PROPERTY,
286 this.modalInstance.instance.open();
290 onAddNodeFilterCapabilities = (): void => {
291 if (this.componentInstanceCapabilitiesMap.size == 0) {
292 this.modalServiceNg2.openAlertModal(I18nTexts.validateCapabilitiesTxt, I18nTexts.validateCapabilitiesMsg);
294 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
295 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilterCapabilities(this.capabilities), this.getDisabled);
296 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
297 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
298 this.modalServiceNg2.addDynamicContentToModalAndBindInputs(
300 ServiceDependenciesEditorComponent,
302 'currentServiceName': this.currentServiceInstance.name,
303 'operatorTypes': this.operatorTypes,
304 'compositeServiceName': this.compositeService.name,
305 'parentServiceInputs': this.parentServiceInputs,
306 'parentServiceProperties': this.parentServiceProperties,
307 'selectedInstanceProperties': this.selectedInstanceProperties,
308 'capabilityNameAndPropertiesMap': this.componentInstanceCapabilitiesMap,
309 'filterType': FilterType.CAPABILITY,
312 this.modalInstance.instance.open();
316 createNodeFilter = (constraintType: string): void => {
317 this.customToscaFunctions = this.modalInstance.instance.dynamicContent.instance.customToscaFunctions;
318 this.isLoading = true;
319 this.topologyTemplateService.createServiceFilterConstraints(
320 this.compositeService.uniqueId,
321 this.currentServiceInstance.uniqueId,
322 new FilterConstraint(this.modalInstance.instance.dynamicContent.instance.currentRule),
323 this.compositeService.componentType,
325 ).subscribe( (response) => {
326 this.emitEventOnChanges(constraintType, response);
327 this.isLoading = false;
329 this.isLoading = false;
331 this.modalServiceNg2.closeCurrentModal();
334 createNodeFilterCapabilities = (constraintType: string): void => {
335 this.isLoading = true;
336 this.topologyTemplateService.createServiceFilterCapabilitiesConstraints(
337 this.compositeService.uniqueId,
338 this.currentServiceInstance.uniqueId,
339 new PropertyFilterConstraintUi(this.modalInstance.instance.dynamicContent.instance.currentRule),
340 this.compositeService.componentType,
342 ).subscribe( (response) => {
343 this.emitEventOnChanges(constraintType, response);
344 this.isLoading = false;
346 this.isLoading = false;
348 this.modalServiceNg2.closeCurrentModal();
351 onSelectNodeFilterCapability(constraintType: string, index: number): void {
352 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
353 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilterCapability(constraintType, index), this.getDisabled);
354 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
355 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
356 const selectedFilterConstraint = new PropertyFilterConstraintUi(this.constraintCapabilities[index]);
357 this.modalServiceNg2.addDynamicContentToModalAndBindInputs(
359 ServiceDependenciesEditorComponent,
361 'filterConstraint': selectedFilterConstraint,
362 'currentServiceName': this.currentServiceInstance.name,
363 'operatorTypes': this.operatorTypes,
364 'compositeServiceName': this.compositeService.name,
365 'parentServiceInputs': this.parentServiceInputs,
366 'parentServiceProperties': this.parentServiceProperties,
367 'selectedInstanceProperties': this.selectedInstanceProperties,
368 'capabilityNameAndPropertiesMap': this.componentInstanceCapabilitiesMap,
369 'filterType': FilterType.CAPABILITY,
372 this.modalInstance.instance.open();
375 onSelectNodeFilter(constraintType: string, index: number): void {
376 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
377 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilter(constraintType, index), this.getDisabled);
378 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
379 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
380 const selectedFilterConstraint = new PropertyFilterConstraintUi(this.constraintProperties[index]);
381 this.modalServiceNg2.addDynamicContentToModalAndBindInputs(
383 ServiceDependenciesEditorComponent,
385 'filterConstraint': selectedFilterConstraint,
386 'currentServiceName': this.currentServiceInstance.name,
387 'operatorTypes': this.operatorTypes,
388 'compositeServiceName': this.compositeService.name,
389 'parentServiceInputs': this.parentServiceInputs,
390 'parentServiceProperties': this.parentServiceProperties,
391 'selectedInstanceProperties': this.selectedInstanceProperties,
392 'customToscaFunctions': this.customToscaFunctions,
393 'filterType': FilterType.PROPERTY
397 this.modalInstance.instance.open();
400 getDisabled = (): boolean => {
401 return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
404 updateNodeFilter = (constraintType: string, index: number): void => {
405 this.isLoading = true;
406 this.topologyTemplateService.updateServiceFilterConstraints(
407 this.compositeService.uniqueId,
408 this.currentServiceInstance.uniqueId,
409 new FilterConstraint(this.modalInstance.instance.dynamicContent.instance.currentRule),
410 this.compositeService.componentType,
413 ).subscribe((response) => {
414 this.emitEventOnChanges(constraintType, response);
415 this.isLoading = false;
417 this.isLoading = false;
419 this.modalServiceNg2.closeCurrentModal();
422 updateNodeFilterCapability = (constraintType: string, index: number): void => {
423 this.isLoading = true;
424 this.topologyTemplateService.updateServiceFilterCapabilitiesConstraint(
425 this.compositeService.uniqueId,
426 this.currentServiceInstance.uniqueId,
427 new PropertyFilterConstraintUi(this.modalInstance.instance.dynamicContent.instance.currentRule),
428 this.compositeService.componentType,
431 ).subscribe((response) => {
432 this.emitEventOnChanges(constraintType, response);
433 this.isLoading = false;
435 this.isLoading = false;
437 this.modalServiceNg2.closeCurrentModal();
440 onDeleteNodeFilter = (constraintType: string, index: number): void => {
441 this.isLoading = true;
442 this.topologyTemplateService.deleteServiceFilterConstraints(
443 this.compositeService.uniqueId,
444 this.currentServiceInstance.uniqueId,
446 this.compositeService.componentType,
448 ).subscribe( (response) => {
449 this.emitEventOnChanges(constraintType, response);
450 this.isLoading = false;
452 this.isLoading = false;
454 this.modalServiceNg2.closeCurrentModal();
457 private emitEventOnChanges(constraintType: string, response) {
458 if (this.properties === constraintType) {
459 this.updateNodeFilterProperties.emit(response.properties);
460 this.constraintProperties = response.properties;
461 this.buildConstraintPropertyLabels();
463 this.updateNodeFilterCapabilities.emit(response.capabilities);
464 this.constraintCapabilities = response.capabilities;
465 this.buildCapabilityFilterConstraintLabels();
469 openDeleteModal = (constraintType: string, index: number): void => {
470 this.modalServiceNg2.createActionModal(I18nTexts.deleteNodeFilterTxt, I18nTexts.deleteNodeFilterMsg,
471 I18nTexts.modalDelete, () => this.onDeleteNodeFilter(constraintType, index), I18nTexts.modalCancel).instance.open();
474 private buildConstraintPropertyLabels(): void {
475 this.constraintPropertyLabels = [];
476 if (!this.constraintProperties) {
479 this.constraintProperties.forEach(
480 constraint => this.constraintPropertyLabels.push(FilterConstraintHelper.buildFilterConstraintLabel(constraint))
484 private buildCapabilityFilterConstraintLabels(): void {
485 this.constraintCapabilityLabels = [];
486 if (!this.constraintCapabilities) {
489 this.constraintCapabilities.forEach(
490 constraint => this.constraintCapabilityLabels.push(FilterConstraintHelper.buildFilterConstraintLabel(constraint))