]>
Commit | Line | Data |
---|---|---|
f46721af | 1 | Ext.define('PVE.form.USBSelector', { |
0fc95a12 | 2 | extend: 'Proxmox.form.ComboGrid', |
f46721af | 3 | alias: ['widget.pveUSBSelector'], |
bce6af85 | 4 | |
f46721af DC |
5 | allowBlank: false, |
6 | autoSelect: false, | |
bce6af85 TL |
7 | anyMatch: true, |
8 | displayField: 'product_and_id', | |
f46721af DC |
9 | valueField: 'usbid', |
10 | editable: true, | |
11 | ||
f46721af DC |
12 | validator: function(value) { |
13 | var me = this; | |
bce6af85 TL |
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 | |
f46721af DC |
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 | } | |
dcf22a4b | 23 | return gettext("Invalid Value"); |
f46721af DC |
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 | var store = new Ext.data.Store({ | |
40 | model: 'pve-usb-' + me.type, | |
41 | proxy: { | |
ca516309 TL |
42 | type: 'proxmox', |
43 | url: `/api2/json/nodes/${nodename}/hardware/usb`, | |
f46721af DC |
44 | }, |
45 | filters: [ | |
8058410f | 46 | function(item) { |
f46721af | 47 | return !!item.data.usbpath && !!item.data.prodid && item.data['class'] != 9; |
f6710aac TL |
48 | }, |
49 | ], | |
f46721af | 50 | }); |
2278a74b TL |
51 | let emptyText = ''; |
52 | if (me.type === 'device') { | |
53 | emptyText = gettext('Passthrough a specific device'); | |
54 | } else { | |
55 | emptyText = gettext('Passthrough a full port'); | |
56 | } | |
f46721af DC |
57 | |
58 | Ext.apply(me, { | |
59 | store: store, | |
2278a74b | 60 | emptyText: emptyText, |
ff49fd46 TL |
61 | listConfig: { |
62 | width: 520, | |
f46721af DC |
63 | columns: [ |
64 | { | |
53e3ea84 | 65 | header: me.type === 'device'?gettext('Device'):gettext('Port'), |
f46721af DC |
66 | sortable: true, |
67 | dataIndex: 'usbid', | |
f6710aac | 68 | width: 80, |
f46721af DC |
69 | }, |
70 | { | |
71 | header: gettext('Manufacturer'), | |
72 | sortable: true, | |
73 | dataIndex: 'manufacturer', | |
f6710aac | 74 | width: 150, |
f46721af DC |
75 | }, |
76 | { | |
77 | header: gettext('Product'), | |
78 | sortable: true, | |
79 | dataIndex: 'product', | |
f6710aac | 80 | flex: 1, |
f46721af DC |
81 | }, |
82 | { | |
83 | header: gettext('Speed'), | |
ff49fd46 | 84 | width: 75, |
f46721af DC |
85 | sortable: true, |
86 | dataIndex: 'speed', | |
87 | renderer: function(value) { | |
ff49fd46 | 88 | let speed_map = { |
8058410f TL |
89 | "10000": "USB 3.1", |
90 | "5000": "USB 3.0", | |
91 | "480": "USB 2.0", | |
92 | "12": "USB 1.x", | |
ff49fd46 TL |
93 | "1.5": "USB 1.x", |
94 | }; | |
95 | return speed_map[value] || value + " Mbps"; | |
f6710aac TL |
96 | }, |
97 | }, | |
98 | ], | |
ff49fd46 | 99 | }, |
f46721af DC |
100 | }); |
101 | ||
102 | me.callParent(); | |
103 | ||
104 | store.load(); | |
f6710aac | 105 | }, |
f46721af DC |
106 | |
107 | }, function() { | |
f46721af DC |
108 | Ext.define('pve-usb-device', { |
109 | extend: 'Ext.data.Model', | |
110 | fields: [ | |
111 | { | |
112 | name: 'usbid', | |
113 | convert: function(val, data) { | |
114 | if (val) { | |
115 | return val; | |
116 | } | |
117 | return data.get('vendid') + ':' + data.get('prodid'); | |
f6710aac | 118 | }, |
f46721af DC |
119 | }, |
120 | 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath', | |
f6710aac TL |
121 | { name: 'port', type: 'number' }, |
122 | { name: 'level', type: 'number' }, | |
123 | { name: 'class', type: 'number' }, | |
124 | { name: 'devnum', type: 'number' }, | |
125 | { name: 'busnum', type: 'number' }, | |
bce6af85 TL |
126 | { |
127 | name: 'product_and_id', | |
128 | type: 'string', | |
129 | convert: (v, rec) => { | |
130 | let res = rec.data.product || gettext('Unkown'); | |
131 | res += " (" + rec.data.usbid + ")"; | |
132 | return res; | |
133 | }, | |
134 | }, | |
f6710aac | 135 | ], |
f46721af DC |
136 | }); |
137 | ||
138 | Ext.define('pve-usb-port', { | |
139 | extend: 'Ext.data.Model', | |
140 | fields: [ | |
141 | { | |
142 | name: 'usbid', | |
f6710aac | 143 | convert: function(val, data) { |
f46721af DC |
144 | if (val) { |
145 | return val; | |
146 | } | |
147 | return data.get('busnum') + '-' + data.get('usbpath'); | |
f6710aac | 148 | }, |
f46721af DC |
149 | }, |
150 | 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath', | |
f6710aac TL |
151 | { name: 'port', type: 'number' }, |
152 | { name: 'level', type: 'number' }, | |
153 | { name: 'class', type: 'number' }, | |
154 | { name: 'devnum', type: 'number' }, | |
155 | { name: 'busnum', type: 'number' }, | |
bce6af85 TL |
156 | { |
157 | name: 'product_and_id', | |
158 | type: 'string', | |
159 | convert: (v, rec) => { | |
160 | let res = rec.data.product || gettext('Unplugged'); | |
161 | res += " (" + rec.data.usbid + ")"; | |
162 | return res; | |
163 | }, | |
164 | }, | |
f6710aac | 165 | ], |
f46721af DC |
166 | }); |
167 | }); |