Thomas Vachuska

ONOS-3505 Skeletal project structure for driver-matrix UI app.

Change-Id: I257a5e1a58f7edb0b13ed8402a3c9032c82db6d1
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<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">
18 + <modelVersion>4.0.0</modelVersion>
19 +
20 + <parent>
21 + <groupId>org.onosproject</groupId>
22 + <artifactId>onos-apps</artifactId>
23 + <version>1.4.0-SNAPSHOT</version>
24 + <relativePath>../pom.xml</relativePath>
25 + </parent>
26 +
27 + <artifactId>onos-app-drivermatrix</artifactId>
28 + <packaging>bundle</packaging>
29 +
30 + <description>Driver behaviour support matric</description>
31 +
32 + <properties>
33 + <onos.app.name>org.onosproject.drivermatrix</onos.app.name>
34 + </properties>
35 +
36 +</project>
1 +/*
2 + * Copyright 2014,2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.drivermatrix;
17 +
18 +import com.google.common.collect.ImmutableList;
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.onosproject.ui.UiExtension;
25 +import org.onosproject.ui.UiExtensionService;
26 +import org.onosproject.ui.UiMessageHandlerFactory;
27 +import org.onosproject.ui.UiView;
28 +import org.slf4j.Logger;
29 +import org.slf4j.LoggerFactory;
30 +
31 +import java.util.List;
32 +
33 +/**
34 + * Skeletal ONOS UI Table-View application component.
35 + */
36 +@Component(immediate = true)
37 +public class DriverMatrixComponent {
38 +
39 + private static final String VIEW_ID = "driverMatrix";
40 + private static final String VIEW_TEXT = "Driver Matrix";
41 +
42 + private final Logger log = LoggerFactory.getLogger(getClass());
43 +
44 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 + protected UiExtensionService uiExtensionService;
46 +
47 + // List of application views
48 + private final List<UiView> uiViews = ImmutableList.of(
49 + new UiView(UiView.Category.OTHER, VIEW_ID, VIEW_TEXT)
50 + );
51 +
52 + // Factory for UI message handlers
53 + private final UiMessageHandlerFactory messageHandlerFactory =
54 + () -> ImmutableList.of(
55 + new DriverMatrixMessageHandler()
56 + );
57 +
58 + // Application UI extension
59 + protected UiExtension extension =
60 + new UiExtension.Builder(getClass().getClassLoader(), uiViews)
61 + .resourcePath(VIEW_ID)
62 + .messageHandlerFactory(messageHandlerFactory)
63 + .build();
64 +
65 + @Activate
66 + protected void activate() {
67 + uiExtensionService.register(extension);
68 + log.info("Started");
69 + }
70 +
71 + @Deactivate
72 + protected void deactivate() {
73 + uiExtensionService.unregister(extension);
74 + log.info("Stopped");
75 + }
76 +
77 +}
1 +/*
2 + * Copyright 2014,2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.drivermatrix;
17 +
18 +import com.fasterxml.jackson.databind.node.ObjectNode;
19 +import com.google.common.collect.ImmutableSet;
20 +import org.onosproject.ui.RequestHandler;
21 +import org.onosproject.ui.UiMessageHandler;
22 +import org.onosproject.ui.table.TableModel;
23 +import org.onosproject.ui.table.TableRequestHandler;
24 +import org.slf4j.Logger;
25 +import org.slf4j.LoggerFactory;
26 +
27 +import java.util.ArrayList;
28 +import java.util.Collection;
29 +import java.util.List;
30 +
31 +/**
32 + * Skeletal ONOS UI Table-View message handler.
33 + */
34 +public class DriverMatrixMessageHandler extends UiMessageHandler {
35 +
36 + private static final String SAMPLE_TABLE_DATA_REQ = "driverMatrixDataRequest";
37 + private static final String SAMPLE_TABLE_DATA_RESP = "driverMatrixDataResponse";
38 + private static final String SAMPLE_TABLES = "driverMatrixs";
39 +
40 + private static final String SAMPLE_TABLE_DETAIL_REQ = "driverMatrixDetailsRequest";
41 + private static final String SAMPLE_TABLE_DETAIL_RESP = "driverMatrixDetailsResponse";
42 + private static final String DETAILS = "details";
43 +
44 + private static final String ID = "id";
45 + private static final String LABEL = "label";
46 + private static final String CODE = "code";
47 + private static final String COMMENT = "comment";
48 + private static final String RESULT = "result";
49 +
50 + private static final String[] COLUMN_IDS = {ID, LABEL, CODE};
51 +
52 + private final Logger log = LoggerFactory.getLogger(getClass());
53 +
54 +
55 + @Override
56 + protected Collection<RequestHandler> createRequestHandlers() {
57 + return ImmutableSet.of(
58 + new SampleTableDataRequestHandler(),
59 + new SampleTableDetailRequestHandler()
60 + );
61 + }
62 +
63 + // handler for sample table requests
64 + private final class SampleTableDataRequestHandler extends TableRequestHandler {
65 +
66 + private SampleTableDataRequestHandler() {
67 + super(SAMPLE_TABLE_DATA_REQ, SAMPLE_TABLE_DATA_RESP, SAMPLE_TABLES);
68 + }
69 +
70 + // if necessary, override defaultColumnId() -- if it isn't "id"
71 +
72 + @Override
73 + protected String[] getColumnIds() {
74 + return COLUMN_IDS;
75 + }
76 +
77 + // if required, override createTableModel() to set column formatters / comparators
78 +
79 + @Override
80 + protected void populateTable(TableModel tm, ObjectNode payload) {
81 + // === NOTE: the table model supplied here will have been created
82 + // via a call to createTableModel(). To assign non-default
83 + // cell formatters or comparators to the table model, override
84 + // createTableModel() and set them there.
85 +
86 + // === retrieve table row items from some service...
87 + // SomeService ss = get(SomeService.class);
88 + // List<Item> items = ss.getItems()
89 +
90 + // fake data for demonstration purposes...
91 + List<Item> items = getItems();
92 + for (Item item : items) {
93 + populateRow(tm.addRow(), item);
94 + }
95 + }
96 +
97 + private void populateRow(TableModel.Row row, Item item) {
98 + row.cell(ID, item.id())
99 + .cell(LABEL, item.label())
100 + .cell(CODE, item.code());
101 + }
102 + }
103 +
104 +
105 + // handler for sample item details requests
106 + private final class SampleTableDetailRequestHandler extends RequestHandler {
107 +
108 + private SampleTableDetailRequestHandler() {
109 + super(SAMPLE_TABLE_DETAIL_REQ);
110 + }
111 +
112 + @Override
113 + public void process(long sid, ObjectNode payload) {
114 + String id = string(payload, ID, "(none)");
115 +
116 + // SomeService ss = get(SomeService.class);
117 + // Item item = ss.getItemDetails(id)
118 +
119 + // fake data for demonstration purposes...
120 + Item item = getItem(id);
121 +
122 + ObjectNode rootNode = objectNode();
123 + ObjectNode data = objectNode();
124 + rootNode.set(DETAILS, data);
125 +
126 + if (item == null) {
127 + rootNode.put(RESULT, "Item with id '" + id + "' not found");
128 + log.warn("attempted to get item detail for id '{}'", id);
129 +
130 + } else {
131 + rootNode.put(RESULT, "Found item with id '" + id + "'");
132 +
133 + data.put(ID, item.id());
134 + data.put(LABEL, item.label());
135 + data.put(CODE, item.code());
136 + data.put(COMMENT, "Some arbitrary comment");
137 + }
138 +
139 + sendMessage(SAMPLE_TABLE_DETAIL_RESP, 0, rootNode);
140 + }
141 + }
142 +
143 +
144 + // ===================================================================
145 + // NOTE: The code below this line is to create fake data for this
146 + // sample code. Normally you would use existing services to
147 + // provide real data.
148 +
149 + // Lookup a single item.
150 + private static Item getItem(String id) {
151 + // We realize this code is really inefficient, but
152 + // it suffices for our purposes of demonstration...
153 + for (Item item : getItems()) {
154 + if (item.id().equals(id)) {
155 + return item;
156 + }
157 + }
158 + return null;
159 + }
160 +
161 + // Produce a list of items.
162 + private static List<Item> getItems() {
163 + List<Item> items = new ArrayList<>();
164 + items.add(new Item("item-1", "foo", 42));
165 + items.add(new Item("item-2", "bar", 99));
166 + items.add(new Item("item-3", "baz", 65));
167 + return items;
168 + }
169 +
170 + // Simple model class to provide sample data
171 + private static class Item {
172 + private final String id;
173 + private final String label;
174 + private final int code;
175 +
176 + Item(String id, String label, int code) {
177 + this.id = id;
178 + this.label = label;
179 + this.code = code;
180 + }
181 +
182 + String id() {
183 + return id;
184 + }
185 +
186 + String label() {
187 + return label;
188 + }
189 +
190 + int code() {
191 + return code;
192 + }
193 + }
194 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * Driver support matrix app.
19 + */
20 +package org.onosproject.drivermatrix;
...\ No newline at end of file ...\ No newline at end of file
1 +/* css for sample table view */
2 +
3 +#ov-driver-matrix h2 {
4 + display: inline-block;
5 +}
6 +
7 +/* Panel Styling */
8 +#ov-driver-matrix-item-details-panel.floatpanel {
9 + position: absolute;
10 + top: 115px;
11 +}
12 +
13 +.light #ov-driver-matrix-item-details-panel.floatpanel {
14 + background-color: rgb(229, 234, 237);
15 +}
16 +.dark #ov-driver-matrix-item-details-panel.floatpanel {
17 + background-color: #3A4042;
18 +}
19 +
20 +#ov-driver-matrix-item-details-panel h3 {
21 + margin: 0;
22 + font-size: large;
23 +}
24 +
25 +#ov-driver-matrix-item-details-panel h4 {
26 + margin: 0;
27 +}
28 +
29 +#ov-driver-matrix-item-details-panel td {
30 + padding: 5px;
31 +}
32 +#ov-driver-matrix-item-details-panel td.label {
33 + font-style: italic;
34 + opacity: 0.8;
35 +}
1 +<!-- partial HTML -->
2 +<div id="ov-driver-matrix">
3 + <div class="tabular-header">
4 + <h2>Items ({{tableData.length}} total)</h2>
5 + <div class="ctrl-btns">
6 + <div class="refresh" ng-class="{active: autoRefresh}"
7 + icon icon-id="refresh" icon-size="36"
8 + tooltip tt-msg="autoRefreshTip"
9 + ng-click="toggleRefresh()"></div>
10 + </div>
11 + </div>
12 +
13 + <div class="summary-list" onos-table-resize>
14 +
15 + <div class="table-header" onos-sortable-header>
16 + <table>
17 + <tr>
18 + <td colId="id" sortable>Item ID </td>
19 + <td colId="label" sortable>Label </td>
20 + <td colId="code" sortable>Code </td>
21 + </tr>
22 + </table>
23 + </div>
24 +
25 + <div class="table-body">
26 + <table>
27 + <tr ng-if="!tableData.length" class="no-data">
28 + <td colspan="3">
29 + No Items found
30 + </td>
31 + </tr>
32 +
33 + <tr ng-repeat="item in tableData track by $index"
34 + ng-click="selectCallback($event, item)"
35 + ng-class="{selected: item.id === selId}">
36 + <td>{{item.id}}</td>
37 + <td>{{item.label}}</td>
38 + <td>{{item.code}}</td>
39 + </tr>
40 + </table>
41 + </div>
42 +
43 + </div>
44 +
45 + <ov-driver-matrix-item-details-panel></ov-driver-matrix-item-details-panel>
46 +</div>
1 +// js for sample app table view
2 +(function () {
3 + 'use strict';
4 +
5 + // injected refs
6 + var $log, $scope, fs, wss;
7 +
8 + // constants
9 + var detailsReq = 'driverMatrixDetailsRequest',
10 + detailsResp = 'driverMatrixDetailsResponse',
11 + pName = 'ov-driver-matrix-item-details-panel',
12 +
13 + propOrder = ['id', 'label', 'code'],
14 + friendlyProps = ['Item ID', 'Item Label', 'Special Code'];
15 +
16 +
17 + function addProp(tbody, index, value) {
18 + var tr = tbody.append('tr');
19 +
20 + function addCell(cls, txt) {
21 + tr.append('td').attr('class', cls).html(txt);
22 + }
23 + addCell('label', friendlyProps[index] + ' :');
24 + addCell('value', value);
25 + }
26 +
27 + function populatePanel(panel) {
28 + var title = panel.append('h3'),
29 + tbody = panel.append('table').append('tbody');
30 +
31 + title.text('Item Details');
32 +
33 + propOrder.forEach(function (prop, i) {
34 + addProp(tbody, i, $scope.panelDetails[prop]);
35 + });
36 +
37 + panel.append('hr');
38 + panel.append('h4').text('Comments');
39 + panel.append('p').text($scope.panelDetails.comment);
40 + }
41 +
42 + function respDetailsCb(data) {
43 + $scope.panelDetails = data.details;
44 + $scope.$apply();
45 + }
46 +
47 + angular.module('ovDriverMatrix', [])
48 + .controller('OvDriverMatrixCtrl',
49 + ['$log', '$scope', 'TableBuilderService',
50 + 'FnService', 'WebSocketService',
51 +
52 + function (_$log_, _$scope_, tbs, _fs_, _wss_) {
53 + $log = _$log_;
54 + $scope = _$scope_;
55 + fs = _fs_;
56 + wss = _wss_;
57 +
58 + var handlers = {};
59 + $scope.panelDetails = {};
60 +
61 + // details response handler
62 + handlers[detailsResp] = respDetailsCb;
63 + wss.bindHandlers(handlers);
64 +
65 + // custom selection callback
66 + function selCb($event, row) {
67 + if ($scope.selId) {
68 + wss.sendEvent(detailsReq, { id: row.id });
69 + } else {
70 + $scope.hidePanel();
71 + }
72 + $log.debug('Got a click on:', row);
73 + }
74 +
75 + // TableBuilderService creating a table for us
76 + tbs.buildTable({
77 + scope: $scope,
78 + tag: 'driverMatrix',
79 + selCb: selCb
80 + });
81 +
82 + // cleanup
83 + $scope.$on('$destroy', function () {
84 + wss.unbindHandlers(handlers);
85 + $log.log('OvDriverMatrixCtrl has been destroyed');
86 + });
87 +
88 + $log.log('OvDriverMatrixCtrl has been created');
89 + }])
90 +
91 + .directive('ovDriverMatrixItemDetailsPanel', ['PanelService', 'KeyService',
92 + function (ps, ks) {
93 + return {
94 + restrict: 'E',
95 + link: function (scope, element, attrs) {
96 + // insert details panel with PanelService
97 + // create the panel
98 + var panel = ps.createPanel(pName, {
99 + width: 200,
100 + margin: 20,
101 + hideMargin: 0
102 + });
103 + panel.hide();
104 + scope.hidePanel = function () { panel.hide(); };
105 +
106 + function closePanel() {
107 + if (panel.isVisible()) {
108 + $scope.selId = null;
109 + panel.hide();
110 + return true;
111 + }
112 + return false;
113 + }
114 +
115 + // create key bindings to handle panel
116 + ks.keyBindings({
117 + esc: [closePanel, 'Close the details panel'],
118 + _helpFormat: ['esc']
119 + });
120 + ks.gestureNotes([
121 + ['click', 'Select a row to show item details']
122 + ]);
123 +
124 + // update the panel's contents when the data is changed
125 + scope.$watch('panelDetails', function () {
126 + if (!fs.isEmptyObject(scope.panelDetails)) {
127 + panel.empty();
128 + populatePanel(panel);
129 + panel.show();
130 + }
131 + });
132 +
133 + // cleanup on destroyed scope
134 + scope.$on('$destroy', function () {
135 + ks.unbindKeys();
136 + ps.destroyPanel(pName);
137 + });
138 + }
139 + };
140 + }]);
141 +}());
1 +<link rel="stylesheet" href="app/view/driverMatrix/driverMatrix.css">
...\ No newline at end of file ...\ No newline at end of file
1 +<script src="app/view/driverMatrix/driverMatrix.js"></script>
...\ No newline at end of file ...\ No newline at end of file
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
61 <module>mlb</module> 61 <module>mlb</module>
62 <module>openstackswitching</module> 62 <module>openstackswitching</module>
63 <module>pathpainter</module> 63 <module>pathpainter</module>
64 + <module>drivermatrix</module>
64 <module>cpman</module> 65 <module>cpman</module>
65 </modules> 66 </modules>
66 67
......