1 /* eslint-disable security/detect-object-injection */
3 Copyright 2020 TATA ELXSI
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
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
17 Author: BARATH KUMAR R (barath.r@tataelxsi.co.in)
21 * @file Page for Operational View Component
23 import { isNullOrUndefined } from 'util';
24 import { Component, Injector, OnInit } from '@angular/core';
25 import { ActivatedRoute } from '@angular/router';
26 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
27 import { TranslateService } from '@ngx-translate/core';
28 import { CONSTANTNUMBER, ERRORDATA } from 'CommonModel';
29 import { environment } from 'environment';
30 import * as HttpStatus from 'http-status-codes';
31 import { OperationalViewAppActionsComponent } from 'OperationalAppActionsComponent';
32 import { OperationalViewAppConfigsComponent } from 'OperationalAppConfigsComponent';
33 import { OperationalViewAppExecutedActionsComponent } from 'OperationalAppExecutedActionsComponent';
34 import { EXECUTEDACTIONS, MACHINES, SET_TIMER, SETMODELS, SETTIMER, VCAAPPLICATIONS, VCADETAILS, VCASTATUS, VCAUNITS } from 'OperationalModel';
35 import { RestService } from 'RestService';
36 import { Observable } from 'rxjs';
37 import { Subscription } from 'rxjs';
38 import { map } from 'rxjs/operators';
39 import { SharedService } from 'SharedService';
42 * @Component takes OperationalViewComponent.html as template url
45 selector: 'app-operational-view',
46 templateUrl: './OperationalViewComponent.html'
48 /** Exporting a class @exports OperationalViewComponent */
49 export class OperationalViewComponent implements OnInit {
50 /** Invoke service injectors @public */
51 public injector: Injector;
53 /** Check the loading results @public */
54 public isLoadingResults: boolean = false;
56 /** Give the message for the loading @public */
57 public message: string = 'PLEASEWAIT';
59 /** Formation of appropriate Data for vcaStatus Details @public */
60 public vcaDetails: VCADETAILS[] = [];
62 /** Contains all methods related to shared @public */
63 public sharedService: SharedService;
65 /** Utilizes rest service for any CRUD operations @public */
66 public restService: RestService;
68 /** variables contains activeID @public */
69 public activeID: string = null;
71 /** variables contains NS Instances ID @public */
72 public instancesID: string = null;
74 /** variables contains URL of operational Dashboard @public */
75 public openURL: string = 'instances/operational-view/';
77 /** variables contains default seconds for the timeout @public */
78 public timeOutDefaultSeconds: number = CONSTANTNUMBER.timeOutDefaultSeconds;
80 /** variables contains minimum seconds for the timeout @public */
81 // eslint-disable-next-line @typescript-eslint/no-magic-numbers
82 public minSeconds: number = 5;
84 /** variables contains maximum seconds for the timeout @public */
85 // eslint-disable-next-line @typescript-eslint/no-magic-numbers
86 public maxSeconds: number = 60;
88 /** variables contains timer calculation value of milliseconds @public */
89 // eslint-disable-next-line @typescript-eslint/no-magic-numbers
90 public timeDefaultCal: number = 1000;
92 /** variables contains timeout @public */
93 public timeOut: number;
95 /** Set the timer button @public */
96 // eslint-disable-next-line no-magic-numbers
97 public setSeconds: SETTIMER[] = SET_TIMER;
99 /** Instance of subscriptions @private */
100 private generateDataSub: Subscription;
102 /** Contains tranlsate instance @private */
103 private translateService: TranslateService;
105 /** Holds teh instance of AuthService class of type AuthService @private */
106 private activatedRoute: ActivatedRoute;
108 /** Instance of the modal service @private */
109 private modalService: NgbModal;
111 /** creates Operational view component */
112 constructor(injector: Injector) {
113 this.injector = injector;
114 this.restService = this.injector.get(RestService);
115 this.sharedService = this.injector.get(SharedService);
116 this.translateService = this.injector.get(TranslateService);
117 this.activatedRoute = this.injector.get(ActivatedRoute);
118 this.modalService = this.injector.get(NgbModal);
122 * Lifecyle Hooks the trigger before component is instantiate
124 public ngOnInit(): void {
125 this.instancesID = this.activatedRoute.snapshot.paramMap.get('id');
127 this.generateDataSub = this.sharedService.dataEvent.subscribe((): void => { this.generateData(); });
129 /** Fetching the juju vca_status data from API and Load it in the respective table @public */
130 public generateData(): void {
131 this.clearTimeoutAndInterval();
132 this.modalService.dismissAll();
133 this.isLoadingResults = true;
134 this.vcaDetails = [];
135 let NSURL: string = environment.NSDINSTANCES_URL;
136 if (this.instancesID !== null) {
137 NSURL = NSURL + '/' + this.instancesID;
138 this.generateIndividualNSData(NSURL);
140 this.generateAllNSData(NSURL);
144 * Show all NS Data that contains the juju vca_status from API and Load it in the table @public
145 * @param NSURL : osm/nslcm/v1/ns_instances
147 public generateAllNSData(NSURL: string): void {
148 this.restService.getResource(NSURL).subscribe((operationalList: VCASTATUS[]): void => {
149 if (operationalList.length > 0) {
150 operationalList.forEach((list: VCASTATUS): void => {
151 if (!isNullOrUndefined(list.vcaStatus)) {
152 const getVCAStatusDetails: VCADETAILS = this.vcaDetailsData(list, false, this.timeOutDefaultSeconds);
153 this.vcaDetails.push(getVCAStatusDetails);
156 if (this.activeID === null && this.vcaDetails.length > 0) {
157 this.activeID = this.vcaDetails[0].ns_id;
160 this.isLoadingResults = false;
161 }, (error: ERRORDATA): void => {
162 this.isLoadingResults = false;
163 this.restService.handleError(error, 'get');
167 * Show the individual NS Data that contains the juju vca_status from generateNSData method and Load it in the table @public
168 * @param NSURL : osm/nslcm/v1/ns_instances/<ID>
170 public generateIndividualNSData(NSURL: string): void {
171 this.generateNSData(NSURL, false, this.timeOutDefaultSeconds).subscribe((getVCAStatusDetails: VCADETAILS): void => {
172 this.vcaDetails.push(getVCAStatusDetails);
173 if (this.activeID === null && this.vcaDetails.length > 0) {
174 this.activeID = this.instancesID;
176 this.isLoadingResults = false;
177 }, (error: ERRORDATA): void => {
178 this.isLoadingResults = false;
179 this.restService.handleError(error, 'get');
183 * Fetching the Individual NS Data that contains the juju vca_status from API and return the VCADetails @public
184 * @param NSURL : osm/nslcm/v1/ns_instances/<ID>
185 * @param liveData : Needs to repeat the httprequest
186 * @param timeOutSeconds : set the timeout seconds to trigger the httprequest
188 public generateNSData(NSURL: string, liveData: boolean, timeOutSeconds: number): Observable<VCADETAILS> {
190 NSURL = NSURL + '?vcaStatusRefresh=true';
192 return this.restService.getResource(NSURL).pipe(map((operationalList: VCASTATUS): VCADETAILS => this.vcaDetailsData(operationalList, liveData, timeOutSeconds)));
195 * Form the VCA Details for each NS Instances
197 public formVCADetails(getData: VCADETAILS): VCADETAILS {
199 isLiveloading: getData.isLiveloading,
200 ns_id: getData.ns_id,
201 vcaStatusModels: getData.vcaStatusModels,
202 timeOutSeconds: getData.timeOutSeconds,
203 vca_id: getData.vca_id,
204 vca_name: getData.vca_name
208 * Assign the VCA Status of Multiple model in getModels array for each NS Instance
210 public assignVCAStatusOfEachModel(getData: SETMODELS): SETMODELS {
212 applications: getData.applications,
213 branches: getData.branches,
214 controller_timestamp: getData.controller_timestamp,
215 executedActions: getData.executedActions,
216 machines: getData.machines,
217 model: getData.model,
218 offers: getData.offers,
219 relations: getData.relations,
220 remote_applications: getData.remote_applications,
221 units: getData.units,
222 unknown_fields: getData.unknown_fields
226 * Use to fetch the vcaDetails from vca_status @public
228 public vcaDetailsData(list: VCASTATUS, liveData: boolean, timeOutSeconds: number): VCADETAILS {
229 const assignVCADetails: VCADETAILS[] = [];
230 const setModels: SETMODELS[] = [];
231 Object.keys(list.vcaStatus).forEach((key: string): void => {
232 const vcaApplication: VCAAPPLICATIONS[] = this.appData(list.vcaStatus[key].applications);
233 const vcaUnits: VCAUNITS[] = this.unitsData(vcaApplication);
234 const vcaMachines: MACHINES[] = this.machinesData(list.vcaStatus[key].machines);
235 const assignNSInstancesID: string = key;
236 list.vcaStatus[key].units = vcaUnits;
237 list.vcaStatus[key].applications = vcaApplication;
238 list.vcaStatus[key].machines = vcaMachines;
239 // eslint-disable-next-line no-self-assign
240 list.vcaStatus[key].relations = list.vcaStatus[key].relations;
241 // eslint-disable-next-line no-self-assign
242 list.vcaStatus[key].model = list.vcaStatus[key].model;
243 const getEachModelData: SETMODELS = this.assignVCAStatusOfEachModel(list.vcaStatus[key]);
244 setModels.push(getEachModelData);
245 list.vcaStatus[assignNSInstancesID].vca_id = key;
246 list.vcaStatus[assignNSInstancesID].vca_name = list.name;
247 list.vcaStatus[assignNSInstancesID].ns_id = list.id;
248 list.vcaStatus[assignNSInstancesID].isLiveloading = liveData;
249 list.vcaStatus[assignNSInstancesID].timeOutSeconds = timeOutSeconds;
250 list.vcaStatus[assignNSInstancesID].vcaStatusModels = setModels;
251 const getAssignedData: VCADETAILS = this.formVCADetails(list.vcaStatus[assignNSInstancesID]);
252 assignVCADetails.push(getAssignedData);
254 return assignVCADetails[0];
257 * Use to fetch the app data from vca_status @public
259 public appData(applicationData: VCAAPPLICATIONS): VCAAPPLICATIONS[] {
260 const vcaApplication: VCAAPPLICATIONS[] = [];
261 Object.keys(applicationData).forEach((applicationKey: string): void => {
262 const charmSplitlist: string[] = applicationData[applicationKey].charm.split('/');
263 const status: string = applicationData[applicationKey].status.status;
264 // eslint-disable-next-line deprecation/deprecation
265 const charm: string = charmSplitlist[1].substr(0, charmSplitlist[1].lastIndexOf('-'));
266 // eslint-disable-next-line deprecation/deprecation
267 const store: string = charmSplitlist[0].substr(0, charmSplitlist[0].lastIndexOf(':'));
268 applicationData[applicationKey].app_id = applicationKey;
269 applicationData[applicationKey].charm = charm;
270 applicationData[applicationKey].status = status;
271 applicationData[applicationKey].scale = Object.keys(applicationData[applicationKey].units).length;
272 applicationData[applicationKey].store = store;
273 applicationData[applicationKey].configs = !isNullOrUndefined(applicationData[applicationKey].configs) ?
274 applicationData[applicationKey].configs : null;
275 applicationData[applicationKey].actions = !isNullOrUndefined(applicationData[applicationKey].actions) ?
276 applicationData[applicationKey].actions : null;
277 vcaApplication.push(applicationData[applicationKey]);
279 return vcaApplication;
282 * Use to fetch the units data from vca_status @public
284 public unitsData(applicationData: VCAAPPLICATIONS[]): VCAUNITS[] {
285 const vcaUnits: VCAUNITS[] = [];
286 applicationData.forEach((applicationList: VCAAPPLICATIONS): void => {
287 Object.keys(applicationList.units).forEach((unitsKey: string): void => {
288 applicationList.units[unitsKey].unit_id = unitsKey;
289 vcaUnits.push(applicationList.units[unitsKey]);
295 * Use to fetch the machines data from vca_status @public
297 public machinesData(machinesData: MACHINES[]): MACHINES[] {
298 const vcaMachines: MACHINES[] = [];
299 Object.keys(machinesData).forEach((machineKey: string): void => {
300 vcaMachines.push(machinesData[machineKey]);
304 /** Show the Config list in modal using modalservice @public */
305 public showExecutedActionsList(executeActionsList: EXECUTEDACTIONS[]): void {
306 // eslint-disable-next-line security/detect-non-literal-fs-filename
307 this.modalService.open(OperationalViewAppExecutedActionsComponent, { size: 'xl', backdrop: 'static' })
308 .componentInstance.params = { executedActions: executeActionsList };
310 /** Show the Config list in modal using modalservice @public */
311 public showConfigList(configList: object): void {
312 // eslint-disable-next-line security/detect-non-literal-fs-filename
313 this.modalService.open(OperationalViewAppConfigsComponent, { size: 'xl', backdrop: 'static' })
314 .componentInstance.params = { configs: configList };
316 /** Show the Config list in modal using modalservice @public */
317 public showActionsList(actionsList: object): void {
318 // eslint-disable-next-line security/detect-non-literal-fs-filename
319 this.modalService.open(OperationalViewAppActionsComponent, { size: 'xl', backdrop: 'static' })
320 .componentInstance.params = { actions: actionsList };
322 /** Call the live data to fetch the latest results @public */
323 public callLiveData(isChecked: boolean, getNSID: string, index: number): void {
324 this.vcaDetails[index].isLiveloading = isChecked;
326 this.stopExistingModelLiveLoading(getNSID);
327 this.generateRefreshedData(getNSID, index, this.vcaDetails[index].timeOutSeconds);
329 this.clearTimeoutAndInterval();
332 /** Fetching the juju vca_status data from API and Load it in the respective model @public */
333 public generateRefreshedData(getNSID: string, index: number, secondsValue: number): void {
334 this.modalService.dismissAll();
335 const liveDataURL: string = environment.NSDINSTANCES_URL + '/' + getNSID;
336 this.generateNSData(liveDataURL, true, secondsValue).subscribe((getVCAStatusDetails: VCADETAILS): void => {
337 this.vcaDetails[index] = getVCAStatusDetails;
338 this.callSetTimeOut(getNSID, index, secondsValue);
339 }, (error: ERRORDATA): void => {
340 this.restService.handleError(error, 'get');
341 if (error.error.status === HttpStatus.NOT_FOUND) {
342 this.vcaDetails.splice(index, 1);
344 this.clearTimeoutAndInterval();
347 /** Call the setimeout to refresh the all models data in regular timeout @public */
348 public callSetTimeOut(id: string, index: number, secondsValue: number): void {
349 this.clearTimeoutAndInterval();
350 this.timeOut = window.setTimeout((): void => {
351 this.generateRefreshedData(id, index, secondsValue);
352 }, secondsValue * this.timeDefaultCal);
354 /** Stop existing model live reload @public */
355 public stopExistingModelLiveLoading(getNSID: string): void {
356 this.clearTimeoutAndInterval();
357 this.vcaDetails.forEach((vcaDetail: VCADETAILS, i: number): void => {
358 if (vcaDetail.ns_id !== getNSID) {
359 vcaDetail.isLiveloading = false;
363 /** Method to show/hide the tables @public */
364 public showHideTables(event: HTMLElement, getTableName: string, index: number): void {
365 let selectedClassName: string = getTableName + index;
366 if (selectedClassName === 'all' + index) {
367 selectedClassName = '';
369 document.querySelectorAll('.filter' + index).forEach((button: HTMLElement): void => {
370 button.classList.remove('active');
371 if (selectedClassName !== '') {
372 if (button.classList.contains(selectedClassName)) {
373 button.classList.add('active');
375 } else if (button.classList.contains('all' + index)) {
376 button.classList.add('active');
379 document.querySelectorAll('.filterTable' + index).forEach((table: HTMLElement): void => {
380 table.classList.remove('hide');
381 if (selectedClassName !== '') {
382 if (!table.classList.contains(selectedClassName)) {
383 table.classList.add('hide');
388 /** Get the timer selected @public */
389 public onSetTimerSelector(getSeconds: number, nsID: string, index: number): void {
390 this.vcaDetails[index].timeOutSeconds = getSeconds;
391 this.callLiveData(true, nsID, index);
393 /** Clear settimeOut and setinterval @public */
394 public clearTimeoutAndInterval(): void {
395 clearTimeout(this.timeOut);
398 * Lifecyle hook which get trigger on component destruction
400 public ngOnDestroy(): void {
401 this.clearTimeoutAndInterval();
402 this.generateDataSub.unsubscribe();