Catalog alignment
[sdc.git] / catalog-ui / src / app / ng2 / components / logic / service-dependencies / service-dependencies.component.ts
1 /*!
2  * Copyright © 2016-2018 European Support Limited
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 import { Component, ComponentRef, EventEmitter, Input, Output } from '@angular/core';
17 import {
18     ButtonModel,
19     ComponentInstance,
20     InputBEModel,
21     ModalModel,
22     PropertyBEModel,
23 } from 'app/models';
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';
32
33 export class ConstraintObject {
34     servicePropertyName: string;
35     constraintOperator: string;
36     sourceType: string;
37     sourceName: string;
38     value: string;
39
40     constructor(input?: any) {
41         if (input) {
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;
47         }
48     }
49 }
50
51 // tslint:disable-next-line:max-classes-per-file
52 export class ConstraintObjectUI extends ConstraintObject{
53     isValidValue: boolean;
54
55     constructor(input?: any) {
56         super(input);
57         if (input) {
58             this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== '';
59         }
60     }
61
62     public updateValidity(isValidValue: boolean) {
63         this.isValidValue = isValidValue;
64     }
65
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;
70     }
71 }
72
73 export const OPERATOR_TYPES = {
74     EQUAL: 'equal',
75     GREATER_THAN: 'greater_than',
76     LESS_THAN: 'less_than'
77 };
78
79 // tslint:disable-next-line:max-classes-per-file
80 class I18nTexts {
81     static uncheckModalTitle: string;
82     static uncheckModalText: string;
83     static modalApprove: string;
84     static modalCancel: string;
85     static modalCreate: string;
86     static modalSave: string;
87     static modalDelete: string;
88     static addRuleTxt: string;
89     static updateRuleTxt: string;
90     static deleteRuleTxt: string;
91     static deleteRuleMsg: string;
92
93     public static translateTexts(translateService) {
94             I18nTexts.uncheckModalTitle = translateService.translate('SERVICE_DEPENDENCY_UNCHECK_TITLE');
95             I18nTexts.uncheckModalText = translateService.translate('SERVICE_DEPENDENCY_UNCHECK_TEXT');
96             I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE');
97             I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
98             I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
99             I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
100             I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
101             I18nTexts.addRuleTxt = translateService.translate('SERVICE_DEPENDENCY_ADD_RULE');
102             I18nTexts.updateRuleTxt = translateService.translate('SERVICE_DEPENDENCY_UPDATE_RULE');
103             I18nTexts.deleteRuleTxt = translateService.translate('SERVICE_DEPENDENCY_DELETE_RULE');
104             I18nTexts.deleteRuleMsg = translateService.translate('SERVICE_DEPENDENCY_DELETE_RULE_MSG');
105     }
106 }
107
108 // tslint:disable-next-line:max-classes-per-file
109 @Component({
110     selector: 'service-dependencies',
111     templateUrl: './service-dependencies.component.html',
112     styleUrls: ['service-dependencies.component.less'],
113     providers: [ModalService, TranslateService]
114 })
115
116 export class ServiceDependenciesComponent {
117     modalInstance: ComponentRef<ModalComponent>;
118     isDependent: boolean;
119     isLoading: boolean;
120     parentServiceInputs: InputBEModel[] = [];
121     rulesList: ConstraintObject[] = [];
122     operatorTypes: any[];
123
124     @Input() readonly: boolean;
125     @Input() compositeService: ComponentMetadata;
126     @Input() currentServiceInstance: ComponentInstance;
127     @Input() selectedInstanceSiblings: ServiceInstanceObject[];
128     @Input() selectedInstanceConstraints: ConstraintObject[] = [];
129     @Input() selectedInstanceProperties: PropertyBEModel[] = [];
130     @Output() updateRulesListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
131     @Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter();
132     @Output() dependencyStatus = new EventEmitter<boolean>();
133
134     constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) {
135     }
136
137     ngOnInit() {
138         this.isLoading = false;
139         this.operatorTypes = [
140             {label: '>', value: OPERATOR_TYPES.GREATER_THAN},
141             {label: '<', value: OPERATOR_TYPES.LESS_THAN},
142             {label: '=', value: OPERATOR_TYPES.EQUAL}
143         ];
144         this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((result: ComponentGenericResponse) => {
145             this.parentServiceInputs = result.inputs;
146         });
147         this.loadRules();
148         this.translateService.languageChangedObservable.subscribe((lang) => {
149             I18nTexts.translateTexts(this.translateService);
150         });
151     }
152
153     ngOnChanges(changes) {
154         if (changes.currentServiceInstance) {
155             this.currentServiceInstance = changes.currentServiceInstance.currentValue;
156             this.isDependent = this.currentServiceInstance.isDependent();
157         }
158         if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
159             this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
160             this.loadRules();
161         }
162     }
163
164     public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => {
165         const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency);
166         const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal);
167         const modalModel: ModalModel = new ModalModel('sm', I18nTexts.uncheckModalTitle, I18nTexts.uncheckModalText, [actionButton, cancelButton]);
168         return this.modalServiceNg2.createCustomModal(modalModel);
169     }
170
171     loadRules() {
172         this.rulesList = this.selectedInstanceConstraints && this.selectedInstanceConstraints.map((co: ConstraintObject) => ({
173                 servicePropertyName: co.servicePropertyName,
174                 constraintOperator: co.constraintOperator,
175                 sourceType: co.sourceType,
176                 sourceName: co.sourceName !== 'SELF' ? co.sourceName : this.compositeService.name,
177                 value: co.value,
178             }));
179     }
180
181     onUncheckDependency = () => {
182         this.modalServiceNg2.closeCurrentModal();
183         this.isLoading = true;
184         const isDepOrig = this.isDependent;
185         const rulesListOrig = this.rulesList;
186         this.currentServiceInstance.unmarkAsDependent();
187         this.updateComponentInstance(isDepOrig, rulesListOrig);
188     }
189
190     onCloseRemoveDependencyModal = () => {
191         this.isDependent = true;
192         this.modalServiceNg2.closeCurrentModal();
193     }
194
195     onCheckDependency = () => {
196         const isDepOrig = this.isDependent;
197         const rulesListOrig = this.rulesList;
198         this.currentServiceInstance.markAsDependent();
199         this.rulesList = [];
200         this.updateComponentInstance(isDepOrig, rulesListOrig);
201     }
202
203     onMarkAsDependent() {
204         if (!this.currentServiceInstance.isDependent()) {
205             this.onCheckDependency();
206         } else {
207             this.openRemoveDependencyModal().instance.open();
208         }
209     }
210
211     updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) {
212         this.isLoading = true;
213         this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId, this.currentServiceInstance).subscribe((updatedServiceIns: ComponentInstance) => {
214             this.currentServiceInstance = new ComponentInstance(updatedServiceIns);
215             this.isDependent = this.currentServiceInstance.isDependent();
216             this.dependencyStatus.emit(this.isDependent);
217             if (this.isDependent) {
218                 this.loadRulesListEvent.emit();
219             }
220             this.isLoading = false;
221         }, (err) => {
222             this.isDependent = isDependentOrigVal;
223             this.rulesList = rulesListOrig;
224             this.isLoading = false;
225             console.log('An error has occurred.');
226         });
227     }
228
229     onAddRule() {
230         const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
231         const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', this.createRule, this.getDisabled);
232         const modalModel: ModalModel = new ModalModel('l', I18nTexts.addRuleTxt, '', [saveButton, cancelButton], 'standard');
233         this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
234         this.modalServiceNg2.addDynamicContentToModal(
235             this.modalInstance,
236             ServiceDependenciesEditorComponent,
237             {
238                 currentServiceName: this.currentServiceInstance.name,
239                 operatorTypes: this.operatorTypes,
240                 compositeServiceName: this.compositeService.name,
241                 parentServiceInputs: this.parentServiceInputs,
242                 selectedInstanceProperties: this.selectedInstanceProperties,
243                 selectedInstanceSiblings: this.selectedInstanceSiblings
244             }
245         );
246         this.modalInstance.instance.open();
247     }
248
249     onSelectRule(index: number) {
250         const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
251         const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateRules(), this.getDisabled);
252         const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateRuleTxt, '', [saveButton, cancelButton], 'standard');
253         this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
254         this.modalServiceNg2.addDynamicContentToModal(
255             this.modalInstance,
256             ServiceDependenciesEditorComponent,
257             {
258                 serviceRuleIndex: index,
259                 serviceRules: _.map(this.rulesList, (rule) => new ConstraintObjectUI(rule)),
260                 currentServiceName: this.currentServiceInstance.name,
261                 operatorTypes: this.operatorTypes,
262                 compositeServiceName: this.compositeService.name,
263                 parentServiceInputs: this.parentServiceInputs,
264                 selectedInstanceProperties: this.selectedInstanceProperties,
265                 selectedInstanceSiblings: this.selectedInstanceSiblings
266             }
267         );
268         this.modalInstance.instance.open();
269     }
270
271     getDisabled = (): boolean =>  {
272         return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
273     }
274
275     createRule  = (): void => {
276         const newRuleToCreate: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule);
277         this.isLoading = true;
278         this.topologyTemplateService.createServiceFilterConstraints(
279             this.compositeService.uniqueId,
280             this.currentServiceInstance.uniqueId,
281             newRuleToCreate
282         ).subscribe( (response) => {
283             this.updateRulesListEvent.emit(response.properties);
284             this.isLoading = false;
285         }, (err) => {
286             this.isLoading = false;
287         });
288         this.modalServiceNg2.closeCurrentModal();
289     }
290
291     updateRules = (): void => {
292         const allRulesToUpdate: ConstraintObject[] = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map((rule) => new ConstraintObject(rule));
293         this.isLoading = true;
294         this.topologyTemplateService.updateServiceFilterConstraints(
295             this.compositeService.uniqueId,
296             this.currentServiceInstance.uniqueId,
297             allRulesToUpdate
298         ).subscribe((response) => {
299             this.updateRulesListEvent.emit(response.properties);
300             this.isLoading = false;
301         }, (err) => {
302             this.isLoading = false;
303         });
304         this.modalServiceNg2.closeCurrentModal();
305     }
306
307     getSymbol(constraintOperator) {
308         switch (constraintOperator) {
309             case OPERATOR_TYPES.LESS_THAN: return '<';
310             case OPERATOR_TYPES.EQUAL: return '=';
311             case OPERATOR_TYPES.GREATER_THAN: return '>';
312         }
313     }
314
315     onDeleteRule = (index: number) => {
316         this.isLoading = true;
317         this.topologyTemplateService.deleteServiceFilterConstraints(
318             this.compositeService.uniqueId,
319             this.currentServiceInstance.uniqueId,
320             index
321         ).subscribe( (response) => {
322             this.updateRulesListEvent.emit(response.properties);
323             this.isLoading = false;
324         }, (err) => {
325             this.isLoading = false;
326         });
327         this.modalServiceNg2.closeCurrentModal();
328     }
329
330     openDeleteModal = (index: number) => {
331         this.modalServiceNg2.createActionModal(I18nTexts.deleteRuleTxt, I18nTexts.deleteRuleMsg,
332             I18nTexts.modalDelete, () => this.onDeleteRule(index), I18nTexts.modalCancel).instance.open();
333     }
334 }