loginData: null, // Data from last login call
- onLogin: function(loginData) {},
+ onLogin: function(loginData) {
+ // override me
+ },
// private
updateLoginData: function(loginData) {
- var me = this;
+ let me = this;
me.loginData = loginData;
Proxmox.Utils.setAuthData(loginData);
- var rt = me.down('pveResourceTree');
+ let rt = me.down('pveResourceTree');
rt.setDatacenterText(loginData.clustername);
PVE.ClusterName = loginData.clustername;
// private
showLogin: function() {
- var me = this;
+ let me = this;
Proxmox.Utils.authClear();
Ext.state.Manager.clear('GuiCap');
handler: function(data) {
me.login = null;
me.updateLoginData(data);
- Proxmox.Utils.checked_command(function() {}); // display subscription status
+ Proxmox.Utils.checked_command(Ext.emptyFn); // display subscription status
},
});
}
me.login.show();
},
- initComponent : function() {
- var me = this;
+ 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 && !PVE.Utils.silenceAuthFailures) { // auth failure
+ 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 (!Proxmox.Utils.authOK()) {
me.showLogin();
- } else {
- if (me.loginData) {
- me.onLogin(me.loginData);
- }
+ } else if (me.loginData) {
+ me.onLogin(me.loginData);
}
Ext.TaskManager.start({
run: function() {
- var ticket = Proxmox.Utils.authOK();
+ let ticket = Proxmox.Utils.authOK();
if (!ticket || !Proxmox.UserName) {
return;
}
url: '/api2/json/access/ticket',
method: 'POST',
success: function(response, opts) {
- var obj = Ext.decode(response.responseText);
+ let obj = Ext.decode(response.responseText);
me.updateLoginData(obj.data);
},
});
},
- interval: 15*60*1000,
+ interval: 15 * 60 * 1000,
});
-
},
});
// private
setContent: function(comp) {
- var me = this;
-
- var cont = me.child('#content');
+ let me = this;
- var lay = cont.getLayout();
-
- var cur = lay.getActiveItem();
+ let view = me.child('#content');
+ let layout = view.getLayout();
+ let current = layout.getActiveItem();
if (comp) {
- Proxmox.Utils.setErrorMask(cont, false);
+ Proxmox.Utils.setErrorMask(view, 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);
+ 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 {
- // helper for cleaning the content when logging out
- cont.removeAll();
+ } else {
+ view.removeAll(); // helper for cleaning the content when logging out
}
},
selectById: function(nodeid) {
- var me = this;
- var tree = me.down('pveResourceTree');
- tree.selectById(nodeid);
+ let me = this;
+ me.down('pveResourceTree').selectById(nodeid);
},
onLogin: function(loginData) {
- var me = this;
+ let me = this;
me.updateUserInfo();
},
});
+ PVE.UIOptions.update();
+
Proxmox.Utils.API2Request({
url: '/cluster/sdn',
method: 'GET',
}
},
});
+
+ 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() {
- var me = this;
- var ui = me.query('#userinfo')[0];
+ let me = this;
+ let ui = me.query('#userinfo')[0];
ui.setText(Ext.String.htmlEncode(Proxmox.UserName || ''));
ui.updateLayout();
},
updateVersionInfo: function() {
- var me = this;
+ let me = this;
- var ui = me.query('#versioninfo')[0];
+ let ui = me.query('#versioninfo')[0];
if (PVE.VersionInfo) {
- var version = PVE.VersionInfo.version;
+ let version = PVE.VersionInfo.version;
ui.update('Virtual Environment ' + version);
} else {
ui.update('Virtual Environment');
ui.updateLayout();
},
- initComponent : function() {
- var me = this;
+ initComponent: function() {
+ let me = this;
Ext.History.init();
- var sprovider = Ext.create('PVE.StateProvider');
- Ext.state.Manager.setProvider(sprovider);
+ let appState = Ext.create('PVE.StateProvider');
+ Ext.state.Manager.setProvider(appState);
- var selview = Ext.create('PVE.form.ViewSelector');
+ let selview = Ext.create('PVE.form.ViewSelector', {
+ flex: 1,
+ padding: '0 5 0 0',
+ });
- var rtree = Ext.createWidget('pveResourceTree', {
+ let 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);
+ 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) {
- var view = combo.getViewFilter();
+ let view = combo.getViewFilter();
rtree.setViewFilter(view);
}
});
- var caps = sprovider.get('GuiCap');
+ let caps = appState.get('GuiCap');
- var createVM = Ext.createWidget('button', {
+ let createVM = Ext.createWidget('button', {
pack: 'end',
margin: '3 5 0 0',
baseCls: 'x-btn',
text: gettext("Create VM"),
disabled: !caps.vms['VM.Allocate'],
handler: function() {
- var wiz = Ext.create('PVE.qemu.CreateWizard', {});
+ let wiz = Ext.create('PVE.qemu.CreateWizard', {});
wiz.show();
},
});
- var createCT = Ext.createWidget('button', {
+ let createCT = Ext.createWidget('button', {
pack: 'end',
margin: '3 5 0 0',
baseCls: 'x-btn',
text: gettext("Create CT"),
disabled: !caps.vms['VM.Allocate'],
handler: function() {
- var wiz = Ext.create('PVE.lxc.CreateWizard', {});
+ let wiz = Ext.create('PVE.lxc.CreateWizard', {});
wiz.show();
},
});
- sprovider.on('statechange', function(sp, key, value) {
+ appState.on('statechange', function(sp, key, value) {
if (key === 'GuiCap' && value) {
caps = value;
createVM.setDisabled(!caps.vms['VM.Allocate']);
items: [
{
region: 'north',
+ title: gettext('Header'), // for ARIA
+ header: false, // avoid rendering the title
layout: {
type: 'hbox',
align: 'middle',
minWidth: 150,
id: 'versioninfo',
html: 'Virtual Environment',
+ style: {
+ 'font-size': '14px',
+ 'line-height': '18px',
+ },
},
{
xtype: 'pveGlobalSearchField',
},
{
text: gettext('Password'),
+ itemId: 'passworditem',
iconCls: 'fa fa-fw fa-key',
handler: function() {
var win = Ext.create('Proxmox.window.PasswordEdit', {
userid: Proxmox.UserName,
+ confirmCurrentPassword: Proxmox.UserName !== 'root@pam',
});
win.show();
},
},
{
text: 'TFA',
+ itemId: 'tfaitem',
iconCls: 'fa fa-fw fa-lock',
handler: function(btn, event, rec) {
- var win = Ext.create('PVE.window.TFAEdit', {
- userid: Proxmox.UserName,
- });
- win.show();
+ Ext.state.Manager.getProvider().set('dctab', { value: 'tfa' }, true);
+ me.selectById('root');
+ },
+ },
+ {
+ iconCls: 'fa fa-paint-brush',
+ text: gettext('Color Theme'),
+ handler: function() {
+ Ext.create('Proxmox.window.ThemeEditWindow')
+ .show();
},
},
{
layout: { type: 'vbox', align: 'stretch' },
margin: '0 0 0 5',
split: true,
- width: 200,
- items: [ selview, rtree ],
+ width: 300,
+ items: [
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ padding: '0 0 5 0',
+ items: [
+ selview,
+ {
+ xtype: 'button',
+ cls: 'x-btn-default-toolbar-small',
+ iconCls: 'fa fa-fw fa-gear x-btn-icon-el-default-toolbar-small',
+ handler: () => {
+ Ext.create('PVE.window.TreeSettingsEdit', {
+ autoShow: true,
+ apiCallDone: () => PVE.UIOptions.fireUIConfigChanged(),
+ });
+ },
+ },
+ ],
+ },
+ rtree,
+ ],
listeners: {
resize: function(panel, width, height) {
var viewWidth = me.getSize().width;
- if (width > viewWidth - 100) {
+ if (width > viewWidth - 100 && viewWidth > 150) {
panel.setWidth(viewWidth - 100);
}
},
stateId: 'pvesouth',
itemId: 'south',
region: 'south',
- margin:'0 5 5 5',
+ margin: '0 5 5 5',
title: gettext('Logs'),
collapsible: true,
header: false,
height: 200,
- split:true,
+ split: true,
listeners: {
resize: function(panel, width, height) {
var viewHeight = me.getSize().height;
- if (height > (viewHeight - 150)) {
+ if (height > viewHeight - 150 && viewHeight > 200) {
panel.setHeight(viewHeight - 150);
}
},
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');
- });
+ Ext.on('resize', function() {
+ let modalWindows = Ext.ComponentQuery.query('window[modal]');
+ if (modalWindows.length > 0) {
+ modalWindows.forEach(win => win.alignTo(me, 'c-c'));
}
});
+
+ let tagSelectors = [];
+ ['circle', 'dense'].forEach((style) => {
+ ['dark', 'light'].forEach((variant) => {
+ tagSelectors.push(`.proxmox-tags-${style} .proxmox-tag-${variant}`);
+ });
+ });
+
+ Ext.create('Ext.tip.ToolTip', {
+ target: me.el,
+ delegate: tagSelectors.join(', '),
+ trackMouse: true,
+ renderTo: Ext.getBody(),
+ border: 0,
+ minWidth: 0,
+ padding: 0,
+ bodyBorder: 0,
+ bodyPadding: 0,
+ dismissDelay: 0,
+ userCls: 'pmx-tag-tooltip',
+ shadow: false,
+ listeners: {
+ beforeshow: function(tip) {
+ let tag = Ext.htmlEncode(tip.triggerElement.innerHTML);
+ let tagEl = Proxmox.Utils.getTagElement(tag, PVE.UIOptions.tagOverrides);
+ tip.update(`<span class="proxmox-tags-full">${tagEl}</span>`);
+ },
+ },
+ });
},
});