]>
Commit | Line | Data |
---|---|---|
06694509 | 1 | // fixme: how can we avoid those lint errors? |
06694509 DM |
2 | Ext.define('Proxmox.window.Edit', { |
3 | extend: 'Ext.window.Window', | |
4 | alias: 'widget.proxmoxWindowEdit', | |
1b07a95a | 5 | |
a33ba257 DM |
6 | // autoLoad trigger a load() after component creation |
7 | autoLoad: false, | |
8 | ||
06694509 DM |
9 | resizable: false, |
10 | ||
11 | // use this tio atimatically generate a title like | |
12 | // Create: <subject> | |
13 | subject: undefined, | |
14 | ||
b33f451f | 15 | // set isCreate to true if you want a Create button (instead |
1b07a95a | 16 | // OK and RESET) |
b33f451f | 17 | isCreate: false, |
06694509 DM |
18 | |
19 | // set to true if you want an Add button (instead of Create) | |
20 | isAdd: false, | |
21 | ||
22 | // set to true if you want an Remove button (instead of Create) | |
23 | isRemove: false, | |
24 | ||
ffea05ec DC |
25 | // custom submitText |
26 | submitText: undefined, | |
27 | ||
06694509 DM |
28 | backgroundDelay: 0, |
29 | ||
a7dcbdeb DM |
30 | // needed for finding the reference to submitbutton |
31 | // because we do not have a controller | |
32 | referenceHolder: true, | |
33 | defaultButton: 'submitbutton', | |
34 | ||
35 | // finds the first form field | |
5d3089cd | 36 | defaultFocus: 'field[disabled=false][hidden=false]', |
a7dcbdeb | 37 | |
06694509 DM |
38 | showProgress: false, |
39 | ||
8d8dbfc5 TL |
40 | showTaskViewer: false, |
41 | ||
fde8e8bb TL |
42 | // gets called if we have a progress bar or taskview and it detected that |
43 | // the task finished. function(success) | |
44 | taskDone: Ext.emptyFn, | |
45 | ||
a498f279 DC |
46 | // gets called when the api call is finished, right at the beginning |
47 | // function(success, response, options) | |
48 | apiCallDone: Ext.emptyFn, | |
49 | ||
42a9df8b DC |
50 | // assign a reference from docs, to add a help button docked to the |
51 | // bottom of the window. If undefined we magically fall back to the | |
52 | // onlineHelp of our first item, if set. | |
53 | onlineHelp: undefined, | |
54 | ||
06694509 | 55 | isValid: function() { |
4b5c6b3f | 56 | let me = this; |
06694509 | 57 | |
4b5c6b3f | 58 | let form = me.formPanel.getForm(); |
06694509 DM |
59 | return form.isValid(); |
60 | }, | |
61 | ||
62 | getValues: function(dirtyOnly) { | |
4b5c6b3f | 63 | let me = this; |
06694509 | 64 | |
4b5c6b3f | 65 | let values = {}; |
06694509 | 66 | |
4b5c6b3f | 67 | let form = me.formPanel.getForm(); |
06694509 DM |
68 | |
69 | form.getFields().each(function(field) { | |
70 | if (!field.up('inputpanel') && (!dirtyOnly || field.isDirty())) { | |
71 | Proxmox.Utils.assemble_field_data(values, field.getSubmitData()); | |
72 | } | |
73 | }); | |
74 | ||
75 | Ext.Array.each(me.query('inputpanel'), function(panel) { | |
76 | Proxmox.Utils.assemble_field_data(values, panel.getValues(dirtyOnly)); | |
77 | }); | |
78 | ||
79 | return values; | |
80 | }, | |
81 | ||
82 | setValues: function(values) { | |
4b5c6b3f | 83 | let me = this; |
06694509 | 84 | |
4b5c6b3f | 85 | let form = me.formPanel.getForm(); |
b24601af TL |
86 | let formfields = form.getFields(); |
87 | ||
88 | Ext.iterate(values, function(id, val) { | |
89 | let fields = formfields.filterBy((f) => | |
01031528 | 90 | (f.id === id || f.name === id || f.dataIndex === id) && !f.up('inputpanel'), |
b24601af TL |
91 | ); |
92 | fields.each((field) => { | |
93 | field.setValue(val); | |
68689d73 TL |
94 | if (form.trackResetOnLoad) { |
95 | field.resetOriginalValue(); | |
96 | } | |
b24601af | 97 | }); |
06694509 | 98 | }); |
1b07a95a | 99 | |
06694509 DM |
100 | Ext.Array.each(me.query('inputpanel'), function(panel) { |
101 | panel.setValues(values); | |
102 | }); | |
103 | }, | |
104 | ||
4e78d719 TL |
105 | setSubmitText: function(text) { |
106 | this.lookup('submitbutton').setText(text); | |
107 | }, | |
108 | ||
06694509 | 109 | submit: function() { |
4b5c6b3f | 110 | let me = this; |
06694509 | 111 | |
4b5c6b3f | 112 | let form = me.formPanel.getForm(); |
06694509 | 113 | |
4b5c6b3f | 114 | let values = me.getValues(); |
06694509 | 115 | Ext.Object.each(values, function(name, val) { |
4b5c6b3f TL |
116 | if (Object.prototype.hasOwnProperty.call(values, name)) { |
117 | if (Ext.isArray(val) && !val.length) { | |
06694509 DM |
118 | values[name] = ''; |
119 | } | |
120 | } | |
121 | }); | |
122 | ||
123 | if (me.digest) { | |
124 | values.digest = me.digest; | |
125 | } | |
126 | ||
127 | if (me.backgroundDelay) { | |
128 | values.background_delay = me.backgroundDelay; | |
129 | } | |
130 | ||
4b5c6b3f | 131 | let url = me.url; |
06694509 DM |
132 | if (me.method === 'DELETE') { |
133 | url = url + "?" + Ext.Object.toQueryString(values); | |
134 | values = undefined; | |
135 | } | |
136 | ||
137 | Proxmox.Utils.API2Request({ | |
138 | url: url, | |
139 | waitMsgTarget: me, | |
140 | method: me.method || (me.backgroundDelay ? 'POST' : 'PUT'), | |
141 | params: values, | |
142 | failure: function(response, options) { | |
a498f279 DC |
143 | me.apiCallDone(false, response, options); |
144 | ||
06694509 DM |
145 | if (response.result && response.result.errors) { |
146 | form.markInvalid(response.result.errors); | |
147 | } | |
148 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
149 | }, | |
150 | success: function(response, options) { | |
4b5c6b3f TL |
151 | let hasProgressBar = |
152 | (me.backgroundDelay || me.showProgress || me.showTaskViewer) && | |
153 | response.result.data; | |
06694509 | 154 | |
a498f279 DC |
155 | me.apiCallDone(true, response, options); |
156 | ||
06694509 DM |
157 | if (hasProgressBar) { |
158 | // stay around so we can trigger our close events | |
159 | // when background action is completed | |
160 | me.hide(); | |
161 | ||
4b5c6b3f TL |
162 | let upid = response.result.data; |
163 | let viewerClass = me.showTaskViewer ? 'Viewer' : 'Progress'; | |
164 | Ext.create('Proxmox.window.Task' + viewerClass, { | |
165 | autoShow: true, | |
06694509 | 166 | upid: upid, |
fde8e8bb | 167 | taskDone: me.taskDone, |
06694509 | 168 | listeners: { |
4b5c6b3f | 169 | destroy: function() { |
06694509 | 170 | me.close(); |
4b5c6b3f TL |
171 | }, |
172 | }, | |
06694509 | 173 | }); |
06694509 DM |
174 | } else { |
175 | me.close(); | |
176 | } | |
4b5c6b3f | 177 | }, |
06694509 DM |
178 | }); |
179 | }, | |
180 | ||
181 | load: function(options) { | |
4b5c6b3f | 182 | let me = this; |
06694509 | 183 | |
4b5c6b3f | 184 | let form = me.formPanel.getForm(); |
06694509 DM |
185 | |
186 | options = options || {}; | |
187 | ||
4b5c6b3f TL |
188 | let newopts = Ext.apply({ |
189 | waitMsgTarget: me, | |
06694509 DM |
190 | }, options); |
191 | ||
4b5c6b3f | 192 | let createWrapper = function(successFn) { |
06694509 DM |
193 | Ext.apply(newopts, { |
194 | url: me.url, | |
195 | method: 'GET', | |
196 | success: function(response, opts) { | |
197 | form.clearInvalid(); | |
8ae2f8c8 | 198 | me.digest = response.result.digest || response.result.data.digest; |
06694509 DM |
199 | if (successFn) { |
200 | successFn(response, opts); | |
201 | } else { | |
202 | me.setValues(response.result.data); | |
203 | } | |
204 | // hack: fix ExtJS bug | |
205 | Ext.Array.each(me.query('radiofield'), function(f) { | |
206 | f.resetOriginalValue(); | |
207 | }); | |
208 | }, | |
209 | failure: function(response, opts) { | |
210 | Ext.Msg.alert(gettext('Error'), response.htmlStatus, function() { | |
211 | me.close(); | |
212 | }); | |
4b5c6b3f | 213 | }, |
06694509 DM |
214 | }); |
215 | }; | |
216 | ||
217 | createWrapper(options.success); | |
218 | ||
219 | Proxmox.Utils.API2Request(newopts); | |
220 | }, | |
221 | ||
4b5c6b3f TL |
222 | initComponent: function() { |
223 | let me = this; | |
06694509 DM |
224 | |
225 | if (!me.url) { | |
226 | throw "no url specified"; | |
227 | } | |
228 | ||
b33f451f DC |
229 | if (me.create) {throw "deprecated parameter, use isCreate";} |
230 | ||
4b5c6b3f | 231 | let items = Ext.isArray(me.items) ? me.items : [me.items]; |
06694509 DM |
232 | |
233 | me.items = undefined; | |
234 | ||
235 | me.formPanel = Ext.create('Ext.form.Panel', { | |
236 | url: me.url, | |
237 | method: me.method || 'PUT', | |
238 | trackResetOnLoad: true, | |
271171f8 | 239 | bodyPadding: me.bodyPadding !== undefined ? me.bodyPadding : 10, |
06694509 | 240 | border: false, |
31a50251 | 241 | defaults: Ext.apply({}, me.defaults, { |
4b5c6b3f | 242 | border: false, |
31a50251 | 243 | }), |
06694509 DM |
244 | fieldDefaults: Ext.apply({}, me.fieldDefaults, { |
245 | labelWidth: 100, | |
4b5c6b3f | 246 | anchor: '100%', |
06694509 | 247 | }), |
4b5c6b3f | 248 | items: items, |
06694509 DM |
249 | }); |
250 | ||
4b5c6b3f | 251 | let inputPanel = me.formPanel.down('inputpanel'); |
1b07a95a | 252 | |
4b5c6b3f | 253 | let form = me.formPanel.getForm(); |
06694509 | 254 | |
4b5c6b3f | 255 | let submitText; |
b33f451f | 256 | if (me.isCreate) { |
ffea05ec DC |
257 | if (me.submitText) { |
258 | submitText = me.submitText; | |
259 | } else if (me.isAdd) { | |
06694509 DM |
260 | submitText = gettext('Add'); |
261 | } else if (me.isRemove) { | |
262 | submitText = gettext('Remove'); | |
263 | } else { | |
264 | submitText = gettext('Create'); | |
265 | } | |
266 | } else { | |
ffea05ec | 267 | submitText = me.submitText || gettext('OK'); |
06694509 DM |
268 | } |
269 | ||
4b5c6b3f | 270 | let submitBtn = Ext.create('Ext.Button', { |
a7dcbdeb | 271 | reference: 'submitbutton', |
06694509 | 272 | text: submitText, |
b33f451f | 273 | disabled: !me.isCreate, |
06694509 DM |
274 | handler: function() { |
275 | me.submit(); | |
4b5c6b3f | 276 | }, |
06694509 DM |
277 | }); |
278 | ||
4b5c6b3f | 279 | let resetBtn = Ext.create('Ext.Button', { |
06694509 DM |
280 | text: 'Reset', |
281 | disabled: true, | |
4b5c6b3f | 282 | handler: function() { |
06694509 | 283 | form.reset(); |
4b5c6b3f | 284 | }, |
06694509 DM |
285 | }); |
286 | ||
4b5c6b3f TL |
287 | let set_button_status = function() { |
288 | let valid = form.isValid(); | |
289 | let dirty = form.isDirty(); | |
b33f451f | 290 | submitBtn.setDisabled(!valid || !(dirty || me.isCreate)); |
06694509 | 291 | resetBtn.setDisabled(!dirty); |
880df5d5 DC |
292 | |
293 | if (inputPanel && inputPanel.hasAdvanced) { | |
294 | // we want to show the advanced options | |
295 | // as soon as some of it is not valid | |
4b5c6b3f TL |
296 | let advancedItems = me.down('#advancedContainer').query('field'); |
297 | let allAdvancedValid = true; | |
880df5d5 DC |
298 | advancedItems.forEach(function(field) { |
299 | if (!field.isValid()) { | |
4b5c6b3f | 300 | allAdvancedValid = false; |
880df5d5 DC |
301 | } |
302 | }); | |
303 | ||
4b5c6b3f | 304 | if (!allAdvancedValid) { |
880df5d5 DC |
305 | inputPanel.setAdvancedVisible(true); |
306 | me.down('#advancedcb').setValue(true); | |
307 | } | |
308 | } | |
06694509 DM |
309 | }; |
310 | ||
311 | form.on('dirtychange', set_button_status); | |
312 | form.on('validitychange', set_button_status); | |
313 | ||
4b5c6b3f | 314 | let colwidth = 300; |
06694509 DM |
315 | if (me.fieldDefaults && me.fieldDefaults.labelWidth) { |
316 | colwidth += me.fieldDefaults.labelWidth - 100; | |
317 | } | |
06694509 | 318 | |
4b5c6b3f | 319 | let twoColumn = inputPanel && (inputPanel.column1 || inputPanel.column2); |
06694509 DM |
320 | |
321 | if (me.subject && !me.title) { | |
b33f451f | 322 | me.title = Proxmox.Utils.dialog_title(me.subject, me.isCreate, me.isAdd); |
06694509 DM |
323 | } |
324 | ||
b33f451f | 325 | if (me.isCreate) { |
4b5c6b3f | 326 | me.buttons = [submitBtn]; |
06694509 | 327 | } else { |
4b5c6b3f | 328 | me.buttons = [submitBtn, resetBtn]; |
06694509 DM |
329 | } |
330 | ||
880df5d5 | 331 | if (inputPanel && inputPanel.hasAdvanced) { |
4b5c6b3f TL |
332 | let sp = Ext.state.Manager.getProvider(); |
333 | let advchecked = sp.get('proxmox-advanced-cb'); | |
880df5d5 DC |
334 | inputPanel.setAdvancedVisible(advchecked); |
335 | me.buttons.unshift( | |
336 | { | |
337 | xtype: 'proxmoxcheckbox', | |
338 | itemId: 'advancedcb', | |
339 | boxLabelAlign: 'before', | |
340 | boxLabel: gettext('Advanced'), | |
341 | stateId: 'proxmox-advanced-cb', | |
342 | value: advchecked, | |
343 | listeners: { | |
344 | change: function(cb, val) { | |
345 | inputPanel.setAdvancedVisible(val); | |
346 | sp.set('proxmox-advanced-cb', val); | |
4b5c6b3f TL |
347 | }, |
348 | }, | |
349 | }, | |
880df5d5 DC |
350 | ); |
351 | } | |
352 | ||
4b5c6b3f | 353 | let onlineHelp = me.onlineHelp; |
c3457485 DM |
354 | if (!onlineHelp && inputPanel && inputPanel.onlineHelp) { |
355 | onlineHelp = inputPanel.onlineHelp; | |
356 | } | |
357 | ||
358 | if (onlineHelp) { | |
4b5c6b3f | 359 | let helpButton = Ext.create('Proxmox.button.Help'); |
06694509 | 360 | me.buttons.unshift(helpButton, '->'); |
c3457485 | 361 | Ext.GlobalEvents.fireEvent('proxmoxShowHelp', onlineHelp); |
06694509 DM |
362 | } |
363 | ||
364 | Ext.applyIf(me, { | |
365 | modal: true, | |
366 | width: twoColumn ? colwidth*2 : colwidth, | |
367 | border: false, | |
4b5c6b3f | 368 | items: [me.formPanel], |
06694509 DM |
369 | }); |
370 | ||
371 | me.callParent(); | |
372 | ||
373 | // always mark invalid fields | |
374 | me.on('afterlayout', function() { | |
375 | // on touch devices, the isValid function | |
376 | // triggers a layout, which triggers an isValid | |
377 | // and so on | |
378 | // to prevent this we disable the layouting here | |
379 | // and enable it afterwards | |
380 | me.suspendLayout = true; | |
381 | me.isValid(); | |
382 | me.suspendLayout = false; | |
383 | }); | |
a33ba257 DM |
384 | |
385 | if (me.autoLoad) { | |
386 | me.load(); | |
387 | } | |
4b5c6b3f | 388 | }, |
06694509 | 389 | }); |