7671d653e43993949fc90f6b7a1a13d191e8695f
[sdc.git] / catalog-ui / src / app / ng2 / components / logic / substitution-filter / substitution-filter.component.ts
1 /*
2 * ============LICENSE_START=======================================================
3 *  Copyright (C) 2020 Nordix Foundation. All rights reserved.
4 *  ================================================================================
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
8 *
9 *        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 or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 *
16 *  SPDX-License-Identifier: Apache-2.0
17 *  ============LICENSE_END=========================================================
18 */
19
20 import {Component, ComponentRef, EventEmitter, Input, Output} from '@angular/core';
21 import {
22   ButtonModel,
23   ComponentInstance,
24   InputBEModel,
25   ModalModel,
26   PropertyBEModel,
27 } from 'app/models';
28 import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
29 import {ServiceDependenciesEditorComponent} from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component';
30 import {ModalService} from 'app/ng2/services/modal.service';
31 import {TranslateService} from 'app/ng2/shared/translator/translate.service';
32 import {ComponentMetadata} from '../../../../models/component-metadata';
33 import {TopologyTemplateService} from '../../../services/component-services/topology-template.service';
34 import {ToscaFilterConstraintType} from "../../../../models/tosca-filter-constraint-type.enum";
35
36 export class ConstraintObject {
37   servicePropertyName: string;
38   constraintOperator: string;
39   sourceType: string;
40   sourceName: string;
41   value: string;
42
43   constructor(input?: any) {
44     if (input) {
45       this.servicePropertyName = input.servicePropertyName;
46       this.constraintOperator = input.constraintOperator;
47       this.sourceType = input.sourceType;
48       this.sourceName = input.sourceName;
49       this.value = input.value;
50     }
51   }
52 }
53
54 export class ConstraintObjectUI extends ConstraintObject {
55   isValidValue: boolean;
56
57   constructor(input?: any) {
58     super(input);
59     if (input) {
60       this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== '';
61     }
62   }
63
64   public updateValidity(isValidValue: boolean) {
65     this.isValidValue = isValidValue;
66   }
67
68   public isValidRule(isStatic) {
69     const isValidValue = isStatic ? this.isValidValue : true;
70     return this.servicePropertyName != null && this.servicePropertyName !== ''
71         && this.value != null && this.value !== '' && isValidValue;
72   }
73 }
74
75 export const OPERATOR_TYPES = {
76   EQUAL: 'equal',
77   GREATER_THAN: 'greater_than',
78   LESS_THAN: 'less_than'
79 };
80
81 class I18nTexts {
82   static addSubstitutionFilterTxt: string;
83   static updateSubstitutionFilterTxt: string;
84   static deleteSubstitutionFilterTxt: string;
85   static deleteSubstitutionFilterMsg: string;
86   static modalCancel: string;
87   static modalCreate: string;
88   static modalSave: string;
89   static modalDelete: string;
90
91   public static translateTexts(translateService) {
92     I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL');
93     I18nTexts.modalCreate = translateService.translate('MODAL_CREATE');
94     I18nTexts.modalSave = translateService.translate('MODAL_SAVE');
95     I18nTexts.modalDelete = translateService.translate('MODAL_DELETE');
96
97     I18nTexts.addSubstitutionFilterTxt = translateService.translate('ADD_SUBSTITUTION_FILTER');
98     I18nTexts.updateSubstitutionFilterTxt = translateService.translate('UPDATE_SUBSTITUTION_FILTER');
99     I18nTexts.deleteSubstitutionFilterTxt = translateService.translate('DELETE_SUBSTITUTION_FILTER');
100     I18nTexts.deleteSubstitutionFilterMsg = translateService.translate('DELETE_SUBSTITUTION_FILTER_MSG');
101   }
102 }
103
104 @Component({
105   selector: 'substitution-filter',
106   templateUrl: './substitution-filter.component.html',
107   styleUrls: ['substitution-filter.component.less'],
108   providers: [ModalService, TranslateService]
109 })
110
111 export class SubstitutionFilterComponent {
112   modalInstance: ComponentRef<ModalComponent>;
113   isLoading: boolean;
114   operatorTypes: any[];
115   constraintProperties: ConstraintObject[] = [];
116   PROPERTIES: string = ToscaFilterConstraintType.PROPERTIES;
117
118   @Input() readonly: boolean;
119   @Input() compositeService: ComponentMetadata;
120   @Input() currentServiceInstance: ComponentInstance;
121   @Input() selectedInstanceConstraints: ConstraintObject[] = [];
122   @Input() selectedInstanceProperties: PropertyBEModel[] = [];
123   @Input() parentServiceProperties: PropertyBEModel[] = [];
124   @Input() parentServiceInputs: InputBEModel[] = [];
125   @Output() updateSubstitutionFilterProperties: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
126   @Output() updateConstraintListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>();
127   @Output() loadConstraintListEvent: EventEmitter<any> = new EventEmitter();
128   @Output() hasSubstitutionFilter = new EventEmitter<boolean>();
129
130   constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) {
131   }
132
133   ngOnInit() {
134     this.isLoading = false;
135     this.operatorTypes = [
136       {label: '>', value: OPERATOR_TYPES.GREATER_THAN},
137       {label: '<', value: OPERATOR_TYPES.LESS_THAN},
138       {label: '=', value: OPERATOR_TYPES.EQUAL}
139     ];
140     this.loadSubstitutionFilter();
141     this.translateService.languageChangedObservable.subscribe((lang) => {
142       I18nTexts.translateTexts(this.translateService);
143     });
144   }
145
146   ngOnChanges(changes) {
147     if (changes.compositeService) {
148       this.compositeService = changes.compositeService.currentValue;
149     }
150     if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) {
151       this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue;
152       this.loadSubstitutionFilter();
153     }
154   }
155
156   private loadSubstitutionFilter = (): void => {
157     this.topologyTemplateService.getSubstitutionFilterConstraints(this.compositeService.componentType, this.compositeService.uniqueId)
158     .subscribe((response) => {
159       if(response.substitutionFilters) {
160         this.constraintProperties = response.substitutionFilters.properties;
161       }
162     });
163   }
164
165   onAddSubstitutionFilter = (constraintType: string) => {
166     const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
167     const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createSubstitutionFilter(constraintType), this.getDisabled);
168     const modalModel: ModalModel = new ModalModel('l', I18nTexts.addSubstitutionFilterTxt, '', [saveButton, cancelButton], 'standard');
169     this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
170     this.modalServiceNg2.addDynamicContentToModal(
171         this.modalInstance,
172         ServiceDependenciesEditorComponent,
173         {
174           currentServiceName: this.currentServiceInstance.name,
175           operatorTypes: this.operatorTypes,
176           compositeServiceName: this.compositeService.name,
177           parentServiceInputs: this.parentServiceInputs,
178           parentServiceProperties: this.parentServiceProperties,
179           selectedInstanceProperties: this.parentServiceProperties,
180         }
181     );
182     this.modalInstance.instance.open();
183   }
184
185   createSubstitutionFilter = (constraintType: string) => {
186     const newSubstitutionFilter: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule);
187     this.isLoading = true;
188     this.topologyTemplateService.createSubstitutionFilterConstraints(
189         this.compositeService.uniqueId,
190         newSubstitutionFilter,
191         this.compositeService.componentType,
192         constraintType
193     ).subscribe((response) => {
194       this.emitEventOnChanges(constraintType, response);
195       this.isLoading = false;
196     }, (err) => {
197       console.error("Failed to Create Substitution Filter on the component with id: ", this.compositeService.uniqueId);
198       this.isLoading = false;
199     });
200     this.modalServiceNg2.closeCurrentModal();
201   }
202
203   onSelectSubstitutionFilter(constraintType: string, index: number) {
204     const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal);
205     const updateButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateSubstitutionFilter(constraintType), this.getDisabled);
206     const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateSubstitutionFilterTxt, '', [updateButton, cancelButton], 'standard');
207     this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
208     this.modalServiceNg2.addDynamicContentToModal(
209         this.modalInstance,
210         ServiceDependenciesEditorComponent,
211         {
212           serviceRuleIndex: index,
213           serviceRules: _.map(this.constraintProperties, (constraint) => new ConstraintObjectUI(constraint)),
214           currentServiceName: this.currentServiceInstance.name,
215           operatorTypes: this.operatorTypes,
216           compositeServiceName: this.compositeService.name,
217           parentServiceInputs: this.parentServiceInputs,
218           parentServiceProperties: this.parentServiceProperties,
219           selectedInstanceProperties: this.parentServiceProperties,
220         }
221     );
222     this.modalInstance.instance.open();
223   }
224
225   updateSubstitutionFilter = (constraintType: string): void => {
226     const constraintToUpdate: ConstraintObject[] = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map((rule) => new ConstraintObject(rule));
227     this.isLoading = true;
228     this.topologyTemplateService.updateSubstitutionFilterConstraints(
229         this.compositeService.uniqueId,
230         constraintToUpdate,
231         this.compositeService.componentType,
232         constraintType
233     ).subscribe((response) => {
234       this.emitEventOnChanges(constraintType, response);
235       this.isLoading = false;
236     }, () => {
237       console.error("Failed to Update Substitution Filter on the component with id: ", this.compositeService.uniqueId);
238       this.isLoading = false;
239     });
240     this.modalServiceNg2.closeCurrentModal();
241   }
242
243   onDeleteSubstitutionFilter = (constraintType: string, index: number) => {
244     this.isLoading = true;
245     this.topologyTemplateService.deleteSubstitutionFilterConstraints(
246         this.compositeService.uniqueId,
247         index,
248         this.compositeService.componentType,
249         constraintType
250     ).subscribe((response) => {
251       this.emitEventOnChanges(constraintType, response);
252       this.isLoading = false;
253     }, (error) => {
254       console.error("Failed to Delete Substitution Filter on the component with id: ",
255           this.compositeService.uniqueId, error);
256       this.isLoading = false;
257     });
258     this.modalServiceNg2.closeCurrentModal();
259   }
260
261   getDisabled = (): boolean => {
262     return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit();
263   }
264
265   getSymbol(constraintOperator) {
266     switch (constraintOperator) {
267       case OPERATOR_TYPES.LESS_THAN:
268         return '<';
269       case OPERATOR_TYPES.EQUAL:
270         return '=';
271       case OPERATOR_TYPES.GREATER_THAN:
272         return '>';
273     }
274   }
275
276   openDeleteModal = (constraintType: string, index: number) => {
277     this.modalServiceNg2.createActionModal(I18nTexts.deleteSubstitutionFilterTxt, I18nTexts.deleteSubstitutionFilterMsg,
278         I18nTexts.modalDelete, () => this.onDeleteSubstitutionFilter(constraintType, index), I18nTexts.modalCancel).instance.open();
279   }
280
281   private emitEventOnChanges(constraintType: string, response) {
282       if (ToscaFilterConstraintType.PROPERTIES === constraintType) {
283               this.updateSubstitutionFilterProperties.emit(response.properties);
284               this.constraintProperties = response.properties;
285       }
286   }
287 }