blob: 18dffa069d9cea9a2ae386ddac12f633292a06e8 [file] [log] [blame]
kumaran.m3b4814a2020-05-01 19:48:54 +05301/*
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 */
21import { Component, Injector, OnInit } from '@angular/core';
22import { Router } from '@angular/router';
23import { TranslateService } from '@ngx-translate/core';
24import { CONFIGCONSTANT, CONSTANTNUMBER, ERRORDATA, VIM_TYPES } from 'CommonModel';
25import { DataService } from 'DataService';
26import { environment } from 'environment';
27import { LocalDataSource } from 'ng2-smart-table';
28import { NSInstanceDetails } from 'NSInstanceModel';
29import Feature from 'ol/Feature';
30import Point from 'ol/geom/Point';
31import { defaults as defaultInteractions } from 'ol/interaction';
32import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
33import Map from 'ol/Map';
34import Overlay from 'ol/Overlay';
35import { fromLonLat } from 'ol/proj.js';
36import OSM from 'ol/source/OSM';
37import VectorSource from 'ol/source/Vector';
38import { Icon, Style } from 'ol/style';
39import View from 'ol/View';
40import { RestService } from 'RestService';
41import { Subscription } from 'rxjs';
42import { SharedService } from 'SharedService';
43import { VimAccountDetails, VIMData } from 'VimAccountModel';
44import { VimAccountsActionComponent } from 'VimAccountsAction';
45/**
46 * Creating component
47 * @Component takes VimAccountDetailsComponent.html as template url
48 */
49@Component({
50 selector: 'app-vim-account-details',
51 templateUrl: './VimAccountDetailsComponent.html',
52 styleUrls: ['./VimAccountDetailsComponent.scss']
53})
54/** Exporting a class @exports VimAccountDetailsComponent */
55export class VimAccountDetailsComponent implements OnInit {
56 /** To inject services @public */
57 public injector: Injector;
58 /** handle translate @public */
59 public translateService: TranslateService;
60 /** initially show the map container@public */
61 public showMap: boolean;
62 /** hide and show popup @public */
63 public popupShow: boolean = false;
64 /** Data of smarttable populate through LocalDataSource @public */
65 public dataSource: LocalDataSource = new LocalDataSource();
66 /** Columns list of the smart table @public */
67 public columnLists: object = {};
68 /** Settings for smarttable to populate the table with columns @public */
69 public settings: object = {};
70 /** initially hide the list@private */
71 public showList: boolean;
72 /** to store locations name @public */
73 public getLocation: GetLocation[];
74 /** Contains content for map popup @public */
75 public popupData: string;
76 /** Check the loading results @public */
77 public isLoadingResults: boolean = true;
78 /** Give the message for the loading @public */
79 public message: string = 'PLEASEWAIT';
80 /** Class for empty and present data @public */
81 public checkDataClass: string;
82 /** Formation of appropriate Data for LocalDatasource @public */
83 public vimData: VIMData[];
84 /** operational State init data @public */
85 public operationalStateFirstStep: string = CONFIGCONSTANT.vimOperationalStateFirstStep;
86 /** operational State running data @public */
87 public operationalStateSecondStep: string = CONFIGCONSTANT.vimOperationalStateStateSecondStep;
88 /** operational State failed data @public */
89 public operationalStateThirdStep: string = CONFIGCONSTANT.vimOperationalStateThirdStep;
90 /** NS Instances operational State failed data @public */
91 public nsinstancesoperationalStateRunning: string = CONFIGCONSTANT.operationalStateSecondStep;
92 /** Instance of the rest service @private */
93 private restService: RestService;
94 /** dataService to pass the data from one component to another @private */
95 private dataService: DataService;
96 /** Contains all methods related to shared @private */
97 private sharedService: SharedService;
98 /** Holds the instance of router class @private */
99 private router: Router;
100 /** ns INstance Data @private */
101 private nsData: NSInstanceDetails[];
102 /** map object @private */
103 private map: Map;
104 /** used to bind marker @private */
105 private vectorSource: VectorSource;
106 /** used to bind vectorSource @private */
107 private vectorLayer: VectorLayer;
108 /** marker @private */
109 private marker: Feature;
110 /** latitude @private */
111 private lat: number;
112 /** longitude @private */
113 private lng: number;
114 /** each vector layer of marker is pushed to layers array @private */
115 private layers: VectorLayer[] = [];
116 /** locationData @private */
117 private locationData: VimAccountDetails[];
118 /** popup array @private */
119 private overLay: Overlay[] = [];
120 /** Instance of subscriptions @private */
121 private generateDataSub: Subscription;
122
123 constructor(injector: Injector) {
124 this.injector = injector;
125 this.restService = this.injector.get(RestService);
126 this.dataService = this.injector.get(DataService);
127 this.sharedService = this.injector.get(SharedService);
128 this.router = this.injector.get(Router);
129 this.translateService = this.injector.get(TranslateService);
130 }
131 /** Lifecyle Hooks the trigger before component is instantiate @public */
132 public ngOnInit(): void {
133 this.osmMapView();
134 this.listView();
135 this.generateColumns();
136 this.generateSettings();
137 this.generateData();
138 this.generateDataSub = this.sharedService.dataEvent.subscribe(() => { this.generateData(); });
139 }
140
141 /** smart table Header Colums @public */
142 public generateColumns(): void {
143 this.columnLists = {
144 name: { title: this.translateService.instant('NAME'), width: '15%', sortDirection: 'asc' },
145 identifier: { title: this.translateService.instant('IDENTIFIER'), width: '25%' },
146 type: {
147 title: this.translateService.instant('TYPE'), width: '15%',
148 filter: {
149 type: 'list',
150 config: {
151 selectText: 'Select',
152 list: VIM_TYPES
153 }
154 }
155 },
156 operationalState: {
157 title: this.translateService.instant('OPERATIONALSTATUS'), width: '15%', type: 'html',
158 filter: {
159 type: 'list',
160 config: {
161 selectText: 'Select',
162 list: [
163 { value: this.operationalStateFirstStep, title: this.operationalStateFirstStep },
164 { value: this.operationalStateSecondStep, title: this.operationalStateSecondStep },
165 { value: this.operationalStateThirdStep, title: this.operationalStateThirdStep }
166 ]
167 }
168 },
169 valuePrepareFunction: (cell: VIMData, row: VIMData): string => {
170 if (row.operationalState === this.operationalStateFirstStep) {
171 return `<span class="icon-label" title="${row.operationalState}">
172 <i class="fas fa-clock text-warning"></i>
173 </span>`;
174 } else if (row.operationalState === this.operationalStateSecondStep) {
175 return `<span class="icon-label" title="${row.operationalState}">
176 <i class="fas fa-check-circle text-success"></i>
177 </span>`;
178 } else if (row.operationalState === this.operationalStateThirdStep) {
179 return `<span class="icon-label" title="${row.operationalState}">
180 <i class="fas fa-times-circle text-danger"></i>
181 </span>`;
182 } else {
183 return `<span>${row.operationalState}</span>`;
184 }
185 }
186 },
187 description: { title: this.translateService.instant('DESCRIPTION'), width: '25%' },
188 Actions: {
189 name: 'Action', width: '5%', filter: false, sort: false, title: this.translateService.instant('ACTIONS'), type: 'custom',
190 valuePrepareFunction: (cell: VIMData, row: VIMData): VIMData => row,
191 renderComponent: VimAccountsActionComponent
192 }
193 };
194 }
195
196 /** smart table Data Settings @public */
197 public generateSettings(): void {
198 this.settings = {
199 edit: {
200 editButtonContent: '<i class="fa fa-edit" title="Edit"></i>',
201 confirmSave: true
202 },
203 delete: {
204 deleteButtonContent: '<i class="far fa-trash-alt" title="delete"></i>',
205 confirmDelete: true
206 },
207 columns: this.columnLists,
208 actions: {
209 add: false,
210 edit: false,
211 delete: false,
212 position: 'right'
213 },
214 attr: this.sharedService.tableClassConfig(),
215 pager: this.sharedService.paginationPagerConfig(),
216 noDataMessage: this.translateService.instant('NODATAMSG')
217 };
218 }
219
220 /** smart table listing manipulation @public */
221 public onChange(perPageValue: number): void {
222 this.dataSource.setPaging(1, perPageValue, true);
223 }
224
225 /** smart table listing manipulation @public */
226 public onUserRowSelect(event: MessageEvent): void {
227 Object.assign(event.data, { page: 'vim-account' });
228 this.dataService.changeMessage(event.data);
229 }
230
231 /** on Navigate to Composer Page @public */
232 public composeVIM(): void {
233 this.router.navigate(['vim/new']).catch(() => {
234 //empty block
235 });
236 }
237
238 /** To show map conatainer @public */
239 public mapView(): void {
240 this.showList = true;
241 this.showMap = false;
242 }
243 /** To show listview @public */
244 public listView(): void {
245 this.showMap = true;
246 this.showList = false;
247 }
248 /** Load the datasource appropriatetype @public */
249 public loadDatasource(getdata: VIMData[]): void {
250 if (getdata.length > 0) {
251 this.checkDataClass = 'dataTables_present';
252 } else {
253 this.checkDataClass = 'dataTables_empty';
254 }
255 this.dataSource.load(getdata).then((data: boolean) => {
256 //empty block
257 }).catch(() => {
258 //empty block
259 });
260 }
261
262 /** Generate generateVIMData object from loop and return for the datasource @public */
263 public generateVIMData(vimAccountData: VimAccountDetails): VIMData {
264 return {
265 name: vimAccountData.name,
266 identifier: vimAccountData._id,
267 type: vimAccountData.vim_type,
268 operationalState: vimAccountData._admin.operationalState,
269 description: vimAccountData.description,
SANDHYA.JS4a7a5422021-05-15 15:35:22 +0530270 instancesData: this.nsData,
271 resources: vimAccountData.resources !== undefined ? vimAccountData.resources : null
kumaran.m3b4814a2020-05-01 19:48:54 +0530272 };
273 }
274
275 /**
276 * Lifecyle hook which get trigger on component destruction
277 */
278 public ngOnDestroy(): void {
279 this.generateDataSub.unsubscribe();
280 }
281
282 /** Fetching the data from server to Load in the smarttable @protected */
283 private generateData(): void {
284 this.isLoadingResults = true;
285 this.vimData = [];
286 this.getNSData().then((): void => {
287 this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccountsData: VimAccountDetails[]) => {
288 this.locationData = vimAccountsData;
289 vimAccountsData.forEach((vimAccountData: VimAccountDetails) => {
290 const vimDataObj: VIMData = this.generateVIMData(vimAccountData);
291 this.vimData.push(vimDataObj);
292 });
293 this.loadDatasource(this.vimData);
294 this.removeLayersOverLay();
295 this.arrayOfLocation();
296 this.isLoadingResults = false;
297 }, (error: ERRORDATA) => {
298 this.restService.handleError(error, 'get');
299 this.isLoadingResults = false;
300 });
301 }).catch((error: ERRORDATA): void => {
302 this.restService.handleError(error, 'get');
303 this.isLoadingResults = false;
304 });
305 }
306
307 /** fetching the nsdata @private */
308 private async getNSData(): Promise<Boolean> {
309 return new Promise<Boolean>((resolve: Function, reject: Function): void => {
310 this.nsData = [];
311 this.restService.getResource(environment.NSDINSTANCES_URL).subscribe((nsdInstancesData: NSInstanceDetails[]) => {
312 const nsRunningInstancesData: NSInstanceDetails[] = nsdInstancesData.filter((instancesData: NSInstanceDetails) =>
Barath Kumar Rd477b852020-07-07 15:24:05 +0530313 instancesData['operational-status'] === this.nsinstancesoperationalStateRunning);
kumaran.m3b4814a2020-05-01 19:48:54 +0530314 this.nsData = nsRunningInstancesData;
315 resolve(true);
316 }, (error: ERRORDATA) => {
317 this.restService.handleError(error, 'get');
318 resolve(true);
319 });
320 });
321 }
322
323 /** create map view @private */
324 private osmMapView(): void {
325 this.map = new Map({
326 target: 'map',
327 layers: [new TileLayer({
328 source: new OSM()
329 })],
330 interactions: defaultInteractions({
331 mouseWheelZoom: true
332 }),
333 view: new View({
334 center: fromLonLat([CONSTANTNUMBER.osmapviewlong, CONSTANTNUMBER.osmapviewlat]),
Barath Kumar Rd477b852020-07-07 15:24:05 +0530335 zoom: 3,
336 minZoom: 1.5
kumaran.m3b4814a2020-05-01 19:48:54 +0530337 })
338 });
339 }
340
341 /** remove the layers and overlay @private */
342 private removeLayersOverLay(): void {
343 this.layers.forEach((layer: VectorLayer) => {
344 this.map.removeLayer(layer);
345 });
346 this.overLay.forEach((lay: Overlay) => {
347 this.map.removeOverlay(lay);
348 });
349 }
350
351 /** filter locations from vimaccounts @private */
352 private arrayOfLocation(): void {
353 this.getLocation = [];
354 this.locationData.filter((item: VimAccountDetails) => {
355 if (item.hasOwnProperty('config')) {
356 if (item.config.hasOwnProperty('location')) {
357 this.getLocation.push({ name: item.name, location: item.config.location, id: item._id });
358 }
359 }
360 });
361 if (this.getLocation !== []) {
362 this.getLocation.filter((loc: GetLocation) => {
363 if (loc.location !== '') {
364 const getLatLong: string[] = loc.location.split(',');
365 this.lng = +getLatLong[CONSTANTNUMBER.splitLongitude];
366 this.lat = +getLatLong[CONSTANTNUMBER.splitLatitude];
367 this.addMarker(getLatLong[0], loc.id, loc.name);
368 }
369 });
370 }
371 }
372 /** add markers on map @private */
373 private addMarker(loc: string, id: string, name: string): void {
374 const container: HTMLElement = document.getElementById('popup');
375 const closer: HTMLElement = document.getElementById('popup-closer');
376 this.popupShow = true;
377 const overlay: Overlay = this.addOverlay(container);
378 this.marker = this.addFeature(loc, id, name);
379 this.setStyleMarker();
380 this.setVectorSource();
381 this.setVectorLayer();
382 this.map.addLayer(this.vectorLayer);
383 this.layers.push(this.vectorLayer);
384 if (this.layers.length === 1) {
385 this.markerClickEvent(closer, overlay);
386 }
387 }
388 /** Create an overlay to anchor the popup to the map @private */
389 private addOverlay(container: HTMLElement): Overlay {
390 return new Overlay({
391 element: container,
392 autoPan: true,
393 autoPanAnimation: {
394 duration: 250
395 }
396 });
397 }
398 /** Return the Feature of creating a marker in the map @private */
399 private addFeature(loc: string, id: string, name: string): Feature {
400 return new Feature({
401 geometry: new Point(fromLonLat([this.lng, this.lat])),
402 location: loc,
403 Id: id,
404 vimName: name
405 });
406 }
407 /** Set the style of the marker @private */
408 private setStyleMarker(): void {
409 this.marker.setStyle(new Style({
410 image: new Icon(({
411 crossOrigin: 'anonymous',
412 src: 'assets/images/map-icon.png'
413 }))
414 }));
415 }
416 /** Set the map vector source @private */
417 private setVectorSource(): void {
418 this.vectorSource = new VectorSource({
419 features: [this.marker]
420 });
421 }
422 /** Set the map vector layer @private */
423 private setVectorLayer(): void {
424 this.vectorLayer = new VectorLayer({
425 source: this.vectorSource
426 });
427 }
428 /** Add a click handler to the map to render the popup. @private */
429 private markerClickEvent(closer: HTMLElement, overlay: Overlay): void {
430 // tslint:disable-next-line: no-any
431 this.map.on('singleclick', (evt: any) => {
432 const feature: Feature = this.map.forEachFeatureAtPixel(evt.pixel,
433 (f: Feature) => {
434 return f;
435 });
436 if (feature) {
437 this.setCoordinates(feature, overlay);
438 } else {
439 this.map.removeOverlay(overlay);
440 }
441 });
442 /** Handle close event for overlay */
443 closer.onclick = (): boolean => {
444 overlay.setPosition(undefined);
445 closer.blur();
446 return false;
447 };
448 }
449 /** Set the coordinates point if the feature is available @private */
450 // tslint:disable-next-line: no-any
451 private setCoordinates(feature: any, overlay: Overlay): void {
452 this.popupData = '';
Barath Kumar R1245fc82021-04-16 13:34:06 +0530453 this.popupData += '<h3 class="popover-header">' + feature.values_.vimName + '- (' + feature.values_.location + ')</h3>';
kumaran.m3b4814a2020-05-01 19:48:54 +0530454 this.popupData += '<ul class="list-unstyled m-2">';
455 const instnaceData: NSInstanceDetails[] = this.nsData.filter((item: NSInstanceDetails) => {
456 if (item.datacenter === feature.values_.Id) {
Barath Kumar R1245fc82021-04-16 13:34:06 +0530457 this.popupData += '<li class="m-2"><a class="d-block text-truncate" target="_parent" href="instances/ns/' + item._id + '"><i class="fa-sitemap fas icons mr-1"></i>'
kumaran.m3b4814a2020-05-01 19:48:54 +0530458 + item.name + '</a></li>';
459 return item;
460 }
461 });
462 if (instnaceData.length === 0) {
463 this.popupData += '<li class="m-2">' + this.translateService.instant('PAGE.DASHBOARD.NOINSTANCES') + '</li>';
464 }
465 this.popupData += '</ul>';
466 const coordinates: number[] = feature.getGeometry().getCoordinates();
467 overlay.setPosition(coordinates);
468 this.overLay.push(overlay);
469 this.map.addOverlay(overlay);
470 }
471}
472
473/** interface for get location */
474interface GetLocation {
475 location: string;
476 id: string;
477 name?: string;
478}