using container here is fine, we do not need panel behaviour which is more bloated. Removes two ARIA warnings. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
		
			
				
	
	
		
			297 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| Ext.define('PBS.MainView', {
 | |
|     extend: 'Ext.container.Container',
 | |
|     xtype: 'mainview',
 | |
| 
 | |
|     title: 'Proxmox Backup Server',
 | |
| 
 | |
|     controller: {
 | |
| 	xclass: 'Ext.app.ViewController',
 | |
| 	routes: {
 | |
| 	    ':path:subpath': {
 | |
| 		action: 'changePath',
 | |
| 		before: 'beforeChangePath',
 | |
|                 conditions: {
 | |
| 		    ':path': '(?:([%a-zA-Z0-9\\-\\_\\s,.]+))',
 | |
| 		    ':subpath': '(?:(?::)([%a-zA-Z0-9\\-\\_\\s,]+))?',
 | |
| 		},
 | |
| 	    },
 | |
| 	},
 | |
| 
 | |
| 	parseRouterPath: function(path) {
 | |
| 	    let xtype = path;
 | |
| 	    let config = {};
 | |
| 	    if (PBS.Utils.isDataStorePath(path)) {
 | |
| 		config.datastore = PBS.Utils.getDataStoreFromPath(path);
 | |
| 		xtype = 'pbsDataStorePanel';
 | |
| 	    } else if (path.indexOf('Changer-') === 0) {
 | |
| 		config.changer = path.slice('Changer-'.length);
 | |
| 		xtype = 'pbsChangerStatus';
 | |
| 	    } else if (path.indexOf('Drive-') === 0) {
 | |
| 		config.drive = path.slice('Drive-'.length);
 | |
| 		xtype = 'pbsDriveStatus';
 | |
| 	    }
 | |
| 
 | |
| 	    return [xtype, config];
 | |
| 	},
 | |
| 
 | |
| 	beforeChangePath: function(path, subpath, action) {
 | |
| 	    var me = this;
 | |
| 
 | |
| 	    let [xtype, config] = me.parseRouterPath(path);
 | |
| 
 | |
| 	    if (!Ext.ClassManager.getByAlias(`widget.${xtype}`)) {
 | |
| 		console.warn(`xtype ${xtype} not found`);
 | |
| 		action.stop();
 | |
| 		return;
 | |
| 	    }
 | |
| 
 | |
| 	    var lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem();
 | |
| 	    if (lastpanel && lastpanel.xtype === xtype) {
 | |
| 		for (const [prop, value] of Object.entries(config)) {
 | |
| 		    if (lastpanel[prop] !== value) {
 | |
| 			action.resume();
 | |
| 			return;
 | |
| 		    }
 | |
| 		}
 | |
| 		// we have the right component already,
 | |
| 		// we just need to select the correct tab
 | |
| 		// default to the first
 | |
| 		subpath = subpath || 0;
 | |
| 		if (lastpanel.getActiveTab) {
 | |
| 		    // we assume lastpanel is a tabpanel
 | |
| 		    if (lastpanel.getActiveTab().getItemId() !== subpath) {
 | |
| 			// set the active tab
 | |
| 			lastpanel.setActiveTab(subpath);
 | |
| 		    }
 | |
| 		    // else we are already there
 | |
| 		}
 | |
| 		action.stop();
 | |
| 		return;
 | |
| 	    }
 | |
| 
 | |
| 	    action.resume();
 | |
| 	},
 | |
| 
 | |
| 	changePath: function(path, subpath) {
 | |
| 	    var me = this;
 | |
| 	    var contentpanel = me.lookupReference('contentpanel');
 | |
| 	    var lastpanel = contentpanel.getLayout().getActiveItem();
 | |
| 
 | |
| 	    let tabChangeListener = function(tp, newc, oldc) {
 | |
| 		let newpath = path;
 | |
| 
 | |
| 		// only add the subpath part for the
 | |
| 		// non-default tabs
 | |
| 		if (tp.items.findIndex('id', newc.id) !== 0) {
 | |
| 		    newpath += `:${newc.getItemId()}`;
 | |
| 		}
 | |
| 
 | |
| 		me.redirectTo(newpath);
 | |
| 	    };
 | |
| 
 | |
| 	    let [xtype, config] = me.parseRouterPath(path);
 | |
| 	    var obj;
 | |
| 	    if (PBS.Utils.isDataStorePath(path)) {
 | |
| 		if (lastpanel && lastpanel.xtype === xtype && !subpath) {
 | |
| 		    let activeTab = lastpanel.getActiveTab();
 | |
| 		    let newpath = path;
 | |
| 		    if (lastpanel.items.indexOf(activeTab) !== 0) {
 | |
| 			subpath = activeTab.getItemId();
 | |
| 			newpath += `:${subpath}`;
 | |
| 		    }
 | |
| 		    me.redirectTo(newpath);
 | |
| 		}
 | |
| 	    }
 | |
| 	    obj = contentpanel.add(Ext.apply(config, {
 | |
| 		xtype,
 | |
| 		nodename: 'localhost',
 | |
| 		border: false,
 | |
| 		activeTab: subpath || 0,
 | |
| 		listeners: {
 | |
| 		    tabchange: tabChangeListener,
 | |
| 		},
 | |
| 	    }));
 | |
| 
 | |
| 	    var treelist = me.lookupReference('navtree');
 | |
| 
 | |
| 	    treelist.select(path, true);
 | |
| 
 | |
| 	    contentpanel.setActiveItem(obj);
 | |
| 
 | |
| 	    if (lastpanel) {
 | |
| 		contentpanel.remove(lastpanel, { destroy: true });
 | |
| 	    }
 | |
| 	},
 | |
| 
 | |
| 	logout: function() {
 | |
| 	    PBS.app.logout();
 | |
| 	},
 | |
| 
 | |
| 	navigate: function(treelist, item) {
 | |
| 	    this.redirectTo(item.get('path'));
 | |
| 	},
 | |
| 
 | |
| 	control: {
 | |
| 	    '[reference=logoutButton]': {
 | |
| 		click: 'logout',
 | |
| 	    },
 | |
| 	},
 | |
| 
 | |
| 	init: function(view) {
 | |
| 	    var me = this;
 | |
| 
 | |
| 	    PBS.data.RunningTasksStore.startUpdate();
 | |
| 	    me.lookupReference('usernameinfo').setText(Proxmox.UserName);
 | |
| 
 | |
| 	    // show login on requestexception
 | |
| 	    // fixme: what about other errors
 | |
| 	    Ext.Ajax.on('requestexception', function(conn, response, options) {
 | |
| 		if (response.status === 401 || response.status === '401') { // auth failure
 | |
| 		    me.logout();
 | |
| 		}
 | |
| 	    });
 | |
| 
 | |
| 	    // get ticket periodically
 | |
| 	    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',
 | |
| 			failure: function() {
 | |
| 			    me.logout();
 | |
| 			},
 | |
| 			success: function(response, opts) {
 | |
| 			    var obj = Ext.decode(response.responseText);
 | |
| 			    PBS.Utils.updateLoginData(obj.data);
 | |
| 			},
 | |
| 		    });
 | |
| 		},
 | |
| 		interval: 15*60*1000,
 | |
| 	    });
 | |
