merge from ecomp a88f0072 - Modern UI
[vid.git] / vid-webpack-master / src / app / instantiationStatus / instantiationStatus.component.ts
1 import {Component, ViewChild} from '@angular/core';
2 import {ServiceInfoService} from '../shared/server/serviceInfo/serviceInfo.service';
3 import {ServiceInfoModel} from '../shared/server/serviceInfo/serviceInfo.model';
4 import {InstantiationStatusComponentService} from './instantiationStatus.component.service';
5 import {ContextMenuComponent, ContextMenuService} from 'ngx-contextmenu';
6 import {AuditInfoModalComponent} from "../shared/components/auditInfoModal/auditInfoModal.component";
7 import * as _ from 'lodash';
8 import {ScrollToConfigOptions, ScrollToService} from '@nicky-lenaers/ngx-scroll-to';
9 import {ConfigurationService} from "../shared/services/configuration.service";
10 import {LogService} from '../shared/utils/log/log.service';
11 import {AppState} from "../shared/store/reducers";
12 import {NgRedux} from '@angular-redux/store';
13 import {JobStatus, ServiceAction} from "../shared/models/serviceInstanceActions";
14 import {DrawingBoardModes} from "../drawingBoard/service-planning/drawing-board.modes";
15
16 export interface MenuAction{
17   name: string;
18   dataTestId: string;
19   className: string;
20   tooltip?: string;
21   click(item: ServiceInfoModel): void;
22   enabled (item?: ServiceInfoModel): boolean;
23   visible (item?: ServiceInfoModel): boolean;
24 }
25
26 @Component({
27   selector : 'instantiation-status',
28   templateUrl : './instantiationStatus.component.html',
29   styleUrls : ['./instantiationStatus.component.scss']
30 })
31 export class InstantiationStatusComponent {
32
33   TIMER_TIME_IN_SECONDS : number = 0;
34   timer = null;
35   dataIsReady : boolean = false;
36   scroll : boolean = false;
37   lastUpdatedDate: Date = null;
38   instantiationStatusComponentService: InstantiationStatusComponentService;
39   configurationService : ConfigurationService;
40   serviceInfoData: ServiceInfoModel[] = null;
41   @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
42
43   public contextMenuActions: Array<MenuAction> = [
44     {
45       name: "Redeploy",
46       dataTestId: "context-menu-retry",
47       className: "fa-repeat",
48       click: (item: ServiceInfoModel) => this.retryItem(item),
49       enabled: () =>  true,
50       visible: (item: ServiceInfoModel) =>  item.isRetryEnabled,
51     },
52     {
53       name: "Open",
54       dataTestId: "context-menu-open",
55       className: "fa-external-link",
56       click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.open(item),
57       enabled: (item: ServiceInfoModel) =>  this.isOpenEnabled(item),
58       visible: () =>  true,
59     },
60     {
61       name: "Audit info",
62       dataTestId: "context-menu-audit-info",
63       className: "fa-info-circle",
64       click: (item: ServiceInfoModel) => this.auditInfo(item),
65       enabled: (item: ServiceInfoModel) =>  this.isAuditInfoEnabled(item),
66       visible: () =>  true,
67     },
68     {
69       name: "Delete",
70       dataTestId: "context-menu-remove",
71       className: "fa-trash-o",
72       click: (item: ServiceInfoModel) => this.deleteItem(item),
73       enabled: (item: ServiceInfoModel) =>  this.isDeleteEnabled(item),
74       visible: () =>  true,
75     },
76     {
77       name: "Hide request",
78       dataTestId: "context-menu-hide",
79       className: "fa-eye-slash",
80       tooltip: "Hide this service from this table",
81       click: (item: ServiceInfoModel) => this.hideItem(item),
82       enabled: (item: ServiceInfoModel) =>  this.isHideEnabled(item),
83       visible: () =>  true,
84     }
85   ];
86
87   flags: any;
88   constructor(private _serviceInfoService: ServiceInfoService,
89               private _instantiationStatusComponentService : InstantiationStatusComponentService,
90               private _contextMenuService: ContextMenuService,
91               private _configurationService : ConfigurationService,
92               private _scrollToService: ScrollToService,
93               private _logService : LogService,
94               private _store: NgRedux<AppState>) {
95     this.instantiationStatusComponentService = _instantiationStatusComponentService;
96     this.configurationService = this._configurationService;
97     this.configurationService.getConfiguration("refreshTimeInstantiationDashboard").subscribe(response => {
98       this.TIMER_TIME_IN_SECONDS = _.isNumber(response) ? response : 0;
99       this.activateInterval();
100       this.refreshData();
101     });
102   }
103
104   activateInterval() {
105     if (this.TIMER_TIME_IN_SECONDS > 0) {
106       this.timer = setInterval(() => {
107         this.refreshData();
108       }, this.TIMER_TIME_IN_SECONDS * 1000);
109     }
110   }
111
112   deactivateInterval() {
113     clearInterval(this.timer);
114   }
115
116   refreshData(): void {
117     this.dataIsReady = false;
118     this._serviceInfoService.getServicesJobInfo(true, this.lastUpdatedDate === null)
119       .subscribe((res: ServiceInfoModel[]) => {
120         this._instantiationStatusComponentService.convertObjectToArray(res).subscribe((res) => {
121           this._logService.info('refresh instantiation status table', res);
122           this.dataIsReady = true;
123           this.lastUpdatedDate = new Date();
124           if (!_.isEqual(this.serviceInfoData, res)) {
125             this.serviceInfoData = res;
126             this.scrollToElement(this.findFirstVisibleJob());
127           }
128         });
129       })
130   }
131
132   trackByFn(index: number, item: ServiceInfoModel){
133     return _.isNil(item) ? null : item.jobId;
134   }
135
136   deleteItem(item: ServiceInfoModel): void {
137     this._serviceInfoService.deleteJob(item.jobId).subscribe(() => {
138       this.refreshData();
139     });
140   }
141
142   hideItem(item: ServiceInfoModel): void {
143     this._serviceInfoService.hideJob(item.jobId).subscribe(() => {
144       this.refreshData();
145     });
146   }
147   
148   retryItem(item: ServiceInfoModel) : void {
149     if (item.isRetryEnabled) {
150       this._instantiationStatusComponentService.retry(item);
151     }
152   }
153
154   auditInfo(jobData : ServiceInfoModel): void {
155     AuditInfoModalComponent.openModal.next(jobData);
156   }
157
158   isOpenEnabled(item: ServiceInfoModel):boolean {
159     switch(item.action) {
160       case ServiceAction.DELETE:
161       return _.includes([ JobStatus.PENDING, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED], item.jobStatus);
162       case ServiceAction.UPDATE:
163         return _.includes([JobStatus.PENDING, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED, JobStatus.FAILED], item.jobStatus);
164       default:
165         return _.includes([JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus);
166     }
167   }
168
169   isAuditInfoEnabled(item: ServiceInfoModel): boolean {
170     if(item.action === ServiceAction.DELETE || item.action=== ServiceAction.UPDATE) {
171       return _.includes([JobStatus.FAILED, JobStatus.IN_PROGRESS, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.PAUSE, JobStatus.COMPLETED], item.jobStatus);
172     }
173     return true;// ServiceAction.INSTANTIATE
174   }
175
176   isDeleteEnabled(item: ServiceInfoModel):boolean {
177     if( item.action === ServiceAction.DELETE || item.action === ServiceAction.UPDATE){
178       return _.includes([JobStatus.PENDING], item.jobStatus);
179     }
180     return _.includes([JobStatus.PENDING, JobStatus.STOPPED], item.jobStatus);
181   }
182
183   isHideEnabled(item: ServiceInfoModel):boolean {
184     return _.includes([JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.STOPPED, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus);
185   }
186
187   public onContextMenu($event: MouseEvent, item: any): void {
188     this._contextMenuService.show.next({
189       contextMenu: this.contextMenu,
190       event: $event,
191       item: item,
192     });
193     $event.preventDefault();
194     $event.stopPropagation();
195   }
196
197   getImagesSrc(imageName : string) : string {
198     return './' + imageName + '.svg';
199   }
200
201   private getHeaderHeaderClientRect(): ClientRect {
202     const element = document.querySelector("#instantiation-status thead") as HTMLElement;
203     return element.getBoundingClientRect();
204   }
205
206   findFirstVisibleJob(): HTMLElement {
207     const elements : any = document.querySelectorAll('#instantiation-status tr');
208     const headerRect = this.getHeaderHeaderClientRect();
209     if (headerRect) {
210       const topEdge = headerRect.bottom;
211       for (let i = 0; i < elements.length; i++) {
212         if (elements[i].getBoundingClientRect().top >= topEdge)
213           return elements[i];
214       }
215     }
216     return null;
217   }
218
219   scrollToElement(currentJob: HTMLElement) {
220     if (currentJob) {
221       const config: ScrollToConfigOptions = {
222         target: currentJob,
223         duration: 0,
224         offset: -1 * (this.getHeaderHeaderClientRect().height + 2),
225       };
226
227       // wait after render
228       setTimeout(() => {
229         this._scrollToService.scrollTo(config);
230       }, 0)
231     }
232   }
233 }