]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/form/USBSelector.js
a67c8765415f7cc8131b10c57f3dd3bdbc3c320a
[pve-manager.git] / www / manager6 / form / USBSelector.js
1 Ext.define('PVE.form.USBSelector', {
2 extend: 'Proxmox.form.ComboGrid',
3 alias: ['widget.pveUSBSelector'],
4
5 allowBlank: false,
6 autoSelect: false,
7 anyMatch: true,
8 displayField: 'product_and_id',
9 valueField: 'usbid',
10 editable: true,
11
12 validator: function(value) {
13 var me = this;
14 if (!value) {
15 return true; // handled later by allowEmpty in the getErrors call chain
16 }
17 value = me.getValue(); // as the valueField is not the displayfield
18 if (me.type === 'device') {
19 return (/^[a-f0-9]{4}:[a-f0-9]{4}$/i).test(value);
20 } else if (me.type === 'port') {
21 return (/^[0-9]+-[0-9]+(\.[0-9]+)*$/).test(value);
22 }
23 return gettext("Invalid Value");
24 },
25
26 initComponent: function() {
27 var me = this;
28
29 var nodename = me.pveSelNode.data.node;
30
31 if (!nodename) {
32 throw "no nodename specified";
33 }
34
35 if (me.type !== 'device' && me.type !== 'port') {
36 throw "no valid type specified";
37 }
38
39 let store = new Ext.data.Store({
40 model: `pve-usb-${me.type}`,
41 proxy: {
42 type: 'proxmox',
43 url: `/api2/json/nodes/${nodename}/hardware/usb`,
44 },
45 filters: [
46 ({ data }) => !!data.usbpath && !!data.prodid && String(data.class) !== "9",
47 ],
48 });
49 let emptyText = '';
50 if (me.type === 'device') {
51 emptyText = gettext('Passthrough a specific device');
52 } else {
53 emptyText = gettext('Passthrough a full port');
54 }
55
56 Ext.apply(me, {
57 store: store,
58 emptyText: emptyText,
59 listConfig: {
60 width: 520,
61 columns: [
62 {
63 header: me.type === 'device'?gettext('Device'):gettext('Port'),
64 sortable: true,
65 dataIndex: 'usbid',
66 width: 80,
67 },
68 {
69 header: gettext('Manufacturer'),
70 sortable: true,
71 dataIndex: 'manufacturer',
72 width: 150,
73 },
74 {
75 header: gettext('Product'),
76 sortable: true,
77 dataIndex: 'product',
78 flex: 1,
79 },
80 {
81 header: gettext('Speed'),
82 width: 75,
83 sortable: true,
84 dataIndex: 'speed',
85 renderer: function(value) {
86 let speed2Class = {
87 "10000": "USB 3.1",
88 "5000": "USB 3.0",
89 "480": "USB 2.0",
90 "12": "USB 1.x",
91 "1.5": "USB 1.x",
92 };
93 return speed2Class[value] || value + " Mbps";
94 },
95 },
96 ],
97 },
98 });
99
100 me.callParent();
101
102 store.load();
103 },
104
105 }, function() {
106 Ext.define('pve-usb-device', {
107 extend: 'Ext.data.Model',
108 fields: [
109 {
110 name: 'usbid',
111 convert: function(val, data) {
112 if (val) {
113 return val;
114 }
115 return data.get('vendid') + ':' + data.get('prodid');
116 },
117 },
118 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath',
119 { name: 'port', type: 'number' },
120 { name: 'level', type: 'number' },
121 { name: 'class', type: 'number' },
122 { name: 'devnum', type: 'number' },
123 { name: 'busnum', type: 'number' },
124 {
125 name: 'product_and_id',
126 type: 'string',
127 convert: (v, rec) => {
128 let res = rec.data.product || gettext('Unknown');
129 res += " (" + rec.data.usbid + ")";
130 return res;
131 },
132 },
133 ],
134 });
135
136 Ext.define('pve-usb-port', {
137 extend: 'Ext.data.Model',
138 fields: [
139 {
140 name: 'usbid',
141 convert: function(val, data) {
142 if (val) {
143 return val;
144 }
145 return data.get('busnum') + '-' + data.get('usbpath');
146 },
147 },
148 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath',
149 { name: 'port', type: 'number' },
150 { name: 'level', type: 'number' },
151 { name: 'class', type: 'number' },
152 { name: 'devnum', type: 'number' },
153 { name: 'busnum', type: 'number' },
154 {
155 name: 'product_and_id',
156 type: 'string',
157 convert: (v, rec) => {
158 let res = rec.data.product || gettext('Unplugged');
159 res += " (" + rec.data.usbid + ")";
160 return res;
161 },
162 },
163 ],
164 });
165 });