]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/qemu/BootOrderEdit.js
ui: bootorder: define all column widths flex
[pve-manager.git] / www / manager6 / qemu / BootOrderEdit.js
CommitLineData
1cc7c672
SR
1Ext.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
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) {
43 bootorder = boot.order.split(';').map(dev => ({name: dev, enabled: true}));
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)
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();
76 list.forEach(dev => bootorder.push({name: dev, enabled: true}));
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) &&
84 !Ext.Array.some(bootorder, x => x.name === key))
85 {
86 disabled.push(key);
adaac36f 87 }
1cc7c672
SR
88 });
89 disabled.sort();
90 disabled.forEach(dev => bootorder.push({name: dev, enabled: false}));
638a57e7 91
1cc7c672
SR
92 // add descriptions
93 bootorder.forEach(entry => {
94 entry.desc = me.vmconfig[entry.name];
adaac36f 95 });
638a57e7 96
1cc7c672
SR
97 me.store.insert(0, bootorder);
98 me.store.fireEvent("update");
638a57e7
DM
99 },
100
1cc7c672
SR
101 calculateValue: function() {
102 let me = this;
103 return me.store.getData().items
104 .filter(x => x.data.enabled)
105 .map(x => x.data.name)
106 .join(';');
adaac36f 107 },
638a57e7 108
1cc7c672
SR
109 onGetValues: function() {
110 let me = this;
111 // Note: we allow an empty value, so no 'delete' option
112 let val = { order: me.calculateValue() };
113 let res = { boot: PVE.Parser.printPropertyString(val) };
114 return res;
115 },
116
117 items: [
118 {
119 xtype: 'grid',
120 reference: 'grid',
121 margin: '0 0 5 0',
eacd918e 122 minHeight: 150,
93775406
TL
123 defaults: {
124 sortable: false,
125 hideable: false,
126 draggable: false,
127 },
1cc7c672 128 columns: [
1cc7c672
SR
129 {
130 header: '#',
595c30aa 131 flex: 4,
1cc7c672 132 renderer: (value, metaData, record, rowIndex) => {
595c30aa 133 let dragHandle = "<i class='pve-grid-fa fa fa-fw fa-reorder cursor-move'></i>";
1cc7c672
SR
134 let idx = (rowIndex + 1).toString();
135 if (record.get('enabled')) {
595c30aa 136 return dragHandle + idx;
1cc7c672 137 } else {
595c30aa 138 return dragHandle + "<span class='faded'>" + idx + "</span>";
1cc7c672
SR
139 }
140 },
141 },
142 {
143 xtype: 'checkcolumn',
144 header: gettext('Enabled'),
145 dataIndex: 'enabled',
595c30aa 146 flex: 4,
1cc7c672
SR
147 },
148 {
149 header: gettext('Device'),
150 dataIndex: 'name',
595c30aa 151 flex: 6,
1cc7c672
SR
152 },
153 {
154 header: gettext('Description'),
155 dataIndex: 'desc',
595c30aa 156 flex: 20,
1cc7c672
SR
157 },
158 ],
159 viewConfig: {
160 plugins: {
161 ptype: 'gridviewdragdrop',
162 dragText: gettext('Drag and drop to reorder'),
adaac36f 163 }
1cc7c672
SR
164 },
165 listeners: {
166 drop: function() {
167 // doesn't fire automatically on reorder
168 this.getStore().fireEvent("update");
adaac36f 169 }
1cc7c672
SR
170 },
171 },
172 {
173 xtype: 'component',
174 html: gettext('Drag and drop to reorder'),
175 },
176 {
177 xtype: 'displayfield',
178 reference: 'emptyWarning',
179 userCls: 'pmx-hint',
180 value: gettext('Warning: No devices selected, the VM will probably not boot!'),
181 },
182 {
183 // for dirty marking and 'reset' function
184 xtype: 'field',
185 reference: 'marker',
186 hidden: true,
187 setValue: function(val) {
188 let me = this;
189 let panel = me.up('pveQemuBootOrderPanel');
190
191 // on form reset, go back to original state
192 if (!panel.inUpdate) {
193 panel.setVMConfig(panel.vmconfig);
adaac36f 194 }
1cc7c672
SR
195
196 // not a subclass, so no callParent; just do it manually
197 me.setRawValue(me.valueToRaw(val));
198 return me.mixins.field.setValue.call(me, val);
199 }
200 },
201 ],
202
203 initComponent: function() {
204 let me = this;
205
638a57e7 206 me.callParent();
1cc7c672
SR
207
208 let controller = me.getController();
209
210 let grid = controller.lookup('grid');
211 let marker = controller.lookup('marker');
212 let emptyWarning = controller.lookup('emptyWarning');
213
214 marker.originalValue = undefined;
215
216 me.store = Ext.create('Ext.data.Store', {
217 model: 'pve-boot-order-entry',
218 listeners: {
219 update: function() {
220 this.commitChanges();
221 let val = me.calculateValue();
222 if (marker.originalValue === undefined) {
223 marker.originalValue = val;
224 }
225 me.inUpdate = true;
226 marker.setValue(val);
227 me.inUpdate = false;
228 marker.checkDirty();
229 emptyWarning.setHidden(val !== '');
230 grid.getView().refresh();
231 }
232 }
233 });
234 grid.setStore(me.store);
638a57e7
DM
235 }
236});
237
238Ext.define('PVE.qemu.BootOrderEdit', {
9fccc702 239 extend: 'Proxmox.window.Edit',
638a57e7 240
ec0bd652 241 items: [{
adaac36f 242 xtype: 'pveQemuBootOrderPanel',
ec0bd652
DC
243 itemId: 'inputpanel'
244 }],
638a57e7 245
adaac36f 246 subject: gettext('Boot Order'),
595c30aa 247 width: 640,
638a57e7 248
adaac36f 249 initComponent : function() {
1cc7c672 250 let me = this;
638a57e7 251 me.callParent();
638a57e7
DM
252 me.load({
253 success: function(response, options) {
adaac36f 254 me.down('#inputpanel').setVMConfig(response.result.data);
638a57e7
DM
255 }
256 });
257 }
258});