]> git.proxmox.com Git - pmg-gui.git/blame - js/Dashboard.js
dashboard: hide cluster resources if it's a single node
[pmg-gui.git] / js / Dashboard.js
CommitLineData
5936e3ef
DC
1Ext.define('PMG.Dashboard', {
2 extend: 'Ext.panel.Panel',
3 xtype: 'pmgDashboard',
4
b047eec0
DC
5 controller: {
6 xclass: 'Ext.app.ViewController',
5936e3ef 7
b047eec0
DC
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: {
c87d46fb 16 type: 'auto',
b047eec0
DC
17 },
18 items: [{
19 xtype: 'form',
de0ebd99 20 bodyPadding: '10 10 10 10',
b047eec0
DC
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'),
c87d46fb 31 fieldLabel: gettext('Hours to show'),
b047eec0
DC
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();
c87d46fb
TL
42 },
43 }],
44 }],
b047eec0
DC
45 }).show();
46 },
5936e3ef 47
b047eec0
DC
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) {
86109d3a 55 viewModel.getStore(item).reload();
b047eec0
DC
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;
b6248f6e 75 var avg_ptime = 'N/A';
b047eec0
DC
76
77 records.forEach(function(item) {
78 bytes_in += item.data.bytes_in;
79 bytes_out += item.data.bytes_out;
b79fbba8
DC
80 // unnormalize
81 count += (item.data.count*item.data.timespan)/60;
b047eec0
DC
82 ptime += item.data.ptimesum;
83 });
84
85 if (count) {
b6248f6e 86 avg_ptime = (ptime/count).toFixed(2) + " s";
b047eec0
DC
87 }
88
89 viewModel.set('bytes_in', Proxmox.Utils.format_size(bytes_in));
90 viewModel.set('bytes_out', Proxmox.Utils.format_size(bytes_out));
b6248f6e 91 viewModel.set('avg_ptime', avg_ptime);
b047eec0
DC
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;
bb7ab2ba 108 var errors = [];
b047eec0
DC
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
91c74e81
DC
123 cpu += item.data.cpu || 0;
124
125 var memory = item.data.memory || { used: 0, total: 1 };
c87d46fb 126 mem += memory.used/memory.total;
91c74e81
DC
127
128 var rootfs = item.data.rootfs || { used: 0, total: 1 };
c87d46fb 129 hd += rootfs.used/rootfs.total;
91c74e81 130
bb7ab2ba
DC
131 if (item.data.conn_error && count > 1) {
132 count--;
133 errors.push({
134 name: item.data.name,
c87d46fb 135 msg: item.data.conn_error,
bb7ab2ba
DC
136 });
137 }
b047eec0
DC
138 });
139
140 var subscriptionPanel = me.lookup('subscription');
141 subscriptionPanel.setSubStatus(subStatus);
142
11eae1a0
FE
143 me.lookup('nodeInfo').setSubscriptionStatus(subStatus);
144
91a4c642
FE
145 // the node info already displays this information in case there is no cluster
146 me.lookup('clusterResources').setHidden(records.length === 1);
147
b047eec0
DC
148 cpu = cpu/count;
149 mem = mem/count;
150 hd = hd/count;
151
152 var cpuPanel = me.lookup('cpu');
153 cpuPanel.updateValue(cpu);
154
131ba4f6 155 var memPanel = me.lookup('mem');
b047eec0
DC
156 memPanel.updateValue(mem);
157
131ba4f6 158 var hdPanel = me.lookup('hd');
b047eec0 159 hdPanel.updateValue(hd);
bb7ab2ba
DC
160
161 if (errors.length && !viewmodel.get('error_shown')) {
162 var text = "";
163 errors.forEach(function(error) {
164 text += error.name + ':<br>' + error.msg + '<br>';
165 });
166 Ext.Msg.alert(gettext('Error'), text);
167 viewmodel.set('error_shown', true);
168 }
b047eec0
DC
169 },
170
11eae1a0
FE
171 updateRepositoryStatus: function(store, records, success) {
172 if (!success) {
173 return;
174 }
175
176 let me = this;
177 me.lookup('nodeInfo').setRepositoryInfo(records[0].data['standard-repos']);
178 },
179
b047eec0
DC
180 init: function(view) {
181 var me = this;
182 var sp = Ext.state.Manager.getProvider();
183 var hours = sp.get('dashboard-hours') || 12;
184 me.setHours(hours, false);
c87d46fb 185 },
b047eec0
DC
186 },
187
188 viewModel: {
189 data: {
190 timespan: 300, // in seconds
191 hours: 12, // in hours
bb7ab2ba 192 error_shown: false,
b047eec0
DC
193 'bytes_in': 0,
194 'bytes_out': 0,
c87d46fb 195 'avg_ptime': 0.0,
b047eec0
DC
196 },
197
198 stores: {
199 cluster: {
200 storeid: 'dash-cluster',
201 type: 'update',
202 interval: 5000,
203 autoStart: true,
b047eec0
DC
204 autoDestroy: true,
205 proxy: {
929f40ff 206 extraParams: { list_single_node: 1 },
b047eec0 207 type: 'proxmox',
c87d46fb 208 url: '/api2/json/config/cluster/status',
b047eec0
DC
209 },
210 listeners: {
c87d46fb
TL
211 load: 'updateClusterStats',
212 },
b047eec0
DC
213 },
214 recentmails: {
215 storeid: 'dash-recent',
216 interval: 5000,
217 type: 'update',
218 autoStart: true,
b047eec0
DC
219 autoDestroy: true,
220 proxy: {
221 type: 'proxmox',
222 url: '/api2/json/statistics/recent',
223 extraParams: {
224 hours: '{hours}',
c87d46fb
TL
225 timespan: '{timespan}',
226 },
b047eec0
DC
227 },
228 fields: [
b79fbba8
DC
229 {
230 type: 'number', name: 'count',
c87d46fb 231 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
232 },
233 {
234 type: 'number', name: 'count_in',
c87d46fb 235 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
236 },
237 {
238 type: 'number', name: 'count_out',
c87d46fb 239 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
240 },
241 {
242 type: 'number', name: 'spam',
c87d46fb 243 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
244 },
245 {
246 type: 'number', name: 'spam_in',
c87d46fb 247 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
248 },
249 {
250 type: 'number', name: 'spam_out',
c87d46fb 251 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
252 },
253 {
254 type: 'number', name: 'virus',
c87d46fb 255 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8
DC
256 },
257 {
258 type: 'number', name: 'virus_in',
c87d46fb 259 convert: PMG.Utils.convert_field_to_per_min,
b79fbba8 260 },
b047eec0
DC
261 { type: 'integer', name: 'virus_out' },
262 { type: 'integer', name: 'bytes_in' },
263 { type: 'integer', name: 'bytes_out' },
264 { type: 'number', name: 'ptimesum' },
c87d46fb 265 { type: 'date', dateFormat: 'timestamp', name: 'time' },
b047eec0
DC
266 ],
267 listeners: {
c87d46fb
TL
268 load: 'updateMailStats',
269 },
b047eec0
DC
270 },
271 receivers: {
272 storeid: 'dash-receivers',
273 interval: 10000,
274 type: 'update',
275 autoStart: true,
b047eec0
DC
276 autoDestroy: true,
277 proxy: {
278 type: 'proxmox',
279 url: '/api2/json/statistics/recentreceivers',
280 extraParams: {
c87d46fb
TL
281 hours: '{hours}',
282 },
b047eec0
DC
283 },
284 fields: [
285 { type: 'integer', name: 'count' },
c87d46fb
TL
286 { type: 'string', name: 'receiver' },
287 ],
288 },
11eae1a0
FE
289 repositories: {
290 storeid: 'dash-repositories',
291 type: 'update',
292 interval: 15000,
293 autoStart: true,
294 autoLoad: true,
295 autoDestroy: true,
296 proxy: {
297 type: 'proxmox',
298 url: '/api2/json/nodes/localhost/apt/repositories',
299 },
300 listeners: {
301 load: 'updateRepositoryStatus',
302 },
303 },
c87d46fb 304 },
b047eec0
DC
305 },
306
307 bind: {
308 title: gettext('Dashboard') + ' (' +
c87d46fb 309 Ext.String.format(gettext('{0} hours'), '{hours}') + ')',
b047eec0
DC
310 },
311
de0ebd99 312 layout: {
c87d46fb 313 type: 'column',
de0ebd99 314 },
b047eec0
DC
315 border: false,
316
317 bodyPadding: '20 0 0 20',
318
319 defaults: {
320 columnWidth: 0.5,
321 xtype: 'panel',
c87d46fb 322 margin: '0 20 20 0',
b047eec0
DC
323 },
324
325 tools: [
326 {
327 type: 'gear',
c87d46fb
TL
328 handler: 'openDashboardOptions',
329 },
b047eec0
DC
330 ],
331
332 scrollable: true,
333
334 items: [
335 {
336 height: 300,
337 flex: 1,
338 iconCls: 'fa fa-tachometer',
339 title: gettext('E-Mail Volume'),
340 layout: {
341 type: 'vbox',
c87d46fb 342 align: 'stretch',
b047eec0
DC
343 },
344 defaults: {
345 xtype: 'pmgMiniGraph',
346 bind: {
c87d46fb
TL
347 store: '{recentmails}',
348 },
b047eec0
DC
349 },
350 items: [
351 {
352 fields: ['count'],
c87d46fb 353 fieldTitles: [gettext('Mails / min')],
b047eec0 354 seriesConfig: {
c87d46fb 355 colors: ['#00617F'],
b047eec0
DC
356 style: {
357 opacity: 0.60,
c87d46fb 358 lineWidth: 1,
b047eec0
DC
359 },
360 highlightCfg: {
361 opacity: 1,
c87d46fb
TL
362 scaling: 1,
363 },
364 },
b047eec0
DC
365 },
366 {
367 fields: ['spam'],
c87d46fb 368 fieldTitles: [gettext('Spam / min')],
b047eec0 369 seriesConfig: {
c87d46fb 370 colors: ['#E67300'],
b047eec0
DC
371 style: {
372 opacity: 0.60,
c87d46fb 373 lineWidth: 1,
b047eec0
DC
374 },
375 highlightCfg: {
376 opacity: 1,
c87d46fb
TL
377 scaling: 1,
378 },
379 },
380 },
381 ],
b047eec0
DC
382 },
383 {
384 xtype: 'container',
385 height: 300,
386 layout: {
387 type: 'vbox',
c87d46fb 388 align: 'stretch',
b047eec0
DC
389 },
390 items: [
391 {
392 xtype: 'pmgMailProcessing',
393 title: gettext('E-Mail Processing'),
394 iconCls: 'fa fa-hourglass-half',
395 height: 180,
396 bind: {
397 data: {
7b18f75e
DC
398 'bytes_in': '{bytes_in}',
399 'bytes_out': '{bytes_out}',
c87d46fb
TL
400 'avg_ptime': '{avg_ptime}',
401 },
402 },
b047eec0
DC
403 },
404 {
405 iconCls: 'fa fa-ticket',
406 title: 'Subscription',
407 reference: 'subscription',
408 xtype: 'pmgSubscriptionInfo',
409 margin: '10 0 0 0',
c87d46fb
TL
410 height: 110,
411 },
412 ],
b047eec0
DC
413 },
414 {
415 height: 250,
416 iconCls: 'fa fa-tasks',
11eae1a0 417 title: gettext('Cluster Resources (average)'),
91a4c642
FE
418 reference: 'clusterResources',
419 hidden: true,
b047eec0
DC
420 bodyPadding: '0 20 0 20',
421 layout: {
422 type: 'hbox',
c87d46fb 423 align: 'center',
b047eec0
DC
424 },
425 defaults: {
426 xtype: 'proxmoxGauge',
427 spriteFontSize: '20px',
c87d46fb 428 flex: 1,
b047eec0
DC
429 },
430 items: [
431 {
432 title: gettext('CPU'),
c87d46fb 433 reference: 'cpu',
b047eec0
DC
434 },
435 {
436 title: gettext('Memory'),
c87d46fb 437 reference: 'mem',
b047eec0
DC
438 },
439 {
440 title: gettext('Storage'),
c87d46fb
TL
441 reference: 'hd',
442 },
443 ],
b047eec0 444 },
11eae1a0
FE
445 {
446 xtype: 'pmgNodeInfoPanel',
447 reference: 'nodeInfo',
448 height: 250,
449 bodyPadding: '10 5 10 5',
450 iconCls: 'fa fa-tasks',
451 },
b047eec0
DC
452 {
453 height: 250,
454 iconCls: 'fa fa-list',
455 title: gettext('Top Receivers'),
456
de0ebd99 457 bodyPadding: '20 20 20 20',
b047eec0
DC
458 layout: {
459 type: 'vbox',
460 pack: 'center',
c87d46fb 461 align: 'stretch',
b047eec0
DC
462 },
463 items: [{
464 xtype: 'grid',
465 bind: {
c87d46fb 466 store: '{receivers}',
b047eec0
DC
467 },
468
469 emptyText: gettext('No data in database'),
470
471 // remove all borders/lines/headers
472 border: false,
473 bodyBorder: false,
474 hideHeaders: true,
475 header: false,
476 columnLines: false,
477 rowLines: false,
478 viewConfig: {
c87d46fb 479 stripeRows: false,
b047eec0
DC
480 },
481
482 columns: [
483 {
484 dataIndex: 'receiver',
485 flex: 1,
c87d46fb 486 text: gettext('Receiver'),
b047eec0
DC
487 },
488 {
489 dataIndex: 'count',
490 align: 'right',
c87d46fb
TL
491 text: gettext('Count'),
492 },
493 ],
494 }],
495 },
496 ],
5936e3ef 497});