From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 57DED93E24 for ; Tue, 20 Sep 2022 14:53:39 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 98BAD1C994 for ; Tue, 20 Sep 2022 14:53:38 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Tue, 20 Sep 2022 14:53:33 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 9B18A444A8 for ; Tue, 20 Sep 2022 14:50:47 +0200 (CEST) From: Dominik Csapak To: pve-devel@lists.proxmox.com Date: Tue, 20 Sep 2022 14:50:38 +0200 Message-Id: <20220920125041.3636561-33-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220920125041.3636561-1-d.csapak@proxmox.com> References: <20220920125041.3636561-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.028 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment POISEN_SPAM_PILL_4 0.1 random spam to be learned in bayes SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [me.name] Subject: [pve-devel] [PATCH manager v3 10/13] ui: add window/USBEdit: edit window for usb mappings X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Sep 2022 12:53:39 -0000 allows to add a single host mapping for usb entries Signed-off-by: Dominik Csapak --- www/manager6/Makefile | 1 + www/manager6/window/USBEdit.js | 248 +++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 www/manager6/window/USBEdit.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index 4a6b02e5..5507276e 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -117,6 +117,7 @@ JSSRC= \ window/Wizard.js \ window/GuestDiskReassign.js \ window/PCIEdit.js \ + window/USBEdit.js \ ha/Fencing.js \ ha/GroupEdit.js \ ha/GroupSelector.js \ diff --git a/www/manager6/window/USBEdit.js b/www/manager6/window/USBEdit.js new file mode 100644 index 00000000..1fec541e --- /dev/null +++ b/www/manager6/window/USBEdit.js @@ -0,0 +1,248 @@ +Ext.define('PVE.node.USBEditWindow', { + extend: 'Proxmox.window.Edit', + + mixins: ['Proxmox.Mixin.CBind'], + + cbindData: function(initialConfig) { + let me = this; + me.isCreate = !me.name || !me.nodename; + me.method = me.isCreate ? 'POST' : 'PUT'; + return { + name: me.name, + nodename: me.nodename, + }; + }, + + submitUrl: function(_url, data) { + let me = this; + let name = me.isCreate ? '' : me.name; + return `/nodes/${data.node}/hardware/mapping/usb/${name}`; + }, + + title: gettext('Add USB mapping'), + + onlineHelp: 'qm_usb_passthrough', + + method: 'POST', + + controller: { + xclass: 'Ext.app.ViewController', + + onGetValues: function(values) { + let me = this; + + var type = me.getView().down('radiofield').getGroupValue(); + + let val = values[type]; + delete values[type]; + + let usbsel = me.lookup(type); + let usbDev = usbsel.getStore().findRecord('usbid', val, 0, false, true, true); + if (!usbDev) { + return {}; + } + + if (type === 'path') { + values.path = val; + } else if (!me.getView().isCreate) { + values.delete = 'path'; + } + + values.vendor = usbDev.data.vendid; + values.device = usbDev.data.prodid; + + return values; + }, + + usbPathChange: function(usbsel, value) { + let me = this; + if (!value) { + return; + } + + let usbDev = usbsel.getStore().findRecord('usbid', value, 0, false, true, true); + if (!usbDev) { + return; + } + + let usbData = { + vendor: usbDev.data.vendid, + device: usbDev.data.prodid, + }; + + ['vendor', 'device'].forEach((fieldName) => { + let field = me.lookup(fieldName); + let oldValue = field.getValue(); + if (oldValue !== usbData[fieldName]) { + field.setValue(usbData[fieldName]); + } + }); + }, + + modeChange: function(field, value) { + let me = this; + let type = field.inputValue; + let usbsel = me.lookup(type); + usbsel.setDisabled(!value); + }, + + nodeChange: function(_field, value) { + this.lookup('hostdevice').setNodename(value); + this.lookup('path').setNodename(value); + }, + + + init: function(view) { + let me = this; + + if (!view.nodename) { + //throw "no nodename given"; + } + }, + + control: { + 'field[name=path]': { + change: 'usbPathChange', + }, + 'radiofield': { + change: 'modeChange', + }, + 'pveNodeSelector': { + change: 'nodeChange', + }, + }, + }, + + items: [ + { + xtype: 'inputpanel', + onGetValues: function(values) { + return this.up('window').getController().onGetValues(values); + }, + + + column1: [ + { + xtype: 'proxmoxtextfield', + hidden: true, + reference: 'vendor', + name: 'vendor', + }, + { + xtype: 'proxmoxtextfield', + hidden: true, + reference: 'device', + name: 'device', + }, + { + xtype: 'pmxDisplayEditField', + fieldLabel: gettext('Name'), + cbind: { + editable: '{!name}', + value: '{name}', + submitValue: '{isCreate}', + }, + name: 'name', + allowBlank: false, + }, + { + xtype: 'pmxDisplayEditField', + fieldLabel: gettext('Node'), + name: 'node', + editConfig: { + xtype: 'pveNodeSelector', + }, + cbind: { + editable: '{!nodename}', + value: '{nodename}', + }, + submitValue: true, + allowBlank: false, + }, + ], + + column2: [ + { + xtype: 'fieldcontainer', + defaultType: 'radiofield', + layout: 'fit', + items: [ + { + name: 'usb', + inputValue: 'hostdevice', + checked: true, + boxLabel: gettext('Use USB Vendor/Device ID'), + submitValue: false, + }, + { + xtype: 'pveUSBSelector', + type: 'device', + reference: 'hostdevice', + name: 'hostdevice', + cbind: { + nodename: '{nodename}', + }, + editable: true, + allowBlank: false, + fieldLabel: gettext('Choose Device'), + labelAlign: 'right', + }, + { + name: 'usb', + inputValue: 'path', + boxLabel: gettext('Use USB Port'), + submitValue: false, + }, + { + xtype: 'pveUSBSelector', + disabled: true, + name: 'path', + reference: 'path', + cbind: { + nodename: '{nodename}', + }, + editable: true, + type: 'port', + allowBlank: false, + fieldLabel: gettext('Choose Port'), + labelAlign: 'right', + }, + ], + }, + ], + + columnB: [ + { + xtype: 'proxmoxtextfield', + fieldLabel: gettext('Comment'), + submitValue: true, + name: 'comment', + cbind: { + deleteEmpty: '{!isCreate}', + }, + }, + ], + }, + ], + + initComponent: function() { + let me = this; + me.callParent(); + + if (!me.name || !me.nodename) { + return; + } + me.load({ + success: function(response) { + let data = response.result.data; + if (data.path) { + data.usb = 'path'; + } else { + data.usb = 'hostdevice'; + data.hostdevice = `${data.vendor}:${data.device}`; + } + me.setValues(data); + }, + }); + }, +}); -- 2.30.2