]> git.proxmox.com Git - pve-manager.git/blob - www/manager/storage/ContentView.js
71864f34058404205cc72576bcf9d51bb2bb3649
[pve-manager.git] / www / manager / storage / ContentView.js
1 Ext.define('PVE.grid.TemplateSelector', {
2 extend: 'Ext.grid.GridPanel',
3
4 alias: ['widget.pveTemplateSelector'],
5
6 initComponent : function() {
7 var me = this;
8
9 if (!me.nodename) {
10 throw "no node name specified";
11 }
12
13 var baseurl = "/nodes/" + me.nodename + "/aplinfo";
14 var store = new Ext.data.Store({
15 model: 'pve-aplinfo',
16 groupField: 'section',
17 proxy: {
18 type: 'pve',
19 url: '/api2/json' + baseurl
20 }
21 });
22
23 var sm = Ext.create('Ext.selection.RowModel', {});
24
25 var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
26 groupHeaderTpl: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
27 });
28
29 var reload = function() {
30 store.load();
31 };
32
33 PVE.Utils.monStoreErrors(me, store);
34
35 Ext.apply(me, {
36 store: store,
37 selModel: sm,
38 stateful: false,
39 viewConfig: {
40 trackOver: false
41 },
42 features: [ groupingFeature ],
43 columns: [
44 {
45 header: gettext('Type'),
46 width: 80,
47 dataIndex: 'type'
48 },
49 {
50 header: gettext('Package'),
51 flex: 1,
52 dataIndex: 'package'
53 },
54 {
55 header: gettext('Version'),
56 width: 80,
57 dataIndex: 'version'
58 },
59 {
60 header: gettext('Description'),
61 flex: 1.5,
62 dataIndex: 'headline'
63 }
64 ],
65 listeners: {
66 afterRender: reload
67 }
68 });
69
70 me.callParent();
71 }
72
73 }, function() {
74
75 Ext.define('pve-aplinfo', {
76 extend: 'Ext.data.Model',
77 fields: [
78 'template', 'type', 'package', 'version', 'headline', 'infopage',
79 'description', 'os', 'section'
80 ],
81 idProperty: 'template'
82 });
83
84 });
85
86 Ext.define('PVE.storage.TemplateDownload', {
87 extend: 'Ext.window.Window',
88 alias: ['widget.pveTemplateDownload'],
89
90 modal: true,
91
92 initComponent : function() {
93 /*jslint confusion: true */
94 var me = this;
95
96 var grid = Ext.create('PVE.grid.TemplateSelector', {
97 border: false,
98 autoScroll: true,
99 nodename: me.nodename
100 });
101
102 var sm = grid.getSelectionModel();
103
104 var submitBtn = Ext.create('PVE.button.Button', {
105 text: gettext('Download'),
106 disabled: true,
107 selModel: sm,
108 handler: function(button, event, rec) {
109 PVE.Utils.API2Request({
110 url: '/nodes/' + me.nodename + '/aplinfo',
111 params: {
112 storage: me.storage,
113 template: rec.data.template
114 },
115 method: 'POST',
116 failure: function (response, opts) {
117 Ext.Msg.alert('Error', response.htmlStatus);
118 },
119 success: function(response, options) {
120 var upid = response.result.data;
121
122 var win = Ext.create('PVE.window.TaskViewer', {
123 upid: upid
124 });
125 win.show();
126 me.close();
127 }
128 });
129 }
130 });
131
132 Ext.applyIf(me, {
133 title: gettext('Templates'),
134 layout: 'fit',
135 width: 600,
136 height: 400,
137 items: grid,
138 buttons: [ submitBtn ]
139 });
140
141 me.callParent();
142 }
143 });
144
145 Ext.define('PVE.storage.Upload', {
146 extend: 'Ext.window.Window',
147 alias: ['widget.pveStorageUpload'],
148
149 resizable: false,
150
151 modal: true,
152
153 initComponent : function() {
154 /*jslint confusion: true */
155 var me = this;
156
157 var xhr;
158
159 if (!me.nodename) {
160 throw "no node name specified";
161 }
162
163 if (!me.storage) {
164 throw "no storage ID specified";
165 }
166
167 var baseurl = "/nodes/" + me.nodename + "/storage/" + me.storage + "/upload";
168
169 var pbar = Ext.create('Ext.ProgressBar', {
170 text: 'Ready',
171 hidden: true
172 });
173
174 me.formPanel = Ext.create('Ext.form.Panel', {
175 method: 'POST',
176 waitMsgTarget: true,
177 bodyPadding: 10,
178 border: false,
179 width: 300,
180 fieldDefaults: {
181 labelWidth: 100,
182 anchor: '100%'
183 },
184 items: [
185 {
186 xtype: 'pveKVComboBox',
187 data: [
188 ['iso', 'ISO image'],
189 ['backup', 'VZDump backup file'],
190 ['vztmpl', 'OpenVZ template']
191 ],
192 fieldLabel: gettext('Content'),
193 name: 'content',
194 value: 'iso'
195 },
196 {
197 xtype: 'filefield',
198 name: 'filename',
199 buttonText: gettext('Select File...'),
200 allowBlank: false
201 },
202 pbar
203 ]
204 });
205
206 var form = me.formPanel.getForm();
207
208 var doStandardSubmit = function() {
209 form.submit({
210 url: "/api2/htmljs" + baseurl,
211 waitMsg: gettext('Uploading file...'),
212 success: function(f, action) {
213 me.close();
214 },
215 failure: function(f, action) {
216 var msg = PVE.Utils.extractFormActionError(action);
217 Ext.Msg.alert(gettext('Error'), msg);
218 }
219 });
220 };
221
222 var updateProgress = function(per, bytes) {
223 var text = (per * 100).toFixed(2) + '%';
224 if (bytes) {
225 text += " (" + PVE.Utils.format_size(bytes) + ')';
226 }
227 pbar.updateProgress(per, text);
228 };
229
230 var abortBtn = Ext.create('Ext.Button', {
231 text: gettext('Abort'),
232 disabled: true,
233 handler: function() {
234 me.close();
235 }
236 });
237
238 var submitBtn = Ext.create('Ext.Button', {
239 text: gettext('Upload'),
240 disabled: true,
241 handler: function(button) {
242 var fd;
243 try {
244 fd = new FormData();
245 } catch (err) {
246 doStandardSubmit();
247 return;
248 }
249
250 button.setDisabled(true);
251 abortBtn.setDisabled(false);
252
253 var field = form.findField('content');
254 fd.append("content", field.getValue());
255 field.setDisabled(true);
256
257 field = form.findField('filename');
258 var file = field.fileInputEl.dom;
259 fd.append("filename", file.files[0]);
260 field.setDisabled(true);
261
262 pbar.setVisible(true);
263 updateProgress(0);
264
265 xhr = new XMLHttpRequest();
266
267 xhr.addEventListener("load", function(e) {
268 if (xhr.status == 200) {
269 me.close();
270 } else {
271 var msg = "Error " + xhr.status.toString() + ": " + Ext.htmlEncode(xhr.statusText);
272 var result = Ext.decode(xhr.responseText);
273 result.message = msg;
274 var htmlStatus = PVE.Utils.extractRequestError(result, true);
275 Ext.Msg.alert(gettext('Error'), htmlStatus, function(btn) {
276 me.close();
277 });
278
279 }
280 }, false);
281
282 xhr.addEventListener("error", function(e) {
283 var msg = "Error " + e.target.status.toString() + " occurred while receiving the document.";
284 Ext.Msg.alert(gettext('Error'), msg, function(btn) {
285 me.close();
286 });
287 });
288
289 xhr.upload.addEventListener("progress", function(evt) {
290 if (evt.lengthComputable) {
291 var percentComplete = evt.loaded / evt.total;
292 updateProgress(percentComplete, evt.loaded);
293 }
294 }, false);
295
296 xhr.open("POST", "/api2/json" + baseurl, true);
297 xhr.send(fd);
298 }
299 });
300
301 form.on('validitychange', function(f, valid) {
302 submitBtn.setDisabled(!valid);
303 });
304
305 Ext.applyIf(me, {
306 title: gettext('Upload'),
307 items: me.formPanel,
308 buttons: [ abortBtn, submitBtn ],
309 listeners: {
310 close: function() {
311 if (xhr) {
312 xhr.abort();
313 }
314 }
315 }
316 });
317
318 me.callParent();
319 }
320 });
321
322 Ext.define('PVE.storage.ContentView', {
323 extend: 'Ext.grid.GridPanel',
324
325 alias: ['widget.pveStorageContentView'],
326
327 initComponent : function() {
328 var me = this;
329
330 var nodename = me.pveSelNode.data.node;
331 if (!nodename) {
332 throw "no node name specified";
333 }
334
335 var storage = me.pveSelNode.data.storage;
336 if (!storage) {
337 throw "no storage ID specified";
338 }
339
340 var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
341 var store = new Ext.data.Store({
342 model: 'pve-storage-content',
343 groupField: 'content',
344 proxy: {
345 type: 'pve',
346 url: '/api2/json' + baseurl
347 },
348 sorters: {
349 property: 'volid',
350 order: 'DESC'
351 }
352 });
353
354 var sm = Ext.create('Ext.selection.RowModel', {});
355
356 var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
357 groupHeaderTpl: '{[ PVE.Utils.format_content_types(values.name) ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
358 });
359
360 var reload = function() {
361 store.load();
362 };
363
364 PVE.Utils.monStoreErrors(me, store);
365
366 Ext.apply(me, {
367 store: store,
368 selModel: sm,
369 stateful: false,
370 viewConfig: {
371 trackOver: false
372 },
373 features: [ groupingFeature ],
374 tbar: [
375 {
376 xtype: 'pveButton',
377 text: gettext('Restore'),
378 selModel: sm,
379 disabled: true,
380 enableFn: function(rec) {
381 return rec && rec.data.content === 'backup';
382 },
383 handler: function(b, e, rec) {
384 var vmtype;
385 if (rec.data.volid.match(/vzdump-qemu-/)) {
386 vmtype = 'qemu';
387 } else if (rec.data.volid.match(/vzdump-openvz-/)) {
388 vmtype = 'openvz';
389 } else {
390 return;
391 }
392
393 var win = Ext.create('PVE.window.Restore', {
394 nodename: nodename,
395 volid: rec.data.volid,
396 volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
397 vmtype: vmtype
398 });
399 win.show();
400 win.on('destroy', reload);
401 }
402 },
403 {
404 xtype: 'pveButton',
405 text: gettext('Remove'),
406 selModel: sm,
407 disabled: true,
408 confirmMsg: function(rec) {
409 return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
410 "'" + rec.data.volid + "'");
411 },
412 enableFn: function(rec) {
413 return rec && rec.data.content !== 'images';
414 },
415 handler: function(b, e, rec) {
416 PVE.Utils.API2Request({
417 url: baseurl + '/' + rec.data.volid,
418 method: 'DELETE',
419 waitMsgTarget: me,
420 callback: function() {
421 reload();
422 },
423 failure: function (response, opts) {
424 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
425 }
426 });
427 }
428 },
429 {
430 text: gettext('Templates'),
431 handler: function() {
432 var win = Ext.create('PVE.storage.TemplateDownload', {
433 nodename: nodename,
434 storage: storage
435 });
436 win.show();
437 win.on('destroy', reload);
438 }
439 },
440 {
441 text: gettext('Upload'),
442 handler: function() {
443 var win = Ext.create('PVE.storage.Upload', {
444 nodename: nodename,
445 storage: storage
446 });
447 win.show();
448 win.on('destroy', reload);
449 }
450 }
451 ],
452 columns: [
453 {
454 header: gettext('Name'),
455 flex: 1,
456 sortable: true,
457 renderer: PVE.Utils.render_storage_content,
458 dataIndex: 'text'
459 },
460 {
461 header: gettext('Format'),
462 width: 100,
463 dataIndex: 'format'
464 },
465 {
466 header: gettext('Size'),
467 width: 100,
468 renderer: PVE.Utils.format_size,
469 dataIndex: 'size'
470 }
471 ],
472 listeners: {
473 show: reload
474 }
475 });
476
477 me.callParent();
478 }
479 }, function() {
480
481 Ext.define('pve-storage-content', {
482 extend: 'Ext.data.Model',
483 fields: [
484 'volid', 'content', 'format', 'size', 'used', 'vmid',
485 'channel', 'id', 'lun',
486 {
487 name: 'text',
488 convert: function(value, record) {
489 if (value) {
490 return value;
491 }
492 return PVE.Utils.render_storage_content(value, {}, record);
493 }
494 }
495 ],
496 idProperty: 'volid'
497 });
498
499 });