Commit 5ff3a19e authored by Guus der Kinderen's avatar Guus der Kinderen Committed by daryl herzmann

OF-1484: admin console tab order (#1020)

* OF-1484: Allow admin console pages to be ordered explicitly.

* OF-1484: Admin console's "Plugins" tab should be on the right.

This commit forces the 'Plugins' tab to be the rightmost tab, even when plugins
add new tabs to the admin console.
parent 89dc17b7
...@@ -245,7 +245,12 @@ tabs, sections and entries in the Admin Console framework. A sample ...@@ -245,7 +245,12 @@ tabs, sections and entries in the Admin Console framework. A sample
<sidebar id="mysidebar" name="My Plugin"> <sidebar id="mysidebar" name="My Plugin">
<item id="my-plugin" name="My Plugin Admin" <item id="my-plugin" name="My Plugin Admin"
url="my-plugin-admin.jsp" url="my-plugin-admin.jsp"
description="Click to administer settings for my plugin" /> description="Click to administer settings for my plugin"
order="4" />
<item id="my-plugin" name="My Plugin Overview"
url="my-plugin-overview.jsp"
description="Click to have an Overview of Plugin usage"
order="2" />
</sidebar> </sidebar>
</tab> </tab>
...@@ -255,10 +260,21 @@ tabs, sections and entries in the Admin Console framework. A sample ...@@ -255,10 +260,21 @@ tabs, sections and entries in the Admin Console framework. A sample
</fieldset> </fieldset>
<p> <p>
In this example, we've defined a new tab "Example", a sidebar section In this example, we've defined a new tab "Example", a sidebar section "My Plugin" and two pages: "My Plugin Admin"
"My Plugin" and a page "My Plugin Admin". We've registered <tt>my-plugin-admin.jsp</tt> and "My Plugin Overview". We've registered <tt>my-plugin-admin.jsp</tt> respectively <tt>my-plugin-overview.jsp</tt>
as the page. You can override existing tabs, sections, and items by using as the pages.
the existing id attribute values in your own <tt>&lt;adminconsole&gt;</tt> defintion. </p>
<p>
By default, the tabs, sidebars and pages will be presented in the order in which they are defined. You can, however,
define explicit ordering by adding an "order" attribute to each element. It's numeric value defines order. If no
order is specified, the value 0 (zero) is used as a default. In the example above, the items are ordered using this
construct. In the admin console, the "My Plugin Overview" page will be presented before the "My Plugin Admin" page,
as its 'order' value is lower. If neither item had defined the 'order' attribute, the presentation of both pages
would have been reversed (as it would have used to order in which the pages are defined in XML).
</p>
<p>
You can override existing tabs, sections, and items by using the existing id attribute values in your own
<tt>&lt;adminconsole&gt;</tt> definition.
</p> </p>
<h3>Admin Console Best Practices</h3> <h3>Admin Console Best Practices</h3>
......
...@@ -16,16 +16,7 @@ ...@@ -16,16 +16,7 @@
package org.jivesoftware.admin; package org.jivesoftware.admin;
import java.io.InputStream; import org.dom4j.*;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; import org.dom4j.io.SAXReader;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.ClassUtils; import org.jivesoftware.util.ClassUtils;
...@@ -33,6 +24,10 @@ import org.jivesoftware.util.LocaleUtils; ...@@ -33,6 +24,10 @@ import org.jivesoftware.util.LocaleUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
/** /**
* A model for admin tab and sidebar info. This class loads in XML definitions of the * A model for admin tab and sidebar info. This class loads in XML definitions of the
* data and produces an in-memory model.<p> * data and produces an in-memory model.<p>
...@@ -348,6 +343,30 @@ public class AdminConsole { ...@@ -348,6 +343,30 @@ public class AdminConsole {
} }
} }
} }
// OF-1484: Order everything explicitly.
orderModel();
}
/**
* Sorts all tabs, their containing sidebars, and their containing entries based on the value of their 'order'
* attributes.
*/
private static void orderModel()
{
final Visitor visitor = new VisitorSupport()
{
@Override
public void visit( Element node )
{
// This orders only the elements from the content, which can get messy if mixed content is of importance.
// At the time of writing, the content other than elements was whitespace text (for indentation), which
// is safe to ignore.
Collections.sort( node.content(), new ElementByOrderAttributeComparator() );
super.visit( node );
}
};
generatedModel.accept( visitor );
} }
private static void overrideTab(Element tab, Element overrideTab) { private static void overrideTab(Element tab, Element overrideTab) {
...@@ -364,6 +383,9 @@ public class AdminConsole { ...@@ -364,6 +383,9 @@ public class AdminConsole {
if (overrideTab.attributeValue("plugin") != null) { if (overrideTab.attributeValue("plugin") != null) {
tab.addAttribute("plugin", overrideTab.attributeValue("plugin")); tab.addAttribute("plugin", overrideTab.attributeValue("plugin"));
} }
if (overrideTab.attributeValue("order") != null) {
tab.addAttribute("order", overrideTab.attributeValue("order"));
}
// Override sidebar items. // Override sidebar items.
for (Iterator i=overrideTab.elementIterator(); i.hasNext(); ) { for (Iterator i=overrideTab.elementIterator(); i.hasNext(); ) {
Element sidebar = (Element)i.next(); Element sidebar = (Element)i.next();
...@@ -390,6 +412,9 @@ public class AdminConsole { ...@@ -390,6 +412,9 @@ public class AdminConsole {
if (overrideSidebar.attributeValue("plugin") != null) { if (overrideSidebar.attributeValue("plugin") != null) {
sidebar.addAttribute("plugin", overrideSidebar.attributeValue("plugin")); sidebar.addAttribute("plugin", overrideSidebar.attributeValue("plugin"));
} }
if (overrideSidebar.attributeValue("order") != null) {
sidebar.addAttribute("order", overrideSidebar.attributeValue("order"));
}
// Override entries. // Override entries.
for (Iterator i=overrideSidebar.elementIterator(); i.hasNext(); ) { for (Iterator i=overrideSidebar.elementIterator(); i.hasNext(); ) {
Element entry = (Element)i.next(); Element entry = (Element)i.next();
...@@ -422,6 +447,9 @@ public class AdminConsole { ...@@ -422,6 +447,9 @@ public class AdminConsole {
if (overrideEntry.attributeValue("plugin") != null) { if (overrideEntry.attributeValue("plugin") != null) {
entry.addAttribute("plugin", overrideEntry.attributeValue("plugin")); entry.addAttribute("plugin", overrideEntry.attributeValue("plugin"));
} }
if (overrideEntry.attributeValue("order") != null) {
entry.addAttribute("order", overrideEntry.attributeValue("order"));
}
// Override any sidebars contained in the entry. // Override any sidebars contained in the entry.
for (Iterator i=overrideEntry.elementIterator(); i.hasNext(); ) { for (Iterator i=overrideEntry.elementIterator(); i.hasNext(); ) {
Element sidebar = (Element)i.next(); Element sidebar = (Element)i.next();
...@@ -452,4 +480,29 @@ public class AdminConsole { ...@@ -452,4 +480,29 @@ public class AdminConsole {
classLoaders[2] = ClassLoader.getSystemClassLoader(); classLoaders[2] = ClassLoader.getSystemClassLoader();
return classLoaders; return classLoaders;
} }
/**
* A comparator that compares Nodes by the value of their 'order' attribute, if the node is an Element. When it is
* not, or when the 'order' attribute is absent, or cannot be parsed as an integer, the value '0' is used.
*
* @author Guus der Kinderen, guus.der.kinderen@gmail.com
*/
private static class ElementByOrderAttributeComparator implements Comparator<Node>
{
@Override
public int compare( Node o1, Node o2 )
{
try
{
final int p1 = o1 instanceof Element ? Integer.valueOf( ((Element)o1).attributeValue( "order", "0" ) ) : 0;
final int p2 = o2 instanceof Element ? Integer.valueOf( ((Element)o2).attributeValue( "order", "0" ) ) : 0;
return Integer.compare( p1, p2 );
}
catch ( NumberFormatException e )
{
Log.warn( "Unable to sort admin console tabs, as a non-numeric 'order' attribute value was found.", e );
return 0;
}
}
}
} }
...@@ -551,7 +551,7 @@ ...@@ -551,7 +551,7 @@
</tab> </tab>
<!-- Plugins --> <!-- Plugins -->
<tab id="tab-plugins" name="${tab.tab-plugins}" url="plugin-admin.jsp" description="${tab.tab-plugins.descr}"> <tab id="tab-plugins" name="${tab.tab-plugins}" url="plugin-admin.jsp" description="${tab.tab-plugins.descr}" order="10000">
<!-- Plugin Admin --> <!-- Plugin Admin -->
<sidebar id="sidebar-plugin-admin" name="${sidebar.sidebar-plugin-admin}"> <sidebar id="sidebar-plugin-admin" name="${sidebar.sidebar-plugin-admin}">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment