Committed by
Gerrit Code Review
Simplified Custom View code (ui archetype).
Change-Id: Ia9d1f1023f287653d00abc3a2f9cf7498f3875e0
Showing
4 changed files
with
111 additions
and
293 deletions
... | @@ -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 | }()); | ... | ... |
-
Please register or login to post a comment