From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH manager 2/6] ui: storage: move node scan selector inside combobox
Date: Wed, 18 Jan 2023 14:12:59 +0100 [thread overview]
Message-ID: <20230118131303.2892050-5-d.csapak@proxmox.com> (raw)
In-Reply-To: <20230118131303.2892050-1-d.csapak@proxmox.com>
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
PVE.data.ResourceStore
Suggested-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/manager6/form/ComboBoxSetStoreNode.js | 45 +++++++++++++-
www/manager6/storage/IScsiEdit.js | 53 +++++++++--------
www/manager6/storage/LVMEdit.js | 71 +++++++++++++++++------
www/manager6/storage/LvmThinEdit.js | 71 +++++++++++++----------
www/manager6/storage/ZFSPoolEdit.js | 29 +++++----
5 files changed, 180 insertions(+), 89 deletions(-)
diff --git a/www/manager6/form/ComboBoxSetStoreNode.js b/www/manager6/form/ComboBoxSetStoreNode.js
index 3490ddd7d..a654636b7 100644
--- a/www/manager6/form/ComboBoxSetStoreNode.js
+++ b/www/manager6/form/ComboBoxSetStoreNode.js
@@ -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();
+ },
});
diff --git a/www/manager6/storage/IScsiEdit.js b/www/manager6/storage/IScsiEdit.js
index 96c1aa28b..6a1e4aeb5 100644
--- a/www/manager6/storage/IScsiEdit.js
+++ b/www/manager6/storage/IScsiEdit.js
@@ -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);
+ },
+ },
}),
];
diff --git a/www/manager6/storage/LVMEdit.js b/www/manager6/storage/LVMEdit.js
index b323a529d..84ee198da 100644
--- a/www/manager6/storage/LVMEdit.js
+++ b/www/manager6/storage/LVMEdit.js
@@ -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({
diff --git a/www/manager6/storage/LvmThinEdit.js b/www/manager6/storage/LvmThinEdit.js
index 92e6c2962..0c288bb04 100644
--- a/www/manager6/storage/LvmThinEdit.js
+++ b/www/manager6/storage/LvmThinEdit.js
@@ -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');
diff --git a/www/manager6/storage/ZFSPoolEdit.js b/www/manager6/storage/ZFSPoolEdit.js
index 65e152beb..df12fbbc8 100644
--- a/www/manager6/storage/ZFSPoolEdit.js
+++ b/www/manager6/storage/ZFSPoolEdit.js
@@ -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', {
--
2.30.2
next prev parent reply other threads:[~2023-01-18 13:13 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-18 13:12 [pve-devel] [PATCH widget-toolkit/pve-manager] move node selection into combogrid Dominik Csapak
2023-01-18 13:12 ` [pve-devel] [PATCH widget-toolkit 1/2] ComboGrid: use the grids view for the error message Dominik Csapak
2023-01-18 13:12 ` [pve-devel] [PATCH widget-toolkit 2/2] ComboGrid: make height for the error configurable Dominik Csapak
2023-01-18 13:12 ` [pve-devel] [PATCH manager 1/6] ui: StorageScanNodeSelector: use null as empty value Dominik Csapak
2023-01-18 13:12 ` Dominik Csapak [this message]
2023-01-18 13:13 ` [pve-devel] [PATCH manager 3/6] ui: storage/LvmThinInputPanel: modernize & cleanup code Dominik Csapak
2023-01-18 13:13 ` [pve-devel] [PATCH manager 4/6] ui: storage/IScsiInputPanel: modernize, cleanup & improve panel Dominik Csapak
2023-01-18 13:13 ` [pve-devel] [PATCH manager 5/6] ui: storage/ZFSPoolInputPanel: modernize & cleanup code Dominik Csapak
2023-01-18 13:13 ` [pve-devel] [PATCH manager 6/6] ui: storage/LVMInputPanel: " Dominik Csapak
2023-01-18 15:08 ` [pve-devel] applied-series: [PATCH widget-toolkit/pve-manager] move node selection into combogrid Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230118131303.2892050-5-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox