Implemented navigation

This commit is contained in:
Ziver Koc 2015-04-25 15:22:44 +00:00
parent 846ed78252
commit b3e0757b29
11 changed files with 203 additions and 90 deletions

View file

@ -24,16 +24,21 @@
<a class="navbar-brand" href="#">{{title}}</a> <a class="navbar-brand" href="#">{{title}}</a>
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
{{#top-nav}} {{#top-nav}}
{{^.sub_navs.length}}
<li><a href="{{.url}}">{{.name}}</a></li>
{{/.sub_navs.length}}
{{#.sub_navs.length}}
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{.name}} {{#.sub_nav.length}}<b class="caret"></b>{{/.sub_nav.length}} {{.name}} <b class="caret"></b>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{{#.sub_nav}} {{#.sub_navs}}
<li><a href="#">{{.name}}</a></li> <li><a href="{{.url}}">{{.name}}</a></li>
{{/.sub_nav}} {{/.sub_navs}}
</ul> </ul>
</li> </li>
{{/.sub_navs.length}}
{{/top-nav}} {{/top-nav}}
</ul> </ul>
</nav> </nav>
@ -44,16 +49,21 @@
<div id="side-bar" class="col-md-2"> <div id="side-bar" class="col-md-2">
<ul class="side-menu nav nav-pills nav-stacked"> <ul class="side-menu nav nav-pills nav-stacked">
{{#side-nav}} {{#side-nav}}
{{^.sub_navs.length}}
<li><a href="{{.url}}">{{.name}}</a></li>
{{/.sub_navs.length}}
{{#.sub_nav.length}}
<li class=""> <li class="">
<a data-toggle="collapse" data-parent="#side-bar" href="#{{.name}}_collapse"> <a data-toggle="collapse" data-parent="#side-bar" href="#{{.name}}_collapse">
{{.name}} {{#.sub_nav.length}}<b class="caret"></b>{{/.sub_nav.length}} {{.name}} <b class="caret"></b>
</a> </a>
<ul id="{{.name}}_collapse" class="side-sub-menu collapse nav nav-pills nav-stacked "> <ul id="{{.name}}_collapse" class="side-sub-menu collapse nav nav-pills nav-stacked ">
{{#.sub_nav}} {{#.sub_navs}}
<li><a href="#">{{.name}}</a></li> <li><a href="{{.url}}">{{.name}}</a></li>
{{/.sub_nav}} {{/.sub_navs}}
</ul> </ul>
</li> </li>
{{/.sub_nav.length}}
{{/side-nav}} {{/side-nav}}
</ul> </ul>
</div> </div>
@ -64,9 +74,9 @@
<!-- Page specific info --> <!-- Page specific info -->
<div class="row"> <div class="row">
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a href="#">Home</a></li> {{#breadcrumb}}
<li><a href="#">Library</a></li> <li><a href="{{.url}}">{{.name}}</a></li>
<li class="active">Data</li> {{/breadcrumb}}
</ol> </ol>
</div> </div>
<!-- Alerts --> <!-- Alerts -->

File diff suppressed because one or more lines are too long

View file

@ -20,9 +20,13 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package wa.server.page; package wa.server;
import wa.server.WAContext; import wa.server.WAContext;
import wa.server.page.ServicesPage;
import wa.server.page.StatusPage;
import wa.server.page.WAPage;
import wa.server.page.struct.WANavigation;
import zutil.io.file.FileUtil; import zutil.io.file.FileUtil;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.net.http.HttpHeaderParser; import zutil.net.http.HttpHeaderParser;
@ -31,23 +35,31 @@ import zutil.net.http.HttpPrintStream;
import zutil.parser.DataNode; import zutil.parser.DataNode;
import zutil.parser.Templator; import zutil.parser.Templator;
import zutil.parser.json.JSONWriter; import zutil.parser.json.JSONWriter;
import zutil.plugin.PluginManager;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.sql.Array;
import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* Created by Ziver on 2015-04-02. * Created by Ziver on 2015-04-02.
*/ */
public abstract class AbstractPage implements HttpPage{ public class WAAbstractPage implements HttpPage{
private static final Logger log = LogUtil.getLogger(); private static final Logger log = LogUtil.getLogger();
private static final String TMPL_FILE = "WebContent/index.tmpl"; private static final String TMPL_FILE = "WebContent/index.tmpl";
private List<WAPage> pages;
private Templator tmpl; private Templator tmpl;
public AbstractPage() { public WAAbstractPage(PluginManager pluginManager) {
try { try {
pages = Arrays.asList(new WAPage[] {
new StatusPage(pluginManager),
new ServicesPage(pluginManager)
});
tmpl = new Templator(FileUtil.find(TMPL_FILE)); tmpl = new Templator(FileUtil.find(TMPL_FILE));
} catch(IOException e){ } catch(IOException e){
log.log(Level.SEVERE, null, e); log.log(Level.SEVERE, null, e);
@ -62,14 +74,20 @@ public abstract class AbstractPage implements HttpPage{
Map<String, Object> session, Map<String, Object> session,
Map<String, String> cookie, Map<String, String> cookie,
Map<String, String> request) throws IOException { Map<String, String> request) throws IOException {
WAContext context = (WAContext)session.get("context"); WAContext context = new WAContext(request);
if(context == null){ List<WANavigation> breadcrumb = context.getBreadcrumb();
context = new WAContext(); WAPage page = null;
if(breadcrumb.size() > 0){
int i = pages.indexOf(breadcrumb.get(0).getResource());
if(i >= 0)
page = pages.get(i);
} }
if(("application/json").equals(client_info.getHeader("ContentType")) || if(("application/json").equals(client_info.getHeader("ContentType")) ||
request.containsKey("json")){ request.containsKey("json")){
DataNode node = jsonResponse(context, client_info, session, cookie, request); DataNode node = null;
if(page != null)
node = page.jsonResponse(context, client_info, session, cookie, request);
if(node != null) { if(node != null) {
out.setHeader("Content-Type", "application/json"); out.setHeader("Content-Type", "application/json");
JSONWriter writer = new JSONWriter(out); JSONWriter writer = new JSONWriter(out);
@ -83,11 +101,15 @@ public abstract class AbstractPage implements HttpPage{
tmpl.set("title", "WebAdmin"); tmpl.set("title", "WebAdmin");
tmpl.set("top-nav", context.getNavigation()); tmpl.set("top-nav", context.getNavigation());
tmpl.set("side-nav-show", true); tmpl.set("side-nav-show", true);
tmpl.set("side-nav", context.getNavigation().get(0).getSubNav()); if(breadcrumb.size() >= 1)
tmpl.set("side-nav", breadcrumb.get(0).getSubNav());
tmpl.set("breadcrumb", breadcrumb);
tmpl.set("alerts", context.getAlerts()); tmpl.set("alerts", context.getAlerts());
//tmpl.set("footer", null); //tmpl.set("footer", null);
Templator content = htmlResponse(context, client_info, session, cookie, request); Templator content = null;
if(page != null)
content = page.htmlResponse(context, client_info, session, cookie, request);
if(content != null) if(content != null)
tmpl.set("content", content.compile()); tmpl.set("content", content.compile());
@ -95,17 +117,4 @@ public abstract class AbstractPage implements HttpPage{
} }
} }
public abstract Templator htmlResponse(WAContext context,
HttpHeaderParser client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request);
public DataNode jsonResponse(WAContext context,
HttpHeaderParser client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request){
return null;
}
} }

View file

@ -26,36 +26,36 @@ import wa.server.page.struct.WAAlert;
import wa.server.page.struct.WANavigation; import wa.server.page.struct.WANavigation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Created by Ziver on 2015-04-06. * Created by Ziver on 2015-04-06.
*/ */
public class WAContext { public class WAContext {
private WANavigation nav;
private ArrayList<WAAlert> alerts; private ArrayList<WAAlert> alerts;
private List<WANavigation> nav;
private List<WANavigation> breadcrumb;
public WAContext(){ public WAContext(Map<String, String> request){
// Navigation
nav = WANavigation.getRootNav(); nav = WANavigation.getRootNav();
/*nav = new WANavigation[]{
new WANavigation("Status"), // Breadcrumb
new WANavigation("Services", new WANavigation[]{ breadcrumb = WANavigation.getNavResource(request);
new WANavigation("Apache"),
new WANavigation("Tomcat"),
new WANavigation("Samba")
}),
new WANavigation("Configure")
};
alerts = new ArrayList<WAAlert>();*/
} }
public List<WANavigation> getNavigation(){
return nav.getSubNav();
}
public ArrayList<WAAlert> getAlerts() { public ArrayList<WAAlert> getAlerts() {
return alerts; return alerts;
} }
public List<WANavigation> getNavigation(){
return nav;
}
public List<WANavigation> getBreadcrumb(){
return breadcrumb;
}
} }

View file

@ -1,6 +1,5 @@
package wa.server; package wa.server;
import wa.server.page.AbstractPage;
import wa.server.page.StatusPage; import wa.server.page.StatusPage;
import zutil.io.file.FileUtil; import zutil.io.file.FileUtil;
import zutil.log.CompactLogFormatter; import zutil.log.CompactLogFormatter;
@ -29,7 +28,7 @@ public class WebAdminServer {
pluginManager = new PluginManager(); pluginManager = new PluginManager();
HttpServer http = new HttpServer(80); HttpServer http = new HttpServer(80);
http.setPage("/", new StatusPage(pluginManager)); http.setPage("/", new WAAbstractPage(pluginManager));
http.setDefaultPage(new HttpFilePage(FileUtil.find("WebContent/"))); http.setDefaultPage(new HttpFilePage(FileUtil.find("WebContent/")));
http.start(); http.start();

View file

@ -22,10 +22,10 @@
package wa.server.page; package wa.server.page;
import wa.server.WAAbstractPage;
import wa.server.WAContext; import wa.server.WAContext;
import wa.server.page.struct.WANavigation; import wa.server.page.struct.WANavigation;
import wa.server.plugin.WAService; import wa.server.plugin.WAService;
import wa.server.plugin.WAStatus;
import zutil.net.http.HttpHeaderParser; import zutil.net.http.HttpHeaderParser;
import zutil.parser.DataNode; import zutil.parser.DataNode;
import zutil.parser.Templator; import zutil.parser.Templator;
@ -37,7 +37,7 @@ import java.util.Map;
/** /**
* Created by Ziver on 2015-04-06. * Created by Ziver on 2015-04-06.
*/ */
public class ServicesPage extends AbstractPage{ public class ServicesPage implements WAPage {
private ArrayList<WAService> plugins; private ArrayList<WAService> plugins;
public ServicesPage(PluginManager pluginManager){ public ServicesPage(PluginManager pluginManager){
@ -46,7 +46,7 @@ public class ServicesPage extends AbstractPage{
WANavigation nav = new WANavigation("Services"); WANavigation nav = new WANavigation("Services");
for(WAService plugin : plugins) for(WAService plugin : plugins)
nav.addSubNav(new WANavigation(plugin.getName())); nav.addSubNav(new WANavigation(plugin.getName()));
WANavigation.getRootNav().addSubNav(nav); WANavigation.addRootNav(nav);
} }

View file

@ -22,6 +22,7 @@
package wa.server.page; package wa.server.page;
import wa.server.WAAbstractPage;
import wa.server.WAContext; import wa.server.WAContext;
import wa.server.page.struct.WANavigation; import wa.server.page.struct.WANavigation;
import wa.server.plugin.WAStatus; import wa.server.plugin.WAStatus;
@ -30,23 +31,22 @@ import zutil.parser.DataNode;
import zutil.parser.Templator; import zutil.parser.Templator;
import zutil.plugin.PluginManager; import zutil.plugin.PluginManager;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
/** /**
* Created by Ziver on 2015-04-06. * Created by Ziver on 2015-04-06.
*/ */
public class StatusPage extends AbstractPage{ public class StatusPage implements WAPage {
private ArrayList<WAStatus> plugins; private ArrayList<WAStatus> plugins;
public StatusPage(PluginManager pluginManager){ public StatusPage(PluginManager pluginManager){
this.plugins = pluginManager.toArray(WAStatus.class); this.plugins = pluginManager.toArray(WAStatus.class);
WANavigation nav = new WANavigation("Status"); WANavigation nav = new WANavigation("Status", this);
for(WAStatus plugin : plugins) for(WAStatus plugin : plugins)
nav.addSubNav(new WANavigation(plugin.getName())); nav.addSubNav(new WANavigation(plugin.getName(), plugin));
WANavigation.getRootNav().addSubNav(nav); WANavigation.addRootNav(nav);
} }
@ -56,14 +56,14 @@ public class StatusPage extends AbstractPage{
Map<String, Object> session, Map<String, Object> session,
Map<String, String> cookie, Map<String, String> cookie,
Map<String, String> request) { Map<String, String> request) {
WAStatus obj = null;
if(request.containsKey("i"))
obj = getPlugin(Integer.parseInt(request.get("i")));
else
obj = getPlugin(0);
if(obj != null) WAStatus obj = getPlugin(context);
return new Templator(obj.html());
if(obj != null) {
Templator tmpl = new Templator(obj.html());
tmpl.set("nav", context.getBreadcrumb().get(1));
return tmpl;
}
return null; return null;
} }
@ -74,7 +74,7 @@ public class StatusPage extends AbstractPage{
Map<String, String> request){ Map<String, String> request){
if(request.containsKey("i")) { if(request.containsKey("i")) {
WAStatus obj = getPlugin(Integer.parseInt(request.get("i"))); WAStatus obj = getPlugin(context);
DataNode root = new DataNode(DataNode.DataType.Map); DataNode root = new DataNode(DataNode.DataType.Map);
obj.jsonUpdate(request, root); obj.jsonUpdate(request, root);
return root; return root;
@ -82,9 +82,14 @@ public class StatusPage extends AbstractPage{
return null; return null;
} }
private WAStatus getPlugin(int i){
if(0 >= i && i < plugins.size()) private WAStatus getPlugin(WAContext context){
return plugins.get(i); if(context.getBreadcrumb().size() >= 2){
int i = plugins.indexOf(context.getBreadcrumb().get(1).getResource());
if(i >= 0)
return plugins.get(i);
}
return null; return null;
} }
} }

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.page;
import wa.server.WAContext;
import zutil.net.http.HttpHeaderParser;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import java.util.Map;
/**
* Created by Ziver on 2015-04-25.
*/
public interface WAPage {
public abstract Templator htmlResponse(WAContext context,
HttpHeaderParser client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request);
public DataNode jsonResponse(WAContext context,
HttpHeaderParser client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request);
}

View file

@ -22,42 +22,62 @@
package wa.server.page.struct; package wa.server.page.struct;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
/** /**
* Created by Ziver on 2015-04-02. * Created by Ziver on 2015-04-02.
*/ */
public class WANavigation { public class WANavigation {
private static WANavigation rootNav; private static int nextId;
private static List<WANavigation> root_nav = new ArrayList<WANavigation>();
private static HashMap<Integer, WANavigation> nav_map = new HashMap<Integer, WANavigation>();
private int id;
private String url;
private String name; private String name;
private ArrayList<WANavigation> subNavs; private ArrayList<WANavigation> sub_navs;
private WANavigation parent_nav;
private Object resource;
public WANavigation(String name) { public WANavigation(String name) {
this.id = nextId++;
this.nav_map.put(this.id, this);
this.url = "?i="+this.id;
this.name = name; this.name = name;
this.subNavs = new ArrayList<>(); this.sub_navs = new ArrayList<>();
} }
public WANavigation(String name, WANavigation[] sub_nav) { public WANavigation(String name, Object resource) {
this(name); this(name);
this.subNavs.addAll(Arrays.asList(sub_nav)); this.setResource(resource);
} }
public void addSubNav(WANavigation subNav) { public void addSubNav(WANavigation subNav) {
this.subNavs.add(subNav); this.sub_navs.add(subNav);
subNav.setParentNav(this );
} }
public List<WANavigation> getSubNav() { public List<WANavigation> getSubNav() {
return subNavs; return sub_navs;
} }
public Object getSubNav(String name) { public Object getSubNav(String name) {
int index = subNavs.indexOf(name); int index = sub_navs.indexOf(name);
if(index >= 0) if(index >= 0)
return subNavs.get(index); return sub_navs.get(index);
return null; return null;
} }
public Object getResource(){
return resource;
}
public void setResource(Object obj){
resource = obj;
}
private void setParentNav(WANavigation nav){
this.parent_nav = nav;
}
public boolean equals(Object o){ public boolean equals(Object o){
if(o instanceof String) if(o instanceof String)
@ -67,9 +87,22 @@ public class WANavigation {
} }
public static WANavigation getRootNav(){ public static void addRootNav(WANavigation nav){
if(rootNav == null) getRootNav().add(nav);
rootNav = new WANavigation("root_nav"); }
return rootNav; public static List<WANavigation> getRootNav(){
return root_nav;
}
public static List<WANavigation> getNavResource(Map<String, String> request) {
LinkedList list = new LinkedList();
if(request.containsKey("i")){
WANavigation current = nav_map.get(Integer.parseInt(request.get("i")));
while(current != null){
list.addFirst(current);
current = current.parent_nav;
}
}
return list;
} }
} }

View file

@ -47,7 +47,7 @@ var hdd_io_data = {
}; };
function updateHdd(){ function updateHdd(){
$.getJSON("?i=0&json&hdd", function( data ) { $.getJSON("{{nav.url}}&json&hdd", function( data ) {
$.each(data['hdd'], function( index, hdd ){ $.each(data['hdd'], function( index, hdd ){
var element = null; var element = null;
var html_id = "hdd-id-" + hdd.id; var html_id = "hdd-id-" + hdd.id;

View file

@ -54,7 +54,7 @@ var cpu_data = {
}; };
function updateCpuChart(){ function updateCpuChart(){
$.getJSON("?i=0&json&cpu", function( data ) { $.getJSON("{{nav.url}}&json&cpu", function( data ) {
// Setup graph // Setup graph
if(cpu_chart == null){ if(cpu_chart == null){
// Fill in cpus // Fill in cpus
@ -102,7 +102,7 @@ var mem_data = [
]; ];
function updateMemChart(){ function updateMemChart(){
$.getJSON("?i=0&json&memory", function( data ) { $.getJSON("{{nav.url}}&json&memory", function( data ) {
if(mem_chart == null){ if(mem_chart == null){
var ctx = $("#mem-chart").get(0).getContext("2d"); var ctx = $("#mem-chart").get(0).getContext("2d");
mem_chart = new Chart(ctx).Doughnut(mem_data, { mem_chart = new Chart(ctx).Doughnut(mem_data, {
@ -123,7 +123,7 @@ function updateMemChart(){
function updateProcTable(){ function updateProcTable(){
$.getJSON("?i=0&json&proc", function( data ) { $.getJSON("{{nav.url}}&json&proc", function( data ) {
$('#proc-list').bootstrapTable({ $('#proc-list').bootstrapTable({
data: data['proc'] data: data['proc']
}); });