From b0ee976fbf4e1d56e3ea69eafd00636daf33bed2 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Tue, 22 Jan 2019 11:48:00 +0100 Subject: [PATCH] gui: add navigation tree --- www/Application.js | 2 +- www/MainView.js | 74 ++++++++++++++++++++++- www/Makefile | 3 + www/NavigationTree.js | 54 +++++++++++++++++ www/Subscription.js | 118 +++++++++++++++++++++++++++++++++++++ www/SystemConfiguration.js | 67 +++++++++++++++++++++ 6 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 www/NavigationTree.js create mode 100644 www/Subscription.js create mode 100644 www/SystemConfiguration.js diff --git a/www/Application.js b/www/Application.js index 8639c515..0bd0e6b9 100644 --- a/www/Application.js +++ b/www/Application.js @@ -6,7 +6,7 @@ Ext.define('PBS.Application', { appProperty: 'app', stores: [ - // 'NavigationStore' + 'NavigationStore' ], layout: 'fit', diff --git a/www/MainView.js b/www/MainView.js index edff93f4..d8bd53d7 100644 --- a/www/MainView.js +++ b/www/MainView.js @@ -20,14 +20,70 @@ Ext.define('PBS.MainView', { beforeChangePath: function(path, subpath, action) { var me = this; + if (!Ext.ClassManager.getByAlias('widget.'+ path)) { + console.warn('xtype "'+path+'" not found'); + action.stop(); + return; + } + + var lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem(); + if (lastpanel && lastpanel.xtype === path) { + // 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) { + changePath: function(path,subpath) { var me = this; var contentpanel = me.lookupReference('contentpanel'); var lastpanel = contentpanel.getLayout().getActiveItem(); + var obj = contentpanel.add({ xtype: path }); + var treelist = me.lookupReference('navtree'); + + treelist.suspendEvents(); + treelist.select(path); + treelist.resumeEvents(); + + if (Ext.isFunction(obj.setActiveTab)) { + obj.setActiveTab(subpath || 0); + obj.addListener('tabchange', function(tabpanel, newc, oldc) { + var newpath = path; + + // only add the subpath part for the + // non-default tabs + if (tabpanel.items.findIndex('id', newc.id) !== 0) { + newpath += ":" + newc.getItemId(); + } + + me.redirectTo(newpath); + }); + } + + contentpanel.setActiveItem(obj); + + if (lastpanel) { + contentpanel.remove(lastpanel, { destroy: true }); + } + + }, + + navigate: function(treelist, item) { + this.redirectTo(item.get('path')); }, init: function(view) { @@ -84,7 +140,21 @@ Ext.define('PBS.MainView', { type: 'vbox', align: 'stretch' }, - items: [{ html: "test" }] + 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: 'panel', diff --git a/www/Makefile b/www/Makefile index d976279e..4a467fb5 100644 --- a/www/Makefile +++ b/www/Makefile @@ -2,6 +2,9 @@ JSSRC= \ Utils.js \ Logo.js \ VersionInfo.js \ + SystemConfiguration.js \ + Subscription.js \ + NavigationTree.js \ Application.js \ MainView.js diff --git a/www/NavigationTree.js b/www/NavigationTree.js new file mode 100644 index 00000000..b3e62cf0 --- /dev/null +++ b/www/NavigationTree.js @@ -0,0 +1,54 @@ +Ext.define('PBS.store.NavigationStore', { + extend: 'Ext.data.TreeStore', + + storeId: 'NavigationStore', + + root: { + expanded: true, + children: [ + { + text: gettext('Configuration'), + iconCls: 'fa fa-gears', + path: 'pbsSystemConfiguration', + expanded: true, + children: [ + { + text: gettext('Data Store'), + iconCls: 'fa fa-envelope-o', + path: 'pbsDataStoreConfiguration', + leaf: true + }, + { + text: gettext('Subscription'), + iconCls: 'fa fa-support', + path: 'pbsSubscription', + leaf: true + } + ] + }, + { + text: gettext('Administration'), + iconCls: 'fa fa-wrench', + path: 'pbsServerAdministration', + leaf: true + } + ] + } +}); + +Ext.define('PBS.view.main.NavigationTree', { + extend: 'Ext.list.Tree', + xtype: 'navigationtree', + + select: function(path) { + var me = this; + var item = me.getStore().findRecord('path', path, 0, false, true, true); + me.setSelection(item); + }, + + animation: false, + expanderOnly: true, + expanderFirst: false, + store: 'NavigationStore', + ui: 'nav' +}); diff --git a/www/Subscription.js b/www/Subscription.js new file mode 100644 index 00000000..72beacc2 --- /dev/null +++ b/www/Subscription.js @@ -0,0 +1,118 @@ +/*global Blob,Proxmox*/ +Ext.define('PBS.SubscriptionKeyEdit', { + extend: 'Proxmox.window.Edit', + + title: gettext('Upload Subscription Key'), + width: 300, + autoLoad: true, + + onlineHelp: 'getting_help', + + items: { + xtype: 'textfield', + name: 'key', + value: '', + fieldLabel: gettext('Subscription Key') + } +}); + +Ext.define('PBS.Subscription', { + extend: 'Proxmox.grid.ObjectGrid', + xtype: 'pbsSubscription', + + title: gettext('Subscription'), + + border: false, + + onlineHelp: 'getting_help', + + viewConfig: { + enableTextSelection: true + }, + + initComponent : function() { + var me = this; + + var reload = function() { + me.rstore.load(); + }; + + var baseurl = '/subscription'; + + var render_status = function(value) { + + var message = me.getObjectValue('message'); + + if (message) { + return value + ": " + message; + } + return value; + }; + + var rows = { + productname: { + header: gettext('Type') + }, + key: { + header: gettext('Subscription Key') + }, + status: { + header: gettext('Status'), + renderer: render_status + }, + message: { + visible: false + }, + serverid: { + header: gettext('Server ID') + }, + sockets: { + header: gettext('Sockets') + }, + checktime: { + header: gettext('Last checked'), + renderer: Proxmox.Utils.render_timestamp + }, + nextduedate: { + header: gettext('Next due date') + } + }; + + Ext.apply(me, { + url: '/api2/json' + baseurl, + cwidth1: 170, + tbar: [ + { + text: gettext('Upload Subscription Key'), + handler: function() { + var win = Ext.create('PBS.SubscriptionKeyEdit', { + url: '/api2/extjs/' + baseurl + }); + win.show(); + win.on('destroy', reload); + } + }, + { + text: gettext('Check'), + handler: function() { + Proxmox.Utils.API2Request({ + params: { force: 1 }, + url: baseurl, + method: 'POST', + waitMsgTarget: me, + failure: function(response, opts) { + Ext.Msg.alert(gettext('Error'), response.htmlStatus); + }, + callback: reload + }); + } + } + ], + rows: rows + }); + + me.callParent(); + + reload(); + } +}); diff --git a/www/SystemConfiguration.js b/www/SystemConfiguration.js new file mode 100644 index 00000000..d8e67ac2 --- /dev/null +++ b/www/SystemConfiguration.js @@ -0,0 +1,67 @@ +/*global Proxmox*/ + +Ext.define('PBS.SystemConfiguration', { + extend: 'Ext.tab.Panel', + xtype: 'pbsSystemConfiguration', + + title: gettext('Configuration') + ': ' + gettext('System'), + border: false, + scrollable: true, + defaults: { border: false }, + items: [ + { + title: gettext('Network/Time'), + itemId: 'network', + xtype: 'panel', + layout: { + type: 'vbox', + align: 'stretch', + multi: true + }, + bodyPadding: '0 0 10 0', + defaults: { + collapsible: true, + animCollapse: false, + margin: '10 10 0 10' + }, + items: [ + { + flex: 1, + minHeight: 200, + title: gettext('Interfaces'), + xtype: 'proxmoxNodeNetworkView', + types: ['bond'], + nodename: Proxmox.NodeName + }, + { + title: gettext('DNS'), + xtype: 'proxmoxNodeDNSView', + nodename: Proxmox.NodeName + }, + { + title: gettext('Time'), + xtype: 'proxmoxNodeTimeView', + nodename: Proxmox.NodeName + } + ] +// }, +// { +// itemId: 'options', +// title: gettext('Options'), +// xtype: 'pbsSystemOptions' + } + ], + + initComponent: function() { + var me = this; + + me.callParent(); + + var networktime = me.getComponent('network'); + Ext.Array.forEach(networktime.query(), function(item) { + item.relayEvents(networktime, [ 'activate', 'deactivate', 'destroy']); + }); + } +}); + +