]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/storage/ContentView.js
1 Ext
.define('PVE.storage.Upload', {
2 extend
: 'Ext.window.Window',
3 alias
: 'widget.pveStorageUpload',
9 initComponent: function() {
13 throw "no node name specified";
16 throw "no storage ID specified";
19 let baseurl
= `/nodes/${me.nodename}/storage/${me.storage}/upload`;
21 let pbar
= Ext
.create('Ext.ProgressBar', {
26 let acceptedExtensions
= {
28 vztmpl
: ".tar.gz, .tar.xz",
31 let defaultContent
= me
.contents
[0] || '';
33 let fileField
= Ext
.create('Ext.form.field.File', {
35 buttonText
: gettext('Select File...'),
37 setAccept: function(content
) {
38 let acceptString
= acceptedExtensions
[content
] || '';
39 this.fileInputEl
.set({
44 afterrender: function(cmp
) {
45 cmp
.setAccept(defaultContent
);
50 me
.formPanel
= Ext
.create('Ext.form.Panel', {
62 xtype
: 'pveContentTypeSelector',
64 fieldLabel
: gettext('Content'),
66 value
: defaultContent
,
69 change: function(cmp
, newValue
, oldValue
) {
70 fileField
.setAccept(newValue
);
79 let form
= me
.formPanel
.getForm();
81 let doStandardSubmit = function() {
83 url
: "/api2/htmljs" + baseurl
,
84 waitMsg
: gettext('Uploading file...'),
85 success: function(f
, action
) {
88 failure: function(f
, action
) {
89 var msg
= PVE
.Utils
.extractFormActionError(action
);
90 Ext
.Msg
.alert(gettext('Error'), msg
);
95 let updateProgress = function(per
, bytes
) {
96 var text
= (per
* 100).toFixed(2) + '%';
98 text
+= " (" + Proxmox
.Utils
.format_size(bytes
) + ')';
100 pbar
.updateProgress(per
, text
);
103 let abortBtn
= Ext
.create('Ext.Button', {
104 text
: gettext('Abort'),
106 handler: function() {
111 let submitBtn
= Ext
.create('Ext.Button', {
112 text
: gettext('Upload'),
114 handler: function(button
) {
123 button
.setDisabled(true);
124 abortBtn
.setDisabled(false);
126 var field
= form
.findField('content');
127 fd
.append("content", field
.getValue());
128 field
.setDisabled(true);
130 field
= form
.findField('filename');
131 var file
= field
.fileInputEl
.dom
;
132 fd
.append("filename", file
.files
[0]);
133 field
.setDisabled(true);
135 pbar
.setVisible(true);
138 let xhr
= new XMLHttpRequest();
141 xhr
.addEventListener("load", function(e
) {
142 if (xhr
.status
=== 200) {
146 let err
= Ext
.htmlEncode(xhr
.statusText
);
147 let msg
= `${gettext('Error')} ${xhr.status.toString()}: ${err}`;
148 if (xhr
.responseText
!== "") {
149 let result
= Ext
.decode(xhr
.responseText
);
150 result
.message
= msg
;
151 msg
= Proxmox
.Utils
.extractRequestError(result
, true);
153 Ext
.Msg
.alert(gettext('Error'), msg
, btn
=> me
.close());
156 xhr
.addEventListener("error", function(e
) {
157 let err
= e
.target
.status
.toString();
158 let msg
= `Error '${err}' occurred while receiving the document.`;
159 Ext
.Msg
.alert(gettext('Error'), msg
, btn
=> me
.close());
162 xhr
.upload
.addEventListener("progress", function(evt
) {
163 if (evt
.lengthComputable
) {
164 let percentComplete
= evt
.loaded
/ evt
.total
;
165 updateProgress(percentComplete
, evt
.loaded
);
169 xhr
.open("POST", `/api2/json${baseurl}`, true);
174 form
.on('validitychange', (f
, valid
) => submitBtn
.setDisabled(!valid
));
177 title
: gettext('Upload'),
179 buttons
: [abortBtn
, submitBtn
],
194 Ext
.define('PVE.storage.DownloadUrl', {
195 extend
: 'Proxmox.window.Edit',
196 alias
: 'widget.pveStorageDownloadUrl',
197 mixins
: ['Proxmox.Mixin.CBind'],
203 showTaskViewer
: true,
205 title
: gettext('Download from URL'),
206 submitText
: gettext('Download'),
208 cbindData: function(initialConfig
) {
211 nodename
: me
.nodename
,
218 url
: '/nodes/{nodename}/storage/{storage}/download-url',
222 xclass
: 'Ext.app.ViewController',
224 urlChange: function(field
) {
226 let view
= me
.getView();
227 field
= view
.down('[name=url]');
228 field
.setValidation(gettext("Please check URL"));
231 size
: gettext("unknown"),
232 mimetype
: gettext("unknown"),
236 urlCheck: function(field
) {
238 let view
= me
.getView();
239 field
= view
.down('[name=url]');
241 size
: gettext("unknown"),
242 mimetype
: gettext("unknown"),
244 Proxmox
.Utils
.API2Request({
245 url
: `/nodes/${view.nodename}/query-url-metadata`,
248 url
: field
.getValue(),
249 'verify-certificates': view
.getValues()['verify-certificates'],
252 failure: function(res
, opt
) {
253 field
.setValidation(res
.result
.message
);
256 success: function(res
, opt
) {
257 field
.setValidation();
260 let data
= res
.result
.data
;
262 filename
: data
.filename
|| "",
263 size
: (data
.size
&& Proxmox
.Utils
.format_size(data
.size
)) || gettext("unknown"),
264 mimetype
: data
.mimetype
|| gettext("unknown"),
270 hashChange: function(field
) {
271 let checksum
= Ext
.getCmp('downloadUrlChecksum');
272 if (field
.getValue() === '__default__') {
273 checksum
.setDisabled(true);
274 checksum
.setValue("");
275 checksum
.allowBlank
= true;
277 checksum
.setDisabled(false);
278 checksum
.allowBlank
= false;
289 xtype
: 'fieldcontainer',
291 fieldLabel
: gettext('URL'),
305 text
: gettext('Check'),
317 fieldLabel
: gettext('File name'),
322 xtype
: 'displayfield',
324 fieldLabel
: gettext('File size'),
325 value
: gettext('unknown'),
330 xtype
: 'displayfield',
332 fieldLabel
: gettext('MIME type'),
333 value
: gettext('unknown'),
338 xtype
: 'pveHashAlgorithmSelector',
339 name
: 'checksum-algorithm',
340 fieldLabel
: gettext('Hash algorithm'),
343 value
: '__default__',
345 change
: 'hashChange',
351 fieldLabel
: gettext('Checksum'),
354 emptyText
: gettext('none'),
355 id
: 'downloadUrlChecksum',
360 xtype
: 'proxmoxcheckbox',
361 name
: 'verify-certificates',
362 fieldLabel
: gettext('Verify certificates'),
372 xtype
: 'hiddenfield',
380 initComponent: function() {
384 throw "no node name specified";
387 throw "no storage ID specified";
394 Ext
.define('PVE.storage.ContentView', {
395 extend
: 'Ext.grid.GridPanel',
397 alias
: 'widget.pveStorageContentView',
403 initComponent: function() {
407 me
.nodename
= me
.pveSelNode
.data
.node
;
409 throw "no node name specified";
412 const nodename
= me
.nodename
;
415 me
.storage
= me
.pveSelNode
.data
.storage
;
417 throw "no storage ID specified";
420 const storage
= me
.storage
;
422 var content
= me
.content
;
424 throw "no content type specified";
427 const baseurl
= `/nodes/${nodename}/storage/${storage}/content`;
428 let store
= me
.store
= Ext
.create('Ext.data.Store', {
429 model
: 'pve-storage-content',
432 url
: '/api2/json' + baseurl
,
444 me
.sm
= Ext
.create('Ext.selection.RowModel', {});
448 let reload
= () => store
.load();
450 Proxmox
.Utils
.monStoreErrors(me
, store
);
455 if (me
.useUploadButton
) {
459 text
: gettext('Upload'),
460 disabled
: !me
.enableUploadButton
,
461 handler: function() {
462 Ext
.create('PVE.storage.Upload', {
467 taskDone
: () => reload(),
473 text
: gettext('Download from URL'),
474 disabled
: !me
.enableDownloadUrlButton
,
475 handler: function() {
476 Ext
.create('PVE.storage.DownloadUrl', {
481 taskDone
: () => reload(),
488 if (!me
.useCustomRemoveButton
) {
490 xtype
: 'proxmoxStdRemoveButton',
493 callback
: () => reload(),
494 baseurl
: baseurl
+ '/',
499 gettext('Search') + ':',
504 enableKeyEvents
: true,
505 emptyText
: gettext('Name, Format'),
509 fn: function(field
) {
510 store
.clearFilter(true);
514 value
: field
.getValue(),
516 caseSensitive
: false,
521 change: function(field
, newValue
, oldValue
) {
522 if (newValue
!== this.originalValue
) {
523 this.triggers
.clear
.setVisible(true);
529 cls
: 'pmx-clear-trigger',
532 handler: function() {
533 this.triggers
.clear
.setVisible(false);
534 this.setValue(this.originalValue
);
542 let availableColumns
= {
544 header
: gettext('Name'),
547 renderer
: PVE
.Utils
.render_storage_content
,
551 header
: gettext('Notes'),
553 renderer
: Ext
.htmlEncode
,
557 header
: gettext('Date'),
562 header
: gettext('Format'),
567 header
: gettext('Size'),
569 renderer
: Proxmox
.Utils
.format_size
,
574 if (me
.hideColumns
) {
575 me
.hideColumns
.forEach(key
=> delete availableColumns
[key
]);
577 if (!me
.hasNotesColumn
) {
578 delete availableColumns
.notes
;
580 if (me
.extraColumns
&& typeof me
.extraColumns
=== 'object') {
581 Object
.assign(availableColumns
, me
.extraColumns
);
583 const columns
= Object
.values(availableColumns
);
598 Ext
.define('pve-storage-content', {
599 extend
: 'Ext.data.Model',
601 'volid', 'content', 'format', 'size', 'used', 'vmid',
602 'channel', 'id', 'lun', 'notes', 'verification',
605 convert: function(value
, record
) {
606 // check for volid, because if you click on a grouping header,
607 // it calls convert (but with an empty volid)
608 if (value
|| record
.data
.volid
=== null) {
611 return PVE
.Utils
.render_storage_content(value
, {}, record
);
616 convert: function(value
, record
) {
617 // check for volid, because if you click on a grouping header,
618 // it calls convert (but with an empty volid)
619 if (value
|| record
.data
.volid
=== null) {
622 let t
= record
.data
.content
;
623 if (t
=== "backup") {
624 let v
= record
.data
.volid
;
625 let match
= v
.match(/(\d{4}_\d{2}_\d{2})-(\d{2}_\d{2}_\d{2})/);
627 let date
= match
[1].replace(/_
/g
, '-');
628 let time
= match
[2].replace(/_
/g
, ':');
629 return date
+ " " + time
;
632 if (record
.data
.ctime
) {
633 let ctime
= new Date(record
.data
.ctime
* 1000);
634 return Ext
.Date
.format(ctime
, 'Y-m-d H:i:s');