[pbs-devel] [PATCH proxmox-backup v2 6/6] ui: replace bucket field by bucket selector

Christian Ebner c.ebner at proxmox.com
Wed Jul 30 16:40:08 CEST 2025


With the goal to improve usability for the datastore creation window,
replace the current bucket textfield with a bucket selector which
fetches available buckets on demand.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
Reviewed-by: Lukas Wagner <l.wagner at proxmox.com>
---
changes since version 1:
- no changes

 www/Makefile                 |  1 +
 www/form/S3BucketSelector.js | 52 ++++++++++++++++++++++++++++++++++++
 www/window/DataStoreEdit.js  | 22 +++++++++++----
 3 files changed, 70 insertions(+), 5 deletions(-)
 create mode 100644 www/form/S3BucketSelector.js

diff --git a/www/Makefile b/www/Makefile
index 4a5cd1ff1..9ebf0445f 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -42,6 +42,7 @@ JSSRC=							\
 	Schema.js					\
 	form/TokenSelector.js				\
 	form/AuthidSelector.js				\
+	form/S3BucketSelector.js			\
 	form/S3ClientSelector.js			\
 	form/RemoteSelector.js				\
 	form/RemoteTargetSelector.js   			\
diff --git a/www/form/S3BucketSelector.js b/www/form/S3BucketSelector.js
new file mode 100644
index 000000000..75b02479f
--- /dev/null
+++ b/www/form/S3BucketSelector.js
@@ -0,0 +1,52 @@
+Ext.define('PBS.form.S3BucketSelector', {
+    extend: 'Proxmox.form.ComboGrid',
+    alias: 'widget.pbsS3BucketSelector',
+
+    allowBlank: false,
+    valueField: 'name',
+    displayField: 'name',
+
+    listConfig: {
+        width: 350,
+        columns: [
+            {
+                header: gettext('Bucket Name'),
+                sortable: true,
+                dataIndex: 'name',
+                renderer: Ext.String.htmlEncode,
+                flex: 1,
+            },
+        ],
+    },
+
+    store: {
+        autoLoad: false,
+        sorters: 'name',
+        fields: ['name'],
+        proxy: {
+            type: 'proxmox',
+            url: `/api2/json/config/s3/${encodeURIComponent(this.endpoint)}/list-buckets`,
+        },
+    },
+
+    setS3Endpoint: function (endpoint) {
+        let me = this;
+
+        if (me.endpoint === endpoint) {
+            return;
+        }
+
+        me.endpoint = endpoint;
+        me.store.removeAll();
+
+        me.setDisabled(false);
+
+        if (!me.firstLoad) {
+            me.clearValue();
+        }
+
+        me.store.proxy.url = `/api2/json/config/s3/${encodeURIComponent(me.endpoint)}/list-buckets`;
+        me.store.load();
+        me.firstLoad = false;
+    },
+});
diff --git a/www/window/DataStoreEdit.js b/www/window/DataStoreEdit.js
index 8296e0b04..1b935ddd3 100644
--- a/www/window/DataStoreEdit.js
+++ b/www/window/DataStoreEdit.js
@@ -74,7 +74,7 @@ Ext.define('PBS.DataStoreEdit', {
                                 let inputPanel = checkbox.up('inputpanel');
                                 let pathField = inputPanel.down('[name=path]');
                                 let uuidEditField = inputPanel.down('[name=backing-device]');
-                                let bucketField = inputPanel.down('[name=bucket]');
+                                let s3BucketSelector = inputPanel.down('[name=bucket]');
                                 let s3ClientSelector = inputPanel.down('[name=s3client]');
                                 let overwriteInUseField =
                                     inputPanel.down('[name=overwrite-in-use]');
@@ -86,9 +86,11 @@ Ext.define('PBS.DataStoreEdit', {
                                 uuidEditField.allowBlank = !isRemovable;
                                 uuidEditField.setValue('');
 
-                                bucketField.setDisabled(!isS3);
-                                bucketField.allowBlank = !isS3;
-                                bucketField.setValue('');
+                                if (!isS3) {
+                                    s3BucketSelector.setDisabled(true);
+                                    s3BucketSelector.setValue('');
+                                }
+                                s3BucketSelector.allowBlank = !isS3;
 
                                 s3ClientSelector.setDisabled(!isS3);
                                 s3ClientSelector.allowBlank = !isS3;
@@ -130,6 +132,13 @@ Ext.define('PBS.DataStoreEdit', {
                         cbind: {
                             editable: '{isCreate}',
                         },
+                        listeners: {
+                            change: function (selector, endpointId) {
+                                let inputPanel = selector.up('inputpanel');
+                                let s3BucketSelector = inputPanel.down('[name=bucket]');
+                                s3BucketSelector.setS3Endpoint(endpointId);
+                            },
+                        },
                     },
                 ],
                 column2: [
@@ -166,11 +175,14 @@ Ext.define('PBS.DataStoreEdit', {
                         emptyText: gettext('Device path'),
                     },
                     {
-                        xtype: 'proxmoxtextfield',
+                        xtype: 'pbsS3BucketSelector',
                         name: 'bucket',
                         fieldLabel: gettext('Bucket'),
                         allowBlank: false,
                         disabled: true,
+                        cbind: {
+                            editable: '{isCreate}',
+                        },
                     },
                 ],
                 columnB: [
-- 
2.47.2





More information about the pbs-devel mailing list