pve-manager/www/manager6/storage/ContentView.js
Fabian Ebner f5e17f156a create ImageView and use it for VM and CT images
The enableFn's that were responsible for switching
between the image remove button and the standard remove button
are not needed anymore.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
2020-11-15 18:41:11 +01:00

404 lines
8.5 KiB
JavaScript

Ext.define('PVE.storage.Upload', {
extend: 'Ext.window.Window',
alias: 'widget.pveStorageUpload',
resizable: false,
modal: true,
initComponent : function() {
var me = this;
var xhr;
if (!me.nodename) {
throw "no node name specified";
}
if (!me.storage) {
throw "no storage ID specified";
}
var baseurl = "/nodes/" + me.nodename + "/storage/" + me.storage + "/upload";
var pbar = Ext.create('Ext.ProgressBar', {
text: 'Ready',
hidden: true
});
let acceptedExtensions = {
iso: ".img, .iso",
vztmpl: ".tar.gz, .tar.xz",
};
let defaultContent = me.contents[0] || '';
let fileField = Ext.create('Ext.form.field.File', {
name: 'filename',
buttonText: gettext('Select File...'),
allowBlank: false,
setAccept: function(content) {
let acceptString = acceptedExtensions[content] || '';
this.fileInputEl.set({
accept: acceptString,
});
},
listeners: {
afterrender: function(cmp) {
cmp.setAccept(defaultContent);
},
},
});
me.formPanel = Ext.create('Ext.form.Panel', {
method: 'POST',
waitMsgTarget: true,
bodyPadding: 10,
border: false,
width: 300,
fieldDefaults: {
labelWidth: 100,
anchor: '100%'
},
items: [
{
xtype: 'pveContentTypeSelector',
cts: me.contents,
fieldLabel: gettext('Content'),
name: 'content',
value: defaultContent,
allowBlank: false,
listeners: {
change: function(cmp, newValue, oldValue) {
fileField.setAccept(newValue);
},
},
},
fileField,
pbar
]
});
var form = me.formPanel.getForm();
var doStandardSubmit = function() {
form.submit({
url: "/api2/htmljs" + baseurl,
waitMsg: gettext('Uploading file...'),
success: function(f, action) {
me.close();
},
failure: function(f, action) {
var msg = PVE.Utils.extractFormActionError(action);
Ext.Msg.alert(gettext('Error'), msg);
}
});
};
var updateProgress = function(per, bytes) {
var text = (per * 100).toFixed(2) + '%';
if (bytes) {
text += " (" + Proxmox.Utils.format_size(bytes) + ')';
}
pbar.updateProgress(per, text);
};
var abortBtn = Ext.create('Ext.Button', {
text: gettext('Abort'),
disabled: true,
handler: function() {
me.close();
}
});
var submitBtn = Ext.create('Ext.Button', {
text: gettext('Upload'),
disabled: true,
handler: function(button) {
var fd;
try {
fd = new FormData();
} catch (err) {
doStandardSubmit();
return;
}
button.setDisabled(true);
abortBtn.setDisabled(false);
var field = form.findField('content');
fd.append("content", field.getValue());
field.setDisabled(true);
field = form.findField('filename');
var file = field.fileInputEl.dom;
fd.append("filename", file.files[0]);
field.setDisabled(true);
pbar.setVisible(true);
updateProgress(0);
xhr = new XMLHttpRequest();
xhr.addEventListener("load", function(e) {
if (xhr.status == 200) {
me.close();
} else {
var msg = gettext('Error') + " " + xhr.status.toString() + ": " + Ext.htmlEncode(xhr.statusText);
if (xhr.responseText !== "") {
var result = Ext.decode(xhr.responseText);
result.message = msg;
msg = Proxmox.Utils.extractRequestError(result, true);
}
Ext.Msg.alert(gettext('Error'), msg, function(btn) {
me.close();
});
}
}, false);
xhr.addEventListener("error", function(e) {
var msg = "Error " + e.target.status.toString() + " occurred while receiving the document.";
Ext.Msg.alert(gettext('Error'), msg, function(btn) {
me.close();
});
});
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
updateProgress(percentComplete, evt.loaded);
}
}, false);
xhr.open("POST", "/api2/json" + baseurl, true);
xhr.send(fd);
}
});
form.on('validitychange', function(f, valid) {
submitBtn.setDisabled(!valid);
});
Ext.apply(me, {
title: gettext('Upload'),
items: me.formPanel,
buttons: [ abortBtn, submitBtn ],
listeners: {
close: function() {
if (xhr) {
xhr.abort();
}
}
}
});
me.callParent();
}
});
Ext.define('PVE.storage.ContentView', {
extend: 'Ext.grid.GridPanel',
alias: 'widget.pveStorageContentView',
viewConfig: {
trackOver: false,
loadMask: false
},
initComponent : function() {
var me = this;
if (!me.nodename) {
me.nodename = me.pveSelNode.data.node;
if (!me.nodename) {
throw "no node name specified";
}
}
var nodename = me.nodename;
if (!me.storage) {
me.storage = me.pveSelNode.data.storage;
if (!me.storage) {
throw "no storage ID specified";
}
}
var storage = me.storage;
var content = me.content;
if (!content) {
throw "no content type specified";
}
var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
var store = me.store = Ext.create('Ext.data.Store', {
model: 'pve-storage-content',
proxy: {
type: 'proxmox',
url: '/api2/json' + baseurl,
extraParams: {
content: content,
},
},
sorters: {
property: 'volid',
order: 'DESC'
}
});
if (!me.sm) {
me.sm = Ext.create('Ext.selection.RowModel', {});
}
var sm = me.sm;
var reload = function() {
store.load();
};
Proxmox.Utils.monStoreErrors(me, store);
var uploadButton = Ext.create('Proxmox.button.Button', {
text: gettext('Upload'),
handler: function() {
var win = Ext.create('PVE.storage.Upload', {
nodename: nodename,
storage: storage,
contents: [content],
});
win.show();
win.on('destroy', reload);
}
});
var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
selModel: sm,
delay: 5,
callback: function() {
reload();
},
baseurl: baseurl + '/'
});
if (!me.tbar) {
me.tbar = [];
}
if (me.useUploadButton) {
me.tbar.push(uploadButton);
}
if (!me.useCustomRemoveButton) {
me.tbar.push(removeButton);
}
me.tbar.push(
'->',
gettext('Search') + ':', ' ',
{
xtype: 'textfield',
width: 200,
enableKeyEvents: true,
listeners: {
buffer: 500,
keyup: function(field) {
store.clearFilter(true);
store.filter([
{
property: 'text',
value: field.getValue(),
anyMatch: true,
caseSensitive: false
}
]);
}
}
}
);
Ext.apply(me, {
store: store,
selModel: sm,
tbar: me.tbar,
columns: [
{
header: gettext('Name'),
flex: 2,
sortable: true,
renderer: PVE.Utils.render_storage_content,
dataIndex: 'text'
},
{
header: gettext('Comment'),
flex: 1,
renderer: Ext.htmlEncode,
dataIndex: 'comment',
},
{
header: gettext('Date'),
width: 150,
dataIndex: 'vdate'
},
{
header: gettext('Format'),
width: 100,
dataIndex: 'format'
},
{
header: gettext('Size'),
width: 100,
renderer: Proxmox.Utils.format_size,
dataIndex: 'size'
},
],
listeners: {
activate: reload
}
});
me.callParent();
}
}, function() {
Ext.define('pve-storage-content', {
extend: 'Ext.data.Model',
fields: [
'volid', 'content', 'format', 'size', 'used', 'vmid',
'channel', 'id', 'lun', 'comment', 'verification',
{
name: 'text',
convert: function(value, record) {
// check for volid, because if you click on a grouping header,
// it calls convert (but with an empty volid)
if (value || record.data.volid === null) {
return value;
}
return PVE.Utils.render_storage_content(value, {}, record);
}
},
{
name: 'vdate',
convert: function(value, record) {
// check for volid, because if you click on a grouping header,
// it calls convert (but with an empty volid)
if (value || record.data.volid === null) {
return value;
}
let t = record.data.content;
if (t === "backup") {
let v = record.data.volid;
let match = v.match(/(\d{4}_\d{2}_\d{2})-(\d{2}_\d{2}_\d{2})/);
if (match) {
let date = match[1].replace(/_/g, '-');
let time = match[2].replace(/_/g, ':');
return date + " " + time;
}
}
if (record.data.ctime) {
let ctime = new Date(record.data.ctime * 1000);
return Ext.Date.format(ctime,'Y-m-d H:i:s');
}
return '';
}
},
],
idProperty: 'volid'
});
});