]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/window/GuestDiskReassign.js
ui: disk reassign: improve default focus behavior
[pve-manager.git] / www / manager6 / window / GuestDiskReassign.js
1 Ext.define('PVE.window.GuestDiskReassign', {
2 extend: 'Proxmox.window.Edit',
3 mixins: ['Proxmox.Mixin.CBind'],
4
5 resizable: false,
6 modal: true,
7 width: 350,
8 border: false,
9 layout: 'fit',
10 showReset: false,
11 showProgress: true,
12 method: 'POST',
13
14 viewModel: {
15 data: {
16 mpType: '',
17 },
18 formulas: {
19 mpMaxCount: get => get('mpType') === 'mp'
20 ? PVE.Utils.mp_counts.mps - 1
21 : PVE.Utils.mp_counts.unused - 1,
22 },
23 },
24
25 cbindData: function() {
26 let me = this;
27 return {
28 vmid: me.vmid,
29 disk: me.disk,
30 isQemu: me.type === 'qemu',
31 nodename: me.nodename,
32 url: () => {
33 let endpoint = me.type === 'qemu' ? 'move_disk' : 'move_volume';
34 return `/nodes/${me.nodename}/${me.type}/${me.vmid}/${endpoint}`;
35 },
36 };
37 },
38
39 cbind: {
40 title: get => get('isQemu') ? gettext('Reassign disk') : gettext('Reassign volume'),
41 submitText: get => get('title'),
42 qemu: '{isQemu}',
43 url: '{url}',
44 },
45
46 getValues: function() {
47 let me = this;
48 let values = me.formPanel.getForm().getValues();
49
50 let params = {
51 vmid: me.vmid,
52 'target-vmid': values.targetVmid,
53 };
54
55 params[me.qemu ? 'disk' : 'volume'] = me.disk;
56
57 if (me.qemu) {
58 params['target-disk'] = `${values.controller}${values.deviceid}`;
59 } else {
60 params['target-volume'] = `${values.mpType}${values.mpId}`;
61 }
62 return params;
63 },
64
65 controller: {
66 xclass: 'Ext.app.ViewController',
67
68 initViewModel: function(model) {
69 let view = this.getView();
70 let mpTypeValue = view.disk.match(/^unused\d+/) ? 'unused' : 'mp';
71 model.set('mpType', mpTypeValue);
72 },
73
74 onMpTypeChange: function(value) {
75 this.getView().getViewModel().set('mpType', value.getValue());
76 this.getView().lookup('mpIdSelector').validate();
77 },
78
79 onTargetVMChange: function(f, vmid) {
80 let me = this;
81 let view = me.getView();
82 let diskSelector = view.lookup('diskSelector');
83 if (!vmid) {
84 diskSelector.setVMConfig(null);
85 me.VMConfig = null;
86 return;
87 }
88
89 let type = view.qemu ? 'qemu' : 'lxc';
90
91 let url = `/nodes/${view.nodename}/${type}/${vmid}/config`;
92 Proxmox.Utils.API2Request({
93 url: url,
94 method: 'GET',
95 failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
96 success: function(response, options) {
97 if (view.qemu) {
98 diskSelector.setVMConfig(response.result.data);
99 diskSelector.setDisabled(false);
100 } else {
101 let mpIdSelector = view.lookup('mpIdSelector');
102 let mpType = view.lookup('mpType');
103
104 view.VMConfig = response.result.data;
105
106 mpIdSelector.setValue(
107 PVE.Utils.nextFreeMP(
108 view.getViewModel().get('mpType'),
109 view.VMConfig,
110 ).id,
111 );
112
113 mpType.setDisabled(false);
114 mpIdSelector.setDisabled(false);
115 mpIdSelector.validate();
116 }
117 },
118 });
119 },
120 },
121
122 defaultFocus: 'sourceDisk',
123 items: [
124 {
125 xtype: 'form',
126 reference: 'moveFormPanel',
127 border: false,
128 fieldDefaults: {
129 labelWidth: 100,
130 anchor: '100%',
131 },
132 items: [
133 {
134 xtype: 'displayfield',
135 name: 'sourceDisk',
136 fieldLabel: gettext('Source'),
137 cbind: {
138 name: get => get('isQemu') ? 'disk' : 'volume',
139 value: '{disk}',
140 },
141 allowBlank: false,
142 },
143 {
144 xtype: 'vmComboSelector',
145 reference: 'targetVMID',
146 name: 'targetVmid',
147 allowBlank: false,
148 fieldLabel: gettext('Target'),
149 bind: {
150 value: '{targetVMID}',
151 },
152 store: {
153 model: 'PVEResources',
154 autoLoad: true,
155 sorters: 'vmid',
156 cbind: {}, // for nested cbinds
157 filters: [
158 {
159 property: 'type',
160 cbind: {
161 value: get => get('isQemu') ? 'qemu' : 'lxc',
162 },
163 },
164 {
165 property: 'node',
166 cbind: {
167 value: '{nodename}',
168 },
169 },
170 {
171 property: 'vmid',
172 operator: '!=',
173 cbind: {
174 value: '{vmid}',
175 },
176 },
177 {
178 property: 'template',
179 value: 0,
180 },
181 ],
182 },
183 listeners: { change: 'onTargetVMChange' },
184 },
185 {
186 xtype: 'pveControllerSelector',
187 reference: 'diskSelector',
188 withUnused: true,
189 disabled: true,
190 cbind: {
191 hidden: '{!isQemu}',
192 },
193 },
194 {
195 xtype: 'container',
196 layout: 'hbox',
197 cbind: {
198 hidden: '{isQemu}',
199 disabled: '{isQemu}',
200 },
201 items: [
202 {
203 xtype: 'pmxDisplayEditField',
204 cbind: {
205 editable: get => !get('disk').match(/^unused\d+/),
206 value: get => get('disk').match(/^unused\d+/) ? 'unused' : 'mp',
207 },
208 disabled: true,
209 name: 'mpType',
210 reference: 'mpType',
211 fieldLabel: gettext('Add as'),
212 submitValue: true,
213 flex: 4,
214 editConfig: {
215 xtype: 'proxmoxKVComboBox',
216 name: 'mpTypeCombo',
217 reference: 'mpTypeCombo',
218 deleteEmpty: false,
219 cbind: {
220 hidden: '{isQemu}',
221 },
222 comboItems: [
223 ['mp', gettext('Mount Point')],
224 ['unused', gettext('Unused')],
225 ],
226 listeners: { change: 'onMpTypeChange' },
227 },
228 },
229 {
230 xtype: 'proxmoxintegerfield',
231 name: 'mpId',
232 reference: 'mpIdSelector',
233 minValue: 0,
234 flex: 1,
235 allowBlank: false,
236 validateOnChange: true,
237 disabled: true,
238 bind: {
239 maxValue: '{mpMaxCount}',
240 },
241 validator: function(value) {
242 let view = this.up('window');
243 let type = view.getViewModel().get('mpType');
244 if (Ext.isDefined(view.VMConfig[`${type}${value}`])) {
245 return "Mount point is already in use.";
246 }
247 return true;
248 },
249 },
250 ],
251 },
252 ],
253 },
254 ],
255
256 initComponent: function() {
257 let me = this;
258
259 if (!me.nodename) {
260 throw "no node name specified";
261 }
262
263 if (!me.vmid) {
264 throw "no VM ID specified";
265 }
266
267 if (!me.type) {
268 throw "no type specified";
269 }
270
271 me.callParent();
272 },
273 });