]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/dc/Backup.js
use windowEdit from widget toolkit
[pve-manager.git] / www / manager6 / dc / Backup.js
1 Ext.define('PVE.dc.BackupEdit', {
2 extend: 'Proxmox.window.Edit',
3 alias: ['widget.pveDcBackupEdit'],
4
5 defaultFocus: undefined,
6
7 initComponent : function() {
8 var me = this;
9
10 me.isCreate = !me.jobid;
11
12 var url;
13 var method;
14
15 if (me.isCreate) {
16 url = '/api2/extjs/cluster/backup';
17 method = 'POST';
18 } else {
19 url = '/api2/extjs/cluster/backup/' + me.jobid;
20 method = 'PUT';
21 }
22
23 var vmidField = Ext.create('Ext.form.field.Hidden', {
24 name: 'vmid'
25 });
26
27 /*jslint confusion: true*/
28 // 'value' can be assigned a string or an array
29 var selModeField = Ext.create('Proxmox.form.KVComboBox', {
30 xtype: 'proxmoxKVComboBox',
31 comboItems: [
32 ['include', gettext('Include selected VMs')],
33 ['all', gettext('All')],
34 ['exclude', gettext('Exclude selected VMs')]
35 ],
36 fieldLabel: gettext('Selection mode'),
37 name: 'selMode',
38 value: ''
39 });
40
41 var sm = Ext.create('Ext.selection.CheckboxModel', {
42 mode: 'SIMPLE',
43 listeners: {
44 selectionchange: function(model, selected) {
45 var sel = [];
46 Ext.Array.each(selected, function(record) {
47 sel.push(record.data.vmid);
48 });
49
50 // to avoid endless recursion suspend the vmidField change
51 // event temporary as it calls us again
52 vmidField.suspendEvent('change');
53 vmidField.setValue(sel);
54 vmidField.resumeEvent('change');
55 }
56 }
57 });
58
59 var storagesel = Ext.create('PVE.form.StorageSelector', {
60 fieldLabel: gettext('Storage'),
61 nodename: 'localhost',
62 storageContent: 'backup',
63 allowBlank: false,
64 name: 'storage'
65 });
66
67 var store = new Ext.data.Store({
68 model: 'PVEResources',
69 sorters: {
70 property: 'vmid',
71 order: 'ASC'
72 }
73 });
74
75 var vmgrid = Ext.createWidget('grid', {
76 store: store,
77 border: true,
78 height: 300,
79 selModel: sm,
80 disabled: true,
81 columns: [
82 {
83 header: 'ID',
84 dataIndex: 'vmid',
85 width: 60
86 },
87 {
88 header: gettext('Node'),
89 dataIndex: 'node'
90 },
91 {
92 header: gettext('Status'),
93 dataIndex: 'uptime',
94 renderer: function(value) {
95 if (value) {
96 return Proxmox.Utils.runningText;
97 } else {
98 return Proxmox.Utils.stoppedText;
99 }
100 }
101 },
102 {
103 header: gettext('Name'),
104 dataIndex: 'name',
105 flex: 1
106 },
107 {
108 header: gettext('Type'),
109 dataIndex: 'type'
110 }
111 ]
112 });
113
114 var nodesel = Ext.create('PVE.form.NodeSelector', {
115 name: 'node',
116 fieldLabel: gettext('Node'),
117 allowBlank: true,
118 editable: true,
119 autoSelect: false,
120 emptyText: '-- ' + gettext('All') + ' --',
121 listeners: {
122 change: function(f, value) {
123 storagesel.setNodename(value || 'localhost');
124 var mode = selModeField.getValue();
125 store.clearFilter();
126 store.filterBy(function(rec) {
127 return (!value || rec.get('node') === value);
128 });
129 if (mode === 'all') {
130 sm.selectAll(true);
131 }
132 }
133 }
134 });
135
136 var column1 = [
137 nodesel,
138 storagesel,
139 {
140 xtype: 'pveDayOfWeekSelector',
141 name: 'dow',
142 fieldLabel: gettext('Day of week'),
143 multiSelect: true,
144 value: ['sat'],
145 allowBlank: false
146 },
147 {
148 xtype: 'timefield',
149 fieldLabel: gettext('Start Time'),
150 name: 'starttime',
151 format: 'H:i',
152 value: '00:00',
153 allowBlank: false
154 },
155 selModeField
156 ];
157
158 var column2 = [
159 {
160 xtype: 'textfield',
161 fieldLabel: gettext('Send email to'),
162 name: 'mailto'
163 },
164 {
165 xtype: 'pveEmailNotificationSelector',
166 fieldLabel: gettext('Email notification'),
167 name: 'mailnotification',
168 deleteEmpty: me.isCreate ? false : true,
169 value: me.isCreate ? 'always' : ''
170 },
171 {
172 xtype: 'pveCompressionSelector',
173 fieldLabel: gettext('Compression'),
174 name: 'compress',
175 deleteEmpty: me.isCreate ? false : true,
176 value: 'lzo'
177 },
178 {
179 xtype: 'pveBackupModeSelector',
180 fieldLabel: gettext('Mode'),
181 value: 'snapshot',
182 name: 'mode'
183 },
184 {
185 xtype: 'proxmoxcheckbox',
186 fieldLabel: gettext('Enable'),
187 name: 'enabled',
188 uncheckedValue: 0,
189 defaultValue: 1,
190 checked: true
191 },
192 vmidField
193 ];
194 /*jslint confusion: false*/
195
196 var ipanel = Ext.create('PVE.panel.InputPanel', {
197 onlineHelp: 'chapter_vzdump',
198 column1: column1,
199 column2: column2,
200 onGetValues: function(values) {
201 if (!values.node) {
202 if (!me.isCreate) {
203 Proxmox.Utils.assemble_field_data(values, { 'delete': 'node' });
204 }
205 delete values.node;
206 }
207
208 var selMode = values.selMode;
209 delete values.selMode;
210
211 if (selMode === 'all') {
212 values.all = 1;
213 values.exclude = '';
214 delete values.vmid;
215 } else if (selMode === 'exclude') {
216 values.all = 1;
217 values.exclude = values.vmid;
218 delete values.vmid;
219 }
220 return values;
221 }
222 });
223
224 var update_vmid_selection = function(list, mode) {
225 if (mode !== 'all') {
226 sm.deselectAll(true);
227 if (list) {
228 Ext.Array.each(list.split(','), function(vmid) {
229 var rec = store.findRecord('vmid', vmid);
230 if (rec) {
231 sm.select(rec, true);
232 }
233 });
234 }
235 }
236 };
237
238 vmidField.on('change', function(f, value) {
239 var mode = selModeField.getValue();
240 update_vmid_selection(value, mode);
241 });
242
243 selModeField.on('change', function(f, value, oldValue) {
244 if (value === 'all') {
245 sm.selectAll(true);
246 vmgrid.setDisabled(true);
247 } else {
248 vmgrid.setDisabled(false);
249 }
250 if (oldValue === 'all') {
251 sm.deselectAll(true);
252 vmidField.setValue('');
253 }
254 var list = vmidField.getValue();
255 update_vmid_selection(list, value);
256 });
257
258 var reload = function() {
259 store.load({
260 params: { type: 'vm' },
261 callback: function() {
262 var node = nodesel.getValue();
263 store.clearFilter();
264 store.filterBy(function(rec) {
265 return (!node || node.length === 0 || rec.get('node') === node);
266 });
267 var list = vmidField.getValue();
268 var mode = selModeField.getValue();
269 if (mode === 'all') {
270 sm.selectAll(true);
271 } else {
272 update_vmid_selection(list, mode);
273 }
274 }
275 });
276 };
277
278 Ext.applyIf(me, {
279 subject: gettext("Backup Job"),
280 url: url,
281 method: method,
282 items: [ ipanel, vmgrid ]
283 });
284
285 me.callParent();
286
287 if (me.isCreate) {
288 selModeField.setValue('include');
289 } else {
290 me.load({
291 success: function(response, options) {
292 var data = response.result.data;
293
294 data.dow = data.dow.split(',');
295
296 if (data.all || data.exclude) {
297 if (data.exclude) {
298 data.vmid = data.exclude;
299 data.selMode = 'exclude';
300 } else {
301 data.vmid = '';
302 data.selMode = 'all';
303 }
304 } else {
305 data.selMode = 'include';
306 }
307
308 me.setValues(data);
309 }
310 });
311 }
312
313 reload();
314 }
315 });
316
317
318 Ext.define('PVE.dc.BackupView', {
319 extend: 'Ext.grid.GridPanel',
320
321 alias: ['widget.pveDcBackupView'],
322
323 onlineHelp: 'chapter_vzdump',
324
325 allText: '-- ' + gettext('All') + ' --',
326 allExceptText: gettext('All except {0}'),
327
328 initComponent : function() {
329 var me = this;
330
331 var store = new Ext.data.Store({
332 model: 'pve-cluster-backup',
333 proxy: {
334 type: 'pve',
335 url: "/api2/json/cluster/backup"
336 }
337 });
338
339 var reload = function() {
340 store.load();
341 };
342
343 var sm = Ext.create('Ext.selection.RowModel', {});
344
345 var run_editor = function() {
346 var rec = sm.getSelection()[0];
347 if (!rec) {
348 return;
349 }
350
351 var win = Ext.create('PVE.dc.BackupEdit',{
352 jobid: rec.data.id
353 });
354 win.on('destroy', reload);
355 win.show();
356 };
357
358 var edit_btn = new Proxmox.button.Button({
359 text: gettext('Edit'),
360 disabled: true,
361 selModel: sm,
362 handler: run_editor
363 });
364
365 var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
366 selModel: sm,
367 baseurl: '/cluster/backup',
368 callback: function() {
369 reload();
370 }
371 });
372
373 Proxmox.Utils.monStoreErrors(me, store);
374
375 Ext.apply(me, {
376 store: store,
377 selModel: sm,
378 stateful: true,
379 stateId: 'grid-dc-backup',
380 viewConfig: {
381 trackOver: false
382 },
383 tbar: [
384 {
385 text: gettext('Add'),
386 handler: function() {
387 var win = Ext.create('PVE.dc.BackupEdit',{});
388 win.on('destroy', reload);
389 win.show();
390 }
391 },
392 remove_btn,
393 edit_btn
394 ],
395 columns: [
396 {
397 header: gettext('Enabled'),
398 width: 80,
399 dataIndex: 'enabled',
400 xtype: 'checkcolumn',
401 sortable: true,
402 disabled: true,
403 disabledCls: 'x-item-enabled',
404 stopSelection: false
405 },
406 {
407 header: gettext('Node'),
408 width: 100,
409 sortable: true,
410 dataIndex: 'node',
411 renderer: function(value) {
412 if (value) {
413 return value;
414 }
415 return me.allText;
416 }
417 },
418 {
419 header: gettext('Day of week'),
420 width: 200,
421 sortable: false,
422 dataIndex: 'dow',
423 renderer: function(val) {
424 var dows = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
425 var selected = [];
426 var cur = -1;
427 val.split(',').forEach(function(day){
428 cur++;
429 var dow = (dows.indexOf(day)+6)%7;
430 if (cur === dow) {
431 if (selected.length === 0 || selected[selected.length-1] === 0) {
432 selected.push(1);
433 } else {
434 selected[selected.length-1]++;
435 }
436 } else {
437 while (cur < dow) {
438 cur++;
439 selected.push(0);
440 }
441 selected.push(1);
442 }
443 });
444
445 cur = -1;
446 var days = [];
447 selected.forEach(function(item) {
448 cur++;
449 if (item > 2) {
450 days.push(Ext.Date.dayNames[(cur+1)] + '-' + Ext.Date.dayNames[(cur+item)%7]);
451 cur += item-1;
452 } else if (item == 2) {
453 days.push(Ext.Date.dayNames[cur+1]);
454 days.push(Ext.Date.dayNames[(cur+2)%7]);
455 cur++;
456 } else if (item == 1) {
457 days.push(Ext.Date.dayNames[(cur+1)%7]);
458 }
459 });
460 return days.join(', ');
461 }
462 },
463 {
464 header: gettext('Start Time'),
465 width: 60,
466 sortable: true,
467 dataIndex: 'starttime'
468 },
469 {
470 header: gettext('Storage'),
471 width: 100,
472 sortable: true,
473 dataIndex: 'storage'
474 },
475 {
476 header: gettext('Selection'),
477 flex: 1,
478 sortable: false,
479 dataIndex: 'vmid',
480 renderer: function(value, metaData, record) {
481 /*jslint confusion: true */
482 if (record.data.all) {
483 if (record.data.exclude) {
484 return Ext.String.format(me.allExceptText, record.data.exclude);
485 }
486 return me.allText;
487 }
488 if (record.data.vmid) {
489 return record.data.vmid;
490 }
491
492 return "-";
493 }
494 }
495 ],
496 listeners: {
497 activate: reload,
498 itemdblclick: run_editor
499 }
500 });
501
502 me.callParent();
503 }
504 }, function() {
505
506 Ext.define('pve-cluster-backup', {
507 extend: 'Ext.data.Model',
508 fields: [
509 'id', 'starttime', 'dow',
510 'storage', 'node', 'vmid', 'exclude',
511 'mailto',
512 { name: 'enabled', type: 'boolean' },
513 { name: 'all', type: 'boolean' },
514 { name: 'snapshot', type: 'boolean' },
515 { name: 'stop', type: 'boolean' },
516 { name: 'suspend', type: 'boolean' },
517 { name: 'compress', type: 'boolean' }
518 ]
519 });
520 });