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