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