]> git.proxmox.com Git - pve-manager.git/commitdiff
ui: storage: move node scan selector inside combobox
authorDominik Csapak <d.csapak@proxmox.com>
Wed, 18 Jan 2023 13:12:59 +0000 (14:12 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 18 Jan 2023 15:01:08 +0000 (16:01 +0100)
by converting the relevant selection boxes to combogrids.
This is done to reduce confusion for how/why to select a node, and
doing it this way it is moved closer to the selection of the actual
value we want. It still restricts the nodes when selecting a specific one.

Show it only when there is more than one node according to the
in-memory PVE.data.ResourceStore info, as for single-node setups
there isn't any other node one could scan anyway.

Suggested-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
www/manager6/form/ComboBoxSetStoreNode.js
www/manager6/storage/IScsiEdit.js
www/manager6/storage/LVMEdit.js
www/manager6/storage/LvmThinEdit.js
www/manager6/storage/ZFSPoolEdit.js

index 3490ddd7d57b214a6b3cd8378173cfad2e6a38aa..a654636b74acc38999d4a0f5d9a0b75cce979de9 100644 (file)
@@ -1,16 +1,57 @@
 Ext.define('PVE.form.ComboBoxSetStoreNode', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'Proxmox.form.ComboGrid',
     config: {
        apiBaseUrl: '/api2/json/nodes/',
        apiSuffix: '',
     },
 
+    showNodeSelector: false,
+
     setNodeName: function(value) {
        let me = this;
        value ||= Proxmox.NodeName;
 
        me.getStore().getProxy().setUrl(`${me.apiBaseUrl}${value}${me.apiSuffix}`);
-       this.clearValue();
+       me.clearValue();
+    },
+
+    nodeChange: function(_field, value) {
+       let me = this;
+       // disable autoSelect if there is already a selection or we have the picker open
+       if (me.getValue() || me.isExpanded) {
+           let autoSelect = me.autoSelect;
+           me.autoSelect = false;
+           me.store.on('afterload', function() {
+               me.autoSelect = autoSelect;
+           }, { single: true });
+       }
+       me.setNodeName(value);
+       me.fireEvent('nodechanged', value);
     },
 
+    initComponent: function() {
+       let me = this;
+
+       if (me.showNodeSelector && PVE.data.ResourceStore.getNodes().length > 1) {
+           me.errorHeight = 140;
+           Ext.apply(me.listConfig ?? {}, {
+               tbar: {
+                   xtype: 'toolbar',
+                   items: [
+                       {
+                           xtype: "pveStorageScanNodeSelector",
+                           autoSelect: false,
+                           fieldLabel: gettext('Node to scan'),
+                           listeners: {
+                               change: (field, value) => me.nodeChange(field, value),
+                           },
+                       },
+                   ],
+               },
+               emptyText: me.listConfig?.emptyText ?? gettext('Nothing found'),
+           });
+       }
+
+       me.callParent();
+    },
 });
