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';
24 import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component';
25 import { ServiceDependenciesEditorComponent } from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component';
26 import { ModalService } from 'app/ng2/services/modal.service';
27 import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
28 import { TranslateService } from 'app/ng2/shared/translator/translate.service';
29 import { ComponentMetadata } from '../../../../models/component-metadata';
30 import { ServiceInstanceObject } from '../../../../models/service-instance-properties-and-interfaces';
31 import { TopologyTemplateService } from '../../../services/component-services/topology-template.service';
33 export class ConstraintObject {
34 servicePropertyName: string;
35 constraintOperator: string;
40 constructor(input?: any) {
42 this.servicePropertyName = input.servicePropertyName;
43 this.constraintOperator = input.constraintOperator;
44 this.sourceType = input.sourceType;
45 this.sourceName = input.sourceName;
46 this.value = input.value;
51 // tslint:disable-next-line:max-classes-per-file
52 export class ConstraintObjectUI extends ConstraintObject{
53 isValidValue: boolean;
55 constructor(input?: any) {
58 this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== '';
62 public updateValidity(isValidValue: boolean) {
63 this.isValidValue = isValidValue;
66 public isValidRule(isStatic) {
67 const isValidValue = isStatic ? this.isValidValue : true;
68 return this.servicePropertyName != null && this.servicePropertyName !== ''
69 && this.value != null && this.value !== '' && isValidValue;
73 export const OPERATOR_TYPES = {
75 GREATER_THAN: 'greater_than',
76 LESS_THAN: 'less_than'
79 // tslint:disable-next-line:max-classes-per-file
81 static removeDirectiveModalTitle: string;
82 static removeDirectiveModalText: string;
83 static updateDirectiveModalTitle: string;
84 static updateDirectiveModalText: string;
85 static modalApprove: string;
86 static modalCancel: string;
87 static modalCreate: string;
88 static modalSave: string;
89 static modalDelete: string;
90 static addNodeFilterTxt: string;
91 static updateNodeFilterTxt: string;
92 static deleteNodeFilterTxt: string;
93 static deleteNodeFilterMsg: string;
95 public static translateTexts(translateService) {
96 I18nTexts.removeDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TITLE');
97 I18nTexts.removeDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_REMOVE_TEXT');
98 I18nTexts.updateDirectiveModalTitle = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TITLE');
99 I18nTexts.updateDirectiveModalText = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_TEXT');
100 I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE');
101 I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
102 I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
103 I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
104 I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
105 I18nTexts.addNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_ADD_NODE_FILTER');
106 I18nTexts.updateNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_UPDATE_NODE_FILTER');
107 I18nTexts.deleteNodeFilterTxt = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER');
108 I18nTexts.deleteNodeFilterMsg = translateService.translate('DIRECTIVES_AND_NODE_FILTER_DELETE_NODE_FILTER_MSG');
112 // tslint:disable-next-line:max-classes-per-file
114 selector: 'service-dependencies',
115 templateUrl: './service-dependencies.component.html',
116 styleUrls: ['service-dependencies.component.less'],
117 providers: [ModalService, TranslateService]
120 export class ServiceDependenciesComponent {
121 modalInstance: ComponentRef<ModalComponent>;
122 isDependent: boolean;
124 parentServiceInputs: InputBEModel[] = [];
125 constraintProperties: ConstraintObject[] = [];
126 constraintCapabilities: ConstraintObject[] = [];
127 operatorTypes: any[];
128 capabilities: string = 'capabilities';
129 properties: string = 'properties';
130 private componentInstancesConstraints: ConstraintObject[] = [];
131 directiveOptions: string[];
133 @Input() readonly: boolean;
134 @Input() compositeService: ComponentMetadata;
135 @Input() currentServiceInstance: ComponentInstance;
136 @Input() selectedInstanceSiblings: ServiceInstanceObject[];
137 @Input() selectedInstanceConstraints: ConstraintObject[] = [];
138 @Input() selectedInstanceProperties: PropertyBEModel[] = [];
139 @Output() updateRulesListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
140 @Output() updateNodeFilterProperties: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
141 @Output() updateNodeFilterCapabilities: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
142 @Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter();
143 @Output() dependencyStatus = new EventEmitter<boolean>();
145 constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) {
149 this.loadDirectives();
150 this.isLoading = false;
151 this.operatorTypes = [
152 {label: '>', value: OPERATOR_TYPES.GREATER_THAN},
153 {label: '<', value: OPERATOR_TYPES.LESS_THAN},
154 {label: '=', value: OPERATOR_TYPES.EQUAL}
156 this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((result: ComponentGenericResponse) => {
157 this.parentServiceInputs = result.inputs;
159 this.loadNodeFilter();
160 this.translateService.languageChangedObservable.subscribe((lang) => {
161 I18nTexts.translateTexts(this.translateService);
166 this.topologyTemplateService.getDirectiveList().subscribe((data: string[]) => {
167 this.directiveOptions = data;
171 ngOnChanges(changes) {
172 if (changes.currentServiceInstance) {
173 this.currentServiceInstance = changes.currentServiceInstance.currentValue;
174 this.isDependent = this.currentServiceInstance.isDependent();
176 if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
177 this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
178 this.loadNodeFilter();
182 private getActualDirectiveValue = (): string => {
183 return this.currentServiceInstance.directives.length > 0 ? this.currentServiceInstance.directives[0] : "";
185 public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => {
186 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
187 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
188 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.removeDirectiveModalTitle,
189 I18nTexts.removeDirectiveModalText, [actionButton, cancelButton]);
190 this.loadNodeFilter();
191 return this.modalServiceNg2.createCustomModal(modalModel);
194 public openUpdateDependencyModal = (): ComponentRef<ModalComponent> => {
195 const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
196 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
197 const modalModel: ModalModel = new ModalModel('sm', I18nTexts.updateDirectiveModalTitle,
198 I18nTexts.updateDirectiveModalText, [actionButton, cancelButton]);
199 return this.modalServiceNg2.createCustomModal(modalModel);
202 private loadNodeFilter = (): void => {
203 this.topologyTemplateService.getServiceFilterConstraints(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((response) => {
204 if (response.nodeFilterforNode && response.nodeFilterforNode[this.currentServiceInstance.uniqueId]) {
205 this.componentInstancesConstraints = response.nodeFilterforNode;
206 const nodeFilterPropertiesResponse: ConstraintObject[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].properties;
207 this.constraintProperties = nodeFilterPropertiesResponse;
208 const nodeFilterCapabilitiesResponse: ConstraintObject[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].capabilities;
209 this.constraintCapabilities = nodeFilterCapabilitiesResponse;
214 onUncheckDependency = () => {
215 this.modalServiceNg2.closeCurrentModal();
216 this.isLoading = true;
217 const isDepOrig = this.isDependent;
218 const rulesListOrig = this.componentInstancesConstraints;
219 this.currentServiceInstance.unmarkAsDependent(this.getActualDirectiveValue());
220 this.updateComponentInstance(isDepOrig, rulesListOrig);
223 onCloseRemoveDependencyModal = () => {
224 this.isDependent = true;
225 this.modalServiceNg2.closeCurrentModal();
228 onOptionsSelected(event: any) {
229 const newDirectiveValue = event.target.value;
230 if (newDirectiveValue.toLowerCase() !== this.getActualDirectiveValue()) {
231 const rulesListOrig = this.componentInstancesConstraints;
232 this.setDirectiveValue(newDirectiveValue);
233 this.constraintProperties = [];
234 this.constraintCapabilities = [];
235 this.updateComponentInstance(this.isDependent, rulesListOrig);
239 private onRemoveDirective() {
240 this.openRemoveDependencyModal().instance.open();
241 this.constraintProperties = [];
242 this.constraintCapabilities = [];
245 private setDirectiveValue(newDirectiveValue: string) {
246 if (this.isDependent) {
247 this.openUpdateDependencyModal().instance.open();
249 this.currentServiceInstance.setDirectiveValue(newDirectiveValue);
252 updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) {
253 this.isLoading = true;
254 this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId,
255 this.compositeService.componentType,
256 this.currentServiceInstance)
257 .subscribe((updatedServiceIns: ComponentInstance) => {
258 this.currentServiceInstance = new ComponentInstance(updatedServiceIns);
259 this.isDependent = this.currentServiceInstance.isDependent();
260 this.dependencyStatus.emit(this.isDependent);
261 if (this.isDependent) {
262 this.loadRulesListEvent.emit();
264 this.isLoading = false;
266 this.isDependent = isDependentOrigVal;
267 this.componentInstancesConstraints = rulesListOrig;
268 this.isLoading = false;
269 console.log('An error has occurred.');
273 onAddNodeFilter = (constraintType: string) => {
274 console.info("constraintType: ", constraintType);
275 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
276 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createNodeFilter(constraintType), this.getDisabled);
277 const modalModel: ModalModel = new ModalModel('l', I18nTexts.addNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
278 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
279 this.modalServiceNg2.addDynamicContentToModal(
281 ServiceDependenciesEditorComponent,
283 currentServiceName: this.currentServiceInstance.name,
284 operatorTypes: this.operatorTypes,
285 compositeServiceName: this.compositeService.name,
286 parentServiceInputs: this.parentServiceInputs,
287 selectedInstanceProperties: this.selectedInstanceProperties,
288 selectedInstanceSiblings: this.selectedInstanceSiblings
291 this.modalInstance.instance.open();
294 onSelectNodeFilter(constraintType: string, index: number) {
295 const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
296 const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilter(constraintType), this.getDisabled);
297 const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard');
298 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
299 this.modalServiceNg2.addDynamicContentToModal(
301 ServiceDependenciesEditorComponent,
303 serviceRuleIndex: index,
304 serviceRules: _.map(this.properties == constraintType ? this.constraintProperties :
305 this.constraintCapabilities, (rule) => new ConstraintObjectUI(rule)),
306 currentServiceName: this.currentServiceInstance.name,
307 operatorTypes: this.operatorTypes,
308 compositeServiceName: this.compositeService.name,
309 parentServiceInputs: this.parentServiceInputs,
310 selectedInstanceProperties: this.selectedInstanceProperties,
311 selectedInstanceSiblings: this.selectedInstanceSiblings
314 this.modalInstance.instance.open();
317 getDisabled = (): boolean => {
318 return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
321 createNodeFilter = (constraintType: string) => {
322 const newRuleToCreate: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule);
323 this.isLoading = true;
324 this.topologyTemplateService.createServiceFilterConstraints(
325 this.compositeService.uniqueId,
326 this.currentServiceInstance.uniqueId,
328 this.compositeService.componentType,
330 ).subscribe( (response) => {
331 this.emitEventOnChanges(constraintType, response);
332 this.isLoading = false;
334 this.isLoading = false;
336 this.modalServiceNg2.closeCurrentModal();
339 updateNodeFilter = (constraintType: string) => {
340 const allRulesToUpdate: ConstraintObject[] = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map((rule) => new ConstraintObject(rule));
341 this.isLoading = true;
342 this.topologyTemplateService.updateServiceFilterConstraints(
343 this.compositeService.uniqueId,
344 this.currentServiceInstance.uniqueId,
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 getSymbol(constraintOperator) {
358 switch (constraintOperator) {
359 case OPERATOR_TYPES.LESS_THAN: return '<';
360 case OPERATOR_TYPES.EQUAL: return '=';
361 case OPERATOR_TYPES.GREATER_THAN: return '>';
365 onDeleteNodeFilter = (constraintType: string, index: number) => {
366 this.isLoading = true;
367 this.topologyTemplateService.deleteServiceFilterConstraints(
368 this.compositeService.uniqueId,
369 this.currentServiceInstance.uniqueId,
371 this.compositeService.componentType,
373 ).subscribe( (response) => {
374 this.emitEventOnChanges(constraintType, response);
375 this.isLoading = false;
377 this.isLoading = false;
379 this.modalServiceNg2.closeCurrentModal();
382 private emitEventOnChanges(constraintType: string, response) {
383 if (this.properties === constraintType) {
384 this.updateNodeFilterProperties.emit(response.properties);
385 this.constraintProperties = response.properties;
387 this.updateNodeFilterCapabilities.emit(response.capabilities);
388 this.constraintCapabilities = response.capabilities;
392 openDeleteModal = (constraintType: string, index: number) => {
393 this.modalServiceNg2.createActionModal(I18nTexts.deleteNodeFilterTxt, I18nTexts.deleteNodeFilterMsg,
394 I18nTexts.modalDelete, () => this.onDeleteNodeFilter(constraintType, index), I18nTexts.modalCancel).instance.open();