pve-manager/www/manager6/Workspace.js
Thomas Lamprecht f64fa68d8c ui: workspace: increase initial resource tree width from 200 to 300 px
we got much more wide screens and higher resolutions nowadays than
when this width was decided (before the famous imported from SVN
commit in 2011).

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2022-11-21 13:38:13 +01:00

500 lines
11 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) {
// override me
},
// private
updateLoginData: function(loginData) {
let me = this;
me.loginData = loginData;
Proxmox.Utils.setAuthData(loginData);
let rt = me.down('pveResourceTree');
rt.setDatacenterText(loginData.clustername);
PVE.ClusterName = loginData.clustername;
if (loginData.cap) {
Ext.state.Manager.set('GuiCap', loginData.cap);
}
me.response401count = 0;
me.onLogin(loginData);
},
// private
showLogin: function() {
let me = this;
Proxmox.Utils.authClear();
Ext.state.Manager.clear('GuiCap');
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(Ext.emptyFn); // display subscription status
},
});
}
me.onLogin(null);
me.login.show();
},
initComponent: function() {
let me = this;
Ext.tip.QuickTipManager.init();
// fixme: what about other errors
Ext.Ajax.on('requestexception', function(conn, response, options) {
if ((response.status === 401 || 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() {
let 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) {
let 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) {
let me = this;
let view = me.child('#content');
let layout = view.getLayout();
let current = layout.getActiveItem();
if (comp) {
Proxmox.Utils.setErrorMask(view, false);
comp.border = false;
view.add(comp);
if (current !== null && layout.getNext()) {
layout.next();
let task = Ext.create('Ext.util.DelayedTask', function() {
view.remove(current);
});
task.delay(10);
}
} else {
view.removeAll(); // helper for cleaning the content when logging out
}
},
selectById: function(nodeid) {
let me = this;
me.down('pveResourceTree').selectById(nodeid);
},
onLogin: function(loginData) {
let 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();
},
});
PVE.Utils.updateUIOptions();
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');
}
},
});
Proxmox.Utils.API2Request({
url: '/access/domains',
method: 'GET',
success: function(response) {
let [_username, realm] = Proxmox.Utils.parse_userid(Proxmox.UserName);
response.result.data.forEach((domain) => {
if (domain.realm === realm) {
let schema = PVE.Utils.authSchema[domain.type];
if (schema) {
me.query('#tfaitem')[0].setHidden(!schema.tfa);
me.query('#passworditem')[0].setHidden(!schema.pwchange);
}
}
});
},
});
}
},
updateUserInfo: function() {
let me = this;
let ui = me.query('#userinfo')[0];
ui.setText(Ext.String.htmlEncode(Proxmox.UserName || ''));
ui.updateLayout();
},
updateVersionInfo: function() {
let me = this;
let ui = me.query('#versioninfo')[0];
if (PVE.VersionInfo) {
let version = PVE.VersionInfo.version;
ui.update('Virtual Environment ' + version);
} else {
ui.update('Virtual Environment');
}
ui.updateLayout();
},
initComponent: function() {
let me = this;
Ext.History.init();
let appState = Ext.create('PVE.StateProvider');
Ext.state.Manager.setProvider(appState);
let selview = Ext.create('PVE.form.ViewSelector');
let rtree = Ext.createWidget('pveResourceTree', {
viewFilter: selview.getViewFilter(),
flex: 1,
selModel: {
selType: 'treemodel',
listeners: {
selectionchange: function(sm, selected) {
if (selected.length <= 0) {
return;
}
let treeNode = selected[0];
let treeTypeToClass = {
root: 'PVE.dc.Config',
node: 'PVE.node.Config',
qemu: 'PVE.qemu.Config',
lxc: 'pveLXCConfig',
storage: 'PVE.storage.Browser',
sdn: 'PVE.sdn.Browser',
pool: 'pvePoolConfig',
};
PVE.curSelectedNode = treeNode;
me.setContent({
xtype: treeTypeToClass[treeNode.data.type || 'root'] || 'pvePanelConfig',
showSearch: treeNode.data.id === 'root' || Ext.isDefined(treeNode.data.groupbyid),
pveSelNode: treeNode,
workspace: me,
viewFilter: selview.getViewFilter(),
});
},
},
},
});
selview.on('select', function(combo, records) {
if (records) {
let view = combo.getViewFilter();
rtree.setViewFilter(view);
}
});
let caps = appState.get('GuiCap');
let 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() {
let wiz = Ext.create('PVE.qemu.CreateWizard', {});
wiz.show();
},
});
let 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() {
let wiz = Ext.create('PVE.lxc.CreateWizard', {});
wiz.show();
},
});
appState.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',
title: gettext('Header'), // for ARIA
header: false, // avoid rendering the title
layout: {
type: 'hbox',
align: 'middle',
},
baseCls: 'x-plain',
defaults: {
baseCls: 'x-plain',
},
border: false,
margin: '2 0 2 5',
items: [
{
xtype: 'proxmoxlogo',
},
{
minWidth: 150,
id: 'versioninfo',
html: 'Virtual Environment',
style: {
'font-size': '14px',
'line-height': '18px',
},
},
{
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'),
itemId: 'passworditem',
iconCls: 'fa fa-fw fa-key',
handler: function() {
var win = Ext.create('Proxmox.window.PasswordEdit', {
userid: Proxmox.UserName,
});
win.show();
},
},
{
text: 'TFA',
itemId: 'tfaitem',
iconCls: 'fa fa-fw fa-lock',
handler: function(btn, event, rec) {
Ext.state.Manager.getProvider().set('dctab', { value: 'tfa' }, true);
me.selectById('root');
},
},
{
iconCls: 'fa fa-language',
text: gettext('Language'),
handler: function() {
Ext.create('Proxmox.window.LanguageEditWindow')
.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: 300,
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() {
let modalWindows = Ext.ComponentQuery.query('window[modal]');
if (modalWindows.length > 0) {
modalWindows.forEach(win => win.alignTo(me, 'c-c'));
}
});
},
});