Simon Hunt

ONOS-1478 - GUI -- Segment navigation menu into categories.

Change-Id: I54bddcada1541ebf2926a6536e4c14bb8a1d3a66
......@@ -41,7 +41,14 @@ public class UiView {
/**
* Represents miscellaneous views.
*/
OTHER("Other");
OTHER("Other"),
/**
* Represents views that do not show in the navigation menu.
* This category should not be specified directly; rather, use
* the {@link UiViewHidden} constructor instead of {@link UiView}.
*/
HIDDEN("(hidden)");
private final String label;
......@@ -64,7 +71,8 @@ public class UiView {
private final Category category;
/**
* Creates a new user interface view descriptor.
* Creates a new user interface view descriptor. The navigation item
* will appear in the navigation menu under the specified category.
*
* @param category view category
* @param id view identifier
......
......@@ -29,7 +29,7 @@ public class UiViewHidden extends UiView {
* @param id view identifier
*/
public UiViewHidden(String id) {
super(Category.OTHER, id, null);
super(Category.HIDDEN, id, null);
}
@Override
......
......@@ -18,7 +18,6 @@ package org.onosproject.ui.impl;
import org.onosproject.ui.UiExtension;
import org.onosproject.ui.UiExtensionService;
import org.onosproject.ui.UiView;
import org.onosproject.ui.UiViewHidden;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
......@@ -29,6 +28,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static com.google.common.collect.ImmutableList.of;
import static com.google.common.io.ByteStreams.toByteArray;
......@@ -41,9 +43,13 @@ public class MainNavResource extends AbstractInjectionResource {
private static final String NAV_HTML = "nav.html";
private static final String INJECT_VIEW_ITEMS_START = "<!-- {INJECTED-VIEW-NAV-START} -->";
private static final String INJECT_VIEW_ITEMS_END = "<!-- {INJECTED-VIEW-NAV-END} -->";
private static final String INJECT_VIEW_ITEMS_START =
"<!-- {INJECTED-VIEW-NAV-START} -->";
private static final String INJECT_VIEW_ITEMS_END =
"<!-- {INJECTED-VIEW-NAV-END} -->";
private static final String HDR_FORMAT =
"<div class=\"nav-hdr\">%s</div>\n";
private static final String NAV_FORMAT =
"<a ng-click=\"navCtrl.hideNav()\" href=\"#/%s\">%s</a>\n";
......@@ -51,31 +57,60 @@ public class MainNavResource extends AbstractInjectionResource {
@Produces(MediaType.TEXT_HTML)
public Response getNavigation() throws IOException {
UiExtensionService service = get(UiExtensionService.class);
InputStream navTemplate = getClass().getClassLoader().getResourceAsStream(NAV_HTML);
String js = new String(toByteArray(navTemplate));
InputStream navTemplate =
getClass().getClassLoader().getResourceAsStream(NAV_HTML);
String html = new String(toByteArray(navTemplate));
int p1s = split(js, 0, INJECT_VIEW_ITEMS_START);
int p1e = split(js, 0, INJECT_VIEW_ITEMS_END);
int p2s = split(js, p1e, null);
int p1s = split(html, 0, INJECT_VIEW_ITEMS_START);
int p1e = split(html, 0, INJECT_VIEW_ITEMS_END);
int p2s = split(html, p1e, null);
StreamEnumeration streams =
new StreamEnumeration(of(stream(js, 0, p1s),
new StreamEnumeration(of(stream(html, 0, p1s),
includeNavItems(service),
stream(js, p1e, p2s)));
stream(html, p1e, p2s)));
return Response.ok(new SequenceInputStream(streams)).build();
}
// Produces an input stream including nav item injections from all extensions.
// Produces an input stream of nav item injections from all extensions.
private InputStream includeNavItems(UiExtensionService service) {
List<UiExtension> extensions = service.getExtensions();
StringBuilder sb = new StringBuilder("\n");
for (UiExtension extension : service.getExtensions()) {
for (UiView view : extension.views()) {
if (!(view instanceof UiViewHidden)) {
sb.append(String.format(NAV_FORMAT, view.id(), view.label()));
for (UiView.Category cat : UiView.Category.values()) {
if (cat == UiView.Category.HIDDEN) {
continue;
}
List<UiView> catViews = getViewsForCat(extensions, cat);
if (!catViews.isEmpty()) {
addCatHeader(sb, cat);
addCatItems(sb, catViews);
}
}
return new ByteArrayInputStream(sb.toString().getBytes());
}
private List<UiView> getViewsForCat(List<UiExtension> extensions,
UiView.Category cat) {
List<UiView> views = new ArrayList<>();
for (UiExtension extension : extensions) {
views.addAll(extension.views().stream().filter(
view -> cat.equals(view.category())
).collect(Collectors.toList()));
}
return views;
}
private void addCatHeader(StringBuilder sb, UiView.Category cat) {
sb.append(String.format(HDR_FORMAT, cat.label()));
}
private void addCatItems(StringBuilder sb, List<UiView> catViews) {
for (UiView view : catViews) {
sb.append(String.format(NAV_FORMAT, view.id(), view.label()));
}
}
}
......
......@@ -22,8 +22,7 @@
position: absolute;
top: 45px;
left: 1px;
Xwidth: 200px;
padding: 0px;
padding: 0;
z-index: 3000;
visibility: hidden;
}
......@@ -37,6 +36,22 @@
box-shadow: 0 2px 8px #111;
}
#nav .nav-hdr {
font-style: italic;
padding: 6px 8px 6px 8px;
}
.light #nav .nav-hdr {
color: #ddd;
border-bottom: solid 1px #999;
background-color: #aaa;
}
.dark #nav .nav-hdr {
color: #888;
border-bottom: solid 1px #444;
background-color: #555;
}
#nav a {
text-decoration: none;
font-size: 14pt;
......@@ -48,7 +63,6 @@
color: #369;
border-bottom: solid #ccc 1px;
}
.dark #nav a {
color: #eee;
border-bottom: solid #333 1px;
......@@ -57,7 +71,6 @@
.light #nav a:hover {
background-color: #ddd;
}
.dark #nav a:hover {
background-color: #777;
}
......