Simon Hunt
Committed by Gerrit Code Review

Simplified Custom View code (ui archetype).

Change-Id: Ia9d1f1023f287653d00abc3a2f9cf7498f3875e0
...@@ -22,165 +22,56 @@ import com.fasterxml.jackson.databind.node.ObjectNode; ...@@ -22,165 +22,56 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
22 import com.google.common.collect.ImmutableSet; 22 import com.google.common.collect.ImmutableSet;
23 import org.onosproject.ui.RequestHandler; 23 import org.onosproject.ui.RequestHandler;
24 import org.onosproject.ui.UiMessageHandler; 24 import org.onosproject.ui.UiMessageHandler;
25 -import org.onosproject.ui.table.TableModel;
26 -import org.onosproject.ui.table.TableRequestHandler;
27 import org.slf4j.Logger; 25 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 26 import org.slf4j.LoggerFactory;
29 27
30 -import java.lang.Override;
31 -import java.util.ArrayList;
32 import java.util.Collection; 28 import java.util.Collection;
33 -import java.util.List;
34 29
35 /** 30 /**
36 * Skeletal ONOS UI Custom-View message handler. 31 * Skeletal ONOS UI Custom-View message handler.
37 */ 32 */
38 public class AppUiMessageHandler extends UiMessageHandler { 33 public class AppUiMessageHandler extends UiMessageHandler {
39 - // TODO: reduce the code down to just the custom view example
40 34
41 private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest"; 35 private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest";
42 private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse"; 36 private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse";
43 - private static final String SAMPLE_CUSTOMS = "sampleCustoms";
44 37
45 - private static final String SAMPLE_CUSTOM_DETAIL_REQ = "sampleCustomDetailsRequest"; 38 + private static final String NUMBER = "number";
46 - private static final String SAMPLE_CUSTOM_DETAIL_RESP = "sampleCustomDetailsResponse"; 39 + private static final String SQUARE = "square";
47 - private static final String DETAILS = "details"; 40 + private static final String CUBE = "cube";
48 - 41 + private static final String MESSAGE = "message";
49 - private static final String ID = "id"; 42 + private static final String MSG_FORMAT = "Next incrememt is %d units";
50 - private static final String LABEL = "label";
51 - private static final String CODE = "code";
52 - private static final String COMMENT = "comment";
53 - private static final String RESULT = "result";
54 -
55 - private static final String[] COLUMN_IDS = { ID, LABEL, CODE };
56 43
57 private final Logger log = LoggerFactory.getLogger(getClass()); 44 private final Logger log = LoggerFactory.getLogger(getClass());
58 45
46 + private long someNumber = 1;
47 + private long someIncrement = 1;
59 48
60 @Override 49 @Override
61 protected Collection<RequestHandler> createRequestHandlers() { 50 protected Collection<RequestHandler> createRequestHandlers() {
62 return ImmutableSet.of( 51 return ImmutableSet.of(
63 - new SampleCustomDataRequestHandler(), 52 + new SampleCustomDataRequestHandler()
64 - new SampleCustomDetailRequestHandler()
65 ); 53 );
66 } 54 }
67 55
68 - // handler for sample table requests 56 + // handler for sample data requests
69 - private final class SampleCustomDataRequestHandler extends TableRequestHandler { 57 + private final class SampleCustomDataRequestHandler extends RequestHandler {
70 58
71 private SampleCustomDataRequestHandler() { 59 private SampleCustomDataRequestHandler() {
72 - super(SAMPLE_CUSTOM_DATA_REQ, SAMPLE_CUSTOM_DATA_RESP, SAMPLE_CUSTOMS); 60 + super(SAMPLE_CUSTOM_DATA_REQ);
73 - }
74 -
75 - @Override
76 - protected String[] getColumnIds() {
77 - return COLUMN_IDS;
78 - }
79 -
80 - @Override
81 - protected void populateTable(TableModel tm, ObjectNode payload) {
82 - // === set custom column cell formatters/comparators if need be...
83 - // tm.setFormatter(CODE, new CodeFormatter());
84 - // tm.setComparator(CODE, new CodeComparator());
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 SampleCustomDetailRequestHandler extends RequestHandler {
107 -
108 - private SampleCustomDetailRequestHandler() {
109 - super(SAMPLE_CUSTOM_DETAIL_REQ);
110 } 61 }
111 62
112 @Override 63 @Override
113 public void process(long sid, ObjectNode payload) { 64 public void process(long sid, ObjectNode payload) {
114 - String id = string(payload, ID, "(none)"); 65 + someIncrement++;
115 - 66 + someNumber += someIncrement;
116 - // SomeService ss = get(SomeService.class); 67 + log.debug("Computing data for {}...", someNumber);
117 - // Item item = ss.getItemDetails(id) 68 +
118 - 69 + ObjectNode result = objectNode();
119 - // fake data for demonstration purposes... 70 + result.put(NUMBER, someNumber);
120 - Item item = getItem(id); 71 + result.put(SQUARE, someNumber * someNumber);
121 - 72 + result.put(CUBE, someNumber * someNumber * someNumber);
122 - ObjectNode rootNode = MAPPER.createObjectNode(); 73 + result.put(MESSAGE, String.format(MSG_FORMAT, someIncrement + 1));
123 - ObjectNode data = MAPPER.createObjectNode(); 74 + sendMessage(SAMPLE_CUSTOM_DATA_RESP, 0, result);
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_CUSTOM_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 } 75 }
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() { return id; }
183 - String label() { return label; }
184 - int code() { return code; }
185 } 76 }
186 } 77 }
...\ No newline at end of file ...\ No newline at end of file
......
1 -/* css for sample app view */ 1 +/* css for sample app custom view */
2 2
3 -#ov-sample h2 { 3 +#ov-sample-custom {
4 - display: inline-block; 4 + padding: 20px;
5 +}
6 +.light #ov-sample-custom {
7 + color: navy;
8 +}
9 +.dark #ov-sample-custom {
10 + color: #88f;
5 } 11 }
6 12
7 -/* Panel Styling */ 13 +#ov-sample-custom .button-panel {
8 -#ov-sample-custom-item-details-panel.floatpanel { 14 + margin: 10px;
9 - position: absolute; 15 + width: 200px;
10 - top: 115px;
11 } 16 }
12 17
13 -.light #ov-sample-custom-item-details-panel.floatpanel { 18 +.light #ov-sample-custom .button-panel {
14 - background-color: rgb(229, 234, 237); 19 + background-color: #ccf;
15 } 20 }
16 -.dark #ov-sample-custom-item-details-panel.floatpanel { 21 +.dark #ov-sample-custom .button-panel {
17 - background-color: #3A4042; 22 + background-color: #444;
18 } 23 }
19 24
20 -#ov-sample-custom-item-details-panel h3 { 25 +#ov-sample-custom .my-button {
21 - margin: 0; 26 + cursor: pointer;
22 - font-size: large; 27 + padding: 4px;
28 + text-align: center;
23 } 29 }
24 30
25 -#ov-sample-custom-item-details-panel h4 { 31 +.light #ov-sample-custom .my-button {
26 - margin: 0; 32 + color: white;
33 + background-color: #99d;
34 +}
35 +.dark #ov-sample-custom .my-button {
36 + color: black;
37 + background-color: #aaa;
27 } 38 }
28 39
29 -#ov-sample-custom-item-details-panel td { 40 +#ov-sample-custom .number {
30 - padding: 5px; 41 + font-size: 140%;
42 + text-align: right;
31 } 43 }
32 -#ov-sample-custom-item-details-panel td.label { 44 +
45 +#ov-sample-custom .quote {
46 + margin: 10px 20px;
33 font-style: italic; 47 font-style: italic;
34 - opacity: 0.8; 48 +}
35 -}
...\ No newline at end of file ...\ No newline at end of file
......
1 <!-- partial HTML --> 1 <!-- partial HTML -->
2 <div id="ov-sample-custom"> 2 <div id="ov-sample-custom">
3 - <div class="tabular-header"> 3 + <div class="button-panel">
4 - <h2>Items ({{tableData.length}} total)</h2> 4 + <div class="my-button" ng-click="getData()">
5 - <div class="ctrl-btns"> 5 + Fetch Data
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> 6 </div>
11 </div> 7 </div>
12 8
13 - <div class="summary-list" onos-table-resize> 9 + <div class="data-panel">
14 - 10 + <table>
15 - <div class="table-header" onos-sortable-header> 11 + <tr>
16 - <table> 12 + <td> Number </td>
17 - <tr> 13 + <td class="number"> {{data.number}} </td>
18 - <td colId="id" sortable>Item ID </td> 14 + </tr>
19 - <td colId="label" sortable>Label </td> 15 + <tr>
20 - <td colId="code" sortable>Code </td> 16 + <td> Square </td>
21 - </tr> 17 + <td class="number"> {{data.square}} </td>
22 - </table> 18 + </tr>
23 - </div> 19 + <tr>
24 - 20 + <td> Cube </td>
25 - <div class="table-body"> 21 + <td class="number"> {{data.cube}} </td>
26 - <table> 22 + </tr>
27 - <tr ng-if="!tableData.length" class="no-data"> 23 + </table>
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 24
25 + <p>
26 + A message from our sponsors:
27 + </p>
28 + <p>
29 + <span class="quote">{{data.message}} </span>
30 + </p>
43 </div> 31 </div>
44 -
45 - <ov-sample-custom-item-details-panel></ov-sample-custom-item-details-panel>
46 </div> 32 </div>
......
...@@ -3,139 +3,67 @@ ...@@ -3,139 +3,67 @@
3 'use strict'; 3 'use strict';
4 4
5 // injected refs 5 // injected refs
6 - var $log, $scope, fs, wss; 6 + var $log, $scope, wss, ks;
7 7
8 // constants 8 // constants
9 - var detailsReq = 'sampleCustomDetailsRequest', 9 + var dataReq = 'sampleCustomDataRequest',
10 - detailsResp = 'sampleCustomDetailsResponse', 10 + dataResp = 'sampleCustomDataResponse';
11 - pName = 'ov-sample-custom-item-details-panel',
12 11
13 - propOrder = ['id', 'label', 'code'], 12 + function addKeyBindings() {
14 - friendlyProps = ['Item ID', 'Item Label', 'Special Code']; 13 + var map = {
14 + space: [getData, 'Fetch data from server'],
15 15
16 + _helpFormat: [
17 + ['space']
18 + ]
19 + };
16 20
17 - function addProp(tbody, index, value) { 21 + ks.keyBindings(map);
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 } 22 }
26 23
27 - function populatePanel(panel) { 24 + function getData() {
28 - var title = panel.append('h3'), 25 + wss.sendEvent(dataReq);
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 } 26 }
41 27
42 - function respDetailsCb(data) { 28 + function respDataCb(data) {
43 - $scope.panelDetails = data.details; 29 + $scope.data = data;
44 $scope.$apply(); 30 $scope.$apply();
45 } 31 }
46 32
33 +
47 angular.module('ovSampleCustom', []) 34 angular.module('ovSampleCustom', [])
48 .controller('OvSampleCustomCtrl', 35 .controller('OvSampleCustomCtrl',
49 - ['$log', '$scope', 'TableBuilderService', 36 + ['$log', '$scope', 'WebSocketService', 'KeyService',
50 - 'FnService', 'WebSocketService',
51 37
52 - function (_$log_, _$scope_, tbs, _fs_, _wss_) { 38 + function (_$log_, _$scope_, _wss_, _ks_) {
53 $log = _$log_; 39 $log = _$log_;
54 $scope = _$scope_; 40 $scope = _$scope_;
55 - fs = _fs_;
56 wss = _wss_; 41 wss = _wss_;
42 + ks = _ks_;
57 43
58 var handlers = {}; 44 var handlers = {};
59 - $scope.panelDetails = {}; 45 + $scope.data = {};
60 46
61 - // details response handler 47 + // data response handler
62 - handlers[detailsResp] = respDetailsCb; 48 + handlers[dataResp] = respDataCb;
63 wss.bindHandlers(handlers); 49 wss.bindHandlers(handlers);
64 50
65 - // custom selection callback 51 + addKeyBindings();
66 - function selCb($event, row) { 52 +
67 - if ($scope.selId) { 53 + // custom click handler
68 - wss.sendEvent(detailsReq, { id: row.id }); 54 + $scope.getData = getData;
69 - } else { 55 +
70 - $scope.hidePanel(); 56 + // get data the first time...
71 - } 57 + getData();
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: 'sampleCustom',
79 - selCb: selCb
80 - });
81 58
82 // cleanup 59 // cleanup
83 $scope.$on('$destroy', function () { 60 $scope.$on('$destroy', function () {
84 wss.unbindHandlers(handlers); 61 wss.unbindHandlers(handlers);
62 + ks.unbindKeys();
85 $log.log('OvSampleCustomCtrl has been destroyed'); 63 $log.log('OvSampleCustomCtrl has been destroyed');
86 }); 64 });
87 65
88 $log.log('OvSampleCustomCtrl has been created'); 66 $log.log('OvSampleCustomCtrl has been created');
89 - }]) 67 + }]);
90 - 68 +
91 - .directive('ovSampleCustomItemDetailsPanel', ['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 }()); 69 }());
......