Simon Hunt
Committed by Gerrit Code Review

ONOS-2851 - Web UI - create archetype for table view based app.

- added uitab overlay archetype.
- renamed stuff so ui apps can coexist.
- WIP ... custom view source needs to be pared down.

Change-Id: I196e10d69ddc231eb0bc9cc5923f29872035b4fd
Showing 22 changed files with 768 additions and 47 deletions
......@@ -38,6 +38,7 @@
<module>bundle</module>
<module>cli</module>
<module>ui</module>
<module>uitab</module>
</modules>
<build>
......
......@@ -26,6 +26,6 @@
<artifactId>onos-ui-archetype</artifactId>
<packaging>maven-archetype</packaging>
<description>ONOS UI overlay archetype</description>
<description>ONOS UI Custom-View overlay archetype</description>
</project>
......
......@@ -22,7 +22,7 @@
<version>${version}</version>
<packaging>bundle</packaging>
<description>ONOS OSGi UI bundle archetype</description>
<description>ONOS OSGi UI Custom-View bundle archetype</description>
<url>http://onosproject.org</url>
<properties>
......
......@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Skeletal ONOS UI application component.
* Skeletal ONOS UI Custom-View application component.
*/
@Component(immediate = true)
public class AppUiComponent {
......@@ -46,7 +46,7 @@ public class AppUiComponent {
// List of application views
private final List<UiView> uiViews = ImmutableList.of(
new UiView(UiView.Category.OTHER, "sample", "Sample")
new UiView(UiView.Category.OTHER, "sampleCustom", "Sample Custom")
);
// Factory for UI message handlers
......
......@@ -33,18 +33,17 @@ import java.util.Collection;
import java.util.List;
/**
* Skeletal ONOS UI message handler.
* <p>
* This example specifically supporting a "table" view.
* Skeletal ONOS UI Custom-View message handler.
*/
public class AppUiMessageHandler extends UiMessageHandler {
// TODO: reduce the code down to just the custom view example
private static final String SAMPLE_DATA_REQ = "sampleDataRequest";
private static final String SAMPLE_DATA_RESP = "sampleDataResponse";
private static final String SAMPLES = "samples";
private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest";
private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse";
private static final String SAMPLE_CUSTOMS = "sampleCustoms";
private static final String SAMPLE_DETAIL_REQ = "sampleDetailsRequest";
private static final String SAMPLE_DETAIL_RESP = "sampleDetailsResponse";
private static final String SAMPLE_CUSTOM_DETAIL_REQ = "sampleCustomDetailsRequest";
private static final String SAMPLE_CUSTOM_DETAIL_RESP = "sampleCustomDetailsResponse";
private static final String DETAILS = "details";
private static final String ID = "id";
......@@ -61,20 +60,18 @@ public class AppUiMessageHandler extends UiMessageHandler {
@Override
protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new SampleDataRequestHandler(),
new SampleDetailRequestHandler()
new SampleCustomDataRequestHandler(),
new SampleCustomDetailRequestHandler()
);
}
// handler for sample table requests
private final class SampleDataRequestHandler extends TableRequestHandler {
private final class SampleCustomDataRequestHandler extends TableRequestHandler {
private SampleDataRequestHandler() {
super(SAMPLE_DATA_REQ, SAMPLE_DATA_RESP, SAMPLES);
private SampleCustomDataRequestHandler() {
super(SAMPLE_CUSTOM_DATA_REQ, SAMPLE_CUSTOM_DATA_RESP, SAMPLE_CUSTOMS);
}
// if necessary, override defaultColumnId() -- if it isn't "id"
@Override
protected String[] getColumnIds() {
return COLUMN_IDS;
......@@ -106,10 +103,10 @@ public class AppUiMessageHandler extends UiMessageHandler {
// handler for sample item details requests
private final class SampleDetailRequestHandler extends RequestHandler {
private final class SampleCustomDetailRequestHandler extends RequestHandler {
private SampleDetailRequestHandler() {
super(SAMPLE_DETAIL_REQ);
private SampleCustomDetailRequestHandler() {
super(SAMPLE_CUSTOM_DETAIL_REQ);
}
@Override
......@@ -139,7 +136,7 @@ public class AppUiMessageHandler extends UiMessageHandler {
data.put(COMMENT, "Some arbitrary comment");
}
sendMessage(SAMPLE_DETAIL_RESP, 0, rootNode);
sendMessage(SAMPLE_CUSTOM_DETAIL_RESP, 0, rootNode);
}
}
......
......@@ -5,31 +5,31 @@
}
/* Panel Styling */
#item-details-panel.floatpanel {
#ov-sample-custom-item-details-panel.floatpanel {
position: absolute;
top: 115px;
}
.light #item-details-panel.floatpanel {
.light #ov-sample-custom-item-details-panel.floatpanel {
background-color: rgb(229, 234, 237);
}
.dark #item-details-panel.floatpanel {
.dark #ov-sample-custom-item-details-panel.floatpanel {
background-color: #3A4042;
}
#item-details-panel h3 {
#ov-sample-custom-item-details-panel h3 {
margin: 0;
font-size: large;
}
#item-details-panel h4 {
#ov-sample-custom-item-details-panel h4 {
margin: 0;
}
#item-details-panel td {
#ov-sample-custom-item-details-panel td {
padding: 5px;
}
#item-details-panel td.label {
#ov-sample-custom-item-details-panel td.label {
font-style: italic;
opacity: 0.8;
}
\ No newline at end of file
}
......
<!-- partial HTML -->
<div id="ov-sample">
<div id="ov-sample-custom">
<div class="tabular-header">
<h2>Items ({{tableData.length}} total)</h2>
<div class="ctrl-btns">
......@@ -42,5 +42,5 @@
</div>
<item-details-panel></item-details-panel>
<ov-sample-custom-item-details-panel></ov-sample-custom-item-details-panel>
</div>
......
// js for sample app view
// js for sample app custom view
(function () {
'use strict';
// injected refs
var $log, $scope, fs, wss, ps;
var $log, $scope, fs, wss;
// constants
var detailsReq = 'sampleDetailsRequest',
detailsResp = 'sampleDetailsResponse',
pName = 'item-details-panel',
var detailsReq = 'sampleCustomDetailsRequest',
detailsResp = 'sampleCustomDetailsResponse',
pName = 'ov-sample-custom-item-details-panel',
propOrder = ['id', 'label', 'code'],
friendlyProps = ['Item ID', 'Item Label', 'Special Code'];
......@@ -44,8 +44,8 @@
$scope.$apply();
}
angular.module('ovSample', [])
.controller('OvSampleCtrl',
angular.module('ovSampleCustom', [])
.controller('OvSampleCustomCtrl',
['$log', '$scope', 'TableBuilderService',
'FnService', 'WebSocketService',
......@@ -75,24 +75,24 @@
// TableBuilderService creating a table for us
tbs.buildTable({
scope: $scope,
tag: 'sample',
tag: 'sampleCustom',
selCb: selCb
});
// cleanup
$scope.$on('$destroy', function () {
wss.unbindHandlers(handlers);
$log.log('OvSampleCustomCtrl has been destroyed');
});
$log.log('OvSampleCtrl has been created');
$log.log('OvSampleCustomCtrl has been created');
}])
.directive('itemDetailsPanel', ['PanelService', 'KeyService',
function (_ps_, ks) {
.directive('ovSampleCustomItemDetailsPanel', ['PanelService', 'KeyService',
function (ps, ks) {
return {
restrict: 'E',
link: function (scope, element, attrs) {
ps = _ps_;
// insert details panel with PanelService
// create the panel
var panel = ps.createPanel(pName, {
......@@ -107,7 +107,9 @@
if (panel.isVisible()) {
$scope.selId = null;
panel.hide();
return true;
}
return false;
}
// create key bindings to handle panel
......
<link rel="stylesheet" href="app/view/sample/sample.css">
\ No newline at end of file
<link rel="stylesheet" href="app/view/sampleCustom/sampleCustom.css">
\ No newline at end of file
......
<script src="app/view/sample/sample.js"></script>
\ No newline at end of file
<script src="app/view/sampleCustom/sampleCustom.js"></script>
\ No newline at end of file
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-archetypes</artifactId>
<version>1.4.0-SNAPSHOT</version>
</parent>
<artifactId>onos-uitab-archetype</artifactId>
<packaging>maven-archetype</packaging>
<description>ONOS UI Table-View overlay archetype</description>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<archetype-descriptor
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
name="onos-uitab" partial="true"
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" packaged="false" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.html</include>
<include>**/*.js</include>
<include>**/*.css</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<packaging>bundle</packaging>
<description>ONOS OSGi UI Table-View bundle archetype</description>
<url>http://onosproject.org</url>
<properties>
<onos.version>1.4.0-SNAPSHOT</onos.version>
<!-- Uncomment to generate ONOS app from this module.
<onos.app.name>org.foo.app</onos.app.name>
<onos.app.origin>Foo, Inc.</onos.app.origin>
-->
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${onos.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${onos.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${onos.version}</version>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.3</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.20.0</version>
<executions>
<execution>
<id>generate-scr-srcdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
<configuration>
<supportedProjectTypes>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
</supportedProjectTypes>
</configuration>
</plugin>
<plugin>
<groupId>org.onosproject</groupId>
<artifactId>onos-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>cfg</id>
<phase>generate-resources</phase>
<goals>
<goal>cfg</goal>
</goals>
</execution>
<execution>
<id>swagger</id>
<phase>generate-sources</phase>
<goals>
<goal>swagger</goal>
</goals>
</execution>
<execution>
<id>app</id>
<phase>package</phase>
<goals>
<goal>app</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/*
* 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.
*/
package ${package};
import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.ui.UiExtension;
import org.onosproject.ui.UiExtensionService;
import org.onosproject.ui.UiMessageHandlerFactory;
import org.onosproject.ui.UiView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Skeletal ONOS UI Table-View application component.
*/
@Component(immediate = true)
public class AppUiComponent {
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected UiExtensionService uiExtensionService;
// List of application views
private final List<UiView> uiViews = ImmutableList.of(
new UiView(UiView.Category.OTHER, "sampleTable", "Sample Table")
);
// Factory for UI message handlers
private final UiMessageHandlerFactory messageHandlerFactory =
() -> ImmutableList.of(
new AppUiMessageHandler()
);
// Application UI extension
protected UiExtension extension =
new UiExtension.Builder(getClass().getClassLoader(), uiViews)
.messageHandlerFactory(messageHandlerFactory)
.build();
@Activate
protected void activate() {
uiExtensionService.register(extension);
log.info("Started");
}
@Deactivate
protected void deactivate() {
uiExtensionService.unregister(extension);
log.info("Stopped");
}
}
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/*
* 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.
*/
package ${package};
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.table.TableModel;
import org.onosproject.ui.table.TableRequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.Override;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Skeletal ONOS UI Table-View message handler.
*/
public class AppUiMessageHandler extends UiMessageHandler {
private static final String SAMPLE_TABLE_DATA_REQ = "sampleTableDataRequest";
private static final String SAMPLE_TABLE_DATA_RESP = "sampleTableDataResponse";
private static final String SAMPLE_TABLES = "sampleTables";
private static final String SAMPLE_TABLE_DETAIL_REQ = "sampleTableDetailsRequest";
private static final String SAMPLE_TABLE_DETAIL_RESP = "sampleTableDetailsResponse";
private static final String DETAILS = "details";
private static final String ID = "id";
private static final String LABEL = "label";
private static final String CODE = "code";
private static final String COMMENT = "comment";
private static final String RESULT = "result";
private static final String[] COLUMN_IDS = { ID, LABEL, CODE };
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new SampleTableDataRequestHandler(),
new SampleTableDetailRequestHandler()
);
}
// handler for sample table requests
private final class SampleTableDataRequestHandler extends TableRequestHandler {
private SampleTableDataRequestHandler() {
super(SAMPLE_TABLE_DATA_REQ, SAMPLE_TABLE_DATA_RESP, SAMPLE_TABLES);
}
// if necessary, override defaultColumnId() -- if it isn't "id"
@Override
protected String[] getColumnIds() {
return COLUMN_IDS;
}
// if required, override createTableModel() to set column formatters / comparators
@Override
protected void populateTable(TableModel tm, ObjectNode payload) {
// === NOTE: the table model supplied here will have been created
// via a call to createTableModel(). To assign non-default
// cell formatters or comparators to the table model, override
// createTableModel() and set them there.
// === retrieve table row items from some service...
// SomeService ss = get(SomeService.class);
// List<Item> items = ss.getItems()
// fake data for demonstration purposes...
List<Item> items = getItems();
for (Item item: items) {
populateRow(tm.addRow(), item);
}
}
private void populateRow(TableModel.Row row, Item item) {
row.cell(ID, item.id())
.cell(LABEL, item.label())
.cell(CODE, item.code());
}
}
// handler for sample item details requests
private final class SampleTableDetailRequestHandler extends RequestHandler {
private SampleTableDetailRequestHandler() {
super(SAMPLE_TABLE_DETAIL_REQ);
}
@Override
public void process(long sid, ObjectNode payload) {
String id = string(payload, ID, "(none)");
// SomeService ss = get(SomeService.class);
// Item item = ss.getItemDetails(id)
// fake data for demonstration purposes...
Item item = getItem(id);
ObjectNode rootNode = MAPPER.createObjectNode();
ObjectNode data = MAPPER.createObjectNode();
rootNode.set(DETAILS, data);
if (item == null) {
rootNode.put(RESULT, "Item with id '" + id + "' not found");
log.warn("attempted to get item detail for id '{}'", id);
} else {
rootNode.put(RESULT, "Found item with id '" + id + "'");
data.put(ID, item.id());
data.put(LABEL, item.label());
data.put(CODE, item.code());
data.put(COMMENT, "Some arbitrary comment");
}
sendMessage(SAMPLE_TABLE_DETAIL_RESP, 0, rootNode);
}
}
// ===================================================================
// NOTE: The code below this line is to create fake data for this
// sample code. Normally you would use existing services to
// provide real data.
// Lookup a single item.
private static Item getItem(String id) {
// We realize this code is really inefficient, but
// it suffices for our purposes of demonstration...
for (Item item : getItems()) {
if (item.id().equals(id)) {
return item;
}
}
return null;
}
// Produce a list of items.
private static List<Item> getItems() {
List<Item> items = new ArrayList<>();
items.add(new Item("item-1", "foo", 42));
items.add(new Item("item-2", "bar", 99));
items.add(new Item("item-3", "baz", 65));
return items;
}
// Simple model class to provide sample data
private static class Item {
private final String id;
private final String label;
private final int code;
Item(String id, String label, int code) {
this.id = id;
this.label = label;
this.code = code;
}
String id() { return id; }
String label() { return label; }
int code() { return code; }
}
}
\ No newline at end of file
/* css for sample app view */
#ov-sample h2 {
display: inline-block;
}
/* Panel Styling */
#ov-sample-table-item-details-panel.floatpanel {
position: absolute;
top: 115px;
}
.light #ov-sample-table-item-details-panel.floatpanel {
background-color: rgb(229, 234, 237);
}
.dark #ov-sample-table-item-details-panel.floatpanel {
background-color: #3A4042;
}
#ov-sample-table-item-details-panel h3 {
margin: 0;
font-size: large;
}
#ov-sample-table-item-details-panel h4 {
margin: 0;
}
#ov-sample-table-item-details-panel td {
padding: 5px;
}
#ov-sample-table-item-details-panel td.label {
font-style: italic;
opacity: 0.8;
}
<!-- partial HTML -->
<div id="ov-sample-table">
<div class="tabular-header">
<h2>Items ({{tableData.length}} total)</h2>
<div class="ctrl-btns">
<div class="refresh" ng-class="{active: autoRefresh}"
icon icon-id="refresh" icon-size="36"
tooltip tt-msg="autoRefreshTip"
ng-click="toggleRefresh()"></div>
</div>
</div>
<div class="summary-list" onos-table-resize>
<div class="table-header" onos-sortable-header>
<table>
<tr>
<td colId="id" sortable>Item ID </td>
<td colId="label" sortable>Label </td>
<td colId="code" sortable>Code </td>
</tr>
</table>
</div>
<div class="table-body">
<table>
<tr ng-if="!tableData.length" class="no-data">
<td colspan="3">
No Items found
</td>
</tr>
<tr ng-repeat="item in tableData track by $index"
ng-click="selectCallback($event, item)"
ng-class="{selected: item.id === selId}">
<td>{{item.id}}</td>
<td>{{item.label}}</td>
<td>{{item.code}}</td>
</tr>
</table>
</div>
</div>
<ov-sample-table-item-details-panel></ov-sample-table-item-details-panel>
</div>
// js for sample app table view
(function () {
'use strict';
// injected refs
var $log, $scope, fs, wss;
// constants
var detailsReq = 'sampleTableDetailsRequest',
detailsResp = 'sampleTableDetailsResponse',
pName = 'ov-sample-table-item-details-panel',
propOrder = ['id', 'label', 'code'],
friendlyProps = ['Item ID', 'Item Label', 'Special Code'];
function addProp(tbody, index, value) {
var tr = tbody.append('tr');
function addCell(cls, txt) {
tr.append('td').attr('class', cls).html(txt);
}
addCell('label', friendlyProps[index] + ' :');
addCell('value', value);
}
function populatePanel(panel) {
var title = panel.append('h3'),
tbody = panel.append('table').append('tbody');
title.text('Item Details');
propOrder.forEach(function (prop, i) {
addProp(tbody, i, $scope.panelDetails[prop]);
});
panel.append('hr');
panel.append('h4').text('Comments');
panel.append('p').text($scope.panelDetails.comment);
}
function respDetailsCb(data) {
$scope.panelDetails = data.details;
$scope.$apply();
}
angular.module('ovSampleTable', [])
.controller('OvSampleTableCtrl',
['$log', '$scope', 'TableBuilderService',
'FnService', 'WebSocketService',
function (_$log_, _$scope_, tbs, _fs_, _wss_) {
$log = _$log_;
$scope = _$scope_;
fs = _fs_;
wss = _wss_;
var handlers = {};
$scope.panelDetails = {};
// details response handler
handlers[detailsResp] = respDetailsCb;
wss.bindHandlers(handlers);
// custom selection callback
function selCb($event, row) {
if ($scope.selId) {
wss.sendEvent(detailsReq, { id: row.id });
} else {
$scope.hidePanel();
}
$log.debug('Got a click on:', row);
}
// TableBuilderService creating a table for us
tbs.buildTable({
scope: $scope,
tag: 'sampleTable',
selCb: selCb
});
// cleanup
$scope.$on('$destroy', function () {
wss.unbindHandlers(handlers);
$log.log('OvSampleTableCtrl has been destroyed');
});
$log.log('OvSampleTableCtrl has been created');
}])
.directive('ovSampleTableItemDetailsPanel', ['PanelService', 'KeyService',
function (ps, ks) {
return {
restrict: 'E',
link: function (scope, element, attrs) {
// insert details panel with PanelService
// create the panel
var panel = ps.createPanel(pName, {
width: 200,
margin: 20,
hideMargin: 0
});
panel.hide();
scope.hidePanel = function () { panel.hide(); };
function closePanel() {
if (panel.isVisible()) {
$scope.selId = null;
panel.hide();
return true;
}
return false;
}
// create key bindings to handle panel
ks.keyBindings({
esc: [closePanel, 'Close the details panel'],
_helpFormat: ['esc']
});
ks.gestureNotes([
['click', 'Select a row to show item details']
]);
// update the panel's contents when the data is changed
scope.$watch('panelDetails', function () {
if (!fs.isEmptyObject(scope.panelDetails)) {
panel.empty();
populatePanel(panel);
panel.show();
}
});
// cleanup on destroyed scope
scope.$on('$destroy', function () {
ks.unbindKeys();
ps.destroyPanel(pName);
});
}
};
}]);
}());
<link rel="stylesheet" href="app/view/sampleTable/sampleTable.css">
\ No newline at end of file
<script src="app/view/sampleTable/sampleTable.js"></script>
\ No newline at end of file
#
# Copyright 2014 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.
#
#Thu Dec 04 09:24:50 PST 2014
package=it.pkg
version=0.1-SNAPSHOT
groupId=archetype.it
artifactId=basic