]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/storage/ContentView.js
ui: makefile: fix order
[pve-manager.git] / www / manager6 / storage / ContentView.js
CommitLineData
4a580e60
DM
1Ext.define('PVE.storage.Upload', {
2 extend: 'Ext.window.Window',
3f90858a 3 alias: 'widget.pveStorageUpload',
4a580e60
DM
4
5 resizable: false,
6
7 modal: true,
8
9 initComponent : function() {
4a580e60
DM
10 var me = this;
11
12 var xhr;
13
14 if (!me.nodename) {
15 throw "no node name specified";
16 }
17
177de3de 18 if (!me.storage) {
4a580e60
DM
19 throw "no storage ID specified";
20 }
21
22 var baseurl = "/nodes/" + me.nodename + "/storage/" + me.storage + "/upload";
23
24 var pbar = Ext.create('Ext.ProgressBar', {
25 text: 'Ready',
26 hidden: true
27 });
28
c128543f
FE
29 let acceptedExtensions = {
30 iso: ".img, .iso",
31 vztmpl: ".tar.gz, .tar.xz",
32 };
33
34 let defaultContent = me.contents[0] || '';
35
36 let fileField = Ext.create('Ext.form.field.File', {
37 name: 'filename',
38 buttonText: gettext('Select File...'),
39 allowBlank: false,
40 setAccept: function(content) {
41 let acceptString = acceptedExtensions[content] || '';
42 this.fileInputEl.set({
43 accept: acceptString,
44 });
45 },
46 listeners: {
47 afterrender: function(cmp) {
48 cmp.setAccept(defaultContent);
49 },
50 },
51 });
52
4a580e60
DM
53 me.formPanel = Ext.create('Ext.form.Panel', {
54 method: 'POST',
55 waitMsgTarget: true,
56 bodyPadding: 10,
57 border: false,
58 width: 300,
59 fieldDefaults: {
60 labelWidth: 100,
61 anchor: '100%'
62 },
63 items: [
64 {
65 xtype: 'pveContentTypeSelector',
6c1a2b86 66 cts: me.contents,
4a580e60
DM
67 fieldLabel: gettext('Content'),
68 name: 'content',
c128543f 69 value: defaultContent,
518a3974
SR
70 allowBlank: false,
71 listeners: {
c128543f
FE
72 change: function(cmp, newValue, oldValue) {
73 fileField.setAccept(newValue);
74 },
75 },
4a580e60 76 },
c128543f 77 fileField,
4a580e60
DM
78 pbar
79 ]
80 });
81
82 var form = me.formPanel.getForm();
83
84 var doStandardSubmit = function() {
85 form.submit({
86 url: "/api2/htmljs" + baseurl,
87 waitMsg: gettext('Uploading file...'),
88 success: function(f, action) {
89 me.close();
90 },
91 failure: function(f, action) {
92 var msg = PVE.Utils.extractFormActionError(action);
93 Ext.Msg.alert(gettext('Error'), msg);
94 }
95 });
96 };
97
98 var updateProgress = function(per, bytes) {
99 var text = (per * 100).toFixed(2) + '%';
100 if (bytes) {
e7ade592 101 text += " (" + Proxmox.Utils.format_size(bytes) + ')';
4a580e60
DM
102 }
103 pbar.updateProgress(per, text);
104 };
177de3de 105
4a580e60
DM
106 var abortBtn = Ext.create('Ext.Button', {
107 text: gettext('Abort'),
108 disabled: true,
109 handler: function() {
110 me.close();
111 }
112 });
113
114 var submitBtn = Ext.create('Ext.Button', {
115 text: gettext('Upload'),
116 disabled: true,
117 handler: function(button) {
118 var fd;
119 try {
120 fd = new FormData();
121 } catch (err) {
122 doStandardSubmit();
123 return;
124 }
125
126 button.setDisabled(true);
127 abortBtn.setDisabled(false);
128
129 var field = form.findField('content');
130 fd.append("content", field.getValue());
131 field.setDisabled(true);
132
133 field = form.findField('filename');
134 var file = field.fileInputEl.dom;
135 fd.append("filename", file.files[0]);
136 field.setDisabled(true);
137
138 pbar.setVisible(true);
139 updateProgress(0);
140
141 xhr = new XMLHttpRequest();
142
177de3de 143 xhr.addEventListener("load", function(e) {
4a580e60
DM
144 if (xhr.status == 200) {
145 me.close();
177de3de 146 } else {
4a580e60 147 var msg = gettext('Error') + " " + xhr.status.toString() + ": " + Ext.htmlEncode(xhr.statusText);
abffa1a6
TM
148 if (xhr.responseText !== "") {
149 var result = Ext.decode(xhr.responseText);
150 result.message = msg;
e7c0216d 151 msg = Proxmox.Utils.extractRequestError(result, true);
abffa1a6 152 }
e7c0216d
TL
153 Ext.Msg.alert(gettext('Error'), msg, function(btn) {
154 me.close();
155 });
177de3de 156 }
4a580e60
DM
157 }, false);
158
159 xhr.addEventListener("error", function(e) {
160 var msg = "Error " + e.target.status.toString() + " occurred while receiving the document.";
161 Ext.Msg.alert(gettext('Error'), msg, function(btn) {
162 me.close();
163 });
164 });
177de3de 165
4a580e60 166 xhr.upload.addEventListener("progress", function(evt) {
177de3de
DC
167 if (evt.lengthComputable) {
168 var percentComplete = evt.loaded / evt.total;
4a580e60 169 updateProgress(percentComplete, evt.loaded);
177de3de 170 }
4a580e60
DM
171 }, false);
172
173 xhr.open("POST", "/api2/json" + baseurl, true);
177de3de 174 xhr.send(fd);
4a580e60
DM
175 }
176 });
177
178 form.on('validitychange', function(f, valid) {
179 submitBtn.setDisabled(!valid);
180 });
181
3b422683 182 Ext.apply(me, {
4a580e60
DM
183 title: gettext('Upload'),
184 items: me.formPanel,
185 buttons: [ abortBtn, submitBtn ],
186 listeners: {
187 close: function() {
188 if (xhr) {
189 xhr.abort();
190 }
191 }
192 }
193 });
194
195 me.callParent();
196 }
197});
198
199Ext.define('PVE.storage.ContentView', {
200 extend: 'Ext.grid.GridPanel',
201
3f90858a 202 alias: 'widget.pveStorageContentView',
4a580e60 203
c90539de
DC
204 viewConfig: {
205 trackOver: false,
22f2f9d6 206 loadMask: false
c90539de 207 },
4a580e60
DM
208 initComponent : function() {
209 var me = this;
210
dbeddeb3
FE
211 if (!me.nodename) {
212 me.nodename = me.pveSelNode.data.node;
213 if (!me.nodename) {
214 throw "no node name specified";
215 }
4a580e60 216 }
dbeddeb3 217 var nodename = me.nodename;
4a580e60 218
dbeddeb3
FE
219 if (!me.storage) {
220 me.storage = me.pveSelNode.data.storage;
221 if (!me.storage) {
222 throw "no storage ID specified";
223 }
4a580e60 224 }
dbeddeb3 225 var storage = me.storage;
4a580e60 226
e8b422bc
FE
227 var content = me.content;
228 if (!content) {
229 throw "no content type specified";
230 }
231
4a580e60 232 var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
dbeddeb3 233 var store = me.store = Ext.create('Ext.data.Store', {
4a580e60 234 model: 'pve-storage-content',
4a580e60 235 proxy: {
56a353b9 236 type: 'proxmox',
e8b422bc
FE
237 url: '/api2/json' + baseurl,
238 extraParams: {
239 content: content,
240 },
4a580e60 241 },
177de3de
DC
242 sorters: {
243 property: 'volid',
244 order: 'DESC'
4a580e60
DM
245 }
246 });
247
dbeddeb3
FE
248 if (!me.sm) {
249 me.sm = Ext.create('Ext.selection.RowModel', {});
250 }
251 var sm = me.sm;
4a580e60 252
4a580e60
DM
253 var reload = function() {
254 store.load();
255 };
256
e7ade592 257 Proxmox.Utils.monStoreErrors(me, store);
4a580e60 258
5720fafa 259 var uploadButton = Ext.create('Proxmox.button.Button', {
6c1a2b86
DC
260 text: gettext('Upload'),
261 handler: function() {
6c1a2b86
DC
262 var win = Ext.create('PVE.storage.Upload', {
263 nodename: nodename,
264 storage: storage,
8798c35b 265 contents: [content],
6c1a2b86
DC
266 });
267 win.show();
268 win.on('destroy', reload);
269 }
270 });
271
c5e224fc
WL
272 var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
273 selModel: sm,
4d23cdef 274 delay: 5,
c5e224fc
WL
275 callback: function() {
276 reload();
277 },
278 baseurl: baseurl + '/'
279 });
280
9ce0c258
FE
281 if (!me.tbar) {
282 me.tbar = [];
283 }
8798c35b
FE
284 if (me.useUploadButton) {
285 me.tbar.push(uploadButton);
286 }
f5e17f15
FE
287 if (!me.useCustomRemoveButton) {
288 me.tbar.push(removeButton);
289 }
9ce0c258 290 me.tbar.push(
9ce0c258
FE
291 '->',
292 gettext('Search') + ':', ' ',
293 {
294 xtype: 'textfield',
295 width: 200,
296 enableKeyEvents: true,
297 listeners: {
298 buffer: 500,
299 keyup: function(field) {
300 store.clearFilter(true);
301 store.filter([
302 {
303 property: 'text',
304 value: field.getValue(),
305 anyMatch: true,
306 caseSensitive: false
307 }
308 ]);
4a580e60
DM
309 }
310 }
9ce0c258
FE
311 }
312 );
313
7ef0f4c3
FE
314 var availableColumns = {
315 'name': {
316 header: gettext('Name'),
317 flex: 2,
318 sortable: true,
319 renderer: PVE.Utils.render_storage_content,
320 dataIndex: 'text'
321 },
322 'comment': {
323 header: gettext('Comment'),
324 flex: 1,
325 renderer: Ext.htmlEncode,
326 dataIndex: 'comment',
327 },
328 'date': {
329 header: gettext('Date'),
330 width: 150,
331 dataIndex: 'vdate'
332 },
333 'format': {
334 header: gettext('Format'),
335 width: 100,
336 dataIndex: 'format'
337 },
338 'size': {
339 header: gettext('Size'),
340 width: 100,
341 renderer: Proxmox.Utils.format_size,
342 dataIndex: 'size'
343 },
344 };
345
346 if (!me.showColumns) {
347 me.showColumns = ['name', 'comment', 'date', 'format', 'size'];
348 }
349 var columns = [];
350 me.showColumns.forEach(function(datum) {
351 columns.push(availableColumns[datum]);
352 });
353
9ce0c258
FE
354 Ext.apply(me, {
355 store: store,
356 selModel: sm,
357 tbar: me.tbar,
7ef0f4c3 358 columns: columns,
4a580e60 359 listeners: {
3b422683 360 activate: reload
4a580e60
DM
361 }
362 });
363
364 me.callParent();
365 }
366}, function() {
367
368 Ext.define('pve-storage-content', {
369 extend: 'Ext.data.Model',
177de3de
DC
370 fields: [
371 'volid', 'content', 'format', 'size', 'used', 'vmid',
957a53bd 372 'channel', 'id', 'lun', 'comment', 'verification',
177de3de
DC
373 {
374 name: 'text',
4a580e60 375 convert: function(value, record) {
86cc7049
DC
376 // check for volid, because if you click on a grouping header,
377 // it calls convert (but with an empty volid)
378 if (value || record.data.volid === null) {
4a580e60
DM
379 return value;
380 }
381 return PVE.Utils.render_storage_content(value, {}, record);
382 }
12d50fcd
TL
383 },
384 {
385 name: 'vdate',
386 convert: function(value, record) {
387 // check for volid, because if you click on a grouping header,
388 // it calls convert (but with an empty volid)
389 if (value || record.data.volid === null) {
390 return value;
391 }
392 let t = record.data.content;
393 if (t === "backup") {
394 let v = record.data.volid;
395 let match = v.match(/(\d{4}_\d{2}_\d{2})-(\d{2}_\d{2}_\d{2})/);
396 if (match) {
a4a86fe9 397 let date = match[1].replace(/_/g, '-');
12d50fcd
TL
398 let time = match[2].replace(/_/g, ':');
399 return date + " " + time;
400 }
401 }
a4a86fe9
DM
402 if (record.data.ctime) {
403 let ctime = new Date(record.data.ctime * 1000);
404 return Ext.Date.format(ctime,'Y-m-d H:i:s');
405 }
12d50fcd
TL
406 return '';
407 }
408 },
4a580e60
DM
409 ],
410 idProperty: 'volid'
411 });
412
413});