| 
 | |
| 
 | |
| 	    // select treeitem and load page from url fragment, if set
 | |
| 	    let token = Ext.util.History.getToken() || 'pbsDashboard';
 | |
| 	    this.redirectTo(token, true);
 | |
| 	},
 | |
|     },
 | |
| 
 | |
|     plugins: 'viewport',
 | |
| 
 | |
|     layout: { type: 'border' },
 | |
| 
 | |
|     items: [
 | |
| 	{
 | |
| 	    region: 'north',
 | |
| 	    xtype: 'container',
 | |
| 	    layout: {
 | |
| 		type: 'hbox',
 | |
| 		align: 'middle',
 | |
| 	    },
 | |
| 	    margin: '2 0 2 5',
 | |
| 	    height: 38,
 | |
| 	    items: [
 | |
| 		{
 | |
| 		    xtype: 'proxmoxlogo',
 | |
| 		    prefix: '',
 | |
| 		},
 | |
| 		{
 | |
| 		    padding: '0 0 0 5',
 | |
| 		    xtype: 'versioninfo',
 | |
| 		},
 | |
| 		{
 | |
| 		    flex: 1,
 | |
| 		    baseCls: 'x-plain',
 | |
| 		},
 | |
| 		{
 | |
| 		    xtype: 'button',
 | |
| 		    baseCls: 'x-btn',
 | |
| 		    cls: 'x-btn-default-toolbar-small proxmox-inline-button',
 | |
| 		    iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
 | |
| 		    text: gettext('Documentation'),
 | |
| 		    href: '/docs/index.html',
 | |
| 		    margin: '0 5 0 0',
 | |
| 		},
 | |
| 		{
 | |
| 		    xtype: 'pbsTaskButton',
 | |
| 		    margin: '0 5 0 0',
 | |
| 		},
 | |
| 		{
 | |
| 		    xtype: 'button',
 | |
| 		    reference: 'usernameinfo',
 | |
| 		    style: {
 | |
| 			// proxmox dark grey p light grey as border
 | |
| 			backgroundColor: '#464d4d',
 | |
| 			borderColor: '#ABBABA',
 | |
| 		    },
 | |
| 		    margin: '0 5 0 0',
 | |
| 		    iconCls: 'fa fa-user',
 | |
| 		    menu: [
 | |
| 			{
 | |
| 			    iconCls: 'fa fa-gear',
 | |
| 			    text: gettext('My Settings'),
 | |
| 			    handler: () => Ext.create('PBS.window.Settings').show(),
 | |
| 			},
 | |
| 			{
 | |
| 			    iconCls: 'fa fa-language',
 | |
| 			    text: gettext('Language'),
 | |
| 			    reference: 'languageButton',
 | |
| 			    handler: () => Ext.create('Proxmox.window.LanguageEditWindow', {
 | |
| 				cookieName: 'PBSLangCookie',
 | |
| 				autoShow: true,
 | |
| 			    }),
 | |
| 			},
 | |
| 			'-',
 | |
| 			{
 | |
| 			    iconCls: 'fa fa-sign-out',
 | |
| 			    text: gettext('Logout'),
 | |
| 			    reference: 'logoutButton',
 | |
| 			},
 | |
| 		    ],
 | |
| 		},
 | |
| 	    ],
 | |
| 	},
 | |
| 	{
 | |
| 	    xtype: 'container',
 | |
| 	    scrollable: 'y',
 | |
| 	    border: false,
 | |
| 	    region: 'west',
 | |
| 	    layout: {
 | |
| 		type: 'vbox',
 | |
| 		align: 'stretch',
 | |
| 	    },
 | |
| 	    items: [{
 | |
| 		xtype: 'navigationtree',
 | |
| 		minWidth: 180,
 | |
| 		reference: 'navtree',
 | |
| 		// we have to define it here until extjs 6.2
 | |
| 		// because of a bug where a viewcontroller does not detect
 | |
| 		// the selectionchange event of a treelist
 | |
| 		listeners: {
 | |
| 		    selectionchange: 'navigate',
 | |
| 		},
 | |
| 	    }, {
 | |
| 		xtype: 'box',
 | |
| 		cls: 'x-treelist-nav',
 | |
| 		flex: 1,
 | |
| 	    }],
 | |
| 	},
 | |
| 	{
 | |
| 	    xtype: 'container',
 | |
| 	    layout: { type: 'card' },
 | |
| 	    region: 'center',
 | |
| 	    border: false,
 | |
| 	    reference: 'contentpanel',
 | |
| 	},
 | |
|     ],
 | |
| });
 |