]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/grid/BackupView.js
ui: guest backup grid: hide file-restore button if not a PBS storage
[pve-manager.git] / www / manager6 / grid / BackupView.js
1 Ext.define('PVE.grid.BackupView', {
2 extend: 'Ext.grid.GridPanel',
3
4 alias: ['widget.pveBackupView'],
5
6 onlineHelp: 'chapter_vzdump',
7
8 stateful: true,
9 stateId: 'grid-guest-backup',
10
11 initComponent: function() {
12 var me = this;
13
14 var nodename = me.pveSelNode.data.node;
15 if (!nodename) {
16 throw "no node name specified";
17 }
18
19 var vmid = me.pveSelNode.data.vmid;
20 if (!vmid) {
21 throw "no VM ID specified";
22 }
23
24 var vmtype = me.pveSelNode.data.type;
25 if (!vmtype) {
26 throw "no VM type specified";
27 }
28
29 var vmtypeFilter;
30 if (vmtype === 'lxc' || vmtype === 'openvz') {
31 vmtypeFilter = function(item) {
32 return PVE.Utils.volume_is_lxc_backup(item.data.volid, item.data.format);
33 };
34 } else if (vmtype === 'qemu') {
35 vmtypeFilter = function(item) {
36 return PVE.Utils.volume_is_qemu_backup(item.data.volid, item.data.format);
37 };
38 } else {
39 throw "unsupported VM type '" + vmtype + "'";
40 }
41
42 var searchFilter = {
43 property: 'volid',
44 value: '',
45 anyMatch: true,
46 caseSensitive: false,
47 };
48
49 var vmidFilter = {
50 property: 'vmid',
51 value: vmid,
52 exactMatch: true,
53 };
54
55 me.store = Ext.create('Ext.data.Store', {
56 model: 'pve-storage-content',
57 sorters: {
58 property: 'volid',
59 order: 'DESC',
60 },
61 filters: [
62 vmtypeFilter,
63 searchFilter,
64 vmidFilter,
65 ],
66 });
67
68 let updateFilter = function() {
69 me.store.filter([
70 vmtypeFilter,
71 searchFilter,
72 vmidFilter,
73 ]);
74 };
75
76 var reload = Ext.Function.createBuffered(function() {
77 if (me.store) {
78 me.store.load();
79 }
80 }, 100);
81
82 let isPBS = false;
83 var setStorage = function(storage) {
84 var url = '/api2/json/nodes/' + nodename + '/storage/' + storage + '/content';
85 url += '?content=backup';
86
87 me.store.setProxy({
88 type: 'proxmox',
89 url: url,
90 });
91
92 reload();
93 };
94
95 let file_restore_btn;
96
97 var storagesel = Ext.create('PVE.form.StorageSelector', {
98 nodename: nodename,
99 fieldLabel: gettext('Storage'),
100 labelAlign: 'right',
101 storageContent: 'backup',
102 allowBlank: false,
103 listeners: {
104 change: function(f, value) {
105 let storage = f.getStore().findRecord('storage', value, 0, false, true, true);
106 if (storage) {
107 isPBS = storage.data.type === 'pbs';
108 me.getColumns().forEach((column) => {
109 let id = column.dataIndex;
110 if (id === 'verification' || id === 'encrypted') {
111 column.setHidden(!isPBS);
112 }
113 });
114 } else {
115 isPBS = false;
116 }
117 setStorage(value);
118 if (file_restore_btn) {
119 file_restore_btn.setHidden(!isPBS);
120 }
121 },
122 },
123 });
124
125 var storagefilter = Ext.create('Ext.form.field.Text', {
126 fieldLabel: gettext('Search'),
127 labelWidth: 50,
128 labelAlign: 'right',
129 enableKeyEvents: true,
130 value: searchFilter.value,
131 listeners: {
132 buffer: 500,
133 keyup: function(field) {
134 me.store.clearFilter(true);
135 searchFilter.value = field.getValue();
136 updateFilter();
137 },
138 },
139 });
140
141 var vmidfilterCB = Ext.create('Ext.form.field.Checkbox', {
142 boxLabel: gettext('Filter VMID'),
143 value: '1',
144 listeners: {
145 change: function(cb, value) {
146 vmidFilter.value = value ? vmid : '';
147 vmidFilter.exactMatch = !!value;
148 updateFilter();
149 },
150 },
151 });
152
153 var sm = Ext.create('Ext.selection.RowModel', {});
154
155 var backup_btn = Ext.create('Ext.button.Button', {
156 text: gettext('Backup now'),
157 handler: function() {
158 var win = Ext.create('PVE.window.Backup', {
159 nodename: nodename,
160 vmid: vmid,
161 vmtype: vmtype,
162 storage: storagesel.getValue(),
163 listeners: {
164 close: function() {
165 reload();
166 },
167 },
168 });
169 win.show();
170 },
171 });
172
173 var restore_btn = Ext.create('Proxmox.button.Button', {
174 text: gettext('Restore'),
175 disabled: true,
176 selModel: sm,
177 enableFn: function(rec) {
178 return !!rec;
179 },
180 handler: function(b, e, rec) {
181 let win = Ext.create('PVE.window.Restore', {
182 nodename: nodename,
183 vmid: vmid,
184 volid: rec.data.volid,
185 volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
186 vmtype: vmtype,
187 isPBS: isPBS,
188 });
189 win.show();
190 win.on('destroy', reload);
191 },
192 });
193
194 var delete_btn = Ext.create('Proxmox.button.StdRemoveButton', {
195 selModel: sm,
196 dangerous: true,
197 delay: 5,
198 confirmMsg: function(rec) {
199 var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
200 "'" + rec.data.volid + "'");
201 msg += " " + gettext('This will permanently erase all data.');
202
203 return msg;
204 },
205 getUrl: function(rec) {
206 var storage = storagesel.getValue();
207 return '/nodes/' + nodename + '/storage/' + storage + '/content/' + rec.data.volid;
208 },
209 callback: function() {
210 reload();
211 },
212 });
213
214 var config_btn = Ext.create('Proxmox.button.Button', {
215 text: gettext('Show Configuration'),
216 disabled: true,
217 selModel: sm,
218 enableFn: function(rec) {
219 return !!rec;
220 },
221 handler: function(b, e, rec) {
222 var storage = storagesel.getValue();
223 if (!storage) {
224 return;
225 }
226
227 var win = Ext.create('PVE.window.BackupConfig', {
228 volume: rec.data.volid,
229 pveSelNode: me.pveSelNode,
230 });
231
232 win.show();
233 },
234 });
235
236 // declared above so that the storage selector can change this buttons hidden state
237 file_restore_btn = Ext.create('Proxmox.button.Button', {
238 text: gettext('File Restore'),
239 disabled: true,
240 selModel: sm,
241 enableFn: function(rec) {
242 return !!rec && isPBS;
243 },
244 hidden: !isPBS,
245 handler: function(b, e, rec) {
246 var storage = storagesel.getValue();
247 Ext.create('Proxmox.window.FileBrowser', {
248 title: gettext('File Restore') + " - " + rec.data.text,
249 listURL: `/api2/json/nodes/localhost/storage/${storage}/file-restore/list`,
250 downloadURL: `/api2/json/nodes/localhost/storage/${storage}/file-restore/download`,
251 extraParams: {
252 volume: rec.data.volid,
253 },
254 archive: PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format) ?
255 'all' : undefined,
256 }).show();
257 },
258 });
259
260 Ext.apply(me, {
261 selModel: sm,
262 tbar: {
263 overflowHandler: 'scroller',
264 items: [
265 backup_btn,
266 restore_btn,
267 delete_btn,
268 '-',
269 config_btn,
270 file_restore_btn,
271 '-',
272 {
273 xtype: 'proxmoxButton',
274 text: gettext('Edit Notes'),
275 disabled: true,
276 handler: function() {
277 let volid = sm.getSelection()[0].data.volid;
278 var storage = storagesel.getValue();
279 Ext.create('Proxmox.window.Edit', {
280 autoLoad: true,
281 width: 600,
282 height: 400,
283 resizable: true,
284 title: gettext('Notes'),
285 url: `/api2/extjs/nodes/${nodename}/storage/${storage}/content/${volid}`,
286 layout: 'fit',
287 items: [
288 {
289 xtype: 'textarea',
290 layout: 'fit',
291 name: 'notes',
292 height: '100%',
293 },
294 ],
295 listeners: {
296 destroy: () => reload(),
297 },
298 }).show();
299 },
300 },
301 '->',
302 storagesel,
303 '-',
304 vmidfilterCB,
305 storagefilter,
306 ],
307 },
308 columns: [
309 {
310 header: gettext('Name'),
311 flex: 2,
312 sortable: true,
313 renderer: PVE.Utils.render_storage_content,
314 dataIndex: 'volid',
315 },
316 {
317 header: gettext('Notes'),
318 dataIndex: 'notes',
319 flex: 1,
320 renderer: Ext.htmlEncode,
321 },
322 {
323 header: gettext('Date'),
324 width: 150,
325 dataIndex: 'vdate',
326 },
327 {
328 header: gettext('Format'),
329 width: 100,
330 dataIndex: 'format',
331 },
332 {
333 header: gettext('Size'),
334 width: 100,
335 renderer: Proxmox.Utils.format_size,
336 dataIndex: 'size',
337 },
338 {
339 header: gettext('VMID'),
340 dataIndex: 'vmid',
341 hidden: true,
342 },
343 {
344 header: gettext('Encrypted'),
345 dataIndex: 'encrypted',
346 renderer: PVE.Utils.render_backup_encryption,
347 },
348 {
349 header: gettext('Verify State'),
350 dataIndex: 'verification',
351 renderer: PVE.Utils.render_backup_verification,
352 },
353 ],
354 });
355
356 me.callParent();
357 },
358 });