]>
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; | |
35a04562 DC |
22 | Proxmox.CSRFPreventionToken = loginData.CSRFPreventionToken; |
23 | Proxmox.UserName = loginData.username; | |
787ae72a DM |
24 | |
25 | if (loginData.cap) { | |
26 | Ext.state.Manager.set('GuiCap', loginData.cap); | |
27 | } | |
28 | ||
29 | // creates a session cookie (expire = null) | |
30 | // that way the cookie gets deleted after browser window close | |
31 | Ext.util.Cookies.set('PVEAuthCookie', loginData.ticket, null, '/', null, true); | |
32 | me.onLogin(loginData); | |
33 | }, | |
34 | ||
35 | // private | |
36 | showLogin: function() { | |
37 | var me = this; | |
38 | ||
e7ade592 | 39 | Proxmox.Utils.authClear(); |
35a04562 | 40 | Proxmox.UserName = null; |
787ae72a DM |
41 | me.loginData = null; |
42 | ||
43 | if (!me.login) { | |
44 | me.login = Ext.create('PVE.window.LoginWindow', { | |
45 | handler: function(data) { | |
46 | me.login = null; | |
47 | me.updateLoginData(data); | |
e7ade592 | 48 | Proxmox.Utils.checked_command(function() {}); // display subscription status |
787ae72a DM |
49 | } |
50 | }); | |
51 | } | |
52 | me.onLogin(null); | |
53 | me.login.show(); | |
54 | }, | |
55 | ||
56 | initComponent : function() { | |
57 | var me = this; | |
58 | ||
59 | Ext.tip.QuickTipManager.init(); | |
60 | ||
61 | // fixme: what about other errors | |
62 | Ext.Ajax.on('requestexception', function(conn, response, options) { | |
fe13284e | 63 | if (response.status == 401 && !PVE.Utils.silenceAuthFailures) { // auth failure |
787ae72a DM |
64 | me.showLogin(); |
65 | } | |
66 | }); | |
67 | ||
787ae72a DM |
68 | me.callParent(); |
69 | ||
e7ade592 | 70 | if (!Proxmox.Utils.authOK()) { |
787ae72a DM |
71 | me.showLogin(); |
72 | } else { | |
73 | if (me.loginData) { | |
74 | me.onLogin(me.loginData); | |
75 | } | |
76 | } | |
77 | ||
78 | Ext.TaskManager.start({ | |
79 | run: function() { | |
e7ade592 | 80 | var ticket = Proxmox.Utils.authOK(); |
35a04562 | 81 | if (!ticket || !Proxmox.UserName) { |
787ae72a DM |
82 | return; |
83 | } | |
84 | ||
85 | Ext.Ajax.request({ | |
86 | params: { | |
35a04562 | 87 | username: Proxmox.UserName, |
787ae72a DM |
88 | password: ticket |
89 | }, | |
90 | url: '/api2/json/access/ticket', | |
91 | method: 'POST', | |
92 | success: function(response, opts) { | |
93 | var obj = Ext.decode(response.responseText); | |
94 | me.updateLoginData(obj.data); | |
95 | } | |
96 | }); | |
97 | }, | |
98 | interval: 15*60*1000 | |
99 | }); | |
100 | ||
101 | } | |
102 | }); | |
103 | ||
787ae72a DM |
104 | Ext.define('PVE.StdWorkspace', { |
105 | extend: 'PVE.Workspace', | |
106 | ||
107 | alias: ['widget.pveStdWorkspace'], | |
108 | ||
109 | // private | |
110 | setContent: function(comp) { | |
111 | var me = this; | |
112 | ||
113 | var cont = me.child('#content'); | |
834ba9e4 DC |
114 | |
115 | var lay = cont.getLayout(); | |
116 | ||
117 | var cur = lay.getActiveItem(); | |
787ae72a DM |
118 | |
119 | if (comp) { | |
e7ade592 | 120 | Proxmox.Utils.setErrorMask(cont, false); |
787ae72a DM |
121 | comp.border = false; |
122 | cont.add(comp); | |
834ba9e4 DC |
123 | if (cur !== null && lay.getNext()) { |
124 | lay.next(); | |
125 | var task = Ext.create('Ext.util.DelayedTask', function(){ | |
126 | cont.remove(cur); | |
127 | }); | |
128 | task.delay(10); | |
129 | } | |
130 | } | |
de7eeaac EK |
131 | else { |
132 | // helper for cleaning the content when logging out | |
133 | cont.removeAll(); | |
134 | } | |
787ae72a DM |
135 | }, |
136 | ||
137 | selectById: function(nodeid) { | |
138 | var me = this; | |
139 | var tree = me.down('pveResourceTree'); | |
140 | tree.selectById(nodeid); | |
141 | }, | |
142 | ||
787ae72a DM |
143 | onLogin: function(loginData) { |
144 | var me = this; | |
145 | ||
146 | me.updateUserInfo(); | |
147 | ||
148 | if (loginData) { | |
149 | PVE.data.ResourceStore.startUpdate(); | |
150 | ||
e7ade592 | 151 | Proxmox.Utils.API2Request({ |
787ae72a DM |
152 | url: '/version', |
153 | method: 'GET', | |
154 | success: function(response) { | |
155 | PVE.VersionInfo = response.result.data; | |
156 | me.updateVersionInfo(); | |
157 | } | |
158 | }); | |
159 | } | |
160 | }, | |
161 | ||
162 | updateUserInfo: function() { | |
163 | var me = this; | |
164 | ||
165 | var ui = me.query('#userinfo')[0]; | |
166 | ||
35a04562 DC |
167 | if (Proxmox.UserName) { |
168 | var msg = Ext.String.format(gettext("You are logged in as {0}"), "'" + Proxmox.UserName + "'"); | |
787ae72a DM |
169 | ui.update('<div class="x-unselectable" style="white-space:nowrap;">' + msg + '</div>'); |
170 | } else { | |
171 | ui.update(''); | |
172 | } | |
6a71fe01 | 173 | ui.updateLayout(); |
787ae72a DM |
174 | }, |
175 | ||
176 | updateVersionInfo: function() { | |
177 | var me = this; | |
178 | ||
179 | var ui = me.query('#versioninfo')[0]; | |
180 | ||
181 | if (PVE.VersionInfo) { | |
2ddb0726 | 182 | var version = PVE.VersionInfo.version + '-' + PVE.VersionInfo.release; |
55d727ca | 183 | ui.update('Virtual Environment ' + version); |
787ae72a | 184 | } else { |
55d727ca | 185 | ui.update('Virtual Environment'); |
787ae72a | 186 | } |
6a71fe01 | 187 | ui.updateLayout(); |
787ae72a DM |
188 | }, |
189 | ||
190 | initComponent : function() { | |
191 | var me = this; | |
192 | ||
193 | Ext.History.init(); | |
194 | ||
195 | var sprovider = Ext.create('PVE.StateProvider'); | |
196 | Ext.state.Manager.setProvider(sprovider); | |
197 | ||
aeb5e2f6 | 198 | var selview = Ext.create('PVE.form.ViewSelector'); |
787ae72a DM |
199 | |
200 | var rtree = Ext.createWidget('pveResourceTree', { | |
201 | viewFilter: selview.getViewFilter(), | |
202 | flex: 1, | |
aeb5e2f6 EK |
203 | selModel: { |
204 | selType: 'treemodel', | |
787ae72a DM |
205 | listeners: { |
206 | selectionchange: function(sm, selected) { | |
787ae72a DM |
207 | if (selected.length > 0) { |
208 | var n = selected[0]; | |
f184350f EK |
209 | var tlckup = { |
210 | root: 'PVE.dc.Config', | |
211 | node: 'PVE.node.Config', | |
212 | qemu: 'PVE.qemu.Config', | |
213 | lxc: 'PVE.lxc.Config', | |
214 | storage: 'PVE.storage.Browser', | |
215 | pool: 'pvePoolConfig' | |
216 | }; | |
217 | var comp = { | |
787ae72a DM |
218 | xtype: tlckup[n.data.type || 'root'] || |
219 | 'pvePanelConfig', | |
787ae72a DM |
220 | showSearch: (n.data.id === 'root') || |
221 | Ext.isDefined(n.data.groupbyid), | |
222 | pveSelNode: n, | |
223 | workspace: me, | |
224 | viewFilter: selview.getViewFilter() | |
225 | }; | |
226 | PVE.curSelectedNode = n; | |
f184350f | 227 | me.setContent(comp); |
787ae72a | 228 | } |
787ae72a DM |
229 | } |
230 | } | |
aeb5e2f6 | 231 | } |
787ae72a DM |
232 | }); |
233 | ||
234 | selview.on('select', function(combo, records) { | |
fb387756 | 235 | if (records) { |
787ae72a DM |
236 | var view = combo.getViewFilter(); |
237 | rtree.setViewFilter(view); | |
238 | } | |
239 | }); | |
240 | ||
241 | var caps = sprovider.get('GuiCap'); | |
242 | ||
243 | var createVM = Ext.createWidget('button', { | |
244 | pack: 'end', | |
f01259ee | 245 | margin: '3 5 0 0', |
787ae72a | 246 | baseCls: 'x-btn', |
d1f155b8 | 247 | iconCls: 'fa fa-desktop', |
787ae72a DM |
248 | text: gettext("Create VM"), |
249 | disabled: !caps.vms['VM.Allocate'], | |
250 | handler: function() { | |
251 | var wiz = Ext.create('PVE.qemu.CreateWizard', {}); | |
252 | wiz.show(); | |
253 | } | |
254 | }); | |
255 | ||
256 | var createCT = Ext.createWidget('button', { | |
257 | pack: 'end', | |
f01259ee | 258 | margin: '3 5 0 0', |
787ae72a | 259 | baseCls: 'x-btn', |
d1f155b8 | 260 | iconCls: 'fa fa-cube', |
787ae72a DM |
261 | text: gettext("Create CT"), |
262 | disabled: !caps.vms['VM.Allocate'], | |
263 | handler: function() { | |
264 | var wiz = Ext.create('PVE.lxc.CreateWizard', {}); | |
265 | wiz.show(); | |
266 | } | |
267 | }); | |
268 | ||
269 | sprovider.on('statechange', function(sp, key, value) { | |
270 | if (key === 'GuiCap' && value) { | |
271 | caps = value; | |
272 | createVM.setDisabled(!caps.vms['VM.Allocate']); | |
273 | createCT.setDisabled(!caps.vms['VM.Allocate']); | |
274 | } | |
275 | }); | |
276 | ||
277 | Ext.apply(me, { | |
278 | layout: { type: 'border' }, | |
279 | border: false, | |
280 | items: [ | |
281 | { | |
282 | region: 'north', | |
787ae72a DM |
283 | layout: { |
284 | type: 'hbox', | |
f76884fd | 285 | align: 'middle' |
787ae72a DM |
286 | }, |
287 | baseCls: 'x-plain', | |
288 | defaults: { | |
289 | baseCls: 'x-plain' | |
290 | }, | |
291 | border: false, | |
f76884fd | 292 | margin: '2 0 2 5', |
787ae72a DM |
293 | items: [ |
294 | { | |
787ae72a | 295 | html: '<a class="x-unselectable" target=_blank href="http://www.proxmox.com">' + |
55d727ca | 296 | '<img style="padding-top:4px;padding-right:5px" src="/pve2/images/proxmox_logo.png"/></a>' |
787ae72a DM |
297 | }, |
298 | { | |
bbcfa5ab | 299 | minWidth: 150, |
787ae72a | 300 | id: 'versioninfo', |
55d727ca | 301 | html: 'Virtual Environment' |
787ae72a | 302 | }, |
839eed58 DC |
303 | { |
304 | xtype: 'pveGlobalSearchField', | |
305 | tree: rtree | |
306 | }, | |
307 | { | |
308 | flex: 1 | |
309 | }, | |
787ae72a DM |
310 | { |
311 | pack: 'end', | |
787ae72a DM |
312 | id: 'userinfo', |
313 | stateful: false | |
314 | }, | |
ce11a8af DC |
315 | { |
316 | xtype: 'button', | |
d0cbdb2b DC |
317 | margin: '0 10 0 3', |
318 | iconCls: 'fa black fa-gear', | |
c359b437 | 319 | userCls: 'pointer', |
d0cbdb2b DC |
320 | handler: function() { |
321 | var win = Ext.create('PVE.window.Settings'); | |
322 | win.show(); | |
ce11a8af DC |
323 | } |
324 | }, | |
3ef58611 | 325 | { |
672a6270 | 326 | xtype: 'proxmoxHelpButton', |
3ef58611 | 327 | hidden: false, |
1e4a853c | 328 | baseCls: 'x-btn', |
41e024ee | 329 | iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ', |
3ef58611 | 330 | listenToGlobalEvent: false, |
c8802a60 | 331 | onlineHelp: 'pve_documentation_index', |
41e024ee | 332 | text: gettext('Documentation'), |
3ef58611 DC |
333 | margin: '0 5 0 0' |
334 | }, | |
6a7465ae EK |
335 | createVM, |
336 | createCT, | |
787ae72a DM |
337 | { |
338 | pack: 'end', | |
f76884fd | 339 | margin: '0 5 0 0', |
787ae72a DM |
340 | xtype: 'button', |
341 | baseCls: 'x-btn', | |
d1f155b8 | 342 | iconCls: 'fa fa-sign-out', |
787ae72a DM |
343 | text: gettext("Logout"), |
344 | handler: function() { | |
de7eeaac | 345 | PVE.data.ResourceStore.loadData([], false); |
787ae72a | 346 | me.showLogin(); |
de7eeaac | 347 | me.setContent(null); |
787ae72a DM |
348 | var rt = me.down('pveResourceTree'); |
349 | rt.clearTree(); | |
de7eeaac EK |
350 | |
351 | // empty the stores of the StatusPanel child items | |
352 | var statusPanels = Ext.ComponentQuery.query('pveStatusPanel grid'); | |
353 | Ext.Array.forEach(statusPanels, function(comp) { | |
354 | if (comp.getStore()) { | |
355 | comp.getStore().loadData([], false); | |
356 | } | |
357 | }); | |
787ae72a | 358 | } |
6a7465ae | 359 | } |
787ae72a DM |
360 | ] |
361 | }, | |
362 | { | |
363 | region: 'center', | |
29aedb75 DC |
364 | stateful: true, |
365 | stateId: 'pvecenter', | |
366 | minWidth: 100, | |
367 | minHeight: 100, | |
787ae72a DM |
368 | id: 'content', |
369 | xtype: 'container', | |
834ba9e4 | 370 | layout: { type: 'card' }, |
787ae72a | 371 | border: false, |
f01259ee | 372 | margin: '0 5 0 0', |
787ae72a DM |
373 | items: [] |
374 | }, | |
375 | { | |
376 | region: 'west', | |
29aedb75 DC |
377 | stateful: true, |
378 | stateId: 'pvewest', | |
379 | itemId: 'west', | |
787ae72a DM |
380 | xtype: 'container', |
381 | border: false, | |
382 | layout: { type: 'vbox', align: 'stretch' }, | |
f01259ee | 383 | margin: '0 0 0 5', |
787ae72a DM |
384 | split: true, |
385 | width: 200, | |
29aedb75 DC |
386 | items: [ selview, rtree ], |
387 | listeners: { | |
388 | resize: function(panel, width, height) { | |
389 | var viewWidth = me.getSize().width; | |
390 | if (width > viewWidth - 100) { | |
391 | panel.setWidth(viewWidth - 100); | |
392 | } | |
393 | } | |
394 | } | |
787ae72a DM |
395 | }, |
396 | { | |
80e8b725 | 397 | xtype: 'pveStatusPanel', |
29aedb75 DC |
398 | stateful: true, |
399 | stateId: 'pvesouth', | |
400 | itemId: 'south', | |
787ae72a | 401 | region: 'south', |
f01259ee | 402 | margin:'0 5 5 5', |
6a87871f DC |
403 | title: gettext('Logs'), |
404 | collapsible: true, | |
405 | header: false, | |
29aedb75 DC |
406 | height: 200, |
407 | split:true, | |
408 | listeners: { | |
409 | resize: function(panel, width, height) { | |
29aedb75 DC |
410 | var viewHeight = me.getSize().height; |
411 | if (height > (viewHeight - 150)) { | |
412 | panel.setHeight(viewHeight - 150); | |
413 | } | |
414 | } | |
415 | } | |
787ae72a DM |
416 | } |
417 | ] | |
418 | }); | |
419 | ||
420 | me.callParent(); | |
421 | ||
422 | me.updateUserInfo(); | |
6c18be66 DC |
423 | |
424 | // on resize, center all modal windows | |
425 | Ext.on('resize', function(){ | |
426 | var wins = Ext.ComponentQuery.query('window[modal]'); | |
427 | if (wins.length > 0) { | |
428 | wins.forEach(function(win){ | |
429 | win.alignTo(me, 'c-c'); | |
430 | }); | |
431 | } | |
432 | }); | |
787ae72a DM |
433 | } |
434 | }); | |
435 |