index 96c1aa28b450aaddbe5917567efab881458586fd..6a1e4aeb5eec0d3b4b8a29d5fdd1f299fad93600 100644 (file)
@@ -6,32 +6,43 @@ Ext.define('PVE.storage.IScsiScan', {
     valueField: 'target',
     displayField: 'target',
     matchFieldWidth: false,
+    allowBlank: false,
+
     listConfig: {
-       loadingText: gettext('Scanning...'),
        width: 350,
+       columns: [
+           {
+               dataIndex: 'target',
+               flex: 1,
+           },
+       ],
+       emptyText: gettext('No iSCSI target found'),
     },
+
     config: {
        apiSuffix: '/scan/iscsi',
     },
-    doRawQuery: function() {
-       // do nothing
-    },
 
-    onTriggerClick: function() {
-       let me = this;
+    showNodeSelector: true,
 
-       if (!me.queryCaching || me.lastQuery !== me.portal) {
-           me.store.removeAll();
+    reload: function() {
+       let me = this;
+       if (!me.isDisabled()) {
+           me.getStore().load();
        }
-
-       me.allQuery = me.portal;
-
-       me.callParent();
     },
 
     setPortal: function(portal) {
        let me = this;
        me.portal = portal;
+       me.getStore().getProxy().setExtraParams({ portal });
+       me.reload();
+    },
+
+    setNodeName: function(value) {
+       let me = this;
+       me.callParent([value]);
+       me.reload();
     },
 
     initComponent: function() {
@@ -81,19 +92,6 @@ Ext.define('PVE.storage.IScsiInputPanel', {
        let me = this;
 
        me.column1 = [
-           {
-               xtype: 'pveStorageScanNodeSelector',
-               disabled: !me.isCreate,
-               hidden: !me.isCreate,
-               listeners: {
-                   change: {
-                       fn: function(field, value) {
-                           me.lookup('iScsiTargetScan').setNodeName(value);
-                           me.lookup('storageNodeRestriction').setValue(value);
-                       },
-                   },
-               },
-           },
            {
                xtype: me.isCreate ? 'textfield' : 'displayfield',
                name: 'portal',
@@ -117,6 +115,11 @@ Ext.define('PVE.storage.IScsiInputPanel', {
                fieldLabel: gettext('Target'),
                allowBlank: false,
                reference: 'iScsiTargetScan',
+               listeners: {
+                   nodechanged: function(value) {
+                       me.lookup('storageNodeRestriction').setValue(value);
+                   },
+               },
            }),
        ];
 
index b323a529d628470c279a37f4a55e166f11d461b4..84ee198da2293fb7627c89047bf57136440ea893 100644 (file)
@@ -5,10 +5,23 @@ Ext.define('PVE.storage.VgSelector', {
     displayField: 'vg',
     queryMode: 'local',
     editable: false,
+
+    listConfig: {
+       columns: [
+           {
+               dataIndex: 'vg',
+               flex: 1,
+           },
+       ],
+       emptyText: gettext('No volume groups found'),
+    },
+
     config: {
        apiSuffix: '/scan/lvm',
     },
 
+    showNodeSelector: true,
+
     setNodeName: function(value) {
        let me = this;
        me.callParent([value]);
@@ -35,9 +48,6 @@ Ext.define('PVE.storage.VgSelector', {
 
        Ext.apply(me, {
            store: store,
-           listConfig: {
-               loadingText: gettext('Scanning...'),
-           },
        });
 
        me.callParent();
@@ -93,6 +103,42 @@ Ext.define('PVE.storage.BaseStorageSelector', {
     },
 });
 
+Ext.define('PVE.storage.LunSelector', {
+    extend: 'PVE.form.FileSelector',
+    alias: 'widget.pveStorageLunSelector',
+
+    nodename: 'localhost',
+    storageContent: 'images',
+    allowBlank: false,
+
+    initComponent: function() {
+       let me = this;
+
+       if (PVE.data.ResourceStore.getNodes().length > 1) {
+           me.errorHeight = 140;
+           Ext.apply(me.listConfig ?? {}, {
+               tbar: {
+                   xtype: 'toolbar',
+                   items: [
+                       {
+                           xtype: "pveStorageScanNodeSelector",
+                           autoSelect: false,
+                           fieldLabel: gettext('Node to scan'),
+                           listeners: {
+                               change: (_field, value) => me.setNodename(value),
+                           },
+                       },
+                   ],
+               },
+               emptyText: me.listConfig?.emptyText ?? gettext('Nothing found'),
+           });
+       }
+
+       me.callParent();
+    },
+
+});
+
 Ext.define('PVE.storage.LVMInputPanel', {
     extend: 'PVE.panel.StorageBase',
 
@@ -118,27 +164,16 @@ Ext.define('PVE.storage.LVMInputPanel', {
                fieldLabel: gettext('Volume group'),
                reference: 'volumeGroupSelector',
                allowBlank: false,
-           });
-           me.column1.push({
-               xtype: 'pveStorageScanNodeSelector',
-               listeners: {
-                   change: {
-                       fn: function(field, value) {
-                           me.lookup('volumeGroupSelector').setNodeName(value);
-                           me.lookup('storageNodeRestriction').setValue(value);
-                       },
-                   },
-               },
+               listeners: {
+                   nodechanged: (value) => me.lookup('storageNodeRestriction').setValue(value),
+               }
            });
 
-           let baseField = Ext.createWidget('pveFileSelector', {
+           let baseField = Ext.createWidget('pveStorageLunSelector', {
                name: 'base',
                hidden: true,
                disabled: true,
-               nodename: 'localhost',
-               storageContent: 'images',
                fieldLabel: gettext('Base volume'),
-               allowBlank: false,
            });
 
            me.column1.push({
index 92e6c29628cb0cc4419e99cad4572db50423f848..0c288bb04a2b4969a86280d950850f7fde431057 100644 (file)
@@ -6,31 +6,40 @@ Ext.define('PVE.storage.TPoolSelector', {
     valueField: 'lv',
     displayField: 'lv',
     editable: false,
+    allowBlank: false,
+
+    listConfig: {
+       emptyText: gettext("No thinpool found"),
+       columns: [
+           {
+               dataIndex: 'lv',
+               flex: 1,
+           },
+       ],
+    },
 
     config: {
        apiSuffix: '/scan/lvmthin',
     },
 
-    doRawQuery: function() {
-       // nothing
-    },
-
-    onTriggerClick: function() {
+    reload: function() {
        let me = this;
-
-       if (!me.queryCaching || me.lastQuery !== me.vg) {
-           me.store.removeAll();
+       if (!me.isDisabled()) {
+           me.getStore().load();
        }
-
-       me.allQuery = me.vg;
-
-       me.callParent();
     },
 
     setVG: function(myvg) {
        let me = this;
-
        me.vg = myvg;
+       me.getStore().getProxy().setExtraParams({ vg: myvg });
+       me.reload();
+    },
+
+    setNodeName: function(value) {
+       let me = this;
+       me.callParent([value]);
+       me.reload();
     },
 
     initComponent: function() {
@@ -52,9 +61,6 @@ Ext.define('PVE.storage.TPoolSelector', {
 
        Ext.apply(me, {
            store: store,
-           listConfig: {
-               loadingText: gettext('Scanning...'),
-           },
        });
 
        me.callParent();
@@ -69,6 +75,19 @@ Ext.define('PVE.storage.BaseVGSelector', {
     displayField: 'vg',
     queryMode: 'local',
     editable: false,
+    allowBlank: false,
+
+    listConfig: {
+       columns: [
+           {
+               dataIndex: 'vg',
+               flex: 1,
+           },
+       ],
+    },
+
+    showNodeSelector: true,
+
     config: {
        apiSuffix: '/scan/lvm',
     },
@@ -97,9 +116,6 @@ Ext.define('PVE.storage.BaseVGSelector', {
 
        Ext.apply(me, {
            store: store,
-           listConfig: {
-               loadingText: gettext('Scanning...'),
-           },
        });
 
        me.callParent();
@@ -135,24 +151,15 @@ Ext.define('PVE.storage.LvmThinInputPanel', {
        });
 
        if (me.isCreate) {
-           me.column1.push({
-               xtype: 'pveStorageScanNodeSelector',
-               listeners: {
-                   change: {
-                       fn: function(field, value) {
-                           me.lookup('thinPoolSelector').setNodeName(value);
-                           me.lookup('volumeGroupSelector').setNodeName(value);
-                           me.lookup('storageNodeRestriction').setValue(value);
-                       },
-                   },
-               },
-           });
-
            me.column1.push(Ext.create('PVE.storage.BaseVGSelector', {
                name: 'vgname',
                fieldLabel: gettext('Volume group'),
                reference: 'volumeGroupSelector',
                listeners: {
+                   nodechanged: function(value) {
+                       me.lookup('thinPoolSelector').setNodeName(value);
+                       me.lookup('storageNodeRestriction').setValue(value);
+                   },
                    change: function(f, value) {
                        if (me.isCreate) {
                            let vgField = me.lookup('thinPoolSelector');
index 65e152beb07e5792cf3ad0fe15bc87d673c0ad03..df12fbbc84d708d35c2bd7d7968ddf787d2b746a 100644 (file)
@@ -5,13 +5,24 @@ Ext.define('PVE.storage.ZFSPoolSelector', {
     displayField: 'pool',
     queryMode: 'local',
     editable: false,
+    allowBlank: false,
+
     listConfig: {
-       loadingText: gettext('Scanning...'),
+       columns: [
+           {
+               dataIndex: 'pool',
+               flex: 1,
+           },
+       ],
+       emptyText: gettext('No ZFS Pools found'),
     },
+
     config: {
        apiSuffix: '/scan/zfs',
     },
 
+    showNodeSelector: true,
+
     setNodeName: function(value) {
        let me = this;
        me.callParent([value]);
@@ -54,22 +65,16 @@ Ext.define('PVE.storage.ZFSPoolInputPanel', {
        me.column1 = [];
 
        if (me.isCreate) {
-           me.column1.push({
-               xtype: 'pveStorageScanNodeSelector',
-               listeners: {
-                   change: {
-                       fn: function(field, value) {
-                           me.lookup('zfsPoolSelector').setNodeName(value);
-                           me.lookup('storageNodeRestriction').setValue(value);
-                       },
-                   },
-               },
-           });
            me.column1.push(Ext.create('PVE.storage.ZFSPoolSelector', {
                name: 'pool',
                fieldLabel: gettext('ZFS Pool'),
                reference: 'zfsPoolSelector',
                allowBlank: false,
+               listeners: {
+                   nodechanged: function(value) {
+                       me.lookup('storageNodeRestriction').setValue(value);
+                   },
+               },
            }));
        } else {
            me.column1.push(Ext.createWidget('displayfield', {