]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/panel/ConfigPanel.js
show guest-agent provided ip address in qemu summary
[pve-manager.git] / www / manager6 / panel / ConfigPanel.js
index 33a483251f23761d0e9abe04570c2fcacb7ed433..e3c71eef2568925e050db7455e10f6a5f774af70 100644 (file)
@@ -1,5 +1,43 @@
 /*
  * Base class for all the multitab config panels
+ *
+ * How to use this:
+ *
+ * You create a subclass of this, and then define your wanted tabs
+ * as items like this:
+ *
+ * items: [{
+ *  title: "myTitle",
+ *  xytpe: "somextype",
+ *  iconCls: 'fa fa-icon',
+ *  groups: ['somegroup'],
+ *  expandedOnInit: true,
+ *  itemId: 'someId'
+ * }]
+ *
+ * this has to be in the declarative syntax, else we
+ * cannot save them for later
+ * (so no Ext.create or Ext.apply of an item in the subclass)
+ *
+ * the groups array expects the itemids of the items
+ * which are the parents, which have to come before they
+ * are used
+ *
+ * if you want following the tree:
+ *
+ * Option1
+ * Option2
+ *   -> SubOption1
+ *     -> SubSubOption1
+ *
+ * the suboption1 group array has to look like this:
+ * groups: ['itemid-of-option2']
+ *
+ * and of subsuboption1:
+ * groups: ['itemid-of-option2', 'itemid-of-suboption1']
+ *
+ * setting the expandedOnInit determines if the item/group is expanded
+ * initially (false by default)
  */
 Ext.define('PVE.panel.Config', {
     extend: 'Ext.panel.Panel',
@@ -8,124 +46,267 @@ Ext.define('PVE.panel.Config', {
     showSearch: true, // add a ressource grid with a search button as first tab
     viewFilter: undefined, // a filter to pass to that ressource grid
 
+    dockedItems: [{
+       // this is needed for the overflow handler
+       xtype: 'toolbar',
+       overflowHandler: 'scroller',
+       dock: 'left',
+       style: {
+           backgroundColor: '#f5f5f5',
+           padding: 0,
+           margin: 0
+       },
+       items: {
+           xtype: 'treelist',
+           itemId: 'menu',
+           ui: 'nav',
+           expanderOnly: true,
+           expanderFirst: false,
+           animation: false,
+           singleExpand: false,
+           listeners: {
+               selectionchange: function(treeList, selection) {
+                   var me = this.up('panel');
+                   me.suspendLayout = true;
+                   me.activateCard(selection.data.id);
+                   me.suspendLayout = false;
+                   me.updateLayout();
+               },
+               itemclick: function(treelist, info) {
+                   var olditem = treelist.getSelection();
+                   var newitem = info.node;
+
+                   // when clicking on the expand arrow,
+                   // we dont select items, but still want
+                   // the original behaviour
+                   if (info.select === false) {
+                       return;
+                   }
+
+                   // if you click on a different item which is open,
+                   // leave it open
+                   // else toggle the clicked item
+                   if (olditem.data.id !== newitem.data.id &&
+                       newitem.data.expanded === true) {
+                       info.toggle = false;
+                   } else {
+                       info.toggle = true;
+                   }
+               }
+           }
+       }
+    },
+    {
+       xtype: 'toolbar',
+       itemId: 'toolbar',
+       dock: 'top',
+       height: 36,
+       overflowHandler: 'scroller'
+    }],
+
+    firstItem: '',
+    layout: 'card',
+    border: 0,
+
+    // used for automated test
+    selectById: function(cardid) {
+       var me = this;
+
+       var root = me.store.getRoot();
+       var selection = root.findChild('id', cardid, true);
+
+       if (selection) {
+           selection.expand();
+           var menu = me.down('#menu');
+           menu.setSelection(selection);
+           return cardid;
+       }
+    },
+
+    activateCard: function(cardid) {
+       var me = this;
+       if (me.savedItems[cardid]) {
+           var curcard = me.getLayout().getActiveItem();
+           var newcard = me.add(me.savedItems[cardid]);
+           me.helpButton.setOnlineHelp(newcard.onlineHelp || me.onlineHelp);
+           if (curcard) {
+               me.setActiveItem(cardid);
+               me.remove(curcard, true);
+
+               // trigger state change
+
+               var ncard = cardid;
+               // Note: '' is alias for first tab.
+               // First tab can be 'search' or something else
+               if (cardid === me.firstItem) {
+                   ncard = '';
+               }
+               if (me.hstateid) {
+                  me.sp.set(me.hstateid, { value: ncard });
+               }
+           }
+       }
+    },
+
     initComponent: function() {
         var me = this;
 
        var stateid = me.hstateid;
 
-       var sp = Ext.state.Manager.getProvider();
+       me.sp = Ext.state.Manager.getProvider();
 
        var activeTab; // leaving this undefined means items[0] will be the default tab
 
-       var hsregex =  /^([^\-\s]+)(-\S+)?$/;
-
        if (stateid) {
-           var state = sp.get(stateid);
+           var state = me.sp.get(stateid);
            if (state && state.value) {
-               var res = hsregex.exec(state.value);
-               if (res && res[1]) {
-                   activeTab = res[1];
-               }
+               // if this tab does not exists, it chooses the first
+               activeTab = state.value;
            }
        }
 
-       var items = me.items || [];
-       me.items = undefined;
+       // get title
+       var title = me.title || me.pveSelNode.data.text;
+       me.title = undefined;
 
+       // create toolbar
        var tbar = me.tbar || [];
        me.tbar = undefined;
 
-       var title = me.title || me.pveSelNode.data.text;
-       me.title = undefined;
+       if (!me.onlineHelp) {
+           switch(me.pveSelNode.data.id) {
+               case 'type/storage':me.onlineHelp = 'chapter-pvesm.html'; break;
+               case 'type/qemu':me.onlineHelp = 'chapter-qm.html'; break;
+               case 'type/lxc':me.onlineHelp = 'chapter-pct.html'; break;
+               case 'type/pool':me.onlineHelp = 'chapter-pveum.html#_pools'; break;
+               case 'type/node':me.onlineHelp = 'chapter-sysadmin.html'; break;
+           }
+       }
 
        tbar.unshift('->');
        tbar.unshift({
            xtype: 'tbtext',
            text: title,
-           baseCls: 'x-panel-header-text',
+           baseCls: 'x-panel-header-text'
+       });
+
+       me.helpButton = Ext.create('Proxmox.button.Help', {
+           hidden: false,
+           listenToGlobalEvent: false,
+           onlineHelp: me.onlineHelp || undefined
        });
 
+       tbar.push(me.helpButton);
 
+       me.dockedItems[1].items = tbar;
+
+       // include search tab
+       me.items = me.items || [];
        if (me.showSearch) {
-           items.unshift({
+           me.items.unshift({
                itemId: 'search',
                title: gettext('Search'),
-               layout: 'fit',
-               plugins: {
-                   ptype: 'lazyitems',
-                   items: {
-                       xtype: 'pveResourceGrid',
-                       pveSelNode: me.pveSelNode
-                   }
-               }
+               iconCls: 'fa fa-search',
+               xtype: 'pveResourceGrid',
+               pveSelNode: me.pveSelNode
            });
        }
 
-       var toolbar = Ext.create('Ext.toolbar.Toolbar', {
-           items: tbar,
-           border: false,
-           height: 36
+       me.savedItems = {};
+       /*jslint confusion:true*/
+       if (me.items[0]) {
+           me.firstItem = me.items[0].itemId;
+       }
+       /*jslint confusion:false*/
+
+       me.store = Ext.create('Ext.data.TreeStore', {
+           root: {
+               expanded: true
+           }
        });
+       var root = me.store.getRoot();
+       me.items.forEach(function(item){
+           var treeitem = Ext.create('Ext.data.TreeModel',{
+               id: item.itemId,
+               text: item.title,
+               iconCls: item.iconCls,
+               leaf: true,
+               expanded: item.expandedOnInit
+           });
+           item.header = false;
+           if (me.savedItems[item.itemId] !== undefined) {
+               throw "itemId already exists, please use another";
+           }
+           me.savedItems[item.itemId] = item;
 
-       var tab = Ext.create('Ext.tab.Panel', {
-           flex: 1,
-           border: true,
-           activeTab: activeTab,
-           defaults: Ext.apply(me.defaults ||  {}, {
-               pveSelNode: me.pveSelNode,
-               viewFilter: me.viewFilter,
-               workspace: me.workspace,
-               border: false
-           }),
-           items: items,
-           listeners: {
-               tabchange: function(tp, newcard, oldcard) {
-                   var ntab = newcard.itemId;
+           var group;
+           var curnode = root;
 
-                   // Note: '' is alias for first tab.
-                   // First tab can be 'search' or something else
-                   if (newcard.itemId === items[0].itemId) {
-                       ntab = '';
-                   }
-                   if (stateid) {
-                       if (newcard.phstateid) {
-                           sp.set(newcard.phstateid, newcard.getHState());
-                       } else {
-                           sp.set(stateid, { value: ntab });
-                       }
-                   }
+           // get/create the group items
+           while (Ext.isArray(item.groups) && item.groups.length > 0) {
+               group = item.groups.shift();
 
-                   // if we have a tabpanel which we declared lazy (with ptype: lazyitems)
-                   // then we have the actual item in items.items[0]
-                   // and there we need to fire the event hide
-                   // because some tabs use this event (which is not fired in this case)
-                   if (oldcard.plugins && oldcard.plugins[0] && oldcard.plugins[0].ptype == 'lazyitems') {
-                       oldcard.items.items[0].fireEvent('hide');
-                   }
+               var child = curnode.findChild('id', group);
+               if (child === null) {
+                   // did not find the group item
+                   // so add it where we are
+                   break;
                }
+               curnode = child;
+           }
+
+           // insert the item
+
+           // lets see if it already exists
+           var node = curnode.findChild('id', item.itemId);
+
+           if (node === null) {
+               curnode.appendChild(treeitem);
+           } else {
+               // should not happen!
+               throw "id already exists";
            }
        });
 
-       Ext.apply(me, {
-           layout: { type: 'vbox', align: 'stretch' },
-           items: [ toolbar, tab]
+       delete me.items;
+       me.defaults = me.defaults || {};
+       Ext.apply(me.defaults, {
+           pveSelNode: me.pveSelNode,
+           viewFilter: me.viewFilter,
+           workspace: me.workspace,
+           border: 0
        });
 
        me.callParent();
 
+       var menu = me.down('#menu');
+       var selection = root.findChild('id', activeTab, true) || root.firstChild;
+       var node = selection;
+       while (node !== root) {
+           node.expand();
+           node = node.parentNode;
+       }
+       menu.setStore(me.store);
+       menu.setSelection(selection);
+
+       // on a state change,
+       // select the new item
        var statechange = function(sp, key, state) {
+           // it the state change is for this panel
            if (stateid && (key === stateid) && state) {
-               var atab = tab.getActiveTab().itemId;
-               var res = hsregex.exec(state.value);
-               var ntab = (res && res[1]) ? res[1] : items[0].itemId;
-               if (ntab && (atab != ntab)) {
-                   tab.setActiveTab(ntab);
+               // get active item
+               var acard = me.getLayout().getActiveItem().itemId;
+               // get the itemid of the new value
+               var ncard = state.value || me.firstItem;
+               if (ncard && (acard != ncard)) {
+                   // select the chosen item
+                   menu.setSelection(root.findChild('id', ncard, true) || root.firstChild);
                }
            }
        };
 
        if (stateid) {
-           me.mon(sp, 'statechange', statechange);
+           me.mon(me.sp, 'statechange', statechange);
        }
     }
 });