pve-manager/www/manager6/Workspace.js
Thomas Lamprecht 35ffde01f0 followup sdn: move a bit below and fix showing on initial load
if the webinterface got loaded the api call to check if SDN is
available did not yet returned, so we could show it by accident -
even if libpve-network-perl wasn't instralled.
Fix that by hiding it (once) in the failure callback of the API call.

also move menu entries below, before Firewall, this fits better to
networking.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2020-03-26 15:21:13 +01:00

476 lines
10 KiB
JavaScript

/*
* Workspace base class
*
* popup login window when auth fails (call onLogin handler)
* update (re-login) ticket every 15 minutes
*
*/
Ext.define('PVE.Workspace', {
extend: 'Ext.container.Viewport',
title: 'Proxmox Virtual Environment',
loginData: null, // Data from last login call
onLogin: function(loginData) {},
// private
updateLoginData: function(loginData) {
var me = this;
me.loginData = loginData;
Proxmox.Utils.setAuthData(loginData);
var rt = me.down('pveResourceTree');
rt.setDatacenterText(loginData.clustername);
if (loginData.cap) {
Ext.state.Manager.set('GuiCap', loginData.cap);
}
me.response401count = 0;
me.onLogin(loginData);
},
// private
showLogin: function() {
var me = this;
Proxmox.Utils.authClear();
Proxmox.UserName = null;
me.loginData = null;
if (!me.login) {
me.login = Ext.create('PVE.window.LoginWindow', {
handler: function(data) {
me.login = null;
me.updateLoginData(data);
Proxmox.Utils.checked_command(function() {}); // display subscription status
}
});
}
me.onLogin(null);
me.login.show();
},
initComponent : function() {
var me = this;
Ext.tip.QuickTipManager.init();
// fixme: what about other errors
Ext.Ajax.on('requestexception', function(conn, response, options) {
if (response.status == 401 && !PVE.Utils.silenceAuthFailures) { // auth failure
// don't immediately show as logged out to cope better with some big
// upgrades, which may temporarily produce a false positive 401 err
me.response401count++;
if (me.response401count > 5) {
me.showLogin();
}
}
});
me.callParent();
if (!Proxmox.Utils.authOK()) {
me.showLogin();
} else {
if (me.loginData) {
me.onLogin(me.loginData);
}
}
Ext.TaskManager.start({
run: function() {
var ticket = Proxmox.Utils.authOK();
if (!ticket || !Proxmox.UserName) {
return;
}
Ext.Ajax.request({
params: {
username: Proxmox.UserName,
password: ticket
},
url: '/api2/json/access/ticket',
method: 'POST',
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
me.updateLoginData(obj.data);
}
});
},
interval: 15*60*1000
});
}
});
Ext.define('PVE.StdWorkspace', {
extend: 'PVE.Workspace',
alias: ['widget.pveStdWorkspace'],
// private
setContent: function(comp) {
var me = this;
var cont = me.child('#content');
var lay = cont.getLayout();
var cur = lay.getActiveItem();
if (comp) {
Proxmox.Utils.setErrorMask(cont, false);
comp.border = false;
cont.add(comp);
if (cur !== null && lay.getNext()) {
lay.next();
var task = Ext.create('Ext.util.DelayedTask', function(){
cont.remove(cur);
});
task.delay(10);
}
}
else {
// helper for cleaning the content when logging out
cont.removeAll();
}
},
selectById: function(nodeid) {
var me = this;
var tree = me.down('pveResourceTree');
tree.selectById(nodeid);
},
onLogin: function(loginData) {
var me = this;
me.updateUserInfo();
if (loginData) {
PVE.data.ResourceStore.startUpdate();
Proxmox.Utils.API2Request({
url: '/version',
method: 'GET',
success: function(response) {
PVE.VersionInfo = response.result.data;
me.updateVersionInfo();
}
});
Proxmox.Utils.API2Request({
url: '/cluster/sdn',
method: 'GET',
success: function(response) {
PVE.SDNInfo = response.result.data;
},
failure: function(response) {
PVE.SDNInfo = null;
let ui = Ext.ComponentQuery.query('treelistitem[text="SDN"]')[0];
if (ui) {
ui.addCls('x-hidden-display');
}
},
});
}
},
updateUserInfo: function() {
var me = this;
var ui = me.query('#userinfo')[0];
ui.setText(Proxmox.UserName || '');
ui.updateLayout();
},
updateVersionInfo: function() {
var me = this;
var ui = me.query('#versioninfo')[0];
if (PVE.VersionInfo) {
var version = PVE.VersionInfo.version;
ui.update('Virtual Environment ' + version);
} else {
ui.update('Virtual Environment');
}
ui.updateLayout();
},
initComponent : function() {
var me = this;
Ext.History.init();
var sprovider = Ext.create('PVE.StateProvider');
Ext.state.Manager.setProvider(sprovider);
var selview = Ext.create('PVE.form.ViewSelector');
var rtree = Ext.createWidget('pveResourceTree', {
viewFilter: selview.getViewFilter(),
flex: 1,
selModel: {
selType: 'treemodel',
listeners: {
selectionchange: function(sm, selected) {
if (selected.length > 0) {
var n = selected[0];
var tlckup = {
root: 'PVE.dc.Config',
node: 'PVE.node.Config',
qemu: 'PVE.qemu.Config',
lxc: 'PVE.lxc.Config',
storage: 'PVE.storage.Browser',
sdn: 'PVE.sdn.Browser',
pool: 'pvePoolConfig'
};
var comp = {
xtype: tlckup[n.data.type || 'root'] ||
'pvePanelConfig',
showSearch: (n.data.id === 'root') ||
Ext.isDefined(n.data.groupbyid),
pveSelNode: n,
workspace: me,
viewFilter: selview.getViewFilter()
};
PVE.curSelectedNode = n;
me.setContent(comp);
}
}
}
}
});
selview.on('select', function(combo, records) {
if (records) {
var view = combo.getViewFilter();
rtree.setViewFilter(view);
}
});
var caps = sprovider.get('GuiCap');
var createVM = Ext.createWidget('button', {
pack: 'end',
margin: '3 5 0 0',
baseCls: 'x-btn',
iconCls: 'fa fa-desktop',
text: gettext("Create VM"),
disabled: !caps.vms['VM.Allocate'],
handler: function() {
var wiz = Ext.create('PVE.qemu.CreateWizard', {});
wiz.show();
}
});
var createCT = Ext.createWidget('button', {
pack: 'end',
margin: '3 5 0 0',
baseCls: 'x-btn',
iconCls: 'fa fa-cube',
text: gettext("Create CT"),
disabled: !caps.vms['VM.Allocate'],
handler: function() {
var wiz = Ext.create('PVE.lxc.CreateWizard', {});
wiz.show();
}
});
sprovider.on('statechange', function(sp, key, value) {
if (key === 'GuiCap' && value) {
caps = value;
createVM.setDisabled(!caps.vms['VM.Allocate']);
createCT.setDisabled(!caps.vms['VM.Allocate']);
}
});
Ext.apply(me, {
layout: { type: 'border' },
border: false,
items: [
{
region: 'north',
layout: {
type: 'hbox',
align: 'middle'
},
baseCls: 'x-plain',
defaults: {
baseCls: 'x-plain'
},
border: false,
margin: '2 0 2 5',
items: [
{
html: '<a class="x-unselectable" target=_blank href="https://www.proxmox.com">' +
'<img style="padding-top:4px;padding-right:5px" src="/pve2/images/proxmox_logo.png"/></a>'
},
{
minWidth: 150,
id: 'versioninfo',
html: 'Virtual Environment'
},
{
xtype: 'pveGlobalSearchField',
tree: rtree
},
{
flex: 1
},
{
xtype: 'proxmoxHelpButton',
hidden: false,
baseCls: 'x-btn',
iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
listenToGlobalEvent: false,
onlineHelp: 'pve_documentation_index',
text: gettext('Documentation'),
margin: '0 5 0 0'
},
createVM,
createCT,
{
pack: 'end',
margin: '0 5 0 0',
id: 'userinfo',
xtype: 'button',
baseCls: 'x-btn',
style: {
// proxmox dark grey p light grey as border
backgroundColor: '#464d4d',
borderColor: '#ABBABA'
},
iconCls: 'fa fa-user',
menu: [
{
iconCls: 'fa fa-gear',
text: gettext('My Settings'),
handler: function() {
var win = Ext.create('PVE.window.Settings');
win.show();
}
},
{
text: gettext('Password'),
iconCls: 'fa fa-fw fa-key',
handler: function() {
var win = Ext.create('Proxmox.window.PasswordEdit', {
userid: Proxmox.UserName
});
win.show();
}
},
{
text: 'TFA',
iconCls: 'fa fa-fw fa-lock',
handler: function(btn, event, rec) {
var win = Ext.create('PVE.window.TFAEdit',{
userid: Proxmox.UserName
});
win.show();
}
},
'-',
{
iconCls: 'fa fa-fw fa-sign-out',
text: gettext("Logout"),
handler: function() {
PVE.data.ResourceStore.loadData([], false);
me.showLogin();
me.setContent(null);
var rt = me.down('pveResourceTree');
rt.setDatacenterText(undefined);
rt.clearTree();
// empty the stores of the StatusPanel child items
var statusPanels = Ext.ComponentQuery.query('pveStatusPanel grid');
Ext.Array.forEach(statusPanels, function(comp) {
if (comp.getStore()) {
comp.getStore().loadData([], false);
}
});
}
}
]
}
]
},
{
region: 'center',
stateful: true,
stateId: 'pvecenter',
minWidth: 100,
minHeight: 100,
id: 'content',
xtype: 'container',
layout: { type: 'card' },
border: false,
margin: '0 5 0 0',
items: []
},
{
region: 'west',
stateful: true,
stateId: 'pvewest',
itemId: 'west',
xtype: 'container',
border: false,
layout: { type: 'vbox', align: 'stretch' },
margin: '0 0 0 5',
split: true,
width: 200,
items: [ selview, rtree ],
listeners: {
resize: function(panel, width, height) {
var viewWidth = me.getSize().width;
if (width > viewWidth - 100) {
panel.setWidth(viewWidth - 100);
}
}
}
},
{
xtype: 'pveStatusPanel',
stateful: true,
stateId: 'pvesouth',
itemId: 'south',
region: 'south',
margin:'0 5 5 5',
title: gettext('Logs'),
collapsible: true,
header: false,
height: 200,
split:true,
listeners: {
resize: function(panel, width, height) {
var viewHeight = me.getSize().height;
if (height > (viewHeight - 150)) {
panel.setHeight(viewHeight - 150);
}
}
}
}
]
});
me.callParent();
me.updateUserInfo();
// on resize, center all modal windows
Ext.on('resize', function(){
var wins = Ext.ComponentQuery.query('window[modal]');
if (wins.length > 0) {
wins.forEach(function(win){
win.alignTo(me, 'c-c');
});
}
});
}
});