* [RFC PATCH pve-manager 1/2] ui: iso selector: add 'reload' button
2026-07-13 11:36 [RFC PATCH pve-manager 0/2] add reload/upload buttons to iso selector Dominik Csapak
@ 2026-07-13 11:36 ` Dominik Csapak
2026-07-13 11:37 ` [RFC PATCH pve-manager 2/2] ui: iso selector: add 'upload' button in the create VM wizard Dominik Csapak
1 sibling, 0 replies; 3+ messages in thread
From: Dominik Csapak @ 2026-07-13 11:36 UTC (permalink / raw)
To: pve-devel
so a user can manually reload the storage list as well as the file list.
This sometimes comes up when e.g. creating a new guest and a user
uploads a new ISO in a different tab.
The new button is added in a new row beneath the file selector and shows
the loading progress until the storage as well as the file selector are
done loading.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/FileSelector.js | 12 ++++++++++++
www/manager6/form/IsoSelector.js | 27 +++++++++++++++++++++++++++
www/manager6/form/StorageSelector.js | 11 +++++++++--
3 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/www/manager6/form/FileSelector.js b/www/manager6/form/FileSelector.js
index b8f6a8c2..af4e4be8 100644
--- a/www/manager6/form/FileSelector.js
+++ b/www/manager6/form/FileSelector.js
@@ -15,6 +15,18 @@ Ext.define('PVE.form.FileSelector', {
},
},
+ reload: function (finishCb) {
+ let me = this;
+ finishCb ??= Ext.emptyFn;
+ if (!me.storage || !me.nodename || me.isDisabled()) {
+ finishCb();
+ return;
+ }
+ me.store.load(() => {
+ finishCb();
+ });
+ },
+
setStorage: function (storage, nodename) {
var me = this;
diff --git a/www/manager6/form/IsoSelector.js b/www/manager6/form/IsoSelector.js
index b2d94ed3..48c10427 100644
--- a/www/manager6/form/IsoSelector.js
+++ b/www/manager6/form/IsoSelector.js
@@ -110,5 +110,32 @@ Ext.define('PVE.form.IsoSelector', {
},
},
},
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ items: [
+ { xtype: 'box', flex: 1 }, // just a spacer
+ {
+ xtype: 'button',
+ reference: 'reloadBtn',
+ iconCls: 'fa fa-refresh',
+ text: gettext('Reload'),
+ handler: function () {
+ let me = this;
+ me.setDisabled(true);
+ me.setIconCls('fa fa-refresh fa-spin');
+ let selector = me.up('pveIsoSelector');
+ let storage = selector.lookup('storage');
+ let fileSelector = selector.lookup('file');
+ storage.reloadStorageList(() => {
+ fileSelector.reload(() => {
+ me.setDisabled(false);
+ me.setIconCls('fa fa-refresh');
+ });
+ });
+ },
+ },
+ ],
+ },
],
});
diff --git a/www/manager6/form/StorageSelector.js b/www/manager6/form/StorageSelector.js
index 0b5e10da..42961f72 100644
--- a/www/manager6/form/StorageSelector.js
+++ b/www/manager6/form/StorageSelector.js
@@ -68,9 +68,11 @@ Ext.define(
],
},
- reloadStorageList: function () {
+ reloadStorageList: function (finishCb) {
let me = this;
+ finishCb ??= Ext.emptyFn;
+
if (me.clusterView) {
me.getStore().setProxy({
type: 'proxmox',
@@ -97,6 +99,7 @@ Ext.define(
me.getStore().setFilters(filters);
} else {
if (!me.nodename) {
+ finishCb();
return;
}
@@ -117,7 +120,11 @@ Ext.define(
});
}
- me.store.load(() => me.validate());
+ me.store.load(() => {
+ let result = me.validate();
+ finishCb();
+ return result;
+ });
},
setTargetNode: function (targetNode) {
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* [RFC PATCH pve-manager 2/2] ui: iso selector: add 'upload' button in the create VM wizard
2026-07-13 11:36 [RFC PATCH pve-manager 0/2] add reload/upload buttons to iso selector Dominik Csapak
2026-07-13 11:36 ` [RFC PATCH pve-manager 1/2] ui: iso selector: add 'reload' button Dominik Csapak
@ 2026-07-13 11:37 ` Dominik Csapak
1 sibling, 0 replies; 3+ messages in thread
From: Dominik Csapak @ 2026-07-13 11:37 UTC (permalink / raw)
To: pve-devel
When first opening the VM create wizard on a new install, it often
happens that no ISO is uploaded yet. Currently this either requires a
second tab to upload it (or doing it manually via the cli) or closing
the wizard, uploading the ISO to the correct storage and then
re-starting the wizard.
Instead, having a direct upload button here, simplifies this by enabling
users to directly upload an iso to the selected storage (if permissions
allow) and automatically select it.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/IsoSelector.js | 48 ++++++++++++++++++++++++++++++++
www/manager6/qemu/CDEdit.js | 1 +
www/manager6/qemu/OSPanel.js | 1 +
3 files changed, 50 insertions(+)
diff --git a/www/manager6/form/IsoSelector.js b/www/manager6/form/IsoSelector.js
index 48c10427..f42cd4ba 100644
--- a/www/manager6/form/IsoSelector.js
+++ b/www/manager6/form/IsoSelector.js
@@ -8,6 +8,10 @@ Ext.define('PVE.form.IsoSelector', {
align: 'stretch',
},
+ // enable an upload button for the currently selected storage, requires the
+ // user to have the Datastore.AllocateTemplate privilege
+ allowUpload: false,
+
nodename: undefined,
insideWizard: false,
labelWidth: undefined,
@@ -15,7 +19,14 @@ Ext.define('PVE.form.IsoSelector', {
cbindData: function () {
let me = this;
+
+ let caps = Ext.state.Manager.get('GuiCap');
+ if (!caps.storage['Datastore.AllocateTemplate']) {
+ me.allowUpload = false;
+ }
+
return {
+ hideUploadButton: !me.allowUpload,
nodename: me.nodename,
insideWizard: me.insideWizard,
};
@@ -54,6 +65,7 @@ Ext.define('PVE.form.IsoSelector', {
let me = this;
me.lookup('storage').setNodename(nodename);
me.lookup('file').setStorage(undefined, nodename);
+ me.nodename = nodename;
},
setDisabled: function (disabled) {
@@ -87,6 +99,7 @@ Ext.define('PVE.form.IsoSelector', {
let selector = me.up('pveIsoSelector');
selector.lookup('file').setStorage(value);
selector.checkChange();
+ selector.lookup('uploadBtn').setDisabled(!value);
},
},
},
@@ -115,6 +128,41 @@ Ext.define('PVE.form.IsoSelector', {
layout: 'hbox',
items: [
{ xtype: 'box', flex: 1 }, // just a spacer
+ {
+ xtype: 'button',
+ reference: 'uploadBtn',
+ iconCls: 'fa fa-upload',
+ text: gettext('Upload'),
+ disabled: true,
+ cbind: {
+ hidden: '{hideUploadButton}',
+ },
+ handler: function () {
+ let me = this;
+ let selector = me.up('pveIsoSelector');
+ let storage = selector.lookup('storage').getValue();
+ let nodename = selector.nodename;
+ if (!storage) {
+ return;
+ }
+ let fileSelector = selector.lookup('file');
+ let win = Ext.create('PVE.window.UploadToStorage', {
+ nodename,
+ storage,
+ content: 'iso',
+ autoShow: true,
+ taskDone: (success) => {
+ if (!success) {
+ return;
+ }
+ fileSelector.reload(() => {
+ let filename = win.getViewModel().get('filename');
+ fileSelector.setValue(`${storage}:iso/${filename}`);
+ });
+ },
+ });
+ },
+ },
{
xtype: 'button',
reference: 'reloadBtn',
diff --git a/www/manager6/qemu/CDEdit.js b/www/manager6/qemu/CDEdit.js
index c185de53..c8e87d97 100644
--- a/www/manager6/qemu/CDEdit.js
+++ b/www/manager6/qemu/CDEdit.js
@@ -100,6 +100,7 @@ Ext.define('PVE.qemu.CDInputPanel', {
me.isosel = Ext.create('PVE.form.IsoSelector', {
nodename: me.nodename,
insideWizard: me.insideWizard,
+ allowUpload: me.insideWizard,
name: 'cdimage',
});
diff --git a/www/manager6/qemu/OSPanel.js b/www/manager6/qemu/OSPanel.js
index 556ad4c3..81508b64 100644
--- a/www/manager6/qemu/OSPanel.js
+++ b/www/manager6/qemu/OSPanel.js
@@ -160,6 +160,7 @@ Ext.define('PVE.qemu.OSPanel', {
xtype: 'pveIsoSelector',
reference: 'isoSelector',
name: 'ide0',
+ allowUpload: true,
insideWizard: true,
hidden: true,
disabled: true,
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread