Thomas Vachuska

Preparing for dynamic GUI extensibility.

Change-Id: Ic25143bb9ad8919d7c9e70d932dde528a9227e6a
......@@ -92,7 +92,7 @@ public class UiExtension {
* @return resource input stream
*/
public InputStream resource(String viewId, String path) {
InputStream is = classLoader.getResourceAsStream(prefix + "views/" + viewId + "/" + path);
InputStream is = classLoader.getResourceAsStream(viewId + "/" + path);
return is;
}
......
......@@ -57,32 +57,44 @@
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<outputDirectory>${basedir}/target/classes/WEB-INF/classes/app/view</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp/app/view</directory>
<filtering>true</filtering>
<excludes>
<exclude>_sdh/**</exclude>
<exclude>test/**</exclude>
</excludes>
</resource>
</resources>
<instructions>
<_wab>src/main/webapp/</_wab>
<Include-Resource>src/main/webapp/app/view,{maven-resources}</Include-Resource>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
javax.ws.rs,javax.ws.rs.core,javax.ws.rs.ext,
com.sun.jersey.api,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
com.fasterxml.jackson.databind.node,
com.google.common.base.*,
com.google.common.collect.*,
com.google.common.io.*,
org.eclipse.jetty.websocket.*,
org.onlab.util.*,
org.onlab.osgi.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!--
-->
</project>
......
......@@ -31,6 +31,7 @@ import java.io.SequenceInputStream;
import static com.google.common.collect.ImmutableList.of;
import static com.google.common.io.ByteStreams.toByteArray;
import static org.onosproject.ui.impl.MainViewResource.SCRIPT;
/**
* Resource for serving the dynamically composed onos.js.
......@@ -38,30 +39,35 @@ import static com.google.common.io.ByteStreams.toByteArray;
@Path("/")
public class MainExtResource extends AbstractInjectionResource {
private static final String MAIN_JS = "/onos-template.js";
private static final String NAV_HTML = "/nav-template.html";
private static final String MAIN_JS = "templates/onos-template.js";
private static final String NAV_HTML = "templates/nav-template.html";
private static final String INJECT_VIEW_IDS_START = "// {INJECTED-VIEW-IDS-START}";
private static final String INJECT_VIEW_IDS_END = "// {INJECTED-VIEW-IDS-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 INJECT_VIEW_IDS = "// {INJECTED-VIEW-IDS}";
private static final String INJECT_VIEW_ITEMS = "<!-- {INJECTED-VIEW-NAV} -->";
private static final String NAV_FORMAT =
" <li> <a ng-click=\"navCtrl.hideNav()\" href=\"#/%s\">%s</a></li>";
@Path("/onos.js")
@GET
@Produces(MediaType.TEXT_HTML)
@Produces(SCRIPT)
public Response getMainModule() throws IOException {
UiExtensionService service = get(UiExtensionService.class);
InputStream jsTemplate = getClass().getClassLoader().getResourceAsStream(MAIN_JS);
String js = new String(toByteArray(jsTemplate));
int p1 = split(js, 0, INJECT_VIEW_IDS);
int p2 = split(js, p1, null);
int p1s = split(js, 0, INJECT_VIEW_IDS_START);
int p1e = split(js, 0, INJECT_VIEW_IDS_END);
int p2s = split(js, p1e, null);
StreamEnumeration streams =
new StreamEnumeration(of(stream(js, 0, p1),
new StreamEnumeration(of(stream(js, 0, p1s),
includeViewIds(service),
stream(js, p1, p2)));
stream(js, p1e, p2s)));
return Response.ok(new SequenceInputStream(streams)).build();
}
......@@ -85,13 +91,14 @@ public class MainExtResource extends AbstractInjectionResource {
InputStream navTemplate = getClass().getClassLoader().getResourceAsStream(NAV_HTML);
String js = new String(toByteArray(navTemplate));
int p1 = split(js, 0, INJECT_VIEW_ITEMS);
int p2 = split(js, p1, null);
int p1s = split(js, 0, INJECT_VIEW_ITEMS_START);
int p1e = split(js, 0, INJECT_VIEW_ITEMS_END);
int p2s = split(js, p1e, null);
StreamEnumeration streams =
new StreamEnumeration(of(stream(js, 0, p1),
new StreamEnumeration(of(stream(js, 0, p1s),
includeNavItems(service),
stream(js, p1, p2)));
stream(js, p1e, p2s)));
return Response.ok(new SequenceInputStream(streams)).build();
}
......
......@@ -37,12 +37,14 @@ import static com.google.common.io.ByteStreams.toByteArray;
@Path("/")
public class MainIndexResource extends AbstractInjectionResource {
private static final String INDEX = "/index-template.html";
private static final String INDEX = "templates/index-template.html";
private static final String INJECT_CSS = "<!-- {INJECTED-STYLESHEETS} -->";
private static final String INJECT_JS = "<!-- {INJECTED-JAVASCRIPT} -->";
private static final String INJECT_CSS_START = "<!-- {INJECTED-STYLESHEETS-START} -->";
private static final String INJECT_CSS_END = "<!-- {INJECTED-STYLESHEETS-END} -->";
private static final String INJECT_JS_START = "<!-- {INJECTED-JAVASCRIPT-START} -->";
private static final String INJECT_JS_END = "<!-- {INJECTED-JAVASCRIPT-END} -->";
@Path("/")
@GET
@Produces(MediaType.TEXT_HTML)
public Response getMainIndex() throws IOException {
......@@ -50,16 +52,18 @@ public class MainIndexResource extends AbstractInjectionResource {
InputStream indexTemplate = getClass().getClassLoader().getResourceAsStream(INDEX);
String index = new String(toByteArray(indexTemplate));
int p1 = split(index, 0, INJECT_JS);
int p2 = split(index, p1, INJECT_CSS);
int p3 = split(index, p2, null);
int p1s = split(index, 0, INJECT_JS_START);
int p1e = split(index, p1s, INJECT_JS_END);
int p2s = split(index, p1e, INJECT_CSS_START);
int p2e = split(index, p2s, INJECT_CSS_END);
int p3s = split(index, p2e, null);
StreamEnumeration streams =
new StreamEnumeration(of(stream(index, 0, p1),
new StreamEnumeration(of(stream(index, 0, p1s),
includeJs(service),
stream(index, p1, p2),
stream(index, p1e, p2s),
includeCss(service),
stream(index, p2, p3)));
stream(index, p2e, p3s)));
return Response.ok(new SequenceInputStream(streams)).build();
}
......
......@@ -33,9 +33,9 @@ import static javax.ws.rs.core.MediaType.TEXT_HTML;
@Path("/")
public class MainViewResource extends AbstractInjectionResource {
private static final String CONTENT_TYPE = "Content-Type";
private static final String STYLESHEET = "text/css";
private static final String SCRIPT = "text/javascript";
static final String CONTENT_TYPE = "Content-Type";
static final String STYLESHEET = "text/css";
static final String SCRIPT = "text/javascript";
@Path("{view}/{resource}")
@GET
......
......@@ -54,7 +54,8 @@ public class UiExtensionManager implements UiExtensionService {
new UiView("topo", "Topology View"),
new UiView("device", "Devices"));
private final UiExtension core = new UiExtension(coreViews, getClass().getClassLoader());
private final UiExtension core = new UiExtension(coreViews, "core",
getClass().getClassLoader());
@Activate
public void activate() {
......
<!DOCTYPE html>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
~ Copyright 2014,2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="data/img/onos-logo.png">
<link rel="shortcut icon" href="../data/img/onos-logo.png">
<title>ONOS Angular</title>
<!-- Third party library code included here -->
......@@ -35,6 +35,7 @@
<script src="app/fw/util/util.js"></script>
<script src="app/fw/util/fn.js"></script>
<script src="app/fw/util/random.js"></script>
<script src="app/fw/util/theme.js"></script>
<script src="app/fw/util/keys.js"></script>
......@@ -57,9 +58,14 @@
<script src="app/fw/widget/widget.js"></script>
<script src="app/fw/widget/table.js"></script>
<script src="app/fw/widget/toolbar.js"></script>
<script src="app/fw/widget/button.js"></script>
<script src="app/fw/layer/layer.js"></script>
<script src="app/fw/layer/panel.js"></script>
<script src="app/fw/layer/flash.js"></script>
<script src="app/fw/layer/quickhelp.js"></script>
<script src="app/fw/layer/veil.js"></script>
<!-- Framework and library stylesheets included here -->
<!-- TODO: use a single catenated-minified file here -->
......@@ -69,16 +75,39 @@
<link rel="stylesheet" href="app/fw/svg/glyph.css">
<link rel="stylesheet" href="app/fw/svg/icon.css">
<link rel="stylesheet" href="app/fw/layer/panel.css">
<link rel="stylesheet" href="app/fw/layer/flash.css">
<link rel="stylesheet" href="app/fw/layer/quickhelp.css">
<link rel="stylesheet" href="app/fw/layer/veil.css">
<link rel="stylesheet" href="app/fw/nav/nav.css">
<!-- This is where contributed javascript will get injected -->
<!-- {INJECTED-JAVASCRIPT} -->
<!-- {INJECTED-JAVASCRIPT-START} -->
<script src="app/view/sample/sample.js"></script>
<script src="app/view/topo/topo.js"></script>
<script src="app/view/topo/topoEvent.js"></script>
<script src="app/view/topo/topoFilter.js"></script>
<script src="app/view/topo/topoForce.js"></script>
<script src="app/view/topo/topoInst.js"></script>
<script src="app/view/topo/topoModel.js"></script>
<script src="app/view/topo/topoOblique.js"></script>
<script src="app/view/topo/topoPanel.js"></script>
<script src="app/view/topo/topoSelect.js"></script>
<script src="app/view/topo/topoTraffic.js"></script>
<script src="app/view/device/device.js"></script>
<!-- {INJECTED-JAVASCRIPT-END} -->
<!-- This is where contributed stylesheets will get injected -->
<!-- {INJECTED-STYLESHEETS} -->
<!-- {INJECTED-STYLESHEETS-START} -->
<link rel="stylesheet" href="app/view/sample/sample.css">
<link rel="stylesheet" href="app/view/topo/topo.css">
<link rel="stylesheet" href="app/view/device/device.css">
<!-- TODO: inject style-sheet refs server-side -->
<!-- {INJECTED-STYLESHEETS-END} -->
</head>
<body class="light" ng-app="onosApp">
<div id="frame" ng-controller="OnosCtrl as onosCtrl">
<div id="frame" ng-controller="OnosCtrl as onosCtrl">
<div id="mast"
ng-controller="MastCtrl as mastCtrl"
ng-include="'app/fw/mast/mast.html'"></div>
......@@ -93,7 +122,9 @@
<div id="alerts"></div>
<div id="flash"></div>
<div id="quickhelp"></div>
<div id="deathmask"></div>
</div>
<div id="veil"
resize
ng-style="resizeWithOffset(0, 0)"></div>
</div>
</body>
</html>
......
......@@ -3,5 +3,6 @@
<h3>(Note - this is temporary)</h3>
<ul>
<!-- {INJECTED-VIEW-NAV} -->
<!-- {INJECTED-VIEW-NAV-START} -->
<!-- {INJECTED-VIEW-NAV-END} -->
</ul>
......
/*
* Copyright 2015 Open Networking Laboratory
* Copyright 2014,2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -36,8 +36,11 @@
// view IDs.. note the first view listed is loaded at startup
var viewIds = [
// TODO: inject view IDs server side
// {INJECTED-VIEW-IDS}
// (end of injected views)
// {INJECTED-VIEW-IDS-START}
'sample',
'topo',
'device',
// {INJECTED-VIEW-IDS-END}
// dummy entry
''
......@@ -62,8 +65,10 @@
.controller('OnosCtrl', [
'$log', '$route', '$routeParams', '$location',
'KeyService', 'ThemeService', 'GlyphService', 'PanelService',
'FlashService', 'QuickHelpService',
function ($log, $route, $routeParams, $location, ks, ts, gs, ps) {
function ($log, $route, $routeParams, $location,
ks, ts, gs, ps, flash, qhs) {
var self = this;
self.$route = $route;
......@@ -74,8 +79,11 @@
// initialize services...
ts.init();
ks.installOn(d3.select('body'));
ks.bindQhs(qhs);
gs.init();
ps.init();
flash.initFlash();
qhs.initQuickHelp();
$log.log('OnosCtrl has been created');
......@@ -94,8 +102,9 @@
function viewCtrlName(vid) {
return 'Ov' + capitalize(vid) + 'Ctrl';
}
function viewTemplateUrl(vid) {
return 'view/' + vid + '/' + vid + '.html';
return 'app/view/' + vid + '/' + vid + '.html';
}
// Add routes for each defined view.
......
......@@ -59,7 +59,7 @@
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>org.onosproject.gui.impl.MainIndexResource</param-value>
<param-value>org.onosproject.ui.impl.MainIndexResource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
......@@ -78,7 +78,7 @@
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>org.onosproject.gui.impl.MainExtResource</param-value>
<param-value>org.onosproject.ui.impl.MainExtResource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
......
......@@ -81,7 +81,7 @@
<link rel="stylesheet" href="fw/nav/nav.css">
<!-- This is where contributed javascript will get injected -->
<!-- {INJECTED-JAVASCRIPT} -->
<!-- {INJECTED-JAVASCRIPT-START} -->
<script src="view/sample/sample.js"></script>
<script src="view/topo/topo.js"></script>
<script src="view/topo/topoEvent.js"></script>
......@@ -94,17 +94,20 @@
<script src="view/topo/topoSelect.js"></script>
<script src="view/topo/topoTraffic.js"></script>
<script src="view/device/device.js"></script>
<!-- TODO: inject javascript refs server-side -->
<!-- {INJECTED-JAVASCRIPT-END} -->
<!-- This is where contributed stylesheets will get injected -->
<!-- {INJECTED-STYLESHEETS} -->
<!-- {INJECTED-STYLESHEETS-START} -->
<link rel="stylesheet" href="view/sample/sample.css">
<link rel="stylesheet" href="view/topo/topo.css">
<link rel="stylesheet" href="view/device/device.css">
<!-- TODO: inject style-sheet refs server-side -->
<!-- {INJECTED-STYLESHEETS-END} -->
</head>
<body class="light" ng-app="onosApp">
<div id="frame" ng-controller="OnosCtrl as onosCtrl">
<div id="frame" ng-controller="OnosCtrl as onosCtrl">
<div id="mast"
ng-controller="MastCtrl as mastCtrl"
ng-include="'fw/mast/mast.html'"></div>
......@@ -122,6 +125,6 @@
<div id="veil"
resize
ng-style="resizeWithOffset(0, 0)"></div>
</div>
</div>
</body>
</html>
......
......@@ -36,11 +36,11 @@
// view IDs.. note the first view listed is loaded at startup
var viewIds = [
// TODO: inject view IDs server side
// {INJECTED-VIEW-IDS}
// {INJECTED-VIEW-IDS-START}
'sample',
'topo',
'device',
// (end of injected views)
// {INJECTED-VIEW-IDS-END}
// dummy entry
''
......@@ -102,6 +102,7 @@
function viewCtrlName(vid) {
return 'Ov' + capitalize(vid) + 'Ctrl';
}
function viewTemplateUrl(vid) {
return 'view/' + vid + '/' + vid + '.html';
}
......