]> git.proxmox.com Git - pmg-gui.git/blob - js/Dashboard.js
attachmentquarantine: fix missing '&' for raw-param addition
[pmg-gui.git] / js / Dashboard.js
1 Ext.define('PMG.Dashboard', {
2 extend: 'Ext.panel.Panel',
3 xtype: 'pmgDashboard',
4
5 controller: {
6 xclass: 'Ext.app.ViewController',
7
8 openDashboardOptions: function() {
9 var me = this;
10 var viewModel = me.getViewModel();
11 Ext.create('Ext.window.Window', {
12 modal: true,
13 width: 300,
14 title: gettext('Dashboard Options'),
15 layout: {
16 type: 'auto',
17 },
18 items: [{
19 xtype: 'form',
20 bodyPadding: '10 10 10 10',
21 defaultButton: 'savebutton',
22 items: [{
23 xtype: 'proxmoxintegerfield',
24 itemId: 'hours',
25 labelWidth: 100,
26 anchor: '100%',
27 allowBlank: false,
28 minValue: 1,
29 maxValue: 24,
30 value: viewModel.get('hours'),
31 fieldLabel: gettext('Hours to show'),
32 }],
33 buttons: [{
34 text: gettext('Save'),
35 reference: 'loginButton',
36 formBind: true,
37 handler: function() {
38 var win = this.up('window');
39 var hours = win.down('#hours').getValue();
40 me.setHours(hours, true);
41 win.close();
42 },
43 }],
44 }],
45 }).show();
46 },
47
48 setHours: function(hours, setState) {
49 var me = this;
50 var viewModel = me.getViewModel();
51 viewModel.set('hours', hours);
52 viewModel.notify();
53
54 Ext.Array.forEach(['recentmails', 'receivers'], function(item) {
55 viewModel.getStore(item).reload();
56 });
57
58 if (setState) {
59 var sp = Ext.state.Manager.getProvider();
60 sp.set('dashboard-hours', hours);
61 }
62 },
63
64 updateMailStats: function(store, records, success) {
65 if (!success) {
66 return;
67 }
68 var me = this;
69 var viewModel = me.getViewModel();
70
71 var count = 0;
72 var bytes_in = 0;
73 var bytes_out = 0;
74 var ptime = 0;
75 var avg_ptime = 'N/A';
76
77 records.forEach(function(item) {
78 bytes_in += item.data.bytes_in;
79 bytes_out += item.data.bytes_out;
80 // unnormalize
81 count += (item.data.count*item.data.timespan)/60;
82 ptime += item.data.ptimesum;
83 });
84
85 if (count) {
86 avg_ptime = (ptime/count).toFixed(2) + " s";
87 }
88
89 viewModel.set('bytes_in', Proxmox.Utils.format_size(bytes_in));
90 viewModel.set('bytes_out', Proxmox.Utils.format_size(bytes_out));
91 viewModel.set('avg_ptime', avg_ptime);
92 },
93
94 updateClusterStats: function(store, records, success) {
95 if (!success) {
96 return;
97 }
98 var me = this;
99 var viewmodel = me.getViewModel();
100
101 var subStatus = 2; // 2 = all good, 1 = different leves, 0 = none
102 var subLevel = "";
103
104 var cpu = 0;
105 var mem = 0;
106 var hd = 0;
107 var count = records.length;
108 var errors = [];
109
110 records.forEach(function(item) {
111 // subscription level check
112 if (subStatus && item.data.level) {
113 if (subLevel !== "" && subLevel !== item.data.level) {
114 subStatus = 1;
115 } else if (subLevel === "") {
116 subLevel = item.data.level;
117 }
118 } else {
119 subStatus = 0;
120 }
121
122 // resources count
123 cpu += item.data.cpu || 0;
124
125 var memory = item.data.memory || { used: 0, total: 1 };
126 mem += memory.used/memory.total;
127
128 var rootfs = item.data.rootfs || { used: 0, total: 1 };
129 hd += rootfs.used/rootfs.total;
130
131 if (item.data.conn_error && count > 1) {
132 count--;
133 errors.push({
134 name: item.data.name,
135 msg: item.data.conn_error,
136 });
137 }
138 });
139
140 var subscriptionPanel = me.lookup('subscription');
141 subscriptionPanel.setSubStatus(subStatus);
142
143 cpu = cpu/count;
144 mem = mem/count;
145 hd = hd/count;
146
147 var cpuPanel = me.lookup('cpu');
148 cpuPanel.updateValue(cpu);
149
150 var memPanel = me.lookup('mem');
151 memPanel.updateValue(mem);
152
153 var hdPanel = me.lookup('hd');
154 hdPanel.updateValue(hd);
155
156 if (errors.length && !viewmodel.get('error_shown')) {
157 var text = "";
158 errors.forEach(function(error) {
159 text += error.name + ':<br>' + error.msg + '<br>';
160 });
161 Ext.Msg.alert(gettext('Error'), text);
162 viewmodel.set('error_shown', true);
163 }
164 },
165
166 init: function(view) {
167 var me = this;
168 var sp = Ext.state.Manager.getProvider();
169 var hours = sp.get('dashboard-hours') || 12;
170 me.setHours(hours, false);
171 },
172 },
173
174 viewModel: {
175 data: {
176 timespan: 300, // in seconds
177 hours: 12, // in hours
178 error_shown: false,
179 'bytes_in': 0,
180 'bytes_out': 0,
181 'avg_ptime': 0.0,
182 },
183
184 stores: {
185 cluster: {
186 storeid: 'dash-cluster',
187 type: 'update',
188 interval: 5000,
189 autoStart: true,
190 autoDestroy: true,
191 proxy: {
192 extraParams: { list_single_node: 1 },
193 type: 'proxmox',
194 url: '/api2/json/config/cluster/status',
195 },
196 listeners: {
197 load: 'updateClusterStats',
198 },
199 },
200 recentmails: {
201 storeid: 'dash-recent',
202 interval: 5000,
203 type: 'update',
204 autoStart: true,
205 autoDestroy: true,
206 proxy: {
207 type: 'proxmox',
208 url: '/api2/json/statistics/recent',
209 extraParams: {
210 hours: '{hours}',
211 timespan: '{timespan}',
212 },
213 },
214 fields: [
215 {
216 type: 'number', name: 'count',
217 convert: PMG.Utils.convert_field_to_per_min,
218 },
219 {
220 type: 'number', name: 'count_in',
221 convert: PMG.Utils.convert_field_to_per_min,
222 },
223 {
224 type: 'number', name: 'count_out',
225 convert: PMG.Utils.convert_field_to_per_min,
226 },
227 {
228 type: 'number', name: 'spam',
229 convert: PMG.Utils.convert_field_to_per_min,
230 },
231 {
232 type: 'number', name: 'spam_in',
233 convert: PMG.Utils.convert_field_to_per_min,
234 },
235 {
236 type: 'number', name: 'spam_out',
237 convert: PMG.Utils.convert_field_to_per_min,
238 },
239 {
240 type: 'number', name: 'virus',
241 convert: PMG.Utils.convert_field_to_per_min,
242 },
243 {
244 type: 'number', name: 'virus_in',
245 convert: PMG.Utils.convert_field_to_per_min,
246 },
247 { type: 'integer', name: 'virus_out' },
248 { type: 'integer', name: 'bytes_in' },
249 { type: 'integer', name: 'bytes_out' },
250 { type: 'number', name: 'ptimesum' },
251 { type: 'date', dateFormat: 'timestamp', name: 'time' },
252 ],
253 listeners: {
254 load: 'updateMailStats',
255 },
256 },
257 receivers: {
258 storeid: 'dash-receivers',
259 interval: 10000,
260 type: 'update',
261 autoStart: true,
262 autoDestroy: true,
263 proxy: {
264 type: 'proxmox',
265 url: '/api2/json/statistics/recentreceivers',
266 extraParams: {
267 hours: '{hours}',
268 },
269 },
270 fields: [
271 { type: 'integer', name: 'count' },
272 { type: 'string', name: 'receiver' },
273 ],
274 },
275 },
276 },
277
278 bind: {
279 title: gettext('Dashboard') + ' (' +
280 Ext.String.format(gettext('{0} hours'), '{hours}') + ')',
281 },
282
283 layout: {
284 type: 'column',
285 },
286 border: false,
287
288 bodyPadding: '20 0 0 20',
289
290 defaults: {
291 columnWidth: 0.5,
292 xtype: 'panel',
293 margin: '0 20 20 0',
294 },
295
296 tools: [
297 {
298 type: 'gear',
299 handler: 'openDashboardOptions',
300 },
301 ],
302
303 scrollable: true,
304
305 items: [
306 {
307 height: 300,
308 flex: 1,
309 iconCls: 'fa fa-tachometer',
310 title: gettext('E-Mail Volume'),
311 layout: {
312 type: 'vbox',
313 align: 'stretch',
314 },
315 defaults: {
316 xtype: 'pmgMiniGraph',
317 bind: {
318 store: '{recentmails}',
319 },
320 },
321 items: [
322 {
323 fields: ['count'],
324 fieldTitles: [gettext('Mails / min')],
325 seriesConfig: {
326 colors: ['#00617F'],
327 style: {
328 opacity: 0.60,
329 lineWidth: 1,
330 },
331 highlightCfg: {
332 opacity: 1,
333 scaling: 1,
334 },
335 },
336 },
337 {
338 fields: ['spam'],
339 fieldTitles: [gettext('Spam / min')],
340 seriesConfig: {
341 colors: ['#E67300'],
342 style: {
343 opacity: 0.60,
344 lineWidth: 1,
345 },
346 highlightCfg: {
347 opacity: 1,
348 scaling: 1,
349 },
350 },
351 },
352 ],
353 },
354 {
355 xtype: 'container',
356 height: 300,
357 layout: {
358 type: 'vbox',
359 align: 'stretch',
360 },
361 items: [
362 {
363 xtype: 'pmgMailProcessing',
364 title: gettext('E-Mail Processing'),
365 iconCls: 'fa fa-hourglass-half',
366 height: 180,
367 bind: {
368 data: {
369 'bytes_in': '{bytes_in}',
370 'bytes_out': '{bytes_out}',
371 'avg_ptime': '{avg_ptime}',
372 },
373 },
374 },
375 {
376 iconCls: 'fa fa-ticket',
377 title: 'Subscription',
378 reference: 'subscription',
379 xtype: 'pmgSubscriptionInfo',
380 margin: '10 0 0 0',
381 height: 110,
382 },
383 ],
384 },
385 {
386 height: 250,
387 iconCls: 'fa fa-tasks',
388 title: gettext('Node Resources'),
389 bodyPadding: '0 20 0 20',
390 layout: {
391 type: 'hbox',
392 align: 'center',
393 },
394 defaults: {
395 xtype: 'proxmoxGauge',
396 spriteFontSize: '20px',
397 flex: 1,
398 },
399 items: [
400 {
401 title: gettext('CPU'),
402 reference: 'cpu',
403 },
404 {
405 title: gettext('Memory'),
406 reference: 'mem',
407 },
408 {
409 title: gettext('Storage'),
410 reference: 'hd',
411 },
412 ],
413 },
414 {
415 height: 250,
416 iconCls: 'fa fa-list',
417 title: gettext('Top Receivers'),
418
419 bodyPadding: '20 20 20 20',
420 layout: {
421 type: 'vbox',
422 pack: 'center',
423 align: 'stretch',
424 },
425 items: [{
426 xtype: 'grid',
427 bind: {
428 store: '{receivers}',
429 },
430
431 emptyText: gettext('No data in database'),
432
433 // remove all borders/lines/headers
434 border: false,
435 bodyBorder: false,
436 hideHeaders: true,
437 header: false,
438 columnLines: false,
439 rowLines: false,
440 viewConfig: {
441 stripeRows: false,
442 },
443
444 columns: [
445 {
446 dataIndex: 'receiver',
447 flex: 1,
448 text: gettext('Receiver'),
449 },
450 {
451 dataIndex: 'count',
452 align: 'right',
453 text: gettext('Count'),
454 },
455 ],
456 }],
457 },
458 ],
459 });