New VIM Design with the config implemented.
[osm/NG-UI.git] / src / app / vim-accounts / new-vimaccount / NewVimaccountComponent.ts
1 /*
2  Copyright 2020 TATA ELXSI
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 or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17 */
18 /**
19  * @file Vim Account Component.
20  */
21 import { HttpHeaders } from '@angular/common/http';
22 import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
23 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
24 import { Router } from '@angular/router';
25 import { TranslateService } from '@ngx-translate/core';
26 import { NotifierService } from 'angular-notifier';
27 import 'codemirror/addon/dialog/dialog';
28 import 'codemirror/addon/display/autorefresh';
29 import 'codemirror/addon/display/fullscreen';
30 import 'codemirror/addon/edit/closebrackets';
31 import 'codemirror/addon/edit/matchbrackets';
32 import 'codemirror/addon/fold/brace-fold';
33 import 'codemirror/addon/fold/foldcode';
34 import 'codemirror/addon/fold/foldgutter';
35 import 'codemirror/addon/search/search';
36 import 'codemirror/addon/search/searchcursor';
37 import 'codemirror/keymap/sublime';
38 import 'codemirror/lib/codemirror';
39 import 'codemirror/mode/javascript/javascript';
40 import 'codemirror/mode/markdown/markdown';
41 import 'codemirror/mode/yaml/yaml';
42 import {
43   APIURLHEADER, ERRORDATA, TYPEAWS, TYPEAZURE, TYPEOPENSTACK, TYPEOPENVIMNEBULA, TYPEOTERS,
44   TYPESECTION, TYPEVMWARE, VIM_TYPES
45 } from 'CommonModel';
46 import { environment } from 'environment';
47 import * as jsyaml from 'js-yaml';
48 import { RestService } from 'RestService';
49 import { SharedService } from 'SharedService';
50 import { isNullOrUndefined } from 'util';
51 import { FEATURES, VIMLOCATION, VIMLOCATIONDATA } from 'VimAccountModel';
52 import { VimAccountDetails, VIMData } from 'VimAccountModel';
53
54 /**
55  * Creating component
56  * @Component takes NewVimaccountComponent.html as template url
57  */
58 @Component({
59   selector: 'app-new-vimaccount',
60   templateUrl: './NewVimaccountComponent.html',
61   styleUrls: ['./NewVimaccountComponent.scss']
62 })
63 /** Exporting a class @exports NewVimaccountComponent */
64 export class NewVimaccountComponent implements OnInit {
65   /** To inject services @public */
66   public injector: Injector;
67
68   /** FormGroup vim New Account added to the form @ html @public */
69   public vimNewAccountForm: FormGroup;
70
71   /** Supported Vim type for the dropdown */
72   public vimType: TYPESECTION[];
73
74   /** Supported Vim type for the dropdown */
75   public selectedVimType: string;
76
77   /** Supported true and false value for the dropdown */
78   public boolValue: {}[];
79
80   /** Form submission Add */
81   public submitted: boolean = false;
82
83   /** Showing more details of collapase */
84   public isCollapsed: boolean = false;
85
86   /** Vim location values @public */
87   public getVIMLocation: VIMLOCATIONDATA[] = [];
88
89   /** Check the Projects loading results @public */
90   public isLocationLoadingResults: boolean = false;
91
92   /** Give the message for the loading @public */
93   public message: string = 'PLEASEWAIT';
94
95   /** set the longitude value of the selected place @public */
96   public setLong: number;
97
98   /** set the latitude value of the selected place @public */
99   public setLat: number;
100
101   /** Handle the formate Change @public */
102   public defaults: {} = {
103     'text/x-yaml': ''
104   };
105
106   /** To Set Mode @public */
107   public mode: string = 'text/x-yaml';
108
109   /** To Set Mode @public */
110   public modeDefault: string = 'yaml';
111
112   /** options @public */
113   public options: {} = {
114     mode: this.modeDefault,
115     showCursorWhenSelecting: true,
116     autofocus: true,
117     autoRefresh: true,
118     lineNumbers: true,
119     lineWrapping: true,
120     foldGutter: true,
121     gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
122     autoCloseBrackets: true,
123     matchBrackets: true,
124     theme: 'neat',
125     keyMap: 'sublime'
126   };
127
128   /** Data @public */
129   public data: string = '';
130
131   /** Controls the File Type List form @public */
132   public fileTypes: { value: string; viewValue: string; }[] = [];
133
134   /** Element ref for fileInput @public */
135   @ViewChild('fileInput', { static: true }) public fileInput: ElementRef;
136
137   /** Element ref for fileInput @public */
138   @ViewChild('fileInputLabel', { static: true }) public fileInputLabel: ElementRef;
139
140   /** Contains all methods related to shared @private */
141   public sharedService: SharedService;
142
143   /** Instance of the rest service @private */
144   private restService: RestService;
145
146   /** Holds the instance of router class @private */
147   private router: Router;
148
149   /** Controls the header form @private */
150   private headers: HttpHeaders;
151
152   /** FormBuilder instance added to the formBuilder @private */
153   private formBuilder: FormBuilder;
154
155   /** Notifier service to popup notification @private */
156   private notifierService: NotifierService;
157
158   /** Contains tranlsate instance @private */
159   private translateService: TranslateService;
160
161   /** VIM Details @private */
162   private vimDetail: VimAccountDetails[];
163
164   /** convenience getter for easy access to form fields */
165   get f(): FormGroup['controls'] { return this.vimNewAccountForm.controls; }
166
167   constructor(injector: Injector) {
168     this.injector = injector;
169     this.restService = this.injector.get(RestService);
170     this.formBuilder = this.injector.get(FormBuilder);
171     this.router = this.injector.get(Router);
172     this.notifierService = this.injector.get(NotifierService);
173     this.translateService = this.injector.get(TranslateService);
174     this.sharedService = this.injector.get(SharedService);
175
176     /** Initializing Form Action */
177     this.vimNewAccountForm = this.formBuilder.group({
178       name: [null, Validators.required],
179       vim_type: [null, Validators.required],
180       vim_tenant_name: [null, Validators.required],
181       description: [null],
182       vim_url: [null, [Validators.required, Validators.pattern(this.sharedService.REGX_URL_PATTERN)]],
183       schema_type: [''],
184       vim_user: [null, Validators.required],
185       vim_password: [null, Validators.required],
186       config: this.paramsBuilder()
187     });
188   }
189
190   /** Generate params for config @public */
191   public paramsBuilder(): FormGroup {
192     return this.formBuilder.group({
193       location: [null]
194     });
195   }
196
197   /**
198    * Lifecyle Hooks the trigger before component is instantiate
199    */
200   public ngOnInit(): void {
201     this.fileTypes = [{ value: 'text/x-yaml', viewValue: 'yaml' }];
202     this.vimType = VIM_TYPES;
203     this.boolValue = [
204       { id: '', name: 'None' },
205       { id: true, name: 'True' },
206       { id: false, name: 'False' }
207     ];
208     this.headers = new HttpHeaders({
209       Accept: 'application/json',
210       'Content-Type': 'application/json',
211       'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
212     });
213     this.getVIMDetails();
214   }
215
216   /** On modal submit newVimAccountSubmit will called @public */
217   public newVimAccountSubmit(): void {
218     this.submitted = true;
219     if (!this.vimNewAccountForm.invalid) {
220       this.isLocationLoadingResults = true;
221       this.sharedService.cleanForm(this.vimNewAccountForm, 'vim');
222       if (!isNullOrUndefined(this.data) && this.data !== '') {
223         Object.assign(this.vimNewAccountForm.value.config, jsyaml.load(this.data.toString(), { json: true }));
224       } else {
225         Object.keys(this.vimNewAccountForm.value.config).forEach((res: string) => {
226           if (res !== 'location') {
227             delete this.vimNewAccountForm.value.config[res];
228           }
229         });
230       }
231
232       if (isNullOrUndefined(this.vimNewAccountForm.value.config.location)) {
233         delete this.vimNewAccountForm.value.config.location;
234       }
235       Object.keys(this.vimNewAccountForm.value.config).forEach((res: string) => {
236         if (isNullOrUndefined(this.vimNewAccountForm.value.config[res]) || this.vimNewAccountForm.value.config[res] === '') {
237           delete this.vimNewAccountForm.value.config[res];
238         }
239       });
240       const apiURLHeader: APIURLHEADER = {
241         url: environment.VIMACCOUNTS_URL,
242         httpOptions: { headers: this.headers }
243       };
244       this.restService.postResource(apiURLHeader, this.vimNewAccountForm.value)
245         .subscribe((result: {}) => {
246           this.notifierService.notify('success', this.translateService.instant('PAGE.VIM.CREATEDSUCCESSFULLY'));
247           this.isLocationLoadingResults = false;
248           this.router.navigate(['vim/details']).catch(() => {
249             // Error Cached;
250           });
251           // Post the New Vim data and reflect in the VIM Details Page.
252         }, (error: ERRORDATA) => {
253           this.restService.handleError(error, 'post');
254           this.isLocationLoadingResults = false;
255         });
256     }
257   }
258
259   /** HandleChange function @public */
260   public handleChange($event: string): void {
261     this.data = $event;
262   }
263
264   /** Routing to VIM Account Details Page @public */
265   public onVimAccountBack(): void {
266     this.router.navigate(['vim/details']).catch(() => {
267       // Error Cached
268     });
269   }
270
271   /** Fetching the location with name,latitude,longitude @public */
272   public fetchLocationLatLong(value: string): void {
273     this.isLocationLoadingResults = true;
274     const newVIMLocation: VIMLOCATIONDATA[] = [];
275     const locationTrack: string = environment.MAPLATLONGAPI_URL;
276     const locationAPIURL: string = locationTrack.replace('{value}', value);
277     this.restService.getResource(locationAPIURL).subscribe((result: VIMLOCATION) => {
278       result.features.forEach((getFeturesResult: FEATURES) => {
279         if ('extent' in getFeturesResult.properties) {
280           getFeturesResult.properties.extent.forEach((extentResult: number, index: number) => {
281             if (index === 0) {
282               this.setLong = extentResult;
283             }
284             if (index === 1) {
285               this.setLat = extentResult;
286             }
287           });
288         } else {
289           getFeturesResult.geometry.coordinates.forEach((coordinateResult: number, index: number) => {
290             if (index === 0) {
291               this.setLong = coordinateResult;
292             }
293             if (index === 1) {
294               this.setLat = coordinateResult;
295             }
296           });
297         }
298         newVIMLocation.push({
299           label: getFeturesResult.properties.name + ',' + getFeturesResult.properties.state + ', ' + getFeturesResult.properties.country,
300           value: getFeturesResult.properties.name + ',' + this.setLong + ',' + this.setLat
301         });
302       });
303       this.getVIMLocation = newVIMLocation;
304       this.isLocationLoadingResults = false;
305     }, (error: ERRORDATA) => {
306       this.restService.handleError(error, 'get');
307       this.isLocationLoadingResults = false;
308     });
309   }
310
311   /** Drag and drop feature and fetchind the details of files  @private */
312   public filesDropped(files: FileList): void {
313     if (files && files.length === 1) {
314       this.sharedService.getFileString(files, 'yaml').then((fileContent: string): void => {
315         const getJson: string = jsyaml.load(fileContent, { json: true });
316         this.defaults['text/x-yaml'] = fileContent;
317         this.data = fileContent;
318       }).catch((err: string): void => {
319         if (err === 'typeError') {
320           this.notifierService.notify('error', this.translateService.instant('YAMLFILETYPEERRROR'));
321         } else {
322           this.notifierService.notify('error', this.translateService.instant('ERROR'));
323         }
324         this.fileInputLabel.nativeElement.innerText = this.translateService.instant('CHOOSEFILE');
325         this.fileInput.nativeElement.value = null;
326       });
327     } else if (files && files.length > 1) {
328       this.notifierService.notify('error', this.translateService.instant('DROPFILESVALIDATION'));
329     }
330     this.fileInputLabel.nativeElement.innerText = files[0].name;
331     this.fileInput.nativeElement.value = null;
332   }
333
334   /** Location chnage event in select box @public */
335   public locationChange(data: { value: string }): void {
336     this.vimDetail.forEach((vimAccountData: VimAccountDetails) => {
337       if (!isNullOrUndefined(vimAccountData.config.location) && !isNullOrUndefined(data)) {
338         if (vimAccountData.config.location === data.value) {
339           this.notifierService.notify('error', this.translateService.instant('PAGE.VIMDETAILS.LOCATIONERROR'));
340           // tslint:disable-next-line: no-backbone-get-set-outside-model
341           this.vimNewAccountForm.controls.config.get('location').setValue(null);
342         }
343       }
344     });
345   }
346
347   /** Load sample config based on VIM type @public */
348   public loadSampleConfig(): void {
349     this.clearConfig();
350     if (this.selectedVimType === 'openstack') {
351       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEOPENSTACK);
352       this.data = JSON.stringify(TYPEOPENSTACK, null, '\t');
353     } else if (this.selectedVimType === 'aws') {
354       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEAWS);
355       this.data = JSON.stringify(TYPEAWS, null, '\t');
356     } else if (this.selectedVimType === 'vmware') {
357       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEVMWARE);
358       this.data = JSON.stringify(TYPEVMWARE, null, '\t');
359     } else if (this.selectedVimType === 'openvim' || this.selectedVimType === 'opennebula') {
360       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEOPENVIMNEBULA);
361       this.data = JSON.stringify(TYPEOPENVIMNEBULA, null, '\t');
362     } else if (this.selectedVimType === 'azure' || this.selectedVimType === 'opennebula') {
363       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEAZURE);
364       this.data = JSON.stringify(TYPEAZURE, null, '\t');
365     } else {
366       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEOTERS);
367       this.data = JSON.stringify(TYPEOTERS, null, '\t');
368     }
369   }
370
371   /** Clear config parameters @public */
372   public clearConfig(): void {
373     this.defaults['text/x-yaml'] = '';
374     this.data = '';
375     this.fileInput.nativeElement.value = null;
376   }
377
378   /** Method to get VIM details @private */
379   private getVIMDetails(): void {
380     this.isLocationLoadingResults = true;
381     this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccountsData: VimAccountDetails[]) => {
382       this.vimDetail = vimAccountsData;
383       this.isLocationLoadingResults = false;
384     }, (error: ERRORDATA) => {
385       this.restService.handleError(error, 'get');
386       this.isLocationLoadingResults = false;
387     });
388   }
389 }