]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/BootOrderEdit.js
ui: eslint: State equalities more precisely
[pve-manager.git] / www / manager6 / qemu / BootOrderEdit.js
1 Ext.define('pve-boot-order-entry', {
2 extend: 'Ext.data.Model',
3 fields: [
4 { name: 'name', type: 'string' },
5 { name: 'enabled', type: 'bool' },
6 { name: 'desc', type: 'string' },
7 ],
8 });
9
10 Ext.define('PVE.qemu.BootOrderPanel', {
11 extend: 'Proxmox.panel.InputPanel',
12 alias: 'widget.pveQemuBootOrderPanel',
13
14 onlineHelp: 'qm_bootorder',
15
16 vmconfig: {}, // store loaded vm config
17 store: undefined,
18
19 inUpdate: false,
20 controller: {
21 xclass: 'Ext.app.ViewController',
22 },
23
24 isCloudinit: (v) => v.match(/media=cdrom/) && v.match(/[:/]vm-\d+-cloudinit/),
25
26 isDisk: function(value) {
27 return PVE.Utils.bus_match.test(value);
28 },
29
30 isBootdev: function(dev, value) {
31 return (this.isDisk(dev) && !this.isCloudinit(value)) ||
32 (/^net\d+/).test(dev) ||
33 (/^hostpci\d+/).test(dev) ||
34 ((/^usb\d+/).test(dev) && !(/spice/).test(value));
35 },
36
37 setVMConfig: function(vmconfig) {
38 let me = this;
39 me.vmconfig = vmconfig;
40
41 me.store.removeAll();
42
43 let boot = PVE.Parser.parsePropertyString(me.vmconfig.boot, "legacy");
44
45 let bootorder = [];
46 if (boot.order) {
47 bootorder = boot.order.split(';').map(dev => ({ name: dev, enabled: true }));
48 } else if (!(/^\s*$/).test(me.vmconfig.boot)) {
49 // legacy style, transform to new bootorder
50 let order = boot.legacy || 'cdn';
51 let bootdisk = me.vmconfig.bootdisk || undefined;
52
53 // get the first 4 characters (acdn)
54 // ignore the rest (there should never be more than 4)
55 let orderList = order.split('').slice(0, 4);
56
57 // build bootdev list
58 for (let i = 0; i < orderList.length; i++) {
59 let list = [];
60 if (orderList[i] === 'c') {
61 if (bootdisk !== undefined && me.vmconfig[bootdisk]) {
62 list.push(bootdisk);
63 }
64 } else if (orderList[i] === 'd') {
65 Ext.Object.each(me.vmconfig, function(key, value) {
66 if (me.isDisk(key) && value.match(/media=cdrom/) && !me.isCloudinit(value)) {
67 list.push(key);
68 }
69 });
70 } else if (orderList[i] === 'n') {
71 Ext.Object.each(me.vmconfig, function(key, value) {
72 if ((/^net\d+/).test(key)) {
73 list.push(key);
74 }
75 });
76 }
77
78 // Object.each iterates in random order, sort alphabetically
79 list.sort();
80 list.forEach(dev => bootorder.push({ name: dev, enabled: true }));
81 }
82 }
83
84 // add disabled devices as well
85 let disabled = [];
86 Ext.Object.each(me.vmconfig, function(key, value) {
87 if (me.isBootdev(key, value) &&
88 !Ext.Array.some(bootorder, x => x.name === key)) {
89 disabled.push(key);
90 }
91 });
92 disabled.sort();
93 disabled.forEach(dev => bootorder.push({ name: dev, enabled: false }));
94
95 // add descriptions
96 bootorder.forEach(entry => {
97 entry.desc = me.vmconfig[entry.name];
98 });
99
100 me.store.insert(0, bootorder);
101 me.store.fireEvent("update");
102 },
103
104 calculateValue: function() {
105 let me = this;
106 return me.store.getData().items
107 .filter(x => x.data.enabled)
108 .map(x => x.data.name)
109 .join(';');
110 },
111
112 onGetValues: function() {
113 let me = this;
114 // Note: we allow an empty value, so no 'delete' option
115 let val = { order: me.calculateValue() };
116 let res = { boot: PVE.Parser.printPropertyString(val) };
117 return res;
118 },
119
120 items: [
121 {
122 xtype: 'grid',
123 reference: 'grid',
124 margin: '0 0 5 0',
125 minHeight: 150,
126 defaults: {
127 sortable: false,
128 hideable: false,
129 draggable: false,
130 },
131 columns: [
132 {
133 header: '#',
134 flex: 4,
135 renderer: (value, metaData, record, rowIndex) => {
136 let dragHandle = "<i class='pve-grid-fa fa fa-fw fa-reorder cursor-move'></i>";
137 let idx = (rowIndex + 1).toString();
138 if (record.get('enabled')) {
139 return dragHandle + idx;
140 } else {
141 return dragHandle + "<span class='faded'>" + idx + "</span>";
142 }
143 },
144 },
145 {
146 xtype: 'checkcolumn',
147 header: gettext('Enabled'),
148 dataIndex: 'enabled',
149 flex: 4,
150 },
151 {
152 header: gettext('Device'),
153 dataIndex: 'name',
154 flex: 6,
155 renderer: (value, metaData, record, rowIndex) => {
156 let desc = record.get('desc');
157
158 let icon = '', iconCls;
159 if (value.match(/^net\d+$/)) {
160 iconCls = 'exchange';
161 } else if (desc.match(/media=cdrom/)) {
162 metaData.tdCls = 'pve-itype-icon-cdrom';
163 } else {
164 iconCls = 'hdd-o';
165 }
166 if (iconCls !== undefined) {
167 metaData.tdCls += 'pve-itype-fa';
168 icon = `<i class="pve-grid-fa fa fa-fw fa-${iconCls}"></i>`;
169 }
170
171 return icon + value;
172 },
173 },
174 {
175 header: gettext('Description'),
176 dataIndex: 'desc',
177 flex: 20,
178 },
179 ],
180 viewConfig: {
181 plugins: {
182 ptype: 'gridviewdragdrop',
183 dragText: gettext('Drag and drop to reorder'),
184 },
185 },
186 listeners: {
187 drop: function() {
188 // doesn't fire automatically on reorder
189 this.getStore().fireEvent("update");
190 },
191 },
192 },
193 {
194 xtype: 'component',
195 html: gettext('Drag and drop to reorder'),
196 },
197 {
198 xtype: 'displayfield',
199 reference: 'emptyWarning',
200 userCls: 'pmx-hint',
201 value: gettext('Warning: No devices selected, the VM will probably not boot!'),
202 },
203 {
204 // for dirty marking and 'reset' function
205 xtype: 'field',
206 reference: 'marker',
207 hidden: true,
208 setValue: function(val) {
209 let me = this;
210 let panel = me.up('pveQemuBootOrderPanel');
211
212 // on form reset, go back to original state
213 if (!panel.inUpdate) {
214 panel.setVMConfig(panel.vmconfig);
215 }
216
217 // not a subclass, so no callParent; just do it manually
218 me.setRawValue(me.valueToRaw(val));
219 return me.mixins.field.setValue.call(me, val);
220 },
221 },
222 ],
223
224 initComponent: function() {
225 let me = this;
226
227 me.callParent();
228
229 let controller = me.getController();
230
231 let grid = controller.lookup('grid');
232 let marker = controller.lookup('marker');
233 let emptyWarning = controller.lookup('emptyWarning');
234
235 marker.originalValue = undefined;
236
237 me.store = Ext.create('Ext.data.Store', {
238 model: 'pve-boot-order-entry',
239 listeners: {
240 update: function() {
241 this.commitChanges();
242 let val = me.calculateValue();
243 if (marker.originalValue === undefined) {
244 marker.originalValue = val;
245 }
246 me.inUpdate = true;
247 marker.setValue(val);
248 me.inUpdate = false;
249 marker.checkDirty();
250 emptyWarning.setHidden(val !== '');
251 grid.getView().refresh();
252 },
253 },
254 });
255 grid.setStore(me.store);
256 },
257 });
258
259 Ext.define('PVE.qemu.BootOrderEdit', {
260 extend: 'Proxmox.window.Edit',
261
262 items: [{
263 xtype: 'pveQemuBootOrderPanel',
264 itemId: 'inputpanel',
265 }],
266
267 subject: gettext('Boot Order'),
268 width: 640,
269
270 initComponent: function() {
271 let me = this;
272 me.callParent();
273 me.load({
274 success: function(response, options) {
275 me.down('#inputpanel').setVMConfig(response.result.data);
276 },
277 });
278 },
279 });