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