]>
Commit | Line | Data |
---|---|---|
787ae72a DM |
1 | /* |
2 | * Workspace base class | |
3 | * | |
4 | * popup login window when auth fails (call onLogin handler) | |
5 | * update (re-login) ticket every 15 minutes | |
6 | * | |
7 | */ | |
8 | ||
9 | Ext.define('PVE.Workspace', { | |
10 | extend: 'Ext.container.Viewport', | |
11 | ||
12 | title: 'Proxmox Virtual Environment', | |
13 | ||
14 | loginData: null, // Data from last login call | |
15 | ||
16 | onLogin: function(loginData) {}, | |
17 | ||
18 | // private | |
19 | updateLoginData: function(loginData) { | |
20 | var me = this; | |
21 | me.loginData = loginData; | |
24d2ed8c | 22 | Proxmox.Utils.setAuthData(loginData); |
787ae72a | 23 | |
3d7b2aa9 TL |
24 | var rt = me.down('pveResourceTree'); |
25 | rt.setDatacenterText(loginData.clustername); | |
9ebe2165 | 26 | PVE.ClusterName = loginData.clustername; |
3d7b2aa9 | 27 | |
787ae72a DM |
28 | if (loginData.cap) { |
29 | Ext.state.Manager.set('GuiCap', loginData.cap); | |
30 | } | |
1370f628 | 31 | me.response401count = 0; |
787ae72a | 32 | |
787ae72a DM |
33 | me.onLogin(loginData); |
34 | }, | |
35 | ||
36 | // private | |
37 | showLogin: function() { | |
38 | var me = this; | |
39 | ||
e7ade592 | 40 | Proxmox.Utils.authClear(); |
9fd1198e | 41 | Ext.state.Manager.clear('GuiCap'); |
35a04562 | 42 | Proxmox.UserName = null; |
787ae72a DM |
43 | me.loginData = null; |
44 | ||
45 | if (!me.login) { | |
46 | me.login = Ext.create('PVE.window.LoginWindow', { | |
47 | handler: function(data) { | |
48 | me.login = null; | |
49 | me.updateLoginData(data); | |
e7ade592 | 50 | Proxmox.Utils.checked_command(function() {}); // display subscription status |
f6710aac | 51 | }, |
787ae72a DM |
52 | }); |
53 | } | |
54 | me.onLogin(null); | |
55 | me.login.show(); | |
56 | }, | |
57 | ||
8058410f | 58 | initComponent: function() { |
787ae72a DM |
59 | var me = this; |
60 | ||
61 | Ext.tip.QuickTipManager.init(); | |
62 | ||
63 | // fixme: what about other errors | |
64 | Ext.Ajax.on('requestexception', function(conn, response, options) { | |
fe13284e | 65 | if (response.status == 401 && !PVE.Utils.silenceAuthFailures) { // auth failure |
1370f628 TL |
66 | // don't immediately show as logged out to cope better with some big |
67 | // upgrades, which may temporarily produce a false positive 401 err | |
68 | me.response401count++; | |
69 | if (me.response401count > 5) { | |
70 | me.showLogin(); | |
71 | } | |
787ae72a DM |
72 | } |
73 | }); | |
74 | ||
787ae72a DM |
75 | me.callParent(); |
76 | ||
e7ade592 | 77 | if (!Proxmox.Utils.authOK()) { |
787ae72a | 78 | me.showLogin(); |
7c8051b4 | 79 | } else { |
787ae72a DM |
80 | if (me.loginData) { |
81 | me.onLogin(me.loginData); | |
82 | } | |
83 | } | |
84 | ||
85 | Ext.TaskManager.start({ | |
86 | run: function() { | |
e7ade592 | 87 | var ticket = Proxmox.Utils.authOK(); |
35a04562 | 88 | if (!ticket || !Proxmox.UserName) { |
787ae72a DM |
89 | return; |
90 | } | |
91 | ||
92 | Ext.Ajax.request({ | |
7c8051b4 | 93 | params: { |
35a04562 | 94 | username: Proxmox.UserName, |
f6710aac | 95 | password: ticket, |
787ae72a DM |
96 | }, |
97 | url: '/api2/json/access/ticket', | |
98 | method: 'POST', | |
99 | success: function(response, opts) { | |
100 | var obj = Ext.decode(response.responseText); | |
101 | me.updateLoginData(obj.data); | |
f6710aac | 102 | }, |
787ae72a DM |
103 | }); |
104 | }, | |
f6710aac | 105 | interval: 15*60*1000, |
787ae72a | 106 | }); |
f6710aac | 107 | }, |
787ae72a DM |
108 | }); |
109 | ||
787ae72a DM |
110 | Ext.define('PVE.StdWorkspace', { |
111 | extend: 'PVE.Workspace', | |
112 | ||
113 | alias: ['widget.pveStdWorkspace'], | |
114 | ||
115 | // private | |
116 | setContent: function(comp) { | |
117 | var me = this; | |
7c8051b4 | 118 | |
787ae72a | 119 | var cont = me.child('#content'); |
834ba9e4 DC |
120 | |
121 | var lay = cont.getLayout(); | |
122 | ||
123 | var cur = lay.getActiveItem(); | |
787ae72a DM |
124 | |
125 | if (comp) { | |
e7ade592 | 126 | Proxmox.Utils.setErrorMask(cont, false); |
787ae72a DM |
127 | comp.border = false; |
128 | cont.add(comp); | |
834ba9e4 DC |
129 | if (cur !== null && lay.getNext()) { |
130 | lay.next(); | |
8058410f | 131 | var task = Ext.create('Ext.util.DelayedTask', function() { |
834ba9e4 DC |
132 | cont.remove(cur); |
133 | }); | |
134 | task.delay(10); | |
135 | } | |
8058410f | 136 | } else { |
de7eeaac EK |
137 | // helper for cleaning the content when logging out |
138 | cont.removeAll(); | |
139 | } | |
787ae72a DM |
140 | }, |
141 | ||
142 | selectById: function(nodeid) { | |
143 | var me = this; | |
144 | var tree = me.down('pveResourceTree'); | |
145 | tree.selectById(nodeid); | |
146 | }, | |
147 | ||
787ae72a DM |
148 | onLogin: function(loginData) { |
149 | var me = this; | |
150 | ||
151 | me.updateUserInfo(); | |
152 | ||
153 | if (loginData) { | |
154 | PVE.data.ResourceStore.startUpdate(); | |
155 | ||
e7ade592 | 156 | Proxmox.Utils.API2Request({ |
787ae72a DM |
157 | url: '/version', |
158 | method: 'GET', | |
159 | success: function(response) { | |
160 | PVE.VersionInfo = response.result.data; | |
161 | me.updateVersionInfo(); | |
f6710aac | 162 | }, |
787ae72a | 163 | }); |
f1ca55fb AD |
164 | |
165 | Proxmox.Utils.API2Request({ | |
166 | url: '/cluster/sdn', | |
167 | method: 'GET', | |
168 | success: function(response) { | |
169 | PVE.SDNInfo = response.result.data; | |
35ffde01 TL |
170 | }, |
171 | failure: function(response) { | |
172 | PVE.SDNInfo = null; | |
173 | let ui = Ext.ComponentQuery.query('treelistitem[text="SDN"]')[0]; | |
174 | if (ui) { | |
175 | ui.addCls('x-hidden-display'); | |
176 | } | |
177 | }, | |
f1ca55fb | 178 | }); |
787ae72a DM |
179 | } |
180 | }, | |
181 | ||
182 | updateUserInfo: function() { | |
183 | var me = this; | |
787ae72a | 184 | var ui = me.query('#userinfo')[0]; |
1011b569 | 185 | ui.setText(Ext.String.htmlEncode(Proxmox.UserName || '')); |
6a71fe01 | 186 | ui.updateLayout(); |
787ae72a DM |
187 | }, |
188 | ||
189 | updateVersionInfo: function() { | |
190 | var me = this; | |
191 | ||
192 | var ui = me.query('#versioninfo')[0]; | |
193 | ||
194 | if (PVE.VersionInfo) { | |
180a86d3 | 195 | var version = PVE.VersionInfo.version; |
55d727ca | 196 | ui.update('Virtual Environment ' + version); |
787ae72a | 197 | } else { |
55d727ca | 198 | ui.update('Virtual Environment'); |
787ae72a | 199 | } |
6a71fe01 | 200 | ui.updateLayout(); |
787ae72a DM |
201 | }, |
202 | ||
8058410f | 203 | initComponent: function() { |
787ae72a DM |
204 | var me = this; |
205 | ||
206 | Ext.History.init(); | |
207 | ||
208 | var sprovider = Ext.create('PVE.StateProvider'); | |
209 | Ext.state.Manager.setProvider(sprovider); | |
210 | ||
aeb5e2f6 | 211 | var selview = Ext.create('PVE.form.ViewSelector'); |
787ae72a DM |
212 | |
213 | var rtree = Ext.createWidget('pveResourceTree', { | |
214 | viewFilter: selview.getViewFilter(), | |
215 | flex: 1, | |
aeb5e2f6 EK |
216 | selModel: { |
217 | selType: 'treemodel', | |
787ae72a DM |
218 | listeners: { |
219 | selectionchange: function(sm, selected) { | |
787ae72a DM |
220 | if (selected.length > 0) { |
221 | var n = selected[0]; | |
f184350f EK |
222 | var tlckup = { |
223 | root: 'PVE.dc.Config', | |
224 | node: 'PVE.node.Config', | |
225 | qemu: 'PVE.qemu.Config', | |
226 | lxc: 'PVE.lxc.Config', | |
227 | storage: 'PVE.storage.Browser', | |
9233148b | 228 | sdn: 'PVE.sdn.Browser', |
f6710aac | 229 | pool: 'pvePoolConfig', |
f184350f EK |
230 | }; |
231 | var comp = { | |
7c8051b4 | 232 | xtype: tlckup[n.data.type || 'root'] || |
787ae72a | 233 | 'pvePanelConfig', |
787ae72a DM |
234 | showSearch: (n.data.id === 'root') || |
235 | Ext.isDefined(n.data.groupbyid), | |
236 | pveSelNode: n, | |
237 | workspace: me, | |
f6710aac | 238 | viewFilter: selview.getViewFilter(), |
787ae72a DM |
239 | }; |
240 | PVE.curSelectedNode = n; | |
f184350f | 241 | me.setContent(comp); |
787ae72a | 242 | } |
f6710aac TL |
243 | }, |
244 | }, | |
245 | }, | |
787ae72a DM |
246 | }); |
247 | ||
7c8051b4 | 248 | selview.on('select', function(combo, records) { |
fb387756 | 249 | if (records) { |
787ae72a DM |
250 | var view = combo.getViewFilter(); |
251 | rtree.setViewFilter(view); | |
252 | } | |
253 | }); | |
254 | ||
255 | var caps = sprovider.get('GuiCap'); | |
256 | ||
257 | var createVM = Ext.createWidget('button', { | |
258 | pack: 'end', | |
f01259ee | 259 | margin: '3 5 0 0', |
787ae72a | 260 | baseCls: 'x-btn', |
d1f155b8 | 261 | iconCls: 'fa fa-desktop', |
787ae72a DM |
262 | text: gettext("Create VM"), |
263 | disabled: !caps.vms['VM.Allocate'], | |
264 | handler: function() { | |
265 | var wiz = Ext.create('PVE.qemu.CreateWizard', {}); | |
266 | wiz.show(); | |
f6710aac | 267 | }, |
787ae72a DM |
268 | }); |
269 | ||
270 | var createCT = Ext.createWidget('button', { | |
271 | pack: 'end', | |
f01259ee | 272 | margin: '3 5 0 0', |
787ae72a | 273 | baseCls: 'x-btn', |
d1f155b8 | 274 | iconCls: 'fa fa-cube', |
787ae72a DM |
275 | text: gettext("Create CT"), |
276 | disabled: !caps.vms['VM.Allocate'], | |
277 | handler: function() { | |
278 | var wiz = Ext.create('PVE.lxc.CreateWizard', {}); | |
279 | wiz.show(); | |
f6710aac | 280 | }, |
787ae72a DM |
281 | }); |
282 | ||
283 | sprovider.on('statechange', function(sp, key, value) { | |
284 | if (key === 'GuiCap' && value) { | |
285 | caps = value; | |
286 | createVM.setDisabled(!caps.vms['VM.Allocate']); | |
287 | createCT.setDisabled(!caps.vms['VM.Allocate']); | |
288 | } | |
289 | }); | |
290 | ||
291 | Ext.apply(me, { | |
292 | layout: { type: 'border' }, | |
293 | border: false, | |
294 | items: [ | |
295 | { | |
296 | region: 'north', | |
7c8051b4 | 297 | layout: { |
787ae72a | 298 | type: 'hbox', |
f6710aac | 299 | align: 'middle', |
787ae72a | 300 | }, |
7c8051b4 | 301 | baseCls: 'x-plain', |
787ae72a | 302 | defaults: { |
f6710aac | 303 | baseCls: 'x-plain', |
787ae72a DM |
304 | }, |
305 | border: false, | |
f76884fd | 306 | margin: '2 0 2 5', |
787ae72a DM |
307 | items: [ |
308 | { | |
d1efcadf | 309 | xtype: 'proxmoxlogo', |
787ae72a DM |
310 | }, |
311 | { | |
bbcfa5ab | 312 | minWidth: 150, |
787ae72a | 313 | id: 'versioninfo', |
f6710aac | 314 | html: 'Virtual Environment', |
787ae72a | 315 | }, |
839eed58 DC |
316 | { |
317 | xtype: 'pveGlobalSearchField', | |
f6710aac | 318 | tree: rtree, |
839eed58 DC |
319 | }, |
320 | { | |
f6710aac | 321 | flex: 1, |
839eed58 | 322 | }, |
3ef58611 | 323 | { |
672a6270 | 324 | xtype: 'proxmoxHelpButton', |
3ef58611 | 325 | hidden: false, |
1e4a853c | 326 | baseCls: 'x-btn', |
41e024ee | 327 | iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ', |
3ef58611 | 328 | listenToGlobalEvent: false, |
c8802a60 | 329 | onlineHelp: 'pve_documentation_index', |
41e024ee | 330 | text: gettext('Documentation'), |
f6710aac | 331 | margin: '0 5 0 0', |
3ef58611 | 332 | }, |
7c8051b4 | 333 | createVM, |
6a7465ae | 334 | createCT, |
787ae72a DM |
335 | { |
336 | pack: 'end', | |
f76884fd | 337 | margin: '0 5 0 0', |
d962846d | 338 | id: 'userinfo', |
787ae72a DM |
339 | xtype: 'button', |
340 | baseCls: 'x-btn', | |
404bf6c8 TL |
341 | style: { |
342 | // proxmox dark grey p light grey as border | |
343 | backgroundColor: '#464d4d', | |
f6710aac | 344 | borderColor: '#ABBABA', |
404bf6c8 | 345 | }, |
d962846d DC |
346 | iconCls: 'fa fa-user', |
347 | menu: [ | |
348 | { | |
349 | iconCls: 'fa fa-gear', | |
350 | text: gettext('My Settings'), | |
351 | handler: function() { | |
352 | var win = Ext.create('PVE.window.Settings'); | |
353 | win.show(); | |
f6710aac | 354 | }, |
d962846d DC |
355 | }, |
356 | { | |
357 | text: gettext('Password'), | |
358 | iconCls: 'fa fa-fw fa-key', | |
359 | handler: function() { | |
360 | var win = Ext.create('Proxmox.window.PasswordEdit', { | |
f6710aac | 361 | userid: Proxmox.UserName, |
d962846d DC |
362 | }); |
363 | win.show(); | |
f6710aac | 364 | }, |
d962846d DC |
365 | }, |
366 | { | |
367 | text: 'TFA', | |
368 | iconCls: 'fa fa-fw fa-lock', | |
369 | handler: function(btn, event, rec) { | |
f6710aac TL |
370 | var win = Ext.create('PVE.window.TFAEdit', { |
371 | userid: Proxmox.UserName, | |
d962846d DC |
372 | }); |
373 | win.show(); | |
f6710aac | 374 | }, |
d962846d | 375 | }, |
428d5e78 DC |
376 | { |
377 | iconCls: 'fa fa-language', | |
378 | text: gettext('Language'), | |
379 | handler: function() { | |
380 | Ext.create('Proxmox.window.LanguageEditWindow') | |
381 | .show(); | |
382 | }, | |
383 | }, | |
d962846d DC |
384 | '-', |
385 | { | |
386 | iconCls: 'fa fa-fw fa-sign-out', | |
387 | text: gettext("Logout"), | |
388 | handler: function() { | |
389 | PVE.data.ResourceStore.loadData([], false); | |
390 | me.showLogin(); | |
391 | me.setContent(null); | |
392 | var rt = me.down('pveResourceTree'); | |
393 | rt.setDatacenterText(undefined); | |
394 | rt.clearTree(); | |
395 | ||
396 | // empty the stores of the StatusPanel child items | |
397 | var statusPanels = Ext.ComponentQuery.query('pveStatusPanel grid'); | |
398 | Ext.Array.forEach(statusPanels, function(comp) { | |
399 | if (comp.getStore()) { | |
400 | comp.getStore().loadData([], false); | |
401 | } | |
402 | }); | |
f6710aac TL |
403 | }, |
404 | }, | |
405 | ], | |
406 | }, | |
407 | ], | |
787ae72a DM |
408 | }, |
409 | { | |
410 | region: 'center', | |
29aedb75 DC |
411 | stateful: true, |
412 | stateId: 'pvecenter', | |
413 | minWidth: 100, | |
414 | minHeight: 100, | |
787ae72a DM |
415 | id: 'content', |
416 | xtype: 'container', | |
834ba9e4 | 417 | layout: { type: 'card' }, |
787ae72a | 418 | border: false, |
f01259ee | 419 | margin: '0 5 0 0', |
f6710aac | 420 | items: [], |
787ae72a DM |
421 | }, |
422 | { | |
423 | region: 'west', | |
29aedb75 DC |
424 | stateful: true, |
425 | stateId: 'pvewest', | |
426 | itemId: 'west', | |
787ae72a DM |
427 | xtype: 'container', |
428 | border: false, | |
429 | layout: { type: 'vbox', align: 'stretch' }, | |
f01259ee | 430 | margin: '0 0 0 5', |
787ae72a DM |
431 | split: true, |
432 | width: 200, | |
8058410f | 433 | items: [selview, rtree], |
29aedb75 DC |
434 | listeners: { |
435 | resize: function(panel, width, height) { | |
436 | var viewWidth = me.getSize().width; | |
437 | if (width > viewWidth - 100) { | |
438 | panel.setWidth(viewWidth - 100); | |
439 | } | |
f6710aac TL |
440 | }, |
441 | }, | |
787ae72a DM |
442 | }, |
443 | { | |
80e8b725 | 444 | xtype: 'pveStatusPanel', |
29aedb75 DC |
445 | stateful: true, |
446 | stateId: 'pvesouth', | |
447 | itemId: 'south', | |
787ae72a | 448 | region: 'south', |
8058410f | 449 | margin: '0 5 5 5', |
6a87871f DC |
450 | title: gettext('Logs'), |
451 | collapsible: true, | |
452 | header: false, | |
29aedb75 | 453 | height: 200, |
8058410f | 454 | split: true, |
29aedb75 DC |
455 | listeners: { |
456 | resize: function(panel, width, height) { | |
29aedb75 DC |
457 | var viewHeight = me.getSize().height; |
458 | if (height > (viewHeight - 150)) { | |
459 | panel.setHeight(viewHeight - 150); | |
460 | } | |
f6710aac TL |
461 | }, |
462 | }, | |
463 | }, | |
464 | ], | |
787ae72a DM |
465 | }); |
466 | ||
467 | me.callParent(); | |
468 | ||
469 | me.updateUserInfo(); | |
6c18be66 DC |
470 | |
471 | // on resize, center all modal windows | |
8058410f | 472 | Ext.on('resize', function() { |
6c18be66 DC |
473 | var wins = Ext.ComponentQuery.query('window[modal]'); |
474 | if (wins.length > 0) { | |
8058410f | 475 | wins.forEach(function(win) { |
6c18be66 DC |
476 | win.alignTo(me, 'c-c'); |
477 | }); | |
478 | } | |
479 | }); | |
f6710aac | 480 | }, |
787ae72a DM |
481 | }); |
482 |