2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing
14 * permissions and limitations under the License.
16 import { Component, ComponentRef, EventEmitter, Input, Output } from '@angular/core';
25 import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
26 import { ServiceDependenciesEditorComponent } from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component';
27 import { ModalService } from 'app/ng2/services/modal.service';
28 import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
29 import { TranslateService } from 'app/ng2/shared/translator/translate.service';
30 import { ComponentMetadata } from '../../../../models/component-metadata';
31 import { ServiceInstanceObject } from '../../../../models/service-instance-properties-and-interfaces';
32 import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
33 import {CapabilitiesFilterPropertiesEditorComponent} from "../../../pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.component";
34 import {CapabilitiesConstraintObject} from "../capabilities-constraint/capabilities-constraint.component";
35 import {ToscaFilterConstraintType} from "../../../../models/tosca-filter-constraint-type.enum";
37 export class ConstraintObject {
38 servicePropertyName: string;
39 constraintOperator: string;
44 constructor(input?: any) {
46 this.servicePropertyName = input.servicePropertyName;
47 this.constraintOperator = input.constraintOperator;
48 this.sourceType = input.sourceType;
49 this.sourceName = input.sourceName;
50 this.value = input.value;
55 // tslint:disable-next-line:max-classes-per-file
56 export class ConstraintObjectUI extends ConstraintObject{
57 isValidValue: boolean;
59 constructor(input?: any) {
62 this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== '';
66 public updateValidity(isValidValue: boolean) {
67 this.isValidValue = isValidValue;
70 public isValidRule(isStatic) {
71 const isValidValue = isStatic ? this.isValidValue : true;
72 return this.servicePropertyName != null && this.servicePropertyName !== ''
73 && this.value != null && this.value !== '' && isValidValue;
77 export const OPERATOR_TYPES = {
79 GREATER_THAN: 'greater_than',
80 LESS_THAN: 'less_than'
83 // tslint:disable-next-line:max-classes-per-file
85 static removeDirectiveModalTitle: string;
86 static removeDirectiveModalText: string;
87 static updateDirectiveModalTitle: string;
88 static updateDirectiveModalText: string;
89 static modalApprove: string;
90 static modalCancel: string;
91 static modalCreate: string;
92 static modalSave: string;
93 static modalDelete: string;
94 static addNodeFilterTxt: string;
95 static updateNodeFilterTxt: string;
96 static deleteNodeFilterTxt: string;
97 static deleteNodeFilterMsg: string;
98 static validateCapabilitiesTxt: string
99 static validateCapabilitiesMsg: string
100 static validateNodePropertiesTxt: string
101 static validateNodePropertiesMsg: string
103 public static translateTexts(translateService) {
104 I18nTexts.removeDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TITLE');
105 I18nTexts.removeDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TEXT');
106 I18nTexts.updateDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TITLE');
107 I18nTexts.updateDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TEXT');
108 I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE');
109 I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
110 I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
111 I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
112 I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
113 I18nTexts.addNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_ADD_NODE_FILTER');
114 I18nTexts.updateNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_NODE_FILTER');
115 I18nTexts.deleteNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER');
116 I18nTexts.deleteNodeFilterMsg = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER_MSG');
117 I18nTexts.validateCapabilitiesTxt = translateService.translate('VALIDATE_CAPABILITIES_TXT');
118 I18nTexts.validateCapabilitiesMsg = translateService.translate('VALIDATE_CAPABILITIES_MSG');
119 I18nTexts.validateNodePropertiesTxt = translateService.translate('VALIDATE_NODE_PROPERTIES_TXT');
120 I18nTexts.validateNodePropertiesMsg = translateService.translate('VALIDATE_NODE_PROPERTIES_MSG');
124 // tslint:disable-next-line:max-classes-per-file
126 selector: 'service-dependencies',
127 templateUrl: './service-dependencies.component.html',
128 styleUrls: ['service-dependencies.component.less'],
129 providers: [ModalService, TranslateService]
132 export class ServiceDependenciesComponent {
133 modalInstance: ComponentRef<ModalComponent>;
134 isDependent: boolean;
136 parentServiceInputs: InputBEModel[] = [];
137 parentServiceProperties: PropertyBEModel[] = [];
138 constraintProperties: ConstraintObject[] = [];
139 constraintCapabilities: CapabilitiesConstraintObject[] = [];
140 operatorTypes: any[];
141 capabilities: string = ToscaFilterConstraintType.CAPABILITIES;
142 properties: string = ToscaFilterConstraintType.PROPERTIES;
143 private componentInstancesConstraints: ConstraintObject[] = [];
144 directiveOptions: string[];
146 @Input() readonly: boolean;
147 @Input() compositeService: ComponentMetadata;
148 @Input() currentServiceInstance: ComponentInstance;
149 @Input() selectedInstanceSiblings: ServiceInstanceObject[];
150 @Input() selectedInstanceConstraints: ConstraintObject[] = [];
151 @Input() selectedInstanceProperties: PropertyBEModel[] = [];
152 @Output() updateRulesListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
153 @Output() updateNodeFilterProperties: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
154 @Output() updateNodeFilterCapabilities: EventEmitter<CapabilitiesConstraintObject[]> = new EventEmitter<CapabilitiesConstraintObject[]>();
155 @Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter();
156 @Output() dependencyStatus = new EventEmitter<boolean>();
158 @Input() componentInstanceCapabilitiesMap: Map<string, PropertyModel[]>;
160 constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) {
164 this.loadDirectives();
165 this.isLoading = false;
166 this.operatorTypes = [
167 {label: '>', value: OPERATOR_TYPES.GREATER_THAN},
168 {label: '<', value: OPERATOR_TYPES.LESS_THAN},
169 {label: '=', value: OPERATOR_TYPES.EQUAL}
171 this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId)
172 .subscribe((result: ComponentGenericResponse) => {
173 this.parentServiceInputs = result.inputs;
174 this.parentServiceProperties = result.properties;
176 this.loadNodeFilter();
177 this.translateService.languageChangedObservable.subscribe((lang) => {
178 I18nTexts.translateTexts(this.translateService);
183 this.topologyTemplateService.getDirectiveList().subscribe((data: string[]) => {
184 this.directiveOptions = data;
188 ngOnChanges(changes) {
189 if (changes.currentServiceInstance) {
190 this.currentServiceInstance = changes.currentServiceInstance.currentValue;
191 this.isDependent = this.currentServiceInstance.isDependent();
193 if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
194 this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
195 this.loadNodeFilter();
199 private getActualDirectiveValue = (): string => {
200 return this.currentServiceInstance.directives.length > 0 ? this.currentServiceInstance.directives[0] : "";
202 public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => {
203 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
204 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
205 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.removeDirectiveModalTitle,
206 I18nTexts.removeDirectiveModalText, [actionButton, cancelButton]);
207 this.loadNodeFilter();
208 return this.modalServiceNg2.createCustomModal(modalModel);
211 public openUpdateDependencyModal = (): ComponentRef<ModalComponent> => {
212 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
213 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
214 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.updateDirectiveModalTitle,
215 I18nTexts.updateDirectiveModalText, [actionButton, cancelButton]);
216 return this.modalServiceNg2.createCustomModal(modalModel);
219 private loadNodeFilter = (): void => {
220 this.topologyTemplateService.getServiceFilterConstraints(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((response) => {
221 if (response.nodeFilterforNode && response.nodeFilterforNode[this.currentServiceInstance.uniqueId]) {
222 this.componentInstancesConstraints = response.nodeFilterforNode;
223 const nodeFilterPropertiesResponse: ConstraintObject[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].properties;
224 this.constraintProperties = nodeFilterPropertiesResponse;
225 const nodeFilterCapabilitiesResponse: CapabilitiesConstraintObject[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].capabilities;
226 this.constraintCapabilities = nodeFilterCapabilitiesResponse;
231 onUncheckDependency = () => {
232 this.modalServiceNg2.closeCurrentModal();
233 this.isLoading = true;
234 const isDepOrig = this.isDependent;
235 const rulesListOrig = this.componentInstancesConstraints;
236 this.currentServiceInstance.unmarkAsDependent(this.getActualDirectiveValue());
237 this.updateComponentInstance(isDepOrig, rulesListOrig);
240 onCloseRemoveDependencyModal = () => {
241 this.isDependent = true;
242 this.modalServiceNg2.closeCurrentModal();
245 onOptionsSelected(event: any) {
246 const newDirectiveValue = event.target.value;
247 if (newDirectiveValue.toLowerCase() !== this.getActualDirectiveValue()) {
248 const rulesListOrig = this.componentInstancesConstraints;
249 this.setDirectiveValue(newDirectiveValue);
250 this.constraintProperties = [];
251 this.constraintCapabilities = [];
252 this.updateComponentInstance(this.isDependent, rulesListOrig);
256 private onRemoveDirective() {
257 this.openRemoveDependencyModal().instance.open();
258 this.constraintProperties = [];
259 this.constraintCapabilities = [];
262 private setDirectiveValue(newDirectiveValue: string) {
263 if (this.isDependent) {
264 this.openUpdateDependencyModal().instance.open();
266 this.currentServiceInstance.setDirectiveValue(newDirectiveValue);
269 updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) {
270 this.isLoading = true;
271 this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId,
272 this.compositeService.componentType,
273 this.currentServiceInstance)
274 .subscribe((updatedServiceIns: ComponentInstance) => {
275 this.currentServiceInstance = new ComponentInstance(updatedServiceIns);
276 this.isDependent = this.currentServiceInstance.isDependent();
277 this.dependencyStatus.emit(this.isDependent);
278 if (this.isDependent) {
279 this.loadRulesListEvent.emit();
281 this.isLoading = false;
283 this.isDependent = isDependentOrigVal;
284 this.componentInstancesConstraints = rulesListOrig;
285 this.isLoading = false;
286 console.log('An error has occurred.');
290 onAddNodeFilter = () => {
291 if (!this.selectedInstanceProperties) {
292 this.modalServiceNg2.openAlertModal(I18nTexts.validateNodePropertiesTxt, I18nTexts.validateNodePropertiesMsg);
294 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
295 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilter(this.properties), this.getDisabled);
296 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
297 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
298 this.modalServiceNg2.addDynamicContentToModal(
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 selectedInstanceSiblings: this.selectedInstanceSiblings
311 this.modalInstance.instance.open();
315 onAddNodeFilterCapabilities = () => {
316 if (this.componentInstanceCapabilitiesMap.size == 0) {
317 this.modalServiceNg2.openAlertModal(I18nTexts.validateCapabilitiesTxt, I18nTexts.validateCapabilitiesMsg);
319 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
320 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilterCapabilities(this.capabilities), this.getDisabled);
321 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
322 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
323 this.modalServiceNg2.addDynamicContentToModal(
325 CapabilitiesFilterPropertiesEditorComponent,
327 currentServiceName: this.currentServiceInstance.name,
328 operatorTypes: this.operatorTypes,
329 compositeServiceName: this.compositeService.name,
330 parentServiceInputs: this.parentServiceInputs,
331 selectedInstanceProperties: this.selectedInstanceProperties,
332 selectedInstanceSiblings: this.selectedInstanceSiblings,
333 componentInstanceCapabilitiesMap: this.componentInstanceCapabilitiesMap
336 this.modalInstance.instance.open();
340 createNodeFilter = (constraintType: string) => {
341 this.isLoading = true;
342 this.topologyTemplateService.createServiceFilterConstraints(
343 this.compositeService.uniqueId,
344 this.currentServiceInstance.uniqueId,
345 new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule),
346 this.compositeService.componentType,
348 ).subscribe( (response) => {
349 this.emitEventOnChanges(constraintType, response);
350 this.isLoading = false;
352 this.isLoading = false;
354 this.modalServiceNg2.closeCurrentModal();
357 createNodeFilterCapabilities = (constraintType: string) => {
358 this.isLoading = true;
359 this.topologyTemplateService.createServiceFilterCapabilitiesConstraints(
360 this.compositeService.uniqueId,
361 this.currentServiceInstance.uniqueId,
362 new CapabilitiesConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule),
363 this.compositeService.componentType,
365 ).subscribe( (response) => {
366 this.emitEventOnChanges(constraintType, response);
367 this.isLoading = false;
369 this.isLoading = false;
371 this.modalServiceNg2.closeCurrentModal();
374 onSelectNodeFilterCapability(constraintType: string, index: number) {
375 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
376 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilterCapability(constraintType, index), this.getDisabled);
377 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
378 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
380 this.modalServiceNg2.addDynamicContentToModal(
382 CapabilitiesFilterPropertiesEditorComponent,
384 serviceRuleIndex: index,
385 serviceRules: _.map(this.constraintCapabilities, (rule) => new CapabilitiesConstraintObject(rule)),
386 currentServiceName: this.currentServiceInstance.name,
387 operatorTypes: this.operatorTypes,
388 compositeServiceName: this.compositeService.name,
389 parentServiceInputs: this.parentServiceInputs,
390 selectedInstanceProperties: this.selectedInstanceProperties,
391 selectedInstanceSiblings: this.selectedInstanceSiblings,
392 componentInstanceCapabilitiesMap: this.componentInstanceCapabilitiesMap
395 this.modalInstance.instance.open();
398 onSelectNodeFilter(constraintType: string, index: number) {
399 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
400 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilter(constraintType, index), this.getDisabled);
401 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
402 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
403 this.modalServiceNg2.addDynamicContentToModal(
405 ServiceDependenciesEditorComponent,
407 serviceRuleIndex: index,
408 serviceRules: _.map(this.constraintProperties, (rule) => new ConstraintObjectUI(rule)),
409 currentServiceName: this.currentServiceInstance.name,
410 operatorTypes: this.operatorTypes,
411 compositeServiceName: this.compositeService.name,
412 parentServiceInputs: this.parentServiceInputs,
413 parentServiceProperties: this.parentServiceProperties,
414 selectedInstanceProperties: this.selectedInstanceProperties,
415 selectedInstanceSiblings: this.selectedInstanceSiblings
418 this.modalInstance.instance.open();
421 getDisabled = (): boolean => {
422 return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
425 updateNodeFilter = (constraintType: string, index: number) => {
426 this.isLoading = true;
427 this.topologyTemplateService.updateServiceFilterConstraints(
428 this.compositeService.uniqueId,
429 this.currentServiceInstance.uniqueId,
430 new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule),
431 this.compositeService.componentType,
434 ).subscribe((response) => {
435 this.emitEventOnChanges(constraintType, response);
436 this.isLoading = false;
438 this.isLoading = false;
440 this.modalServiceNg2.closeCurrentModal();
443 updateNodeFilterCapability= (constraintType: string, index: number) => {
444 this.isLoading = true;
445 this.topologyTemplateService.updateServiceFilterCapabilitiesConstraint(
446 this.compositeService.uniqueId,
447 this.currentServiceInstance.uniqueId,
448 new CapabilitiesConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule),
449 this.compositeService.componentType,
452 ).subscribe((response) => {
453 this.emitEventOnChanges(constraintType, response);
454 this.isLoading = false;
456 this.isLoading = false;
458 this.modalServiceNg2.closeCurrentModal();
461 getSymbol(constraintOperator) {
462 switch (constraintOperator) {
463 case OPERATOR_TYPES.LESS_THAN: return '<';
464 case OPERATOR_TYPES.EQUAL: return '=';
465 case OPERATOR_TYPES.GREATER_THAN: return '>';
469 onDeleteNodeFilter = (constraintType: string, index: number) => {
470 this.isLoading = true;
471 this.topologyTemplateService.deleteServiceFilterConstraints(
472 this.compositeService.uniqueId,
473 this.currentServiceInstance.uniqueId,
475 this.compositeService.componentType,
477 ).subscribe( (response) => {
478 this.emitEventOnChanges(constraintType, response);
479 this.isLoading = false;
481 this.isLoading = false;
483 this.modalServiceNg2.closeCurrentModal();
486 private emitEventOnChanges(constraintType: string, response) {
487 if (this.properties === constraintType) {
488 this.updateNodeFilterProperties.emit(response.properties);
489 this.constraintProperties = response.properties;
491 this.updateNodeFilterCapabilities.emit(response.capabilities);
492 this.constraintCapabilities = response.capabilities;
496 openDeleteModal = (constraintType: string, index: number) => {
497 this.modalServiceNg2.createActionModal(I18nTexts.deleteNodeFilterTxt, I18nTexts.deleteNodeFilterMsg,
498 I18nTexts.modalDelete, () => this.onDeleteNodeFilter(constraintType, index), I18nTexts.modalCancel).instance.open();