5e0c2a8cdcc95f76f961737d7cde1ff674d2b7a2
[vid.git] / vid-webpack-master / src / app / instantiationStatus / instantiationStatus.component.ts
1 import {Component, OnInit, 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 {ActivatedRoute} from "@angular/router";
15 import {FeatureFlagsService, Features} from "../shared/services/featureFlag/feature-flags.service";
16
17 export interface MenuAction{
18   name: string;
19   dataTestId: string;
20   className: string;
21   tooltip?: string;
22   click(item: ServiceInfoModel): void;
23   enabled (item?: ServiceInfoModel): boolean;
24   visible (item?: ServiceInfoModel): boolean;
25 }
26
27 @Component({
28   selector : 'instantiation-status',
29   templateUrl : './instantiationStatus.component.html',
30   styleUrls : ['./instantiationStatus.component.scss']
31 })
32 export class InstantiationStatusComponent implements OnInit {
33
34   TIMER_TIME_IN_SECONDS : number = 0;
35   timer = null;
36   dataIsReady : boolean = false;
37   scroll : boolean = false;
38   lastUpdatedDate: Date = null;
39   instantiationStatusComponentService: InstantiationStatusComponentService;
40   configurationService : ConfigurationService;
41   serviceInfoData: ServiceInfoModel[] = null;
42   @ViewChild(ContextMenuComponent, {static: false}) public contextMenu: ContextMenuComponent;
43
44   public contextMenuActions: Array<MenuAction> = [
45     {
46       name: "Redeploy",
47       dataTestId: "context-menu-retry",
48       className: "fa-repeat",
49       click: (item: ServiceInfoModel) => this.retryItem(item),
50       enabled: () =>  true,
51       visible: (item: ServiceInfoModel) =>  (item.isRetryEnabled && (item.jobStatus !== JobStatus.COMPLETED_AND_PAUSED)),
52     },
53     {
54       name: "Resume",
55       dataTestId: "context-menu-retry",
56       className: "fa-repeat",
57       click: (item: ServiceInfoModel) => this.resumeItem(item),
58       enabled: () =>  true,
59       visible: (item: ServiceInfoModel) =>  (item.isRetryEnabled && (item.jobStatus === JobStatus.COMPLETED_AND_PAUSED)),
60     },
61     {
62       name: "Open",
63       dataTestId: "context-menu-open",
64       className: "fa-external-link",
65       click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.open(item),
66       enabled: (item: ServiceInfoModel) =>  this.isOpenEnabled(item),
67       visible: () =>  true,
68     },
69     {
70       name: "New View/Edit",
71       dataTestId: "context-menu-new-view-edit",
72       className: "fa-pencil",
73       click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.forwardToNewViewEdit(item),
74       enabled: () => true,
75       visible: () => this.instantiationStatusComponentService.isNewViewEditVisible(),
76     },
77     {
78       name: "Create another one",
79       dataTestId: "context-menu-create-another-one",
80       className: "fa-clone",
81       click: (item: ServiceInfoModel) => this.instantiationStatusComponentService.recreate(item),
82       enabled: (item: ServiceInfoModel) =>  this.instantiationStatusComponentService.isRecreateEnabled(item),
83       visible: () =>  this.instantiationStatusComponentService.isRecreateVisible(),
84     },
85     {
86       name: "Audit info",
87       dataTestId: "context-menu-audit-info",
88       className: "fa-info-circle",
89       click: (item: ServiceInfoModel) => this.auditInfo(item),
90       enabled: (item: ServiceInfoModel) =>  this.isAuditInfoEnabled(item),
91       visible: () =>  true,
92     },
93     {
94       name: "Delete",
95       dataTestId: "context-menu-remove",
96       className: "fa-trash-o",
97       click: (item: ServiceInfoModel) => this.deleteItem(item),
98       enabled: (item: ServiceInfoModel) =>  this.isDeleteEnabled(item),
99       visible: () =>  true,
100     },
101     {
102       name: "Hide request",
103       dataTestId: "context-menu-hide",
104       className: "fa-eye-slash",
105       tooltip: "Hide this service from this table",
106       click: (item: ServiceInfoModel) => this.hideItem(item),
107       enabled: (item: ServiceInfoModel) =>  this.isHideEnabled(item),
108       visible: () =>  true,
109     }
110   ];
111
112   flags: any;
113   filterText: string;
114   constructor(private _serviceInfoService: ServiceInfoService,
115               private _instantiationStatusComponentService : InstantiationStatusComponentService,
116               private _contextMenuService: ContextMenuService,
117               private _configurationService : ConfigurationService,
118               private _scrollToService: ScrollToService,
119               private _logService : LogService,
120               private route: ActivatedRoute,
121               private _store: NgRedux<AppState>) {
122     this.instantiationStatusComponentService = _instantiationStatusComponentService;
123     this.configurationService = this._configurationService;
124     this.configurationService.getConfiguration("refreshTimeInstantiationDashboard").subscribe(response => {
125       this.TIMER_TIME_IN_SECONDS = _.isNumber(response) ? response : 0;
126       this.activateInterval();
127       this.refreshData();
128     });
129   }
130
131   ngOnInit() {
132     let filterTextParam =  this.route.snapshot.queryParams["filterText"];
133     this.filterText = filterTextParam ? filterTextParam : "" ;
134   }
135
136   activateInterval() {
137     if (this.TIMER_TIME_IN_SECONDS > 0) {
138       this.timer = setInterval(() => {
139         this.refreshData();
140       }, this.TIMER_TIME_IN_SECONDS * 1000);
141     }
142   }
143
144   deactivateInterval() {
145     clearInterval(this.timer);
146   }
147
148   refreshData(): void {
149     this.dataIsReady = false;
150     this._serviceInfoService.getServicesJobInfo(this.lastUpdatedDate === null)
151       .subscribe((res: ServiceInfoModel[]) => {
152         this._instantiationStatusComponentService.convertObjectToArray(res).subscribe((res) => {
153           this._logService.info('refresh instantiation status table', res);
154           this.dataIsReady = true;
155           this.lastUpdatedDate = new Date();
156           if (!_.isEqual(this.serviceInfoData, res)) {
157             this.serviceInfoData = res;
158             this.scrollToElement(this.findFirstVisibleJob());
159           }
160         });
161       })
162   }
163
164   trackByFn(index: number, item: ServiceInfoModel){
165     return _.isNil(item) ? null : item.jobId;
166   }
167
168   deleteItem(item: ServiceInfoModel): void {
169     this._serviceInfoService.deleteJob(item.jobId).subscribe(() => {
170       this.refreshData();
171     });
172   }
173
174   hideItem(item: ServiceInfoModel): void {
175     this._serviceInfoService.hideJob(item.jobId).subscribe(() => {
176       this.refreshData();
177     });
178   }
179
180   retryItem(item: ServiceInfoModel) : void {
181     if (item.isRetryEnabled) {
182       this._instantiationStatusComponentService.retry(item);
183     }
184   }
185
186   resumeItem(item: ServiceInfoModel) : void {
187     if(item.isRetryEnabled && item.jobStatus === JobStatus.COMPLETED_AND_PAUSED){
188       this._instantiationStatusComponentService.resume(item);
189     }
190   }
191
192   auditInfo(jobData : ServiceInfoModel): void {
193     AuditInfoModalComponent.openModal.next(jobData);
194   }
195
196   isOpenEnabled(item: ServiceInfoModel):boolean {
197     switch(item.action) {
198       case ServiceAction.DELETE:
199       return _.includes([ JobStatus.PENDING, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED], item.jobStatus);
200       case ServiceAction.UPDATE:
201         return _.includes([JobStatus.PENDING, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED, JobStatus.FAILED], item.jobStatus);
202       default:
203         return _.includes([JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus);
204     }
205   }
206
207   isAuditInfoEnabled(item: ServiceInfoModel): boolean {
208     if(item.action === ServiceAction.DELETE || item.action=== ServiceAction.UPDATE) {
209       return _.includes([JobStatus.FAILED, JobStatus.IN_PROGRESS, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.PAUSE, JobStatus.COMPLETED], item.jobStatus);
210     }
211     return true;// ServiceAction.INSTANTIATE
212   }
213
214   isDeleteEnabled(item: ServiceInfoModel):boolean {
215     if( item.action === ServiceAction.DELETE || item.action === ServiceAction.UPDATE){
216       return _.includes([JobStatus.PENDING], item.jobStatus);
217     }
218     return _.includes([JobStatus.PENDING, JobStatus.STOPPED], item.jobStatus);
219   }
220
221   isHideEnabled(item: ServiceInfoModel):boolean {
222     return _.includes([JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.STOPPED, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus);
223   }
224
225   public onContextMenu($event: MouseEvent, item: any): void {
226     this._contextMenuService.show.next({
227       contextMenu: this.contextMenu,
228       event: $event,
229       item: item,
230     });
231     $event.preventDefault();
232     $event.stopPropagation();
233   }
234
235   getImagesSrc(imageName : string) : string {
236     return './' + imageName + '.svg';
237   }
238
239   private getHeaderHeaderClientRect(): ClientRect {
240     const element = document.querySelector("#instantiation-status thead") as HTMLElement;
241     return element.getBoundingClientRect();
242   }
243
244   findFirstVisibleJob(): HTMLElement {
245     const elements : any = document.querySelectorAll('#instantiation-status tr');
246     const headerRect = this.getHeaderHeaderClientRect();
247     if (headerRect) {
248       const topEdge = headerRect.bottom;
249       for (let i = 0; i < elements.length; i++) {
250         if (elements[i].getBoundingClientRect().top >= topEdge)
251           return elements[i];
252       }
253     }
254     return null;
255   }
256
257   scrollToElement(currentJob: HTMLElement) {
258     if (currentJob) {
259       const config: ScrollToConfigOptions = {
260         target: currentJob,
261         duration: 0,
262         offset: -1 * (this.getHeaderHeaderClientRect().height + 2),
263       };
264
265       // wait after render
266       setTimeout(() => {
267         this._scrollToService.scrollTo(config);
268       }, 0)
269     }
270   }
271
272   isInstantiationStatusFilterFlagOn() {
273     return FeatureFlagsService.getFlagState(Features.FLAG_2004_INSTANTIATION_STATUS_FILTER, this._store);
274   }
275 }