]> git.proxmox.com Git - proxmox-backup.git/blame - www/Dashboard.js
api: disks: cleanup use statement
[proxmox-backup.git] / www / Dashboard.js
CommitLineData
84b9eced
TL
1Ext.define('PBS.Dashboard', {
2 extend: 'Ext.panel.Panel',
3 xtype: 'pbsDashboard',
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: {
65b0cea6 16 type: 'auto',
84b9eced
TL
17 },
18 items: [{
19 xtype: 'form',
20 bodyPadding: '10 10 10 10',
21 defaultButton: 'savebutton',
22 items: [{
23 xtype: 'proxmoxintegerfield',
ad9d1625 24 itemId: 'days',
84b9eced
TL
25 labelWidth: 100,
26 anchor: '100%',
27 allowBlank: false,
28 minValue: 1,
ad9d1625
DC
29 maxValue: 60,
30 value: viewModel.get('days'),
6e0f58e7 31 fieldLabel: gettext('Days to show'),
84b9eced
TL
32 }],
33 buttons: [{
34 text: gettext('Save'),
ad9d1625 35 reference: 'savebutton',
84b9eced
TL
36 formBind: true,
37 handler: function() {
38 var win = this.up('window');
ad9d1625
DC
39 var days = win.down('#days').getValue();
40 me.setDays(days, true);
84b9eced 41 win.close();
65b0cea6
TL
42 },
43 }],
44 }],
84b9eced
TL
45 }).show();
46 },
47
ad9d1625 48 setDays: function(days, setState) {
84b9eced
TL
49 var me = this;
50 var viewModel = me.getViewModel();
ad9d1625 51 viewModel.set('days', days);
84b9eced
TL
52 viewModel.notify();
53
ad9d1625
DC
54 viewModel.getStore('tasks').reload();
55
84b9eced
TL
56 if (setState) {
57 var sp = Ext.state.Manager.getProvider();
ad9d1625 58 sp.set('dashboard-days', days);
84b9eced
TL
59 }
60 },
61
62
63 updateSubscription: function(store, records, success) {
739a5145
DC
64 if (!success) { return; }
65 let me = this;
66 let subStatus = records[0].data.status === 'Active' ? 2 : 0; // 2 = all good, 1 = different leves, 0 = none
67 me.lookup('subscription').setSubStatus(subStatus);
84b9eced
TL
68 },
69
70 updateUsageStats: function(store, records, success) {
71 if (!success) {
72 return;
73 }
74 if (records === undefined || records.length < 1) {
75 return;
76 }
77 let me = this;
78 let viewmodel = me.getViewModel();
79
80 let res = records[0].data;
1f0d23f7 81 viewmodel.set('fingerprint', res.info.fingerprint || Proxmox.Utils.unknownText);
84b9eced
TL
82
83 let cpu = res.cpu,
84 mem = res.memory,
34020b92 85 root = res.root;
84b9eced
TL
86
87 var cpuPanel = me.lookup('cpu');
88 cpuPanel.updateValue(cpu);
89
90 var memPanel = me.lookup('mem');
91 memPanel.updateValue(mem.used / mem.total);
92
34020b92
DC
93 var hdPanel = me.lookup('root');
94 hdPanel.updateValue(root.used / root.total);
84b9eced
TL
95 },
96
1f0d23f7
DC
97 showFingerPrint: function() {
98 let me = this;
99 let vm = me.getViewModel();
100 let fingerprint = vm.get('fingerprint');
101 Ext.create('Ext.window.Window', {
102 modal: true,
103 width: 600,
104 title: gettext('Fingerprint'),
105 layout: 'form',
106 bodyPadding: '10 0',
107 items: [
108 {
109 xtype: 'textfield',
e4ee7b7a 110 inputId: 'fingerprintField',
1f0d23f7
DC
111 value: fingerprint,
112 editable: false,
113 },
114 ],
115 buttons: [
116 {
e4ee7b7a 117 xtype: 'button',
d257c2ec 118 iconCls: 'fa fa-clipboard',
e4ee7b7a
TL
119 handler: function(b) {
120 var el = document.getElementById('fingerprintField');
121 el.select();
122 document.execCommand("copy");
123 },
65b0cea6 124 text: gettext('Copy'),
e4ee7b7a
TL
125 },
126 {
d257c2ec 127 text: gettext('Ok'),
1f0d23f7
DC
128 handler: function() {
129 this.up('window').close();
130 },
131 },
132 ],
133 }).show();
134 },
135
195d7c90
DC
136 updateTasks: function(store, records, success) {
137 if (!success) return;
138 let me = this;
4acd7229 139 let viewModel = me.getViewModel();
195d7c90
DC
140
141 records.sort((a, b) => a.data.duration - b.data.duration);
142 let top10 = records.slice(-10);
143 me.lookup('longesttasks').updateTasks(top10);
144
145 let data = {
65b0cea6
TL
146 backup: { error: 0, warning: 0, ok: 0 },
147 prune: { error: 0, warning: 0, ok: 0 },
148 garbage_collection: { error: 0, warning: 0, ok: 0 },
149 sync: { error: 0, warning: 0, ok: 0 },
4acd7229 150 verify: { error: 0, warning: 0, ok: 0 },
195d7c90
DC
151 };
152
153 records.forEach(record => {
21486225
TL
154 let task = record.data;
155 let type = task.worker_type;
195d7c90
DC
156 if (type === 'syncjob') {
157 type = 'sync';
158 }
159
4acd7229
DC
160 if (type.startsWith('verify')) {
161 type = 'verify';
162 }
163
21486225
TL
164 if (data[type] && task.status) {
165 let parsed = Proxmox.Utils.parse_task_status(task.status);
195d7c90
DC
166 data[type][parsed]++;
167 }
168 });
169
dee74aa4 170 me.lookup('tasksummary').updateTasks(data, viewModel.get('sinceEpoch'));
195d7c90
DC
171 },
172
84b9eced
TL
173 init: function(view) {
174 var me = this;
175 var sp = Ext.state.Manager.getProvider();
ad9d1625
DC
176 var days = sp.get('dashboard-days') || 30;
177 me.setDays(days, false);
65b0cea6 178 },
84b9eced
TL
179 },
180
181 viewModel: {
182 data: {
1f0d23f7 183 fingerprint: "",
ad9d1625 184 days: 30,
84b9eced
TL
185 },
186
1f0d23f7
DC
187 formulas: {
188 disableFPButton: (get) => get('fingerprint') === "",
ad9d1625 189 sinceEpoch: (get) => (Date.now()/1000 - get('days') * 24*3600).toFixed(0),
1f0d23f7
DC
190 },
191
84b9eced
TL
192 stores: {
193 usage: {
194 storeid: 'dash-usage',
195 type: 'update',
196 interval: 3000,
197 autoStart: true,
198 autoLoad: true,
199 autoDestroy: true,
200 proxy: {
201 type: 'proxmox',
65b0cea6 202 url: '/api2/json/nodes/localhost/status',
84b9eced
TL
203 },
204 listeners: {
65b0cea6
TL
205 load: 'updateUsageStats',
206 },
84b9eced
TL
207 },
208 subscription: {
209 storeid: 'dash-subscription',
210 type: 'update',
211 interval: 10000,
212 autoStart: true,
213 autoLoad: true,
214 autoDestroy: true,
215 proxy: {
216 type: 'proxmox',
65b0cea6 217 url: '/api2/json/nodes/localhost/subscription',
84b9eced
TL
218 },
219 listeners: {
65b0cea6
TL
220 load: 'updateSubscription',
221 },
84b9eced 222 },
195d7c90
DC
223 tasks: {
224 storeid: 'dash-tasks',
225 type: 'update',
226 interval: 15000,
227 autoStart: true,
228 autoLoad: true,
229 autoDestroy: true,
230 model: 'proxmox-tasks',
231 proxy: {
232 type: 'proxmox',
65b0cea6 233 url: '/api2/json/status/tasks',
ad9d1625
DC
234 extraParams: {
235 since: '{sinceEpoch}',
236 },
195d7c90
DC
237 },
238 listeners: {
65b0cea6
TL
239 load: 'updateTasks',
240 },
195d7c90 241 },
65b0cea6 242 },
84b9eced
TL
243 },
244
ad9d1625 245 title: gettext('Dashboard'),
84b9eced
TL
246
247 layout: {
65b0cea6 248 type: 'column',
84b9eced
TL
249 },
250
251 bodyPadding: '20 0 0 20',
252
253 defaults: {
254 columnWidth: 0.49,
255 xtype: 'panel',
65b0cea6 256 margin: '0 20 20 0',
84b9eced
TL
257 },
258
ad9d1625
DC
259 tools: [
260 {
261 type: 'gear',
a2920c37 262 tooltip: gettext('Edit dashboard settings'),
ad9d1625
DC
263 handler: 'openDashboardOptions',
264 },
265 ],
266
84b9eced
TL
267 scrollable: true,
268
269 items: [
270 {
271 height: 250,
272 iconCls: 'fa fa-tasks',
273 title: gettext('Server Resources'),
274 bodyPadding: '0 20 0 20',
1f0d23f7
DC
275 tools: [
276 {
277 xtype: 'button',
278 text: gettext('Show Fingerprint'),
279 handler: 'showFingerPrint',
280 bind: {
281 disabled: '{disableFPButton}',
282 },
283 },
284 ],
84b9eced
TL
285 layout: {
286 type: 'hbox',
65b0cea6 287 align: 'center',
84b9eced
TL
288 },
289 defaults: {
290 xtype: 'proxmoxGauge',
291 spriteFontSize: '20px',
65b0cea6 292 flex: 1,
84b9eced
TL
293 },
294 items: [
295 {
296 title: gettext('CPU'),
65b0cea6 297 reference: 'cpu',
84b9eced
TL
298 },
299 {
300 title: gettext('Memory'),
65b0cea6 301 reference: 'mem',
84b9eced
TL
302 },
303 {
34020b92 304 title: gettext('Root Disk'),
65b0cea6
TL
305 reference: 'root',
306 },
307 ],
84b9eced 308 },
ae66873c
DC
309 {
310 xtype: 'pbsDatastoresStatistics',
311 height: 250,
312 },
84b9eced 313 {
195d7c90 314 xtype: 'pbsLongestTasks',
ad9d1625
DC
315 bind: {
316 title: gettext('Longest Tasks') + ' (' +
317 Ext.String.format(gettext('{0} days'), '{days}') + ')',
318 },
195d7c90 319 reference: 'longesttasks',
84b9eced 320 height: 250,
195d7c90
DC
321 },
322 {
323 xtype: 'pbsRunningTasks',
324 height: 250,
325 },
326 {
ad9d1625
DC
327 bind: {
328 title: gettext('Task Summary') + ' (' +
329 Ext.String.format(gettext('{0} days'), '{days}') + ')',
330 },
195d7c90
DC
331 xtype: 'pbsTaskSummary',
332 reference: 'tasksummary',
333 },
334 {
335 iconCls: 'fa fa-ticket',
336 title: 'Subscription',
337 height: 166,
338 reference: 'subscription',
739a5145 339 xtype: 'pbsSubscriptionInfo',
84b9eced 340 },
65b0cea6 341 ],
84b9eced
TL
342});
343
739a5145 344Ext.define('PBS.dashboard.SubscriptionInfo', {
84b9eced 345 extend: 'Ext.panel.Panel',
739a5145 346 xtype: 'pbsSubscriptionInfo',
84b9eced
TL
347
348 style: {
65b0cea6 349 cursor: 'pointer',
84b9eced
TL
350 },
351
739a5145
DC
352 layout: {
353 type: 'hbox',
354 align: 'middle',
355 },
356
357 items: [
358 {
359 xtype: 'box',
360 itemId: 'icon',
361 data: {
362 icon: 'question-circle',
363 },
364 width: 100,
365 tpl: '<center><i class="fa fa-3x fa-{icon}"></i></center>',
366 },
367 {
368 flex: 1,
369 xtype: 'box',
370 data: {
371 message: gettext('Unknown'),
372 },
373 itemId: 'message',
374 tpl: '<center>{message}</center>',
375 },
376 ],
377
84b9eced
TL
378 setSubStatus: function(status) {
379 var me = this;
739a5145
DC
380 let icon = '';
381 let message = '';
84b9eced
TL
382
383 switch (status) {
384 case 2:
739a5145
DC
385 icon = 'check good';
386 message = gettext('Your subscription status is valid.');
84b9eced 387 break;
2e75b6d8 388 case 1:
739a5145
DC
389 icon = 'exclamation-triangle warning';
390 message = gettext('Warning: Your subscription levels are not the same.');
84b9eced 391 break;
2e75b6d8 392 case 0:
739a5145
DC
393 icon = 'times-circle critical';
394 message = gettext('This node does not have a subscription.');
84b9eced
TL
395 break;
396 default:
397 throw 'invalid subscription status';
398 }
739a5145
DC
399 me.getComponent('icon').update({ icon });
400 me.getComponent('message').update({ message });
84b9eced 401 },
84b9eced
TL
402
403 listeners: {
404 click: {
405 element: 'body',
406 fn: function() {
407 var mainview = this.component.up('mainview');
739a5145 408 mainview.getController().redirectTo('pbsSubscription');
65b0cea6
TL
409 },
410 },
411 },
84b9eced 412});