]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/components/notifications-sidebar/notifications-sidebar.component.ts
8c5caf7ff6bd69c8eb0e51ff573dc95bed139b28
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / components / notifications-sidebar / notifications-sidebar.component.ts
1 import {
2 ChangeDetectionStrategy,
3 ChangeDetectorRef,
4 Component,
5 HostBinding,
6 NgZone,
7 OnDestroy,
8 OnInit
9 } from '@angular/core';
10
11 import { Mutex } from 'async-mutex';
12 import _ from 'lodash';
13 import moment from 'moment';
14 import { Subscription } from 'rxjs';
15
16 import { Icons } from '~/app/shared/enum/icons.enum';
17 import { CdNotification } from '~/app/shared/models/cd-notification';
18 import { ExecutingTask } from '~/app/shared/models/executing-task';
19 import { FinishedTask } from '~/app/shared/models/finished-task';
20 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
21 import { NotificationService } from '~/app/shared/services/notification.service';
22 import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
23 import { PrometheusNotificationService } from '~/app/shared/services/prometheus-notification.service';
24 import { SummaryService } from '~/app/shared/services/summary.service';
25 import { TaskMessageService } from '~/app/shared/services/task-message.service';
26
27 @Component({
28 selector: 'cd-notifications-sidebar',
29 templateUrl: './notifications-sidebar.component.html',
30 styleUrls: ['./notifications-sidebar.component.scss'],
31 changeDetection: ChangeDetectionStrategy.OnPush
32 })
33 export class NotificationsSidebarComponent implements OnInit, OnDestroy {
34 @HostBinding('class.active') isSidebarOpened = false;
35
36 notifications: CdNotification[];
37 private interval: number;
38 private timeout: number;
39
40 executingTasks: ExecutingTask[] = [];
41
42 private subs = new Subscription();
43
44 icons = Icons;
45
46 // Tasks
47 last_task = '';
48 mutex = new Mutex();
49
50 simplebar = {
51 autoHide: false
52 };
53
54 constructor(
55 public notificationService: NotificationService,
56 private summaryService: SummaryService,
57 private taskMessageService: TaskMessageService,
58 private prometheusNotificationService: PrometheusNotificationService,
59 private authStorageService: AuthStorageService,
60 private prometheusAlertService: PrometheusAlertService,
61 private ngZone: NgZone,
62 private cdRef: ChangeDetectorRef
63 ) {
64 this.notifications = [];
65 }
66
67 ngOnDestroy() {
68 window.clearInterval(this.interval);
69 window.clearTimeout(this.timeout);
70 this.subs.unsubscribe();
71 }
72
73 ngOnInit() {
74 this.last_task = window.localStorage.getItem('last_task');
75
76 const permissions = this.authStorageService.getPermissions();
77 if (permissions.prometheus.read && permissions.configOpt.read) {
78 this.triggerPrometheusAlerts();
79 this.ngZone.runOutsideAngular(() => {
80 this.interval = window.setInterval(() => {
81 this.ngZone.run(() => {
82 this.triggerPrometheusAlerts();
83 });
84 }, 5000);
85 });
86 }
87
88 this.subs.add(
89 this.notificationService.data$.subscribe((notifications: CdNotification[]) => {
90 this.notifications = _.orderBy(notifications, ['timestamp'], ['desc']);
91 this.cdRef.detectChanges();
92 })
93 );
94
95 this.subs.add(
96 this.notificationService.sidebarSubject.subscribe((forceClose) => {
97 if (forceClose) {
98 this.isSidebarOpened = false;
99 } else {
100 this.isSidebarOpened = !this.isSidebarOpened;
101 }
102
103 window.clearTimeout(this.timeout);
104 this.timeout = window.setTimeout(() => {
105 this.cdRef.detectChanges();
106 }, 0);
107 })
108 );
109
110 this.subs.add(
111 this.summaryService.subscribe((summary) => {
112 this._handleTasks(summary.executing_tasks);
113
114 this.mutex.acquire().then((release) => {
115 _.filter(
116 summary.finished_tasks,
117 (task: FinishedTask) => !this.last_task || moment(task.end_time).isAfter(this.last_task)
118 ).forEach((task) => {
119 const config = this.notificationService.finishedTaskToNotification(task, task.success);
120 const notification = new CdNotification(config);
121 notification.timestamp = task.end_time;
122 notification.duration = task.duration;
123
124 if (!this.last_task || moment(task.end_time).isAfter(this.last_task)) {
125 this.last_task = task.end_time;
126 window.localStorage.setItem('last_task', this.last_task);
127 }
128
129 this.notificationService.save(notification);
130 });
131
132 this.cdRef.detectChanges();
133
134 release();
135 });
136 })
137 );
138 }
139
140 _handleTasks(executingTasks: ExecutingTask[]) {
141 for (const excutingTask of executingTasks) {
142 excutingTask.description = this.taskMessageService.getRunningTitle(excutingTask);
143 }
144 this.executingTasks = executingTasks;
145 }
146
147 private triggerPrometheusAlerts() {
148 this.prometheusAlertService.refresh();
149 this.prometheusNotificationService.refresh();
150 }
151
152 removeAll() {
153 this.notificationService.removeAll();
154 }
155
156 remove(index: number) {
157 this.notificationService.remove(index);
158 }
159
160 closeSidebar() {
161 this.isSidebarOpened = false;
162 }
163
164 trackByFn(index: number) {
165 return index;
166 }
167 }