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 { CapabilitiesConstraintObjectUI} from "../capabilities-constraint/capabilities-constraint.component";
35 import {ToscaFilterConstraintType} from "../../../../models/tosca-filter-constraint-type.enum";
36 import {CompositionService} from "../../../pages/composition/composition.service";
38 export class ConstraintObject {
39 servicePropertyName: string;
40 constraintOperator: string;
45 constructor(input?: any) {
47 this.servicePropertyName = input.servicePropertyName;
48 this.constraintOperator = input.constraintOperator;
49 this.sourceType = input.sourceType;
50 this.sourceName = input.sourceName;
51 this.value = input.value;
56 // tslint:disable-next-line:max-classes-per-file
57 export class ConstraintObjectUI extends ConstraintObject{
58 isValidValue: boolean;
60 constructor(input?: any) {
63 this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== '';
67 public updateValidity(isValidValue: boolean) {
68 this.isValidValue = isValidValue;
71 public isValidRule(isStatic) {
72 const isValidValue = isStatic ? this.isValidValue : true;
73 return this.servicePropertyName != null && this.servicePropertyName !== ''
74 && this.value != null && this.value !== '' && isValidValue;
78 export const OPERATOR_TYPES = {
80 GREATER_THAN: 'greater_than',
81 LESS_THAN: 'less_than',
82 GREATER_OR_EQUAL: 'greater_or_equal',
83 LESS_OR_EQUAL: 'less_or_equal'
86 // tslint:disable-next-line:max-classes-per-file
88 static removeDirectiveModalTitle: string;
89 static removeDirectiveModalText: string;
90 static updateDirectiveModalTitle: string;
91 static updateDirectiveModalText: string;
92 static modalApprove: string;
93 static modalCancel: string;
94 static modalCreate: string;
95 static modalSave: string;
96 static modalDelete: string;
97 static addNodeFilterTxt: string;
98 static updateNodeFilterTxt: string;
99 static deleteNodeFilterTxt: string;
100 static deleteNodeFilterMsg: string;
101 static validateCapabilitiesTxt: string
102 static validateCapabilitiesMsg: string
103 static validateNodePropertiesTxt: string
104 static validateNodePropertiesMsg: string
106 public static translateTexts(translateService) {
107 I18nTexts.removeDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TITLE');
108 I18nTexts.removeDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TEXT');
109 I18nTexts.updateDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TITLE');
110 I18nTexts.updateDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TEXT');
111 I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE');
112 I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
113 I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
114 I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
115 I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
116 I18nTexts.addNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_ADD_NODE_FILTER');
117 I18nTexts.updateNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_NODE_FILTER');
118 I18nTexts.deleteNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER');
119 I18nTexts.deleteNodeFilterMsg = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER_MSG');
120 I18nTexts.validateCapabilitiesTxt = translateService.translate('VALIDATE_CAPABILITIES_TXT');
121 I18nTexts.validateCapabilitiesMsg = translateService.translate('VALIDATE_CAPABILITIES_MSG');
122 I18nTexts.validateNodePropertiesTxt = translateService.translate('VALIDATE_NODE_PROPERTIES_TXT');
123 I18nTexts.validateNodePropertiesMsg = translateService.translate('VALIDATE_NODE_PROPERTIES_MSG');
127 // tslint:disable-next-line:max-classes-per-file
129 selector: 'service-dependencies',
130 templateUrl: './service-dependencies.component.html',
131 styleUrls: ['service-dependencies.component.less'],
132 providers: [ModalService, TranslateService]
135 export class ServiceDependenciesComponent {
136 modalInstance: ComponentRef<ModalComponent>;
137 isDependent: boolean;
139 parentServiceInputs: InputBEModel[] = [];
140 parentServiceProperties: PropertyBEModel[] = [];
141 constraintProperties: ConstraintObject[] = [];
142 constraintCapabilities: CapabilitiesConstraintObjectUI[] = [];
143 operatorTypes: any[];
144 capabilities: string = ToscaFilterConstraintType.CAPABILITIES;
145 properties: string = ToscaFilterConstraintType.PROPERTIES;
146 private componentInstancesConstraints: ConstraintObject[] = [];
149 @Input() readonly: boolean;
150 @Input() compositeService: ComponentMetadata;
151 @Input() currentServiceInstance: ComponentInstance;
152 @Input() selectedInstanceSiblings: ServiceInstanceObject[];
153 @Input() selectedInstanceConstraints: ConstraintObject[] = [];
154 @Input() selectedInstanceProperties: PropertyBEModel[] = [];
155 @Output() updateRulesListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
156 @Output() updateNodeFilterProperties: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
157 @Output() updateNodeFilterCapabilities: EventEmitter<CapabilitiesConstraintObjectUI[]> = new EventEmitter<CapabilitiesConstraintObjectUI[]>();
158 @Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter();
159 @Output() dependencyStatus = new EventEmitter<boolean>();
161 @Input() componentInstanceCapabilitiesMap: Map<string, PropertyModel[]>;
163 constructor(private topologyTemplateService: TopologyTemplateService,
164 private modalServiceNg2: ModalService,
165 private translateService: TranslateService,
166 private compositionService: CompositionService) {
170 this.isLoading = false;
171 this.operatorTypes = [
172 {label: '>', value: OPERATOR_TYPES.GREATER_THAN},
173 {label: '<', value: OPERATOR_TYPES.LESS_THAN},
174 {label: '=', value: OPERATOR_TYPES.EQUAL},
175 {label: '>=', value: OPERATOR_TYPES.GREATER_OR_EQUAL},
176 {label: '<=', value: OPERATOR_TYPES.LESS_OR_EQUAL}
178 this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId)
179 .subscribe((result: ComponentGenericResponse) => {
180 this.parentServiceInputs = result.inputs;
181 this.parentServiceProperties = result.properties;
183 this.loadNodeFilter();
184 this.translateService.languageChangedObservable.subscribe((lang) => {
185 I18nTexts.translateTexts(this.translateService);
189 ngOnChanges(changes) {
190 if (changes.currentServiceInstance) {
191 this.currentServiceInstance = changes.currentServiceInstance.currentValue;
192 this.isDependent = this.currentServiceInstance.isDependent();
194 if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
195 this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
196 this.loadNodeFilter();
200 private getActualDirectiveValue = (): string[] => {
201 return this.currentServiceInstance.directives.length > 0 ? this.currentServiceInstance.directives : [];
204 public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => {
205 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
206 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
207 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.removeDirectiveModalTitle,
208 I18nTexts.removeDirectiveModalText, [actionButton, cancelButton]);
209 this.loadNodeFilter();
210 return this.modalServiceNg2.createCustomModal(modalModel);
213 public openUpdateDependencyModal = (): ComponentRef<ModalComponent> => {
214 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
215 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
216 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.updateDirectiveModalTitle,
217 I18nTexts.updateDirectiveModalText, [actionButton, cancelButton]);
218 return this.modalServiceNg2.createCustomModal(modalModel);
221 private loadNodeFilter = (): void => {
222 this.topologyTemplateService.getServiceFilterConstraints(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((response) => {
223 if (response.nodeFilterforNode && response.nodeFilterforNode[this.currentServiceInstance.uniqueId]) {
224 this.componentInstancesConstraints = response.nodeFilterforNode;
225 const nodeFilterPropertiesResponse: ConstraintObject[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].properties;
226 this.constraintProperties = nodeFilterPropertiesResponse;
227 const nodeFilterCapabilitiesResponse: CapabilitiesConstraintObjectUI[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].capabilities;
228 this.constraintCapabilities = nodeFilterCapabilitiesResponse;
233 onUncheckDependency = () => {
234 this.modalServiceNg2.closeCurrentModal();
235 this.isLoading = true;
236 const isDepOrig = this.isDependent;
237 const rulesListOrig = this.componentInstancesConstraints;
238 this.currentServiceInstance.unmarkAsDependent(this.getActualDirectiveValue());
239 this.updateComponentInstance(isDepOrig, rulesListOrig);
242 onCloseRemoveDependencyModal = () => {
243 this.isDependent = true;
244 this.modalServiceNg2.closeCurrentModal();
247 onAddDirectives(directives: string[]) {
248 this.isEditable = false;
249 this.setDirectiveValue(directives);
250 const rulesListOrig = this.componentInstancesConstraints;
251 this.constraintProperties = [];
252 this.constraintCapabilities = [];
253 this.loadNodeFilter();
254 this.updateComponentInstance(this.isDependent, rulesListOrig);
257 private onRemoveDirective() {
258 this.openRemoveDependencyModal().instance.open();
259 this.constraintProperties = [];
260 this.constraintCapabilities = [];
263 private onEditDirectives() {
264 this.isEditable = true;
267 private setDirectiveValue(newDirectiveValues: string[]) {
268 this.currentServiceInstance.setDirectiveValue(newDirectiveValues);
271 updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) {
272 this.isLoading = true;
273 this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId,
274 this.compositeService.componentType,
275 this.currentServiceInstance)
276 .subscribe((updatedServiceIns: ComponentInstance) => {
277 const selectedComponentInstance = this.compositionService.getComponentInstances()
278 .find(componentInstance => componentInstance.uniqueId == this.currentServiceInstance.uniqueId);
279 selectedComponentInstance.directives = updatedServiceIns.directives;
280 this.currentServiceInstance = new ComponentInstance(updatedServiceIns);
281 this.isDependent = this.currentServiceInstance.isDependent();
282 this.dependencyStatus.emit(this.isDependent);
283 if (this.isDependent) {
284 this.loadRulesListEvent.emit();
286 this.isLoading = false;
288 this.isDependent = isDependentOrigVal;
289 this.componentInstancesConstraints = rulesListOrig;
290 this.isLoading = false;
291 console.log('An error has occurred.');
295 onAddNodeFilter = () => {
296 if (!this.selectedInstanceProperties) {
297 this.modalServiceNg2.openAlertModal(I18nTexts.validateNodePropertiesTxt, I18nTexts.validateNodePropertiesMsg);
299 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
300 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilter(this.properties), this.getDisabled);
301 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
302 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
303 this.modalServiceNg2.addDynamicContentToModal(
305 ServiceDependenciesEditorComponent,
307 currentServiceName: this.currentServiceInstance.name,
308 operatorTypes: this.operatorTypes,
309 compositeServiceName: this.compositeService.name,
310 parentServiceInputs: this.parentServiceInputs,
311 parentServiceProperties: this.parentServiceProperties,
312 selectedInstanceProperties: this.selectedInstanceProperties,
313 selectedInstanceSiblings: this.selectedInstanceSiblings
316 this.modalInstance.instance.open();
320 onAddNodeFilterCapabilities = () => {
321 if (this.componentInstanceCapabilitiesMap.size == 0) {
322 this.modalServiceNg2.openAlertModal(I18nTexts.validateCapabilitiesTxt, I18nTexts.validateCapabilitiesMsg);
324 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
325 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilterCapabilities(this.capabilities), this.getDisabled);
326 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
327 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
328 this.modalServiceNg2.addDynamicContentToModal(
330 CapabilitiesFilterPropertiesEditorComponent,
332 currentServiceName: this.currentServiceInstance.name,
333 operatorTypes: this.operatorTypes,
334 compositeServiceName: this.compositeService.name,
335 parentServiceInputs: this.parentServiceInputs,
336 selectedInstanceProperties: this.selectedInstanceProperties,
337 selectedInstanceSiblings: this.selectedInstanceSiblings,
338 componentInstanceCapabilitiesMap: this.componentInstanceCapabilitiesMap
341 this.modalInstance.instance.open();
345 createNodeFilter = (constraintType: string) => {
346 this.isLoading = true;
347 this.topologyTemplateService.createServiceFilterConstraints(
348 this.compositeService.uniqueId,
349 this.currentServiceInstance.uniqueId,
350 new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule),
351 this.compositeService.componentType,
353 ).subscribe( (response) => {
354 this.emitEventOnChanges(constraintType, response);
355 this.isLoading = false;
357 this.isLoading = false;
359 this.modalServiceNg2.closeCurrentModal();
362 createNodeFilterCapabilities = (constraintType: string) => {
363 this.isLoading = true;
364 this.topologyTemplateService.createServiceFilterCapabilitiesConstraints(
365 this.compositeService.uniqueId,
366 this.currentServiceInstance.uniqueId,
367 new CapabilitiesConstraintObjectUI(this.modalInstance.instance.dynamicContent.instance.currentRule),
368 this.compositeService.componentType,
370 ).subscribe( (response) => {
371 this.emitEventOnChanges(constraintType, response);
372 this.isLoading = false;
374 this.isLoading = false;
376 this.modalServiceNg2.closeCurrentModal();
379 onSelectNodeFilterCapability(constraintType: string, index: number) {
380 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
381 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilterCapability(constraintType, index), this.getDisabled);
382 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
383 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
385 this.modalServiceNg2.addDynamicContentToModal(
387 CapabilitiesFilterPropertiesEditorComponent,
389 serviceRuleIndex: index,
390 serviceRules: _.map(this.constraintCapabilities, (rule) => new CapabilitiesConstraintObjectUI(rule)),
391 currentServiceName: this.currentServiceInstance.name,
392 operatorTypes: this.operatorTypes,
393 compositeServiceName: this.compositeService.name,
394 parentServiceInputs: this.parentServiceInputs,
395 selectedInstanceProperties: this.selectedInstanceProperties,
396 selectedInstanceSiblings: this.selectedInstanceSiblings,
397 componentInstanceCapabilitiesMap: this.componentInstanceCapabilitiesMap
400 this.modalInstance.instance.open();
403 onSelectNodeFilter(constraintType: string, index: number) {
404 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
405 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilter(constraintType, index), this.getDisabled);
406 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
407 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
408 this.modalServiceNg2.addDynamicContentToModal(
410 ServiceDependenciesEditorComponent,
412 serviceRuleIndex: index,
413 serviceRules: _.map(this.constraintProperties, (rule) => new ConstraintObjectUI(rule)),
414 currentServiceName: this.currentServiceInstance.name,
415 operatorTypes: this.operatorTypes,
416 compositeServiceName: this.compositeService.name,
417 parentServiceInputs: this.parentServiceInputs,
418 parentServiceProperties: this.parentServiceProperties,
419 selectedInstanceProperties: this.selectedInstanceProperties,
420 selectedInstanceSiblings: this.selectedInstanceSiblings
423 this.modalInstance.instance.open();
426 getDisabled = (): boolean => {
427 return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
430 updateNodeFilter = (constraintType: string, index: number) => {
431 this.isLoading = true;
432 this.topologyTemplateService.updateServiceFilterConstraints(
433 this.compositeService.uniqueId,
434 this.currentServiceInstance.uniqueId,
435 new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule),
436 this.compositeService.componentType,
439 ).subscribe((response) => {
440 this.emitEventOnChanges(constraintType, response);
441 this.isLoading = false;
443 this.isLoading = false;
445 this.modalServiceNg2.closeCurrentModal();
448 updateNodeFilterCapability= (constraintType: string, index: number) => {
449 this.isLoading = true;
450 this.topologyTemplateService.updateServiceFilterCapabilitiesConstraint(
451 this.compositeService.uniqueId,
452 this.currentServiceInstance.uniqueId,
453 new CapabilitiesConstraintObjectUI(this.modalInstance.instance.dynamicContent.instance.currentRule),
454 this.compositeService.componentType,
457 ).subscribe((response) => {
458 this.emitEventOnChanges(constraintType, response);
459 this.isLoading = false;
461 this.isLoading = false;
463 this.modalServiceNg2.closeCurrentModal();
466 getSymbol(constraintOperator) {
467 switch (constraintOperator) {
468 case OPERATOR_TYPES.LESS_THAN: return '<';
469 case OPERATOR_TYPES.EQUAL: return '=';
470 case OPERATOR_TYPES.GREATER_THAN: return '>';
471 case OPERATOR_TYPES.GREATER_OR_EQUAL: return '>=';
472 case OPERATOR_TYPES.LESS_OR_EQUAL: return '<=';
476 onDeleteNodeFilter = (constraintType: string, index: number) => {
477 this.isLoading = true;
478 this.topologyTemplateService.deleteServiceFilterConstraints(
479 this.compositeService.uniqueId,
480 this.currentServiceInstance.uniqueId,
482 this.compositeService.componentType,
484 ).subscribe( (response) => {
485 this.emitEventOnChanges(constraintType, response);
486 this.isLoading = false;
488 this.isLoading = false;
490 this.modalServiceNg2.closeCurrentModal();
493 private emitEventOnChanges(constraintType: string, response) {
494 if (this.properties === constraintType) {
495 this.updateNodeFilterProperties.emit(response.properties);
496 this.constraintProperties = response.properties;
498 this.updateNodeFilterCapabilities.emit(response.capabilities);
499 this.constraintCapabilities = response.capabilities;
503 openDeleteModal = (constraintType: string, index: number) => {
504 this.modalServiceNg2.createActionModal(I18nTexts.deleteNodeFilterTxt, I18nTexts.deleteNodeFilterMsg,
505 I18nTexts.modalDelete, () => this.onDeleteNodeFilter(constraintType, index), I18nTexts.modalCancel).instance.open();