NG-UI Design Changes
[osm/NG-UI.git] / src / services / SharedService.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 Provider for Shared Service
20  */
21 import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
22 import { EventEmitter, Injectable, Output } from '@angular/core';
23 import { FormArray, FormGroup } from '@angular/forms';
24 import { Router } from '@angular/router';
25 import { CONSTANTNUMBER, ERRORDATA, GETAPIURLHEADER, PACKAGEINFO, PAGERSMARTTABLE, SMARTTABLECLASS, TARSETTINGS } from 'CommonModel';
26 import { environment } from 'environment';
27 import * as HttpStatus from 'http-status-codes';
28 import * as untar from 'js-untar';
29 import * as pako from 'pako';
30 import { RestService } from 'RestService';
31 import { isNullOrUndefined } from 'util';
32
33 /** This is added globally by the tar.js library */
34 // tslint:disable-next-line: no-any
35 declare const Tar: any;
36
37 /**
38  * An Injectable is a class adorned with the @Injectable decorator function.
39  * @Injectable takes a metadata object that tells Angular how to compile and run module code
40  */
41 @Injectable({
42     providedIn: 'root'
43 })
44 /** Exporting a class @exports SharedService */
45 export class SharedService {
46     /** call the parent using event information @private */
47     @Output() public dataEvent: EventEmitter<{}> = new EventEmitter<{}>();
48
49     /** Variables to hold regexp pattern for URL */
50     // tslint:disable-next-line: max-line-length
51     public REGX_URL_PATTERN: RegExp = new RegExp(/^(http?|ftp|https):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z0-9]{2,15})(:((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4})))*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/);
52
53     /** Variables to hold regexp pattern for IP Address */
54     public REGX_IP_PATTERN: RegExp = new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$/);
55
56     /** Variables to hold regexp pattern for Port Number */
57     // tslint:disable-next-line: max-line-length
58     public REGX_PORT_PATTERN: RegExp = new RegExp(/^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$/);
59
60     /** Variables to hold regexp pattern for DPID */
61     public REGX_DPID_PATTERN: RegExp = new RegExp(/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){7}$/);
62
63     /** Variable to hold regexp pattern for password */
64     // tslint:disable-next-line: max-line-length
65     public REGX_PASSWORD_PATTERN: RegExp = new RegExp(/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/);
66
67     /** FormGroup instance added to the form @ html @public */
68     public formGroup: FormGroup;
69
70     /** Controls the go to top button on scroll  @public */
71     public showGotoTop: boolean;
72
73     /** Holds OSM Version value @public */
74     public osmVersion: string;
75
76     /** express number for time manupulation -2 */
77     private epochTimeMinus2: number = -2;
78
79     /** express number for time manupulation 1000 */
80     private epochTime1000: number = 1000;
81
82     /** Random string generator length */
83     private randomStringLength: number = 4;
84
85     /** Instance of the rest service @private */
86     private restService: RestService;
87
88     /** Service holds the router information @private */
89     private router: Router;
90
91     /** Random color string generator length @private */
92     private colorStringLength: number = 256;
93
94     /** Check for the root directory @private */
95     private directoryCount: number = 2;
96
97     constructor(restService: RestService, router: Router) {
98         this.restService = restService;
99         this.router = router;
100     }
101
102     /** convert epoch time function @public */
103     public convertEpochTime(unixtimestamp: number): string {
104         const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
105             'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
106         const date: Date = new Date(unixtimestamp * this.epochTime1000);
107         const year: number = date.getFullYear();
108         const month: string = monthsArr[date.getMonth()];
109         const day: number = date.getDate();
110         const hours: number = date.getHours();
111         const minutes: string = '0' + date.getMinutes();
112         const seconds: string = '0' + date.getSeconds();
113         return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
114             + seconds.substr(this.epochTimeMinus2);
115     }
116
117     /** Download Files function @public */
118     public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
119         const downloadLink: HTMLAnchorElement = document.createElement('a');
120         downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
121         if (shortName !== undefined) {
122             if (window.navigator.msSaveOrOpenBlob) {
123                 window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
124             } else {
125                 downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
126                 document.body.appendChild(downloadLink);
127                 downloadLink.click();
128             }
129         }
130     }
131
132     /** Call this method after delete perform action is completed in the ng-smart-table data @public */
133     public callData(): void {
134         this.dataEvent.emit();
135     }
136
137     /** Generate random string @public */
138     public randomString(): string {
139         const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
140         let result: string = '';
141         // tslint:disable-next-line:no-increment-decrement
142         for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
143             result += chars[Math.floor(Math.random() * chars.length)];
144         }
145         return result;
146     }
147     /** Function to read uploaded file String @public */
148     public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
149         const reader: FileReader = new FileReader();
150         return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
151             if (this.vaildataFileInfo(files[0], fileType)) {
152                 this.readFileContent(reader, files[0], fileType);
153             } else {
154                 reject('typeError');
155             }
156             reader.onload = (): void => {
157                 if (reader.result === null) {
158                     reject('contentError');
159                 }
160                 resolve(reader.result);
161             };
162             reader.onerror = (event: Event): void => {
163                 reject('contentError');
164             };
165         });
166     }
167     /** Method to handle tar and tar.gz file for shared YAML file content @public */
168     public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
169         return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
170             const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
171             let apiUrl: string = '';
172             apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
173                 environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
174             this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
175                 try {
176                     // tslint:disable-next-line: no-any
177                     const tar: any = new Tar();
178                     const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
179                     untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
180                         const getFoldersFiles: {}[] = extractedFiles;
181                         const folderNameStr: string = extractedFiles[0].name;
182                         getFoldersFiles.forEach((value: TARSETTINGS) => {
183                             const getRootFolder: string[] = value.name.split('/');
184                             if (value.name.startsWith(folderNameStr) &&
185                                 (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
186                                 getRootFolder.length === this.directoryCount) {
187                                 tar.append(value.name, packageInfo.descriptor, { type: value.type });
188                             } else {
189                                 if (value.type !== 'L') {
190                                     tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
191                                 }
192                             }
193                         });
194                         const out: Uint8Array = tar.out;
195                         const originalOutput: Uint8Array = pako.gzip(out);
196                         resolve(originalOutput.buffer);
197                     }, (err: string) => {
198                         reject('');
199                     });
200                 } catch (e) {
201                     reject('');
202                 }
203             }, (error: HttpErrorResponse) => {
204                 if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
205                     this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
206                 } else {
207                     this.restService.handleError(error, 'get');
208                     reject('');
209                 }
210             });
211         });
212     }
213     /** Method to check given string is JSON or not @public */
214     public checkJson(jsonString: string): boolean {
215         jsonString = jsonString.replace(/'/g, '"');
216         try {
217             JSON.parse(jsonString);
218         } catch (e) {
219             return false;
220         }
221         return true;
222     }
223     /** Clean the form before submit @public */
224     public cleanForm(formGroup: FormGroup): void {
225         Object.keys(formGroup.controls).forEach((key: string) => {
226             if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'vimconfig') {
227                 // tslint:disable-next-line: no-shadowed-variable
228                 for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
229                     const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
230                     this.cleanForm(newFormGroup);
231                 }
232             } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'vimconfig') {
233                 if (!Array.isArray(formGroup.get(key).value)) {
234                     if (typeof formGroup.get(key).value === 'string') {
235                         formGroup.get(key).setValue(formGroup.get(key).value.trim());
236                     }
237                 }
238             } else if (key === 'vimconfig') {
239                 const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
240                 this.cleanForm(newFormGroup);
241             }
242         });
243     }
244     /** Method to return the config of pager value for ngSmarttable @public */
245     public paginationPagerConfig(): PAGERSMARTTABLE {
246         return {
247             display: true,
248             perPage: environment.paginationNumber
249         };
250     }
251     /** Method to return the class for the table for ngSmarttable @public */
252     public tableClassConfig(): SMARTTABLECLASS {
253         return {
254             class: 'table list-data'
255         };
256     }
257     /** Method to return all languages name and its code @public */
258     public languageCodeList(): {}[] {
259         return [
260             { code: 'en', language: 'English' },
261             { code: 'es', language: 'Spanish' },
262             { code: 'pt', language: 'Portuguese' },
263             { code: 'de', language: 'German' }
264         ];
265     }
266     /** Fetch OSM Version @public */
267     public fetchOSMVersion(): void {
268         this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
269             const version: string[] = res.version.split('+');
270             if (!isNullOrUndefined(version[0])) {
271                 this.osmVersion = version[0];
272             } else {
273                 this.osmVersion = null;
274             }
275         }, (error: ERRORDATA) => {
276             this.osmVersion = null;
277             this.restService.handleError(error, 'get');
278         });
279     }
280     /** Random RGB color code generator @public */
281     public generateColor(): string {
282         const x: number = Math.floor(Math.random() * this.colorStringLength);
283         const y: number = Math.floor(Math.random() * this.colorStringLength);
284         const z: number = Math.floor(Math.random() * this.colorStringLength);
285         return 'rgb(' + x + ',' + y + ',' + z + ')';
286     }
287     /** Method to validate file extension and size @private */
288     private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
289         const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
290         const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
291         if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
292             return true;
293         }
294         return false;
295     }
296     /** Method to read file content based on type @private */
297     private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
298         if (fileType === 'gz') {
299             reader.readAsArrayBuffer(fileInfo);
300         } else {
301             reader.readAsText(fileInfo);
302         }
303     }
304     /** Method to handle http options @public */
305     private getHttpOptions(): GETAPIURLHEADER {
306         return {
307             headers: new HttpHeaders({
308                 Accept: 'application/gzip, application/json',
309                 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
310             }),
311             responseType: 'arraybuffer'
312         };
313     }
314 }