Committed by
Gerrit Code Review
ONOS-3505: Basic behaviour of drivers table implemented.
- WIP -- still need to fix scrolling, styling, etc. Change-Id: I376155ab1375ea4b4b136969b89f74c3733178b8
Showing
4 changed files
with
121 additions
and
69 deletions
| ... | @@ -30,24 +30,24 @@ import org.slf4j.LoggerFactory; | ... | @@ -30,24 +30,24 @@ import org.slf4j.LoggerFactory; |
| 30 | import java.util.ArrayList; | 30 | import java.util.ArrayList; |
| 31 | import java.util.Collection; | 31 | import java.util.Collection; |
| 32 | import java.util.Comparator; | 32 | import java.util.Comparator; |
| 33 | -import java.util.HashMap; | ||
| 34 | import java.util.HashSet; | 33 | import java.util.HashSet; |
| 35 | import java.util.List; | 34 | import java.util.List; |
| 36 | -import java.util.Map; | ||
| 37 | import java.util.Set; | 35 | import java.util.Set; |
| 38 | 36 | ||
| 39 | /** | 37 | /** |
| 40 | - * Message handler for device view related messages. | 38 | + * Message handler for driver matrix view related messages. |
| 41 | */ | 39 | */ |
| 42 | public class DriverViewMessageHandler extends UiMessageHandler { | 40 | public class DriverViewMessageHandler extends UiMessageHandler { |
| 43 | 41 | ||
| 44 | private final Logger log = LoggerFactory.getLogger(getClass()); | 42 | private final Logger log = LoggerFactory.getLogger(getClass()); |
| 45 | 43 | ||
| 44 | + private static final int ONE = 1; | ||
| 46 | private static final String DRIVER_DATA_REQUEST = "driverDataRequest"; | 45 | private static final String DRIVER_DATA_REQUEST = "driverDataRequest"; |
| 47 | private static final String DRIVER_DATA_RESPONSE = "driverDataResponse"; | 46 | private static final String DRIVER_DATA_RESPONSE = "driverDataResponse"; |
| 48 | 47 | ||
| 49 | private static final String DRIVERS = "drivers"; | 48 | private static final String DRIVERS = "drivers"; |
| 50 | private static final String BEHAVIOURS = "behaviours"; | 49 | private static final String BEHAVIOURS = "behaviours"; |
| 50 | + private static final String MATRIX = "matrix"; | ||
| 51 | 51 | ||
| 52 | private static final Comparator<? super Class<? extends Behaviour>> BEHAVIOUR_BY_NAME = | 52 | private static final Comparator<? super Class<? extends Behaviour>> BEHAVIOUR_BY_NAME = |
| 53 | (o1, o2) -> o1.getSimpleName().compareTo(o2.getSimpleName()); | 53 | (o1, o2) -> o1.getSimpleName().compareTo(o2.getSimpleName()); |
| ... | @@ -59,11 +59,12 @@ public class DriverViewMessageHandler extends UiMessageHandler { | ... | @@ -59,11 +59,12 @@ public class DriverViewMessageHandler extends UiMessageHandler { |
| 59 | protected Collection<RequestHandler> createRequestHandlers() { | 59 | protected Collection<RequestHandler> createRequestHandlers() { |
| 60 | return ImmutableSet.of( | 60 | return ImmutableSet.of( |
| 61 | new DataRequestHandler() | 61 | new DataRequestHandler() |
| 62 | + // TODO: for row selection, produce data for detail panel | ||
| 62 | // new DetailRequestHandler() | 63 | // new DetailRequestHandler() |
| 63 | ); | 64 | ); |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | - // handler for device table requests | 67 | + // handler for driver matrix requests |
| 67 | private final class DataRequestHandler extends RequestHandler { | 68 | private final class DataRequestHandler extends RequestHandler { |
| 68 | 69 | ||
| 69 | private DataRequestHandler() { | 70 | private DataRequestHandler() { |
| ... | @@ -72,54 +73,46 @@ public class DriverViewMessageHandler extends UiMessageHandler { | ... | @@ -72,54 +73,46 @@ public class DriverViewMessageHandler extends UiMessageHandler { |
| 72 | 73 | ||
| 73 | @Override | 74 | @Override |
| 74 | public void process(long sid, ObjectNode payload) { | 75 | public void process(long sid, ObjectNode payload) { |
| 75 | - // Search for drivers producing two artifacts: | ||
| 76 | - // 1) list of abstract behaviours as column listing | ||
| 77 | - // 2) sparse matrix of drivers-to-concrete behaviours | ||
| 78 | - | ||
| 79 | DriverService driverService = get(DriverService.class); | 76 | DriverService driverService = get(DriverService.class); |
| 80 | 77 | ||
| 81 | - // Collect all behaviours for all drivers | 78 | + List<Driver> drivers = new ArrayList<>(driverService.getDrivers()); |
| 82 | - Map<Driver, Set<Class<? extends Behaviour>>> driverBehaviours = new HashMap<>(); | 79 | + drivers = orderDrivers(drivers); |
| 83 | - driverService.getDrivers().forEach(d -> driverBehaviours.put(d, d.behaviours())); | ||
| 84 | - | ||
| 85 | - // Order all drivers | ||
| 86 | - List<Driver> drivers = orderDrivers(driverBehaviours.keySet()); | ||
| 87 | 80 | ||
| 88 | // Produce a union of all behaviours (and order them) | 81 | // Produce a union of all behaviours (and order them) |
| 89 | - List<Class<? extends Behaviour>> behaviours = orderBehaviours(driverBehaviours.values()); | 82 | + List<Class<? extends Behaviour>> behaviours = orderBehaviours(drivers); |
| 90 | 83 | ||
| 91 | // Produce a JSON structure and send it | 84 | // Produce a JSON structure and send it |
| 92 | - sendMessage(DRIVER_DATA_RESPONSE, 0, driversJson(driverBehaviours, drivers, behaviours)); | 85 | + sendMessage(DRIVER_DATA_RESPONSE, 0, driversJson(drivers, behaviours)); |
| 93 | } | 86 | } |
| 94 | 87 | ||
| 95 | - private List<Driver> orderDrivers(Set<Driver> drivers) { | 88 | + private List<Driver> orderDrivers(List<Driver> drivers) { |
| 96 | // For now order by alphanumeric name of the driver | 89 | // For now order by alphanumeric name of the driver |
| 97 | - List<Driver> ordered = new ArrayList<>(drivers); | 90 | + drivers.sort(DRIVER_BY_NAME); |
| 98 | - ordered.sort(DRIVER_BY_NAME); | 91 | + return drivers; |
| 99 | - return ordered; | ||
| 100 | } | 92 | } |
| 101 | 93 | ||
| 102 | - private List<Class<? extends Behaviour>> | 94 | + private List<Class<? extends Behaviour>> orderBehaviours(List<Driver> drivers) { |
| 103 | - orderBehaviours(Collection<Set<Class<? extends Behaviour>>> behaviours) { | 95 | + // first, produce a set-union of all behaviours from all drivers... |
| 104 | - // For now order by alphanumeric name of the abstract behaviour simple name | ||
| 105 | Set<Class<? extends Behaviour>> allBehaviours = new HashSet<>(); | 96 | Set<Class<? extends Behaviour>> allBehaviours = new HashSet<>(); |
| 106 | - behaviours.forEach(allBehaviours::addAll); | 97 | + drivers.forEach(d -> allBehaviours.addAll(d.behaviours())); |
| 98 | + | ||
| 99 | + // for now, order by alphanumeric name of the abstract behaviour simple name | ||
| 107 | List<Class<? extends Behaviour>> ordered = new ArrayList<>(allBehaviours); | 100 | List<Class<? extends Behaviour>> ordered = new ArrayList<>(allBehaviours); |
| 108 | ordered.sort(BEHAVIOUR_BY_NAME); | 101 | ordered.sort(BEHAVIOUR_BY_NAME); |
| 109 | return ordered; | 102 | return ordered; |
| 110 | } | 103 | } |
| 111 | 104 | ||
| 112 | - private ObjectNode driversJson(Map<Driver, Set<Class<? extends Behaviour>>> driverBehaviours, | 105 | + private ObjectNode driversJson(List<Driver> drivers, |
| 113 | - List<Driver> drivers, | ||
| 114 | List<Class<? extends Behaviour>> behaviours) { | 106 | List<Class<? extends Behaviour>> behaviours) { |
| 115 | ObjectNode root = objectNode(); | 107 | ObjectNode root = objectNode(); |
| 116 | addBehaviours(root, behaviours); | 108 | addBehaviours(root, behaviours); |
| 117 | addDrivers(root, drivers); | 109 | addDrivers(root, drivers); |
| 118 | - addRelationships(root, drivers, behaviours, driverBehaviours); | 110 | + addMatrixCells(root, drivers); |
| 119 | return root; | 111 | return root; |
| 120 | } | 112 | } |
| 121 | 113 | ||
| 122 | - private void addBehaviours(ObjectNode root, List<Class<? extends Behaviour>> behaviours) { | 114 | + private void addBehaviours(ObjectNode root, |
| 115 | + List<Class<? extends Behaviour>> behaviours) { | ||
| 123 | ArrayNode array = arrayNode(); | 116 | ArrayNode array = arrayNode(); |
| 124 | root.set(BEHAVIOURS, array); | 117 | root.set(BEHAVIOURS, array); |
| 125 | behaviours.forEach(b -> array.add(b.getSimpleName())); | 118 | behaviours.forEach(b -> array.add(b.getSimpleName())); |
| ... | @@ -131,9 +124,19 @@ public class DriverViewMessageHandler extends UiMessageHandler { | ... | @@ -131,9 +124,19 @@ public class DriverViewMessageHandler extends UiMessageHandler { |
| 131 | drivers.forEach(d -> array.add(d.name())); | 124 | drivers.forEach(d -> array.add(d.name())); |
| 132 | } | 125 | } |
| 133 | 126 | ||
| 134 | - private void addRelationships(ObjectNode root, | 127 | + private void addMatrixCells(ObjectNode root, List<Driver> drivers) { |
| 135 | - List<Driver> drivers, List<Class<? extends Behaviour>> behaviours, | 128 | + ObjectNode matrix = objectNode(); |
| 136 | - Map<Driver, Set<Class<? extends Behaviour>>> driverBehaviours) { | 129 | + root.set(MATRIX, matrix); |
| 130 | + | ||
| 131 | + drivers.forEach(d -> { | ||
| 132 | + ObjectNode dnode = objectNode(); | ||
| 133 | + matrix.set(d.name(), dnode); | ||
| 134 | + | ||
| 135 | + d.behaviours().forEach(b -> { | ||
| 136 | + // TODO: can put a payload here, rather than a '1' marker | ||
| 137 | + dnode.put(b.getSimpleName(), ONE); | ||
| 138 | + }); | ||
| 139 | + }); | ||
| 137 | } | 140 | } |
| 138 | } | 141 | } |
| 139 | 142 | ... | ... |
| 1 | -/* css for sample table view */ | 1 | +/* css for driver matrix view */ |
| 2 | 2 | ||
| 3 | #ov-driver-matrix h2 { | 3 | #ov-driver-matrix h2 { |
| 4 | display: inline-block; | 4 | display: inline-block; |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | +#ov-driver-matrix table { | ||
| 8 | + margin-left: 20px; | ||
| 9 | +} | ||
| 10 | + | ||
| 11 | +#ov-driver-matrix .table-header-rotated { | ||
| 12 | + border-collapse: collapse; | ||
| 13 | +} | ||
| 14 | +#ov-driver-matrix .table-header-rotated td { | ||
| 15 | + width: 30px; | ||
| 16 | +} | ||
| 17 | +#ov-driver-matrix .table-header-rotated td.xmark { | ||
| 18 | + background-color: yellow; | ||
| 19 | +} | ||
| 20 | +#ov-driver-matrix .table-header-rotated td { | ||
| 21 | + text-align: center; | ||
| 22 | + padding: 2px 5px; | ||
| 23 | + border: 1px solid #ccc; | ||
| 24 | +} | ||
| 25 | +#ov-driver-matrix .table-header-rotated th.rotate { | ||
| 26 | + height: 140px; | ||
| 27 | + white-space: nowrap; | ||
| 28 | +} | ||
| 29 | +#ov-driver-matrix .table-header-rotated th.rotate > div { | ||
| 30 | + -webkit-transform: translate(25px, 51px) rotate(-45deg); | ||
| 31 | + transform: translate(25px, 51px) rotate(-45deg); | ||
| 32 | + width: 30px; | ||
| 33 | +} | ||
| 34 | +#ov-driver-matrix .table-header-rotated th.rotate > div > span { | ||
| 35 | + border-bottom: 1px solid #ccc; | ||
| 36 | + padding: 5px 10px; | ||
| 37 | +} | ||
| 38 | +#ov-driver-matrix .table-header-rotated th.row-header { | ||
| 39 | + padding: 0 10px; | ||
| 40 | + border-bottom: 1px solid #ccc; | ||
| 41 | + text-align: right; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | + | ||
| 7 | /* Panel Styling */ | 45 | /* Panel Styling */ |
| 8 | #ov-driver-matrix-item-details-panel.floatpanel { | 46 | #ov-driver-matrix-item-details-panel.floatpanel { |
| 9 | position: absolute; | 47 | position: absolute; |
| ... | @@ -33,3 +71,4 @@ | ... | @@ -33,3 +71,4 @@ |
| 33 | font-style: italic; | 71 | font-style: italic; |
| 34 | opacity: 0.8; | 72 | opacity: 0.8; |
| 35 | } | 73 | } |
| 74 | + | ... | ... |
| 1 | <!-- partial HTML --> | 1 | <!-- partial HTML --> |
| 2 | <div id="ov-driver-matrix"> | 2 | <div id="ov-driver-matrix"> |
| 3 | <div class="tabular-header"> | 3 | <div class="tabular-header"> |
| 4 | - <h2>Items ({{tableData.length}} total)</h2> | 4 | + <h2>Driver Matrix</h2> |
| 5 | <div class="ctrl-btns"> | 5 | <div class="ctrl-btns"> |
| 6 | + <!-- TODO: fix (or remove) refresh button --> | ||
| 6 | <div class="refresh" ng-class="{active: autoRefresh}" | 7 | <div class="refresh" ng-class="{active: autoRefresh}" |
| 7 | icon icon-id="refresh" icon-size="36" | 8 | icon icon-id="refresh" icon-size="36" |
| 8 | tooltip tt-msg="autoRefreshTip" | 9 | tooltip tt-msg="autoRefreshTip" |
| ... | @@ -10,37 +11,36 @@ | ... | @@ -10,37 +11,36 @@ |
| 10 | </div> | 11 | </div> |
| 11 | </div> | 12 | </div> |
| 12 | 13 | ||
| 13 | - <div class="summary-list" onos-table-resize> | 14 | + <!-- TODO: handle resizing / scrolling --> |
| 14 | - | 15 | + <div class="driver-matrix"> |
| 15 | - <div class="table-header" onos-sortable-header> | 16 | + <table class="table-header-rotated"> |
| 16 | - <table> | 17 | + <thead> |
| 17 | <tr> | 18 | <tr> |
| 18 | - <td colId="id" sortable>Item ID </td> | 19 | + <!-- first column header is not rotated --> |
| 19 | - <td colId="label" sortable>Label </td> | 20 | + <th></th> |
| 20 | - <td colId="code" sortable>Code </td> | 21 | + <!-- following headers are rotated --> |
| 22 | + <th class="rotate" ng-repeat="beh in behaviours track by $index"> | ||
| 23 | + <div><span>{{beh}}</span></div> | ||
| 24 | + </th> | ||
| 21 | </tr> | 25 | </tr> |
| 22 | - </table> | ||
| 23 | - </div> | ||
| 24 | 26 | ||
| 25 | - <div class="table-body"> | 27 | + </thead> |
| 26 | - <table> | ||
| 27 | - <tr ng-if="!tableData.length" class="no-data"> | ||
| 28 | - <td colspan="3"> | ||
| 29 | - No Items found | ||
| 30 | - </td> | ||
| 31 | - </tr> | ||
| 32 | 28 | ||
| 33 | - <tr ng-repeat="item in tableData track by $index" | 29 | + <tbody> |
| 34 | - ng-click="selectCallback($event, item)" | 30 | + <tr ng-repeat="drv in drivers track by $index"> |
| 35 | - ng-class="{selected: item.id === selId}"> | 31 | + <!--ng-click="selectCallback($event, item)"--> |
| 36 | - <td>{{item.id}}</td> | 32 | + <!--ng-class="{selected: item.id === selId}">--> |
| 37 | - <td>{{item.label}}</td> | 33 | + <th class="row-header"> |
| 38 | - <td>{{item.code}}</td> | 34 | + {{drv}} |
| 35 | + </th> | ||
| 36 | + <td ng-repeat="beh in behaviours track by $index" | ||
| 37 | + ng-class="{'xmark':cellMarked(drv, beh)}"> | ||
| 38 | + {{cellValue(drv, beh)}} | ||
| 39 | + </td> | ||
| 39 | </tr> | 40 | </tr> |
| 41 | + </tbody> | ||
| 40 | </table> | 42 | </table> |
| 41 | </div> | 43 | </div> |
| 42 | 44 | ||
| 43 | - </div> | ||
| 44 | - | ||
| 45 | <ov-driver-matrix-item-details-panel></ov-driver-matrix-item-details-panel> | 45 | <ov-driver-matrix-item-details-panel></ov-driver-matrix-item-details-panel> |
| 46 | </div> | 46 | </div> | ... | ... |
| 1 | -// js for sample app table view | 1 | +// js for driver view |
| 2 | (function () { | 2 | (function () { |
| 3 | 'use strict'; | 3 | 'use strict'; |
| 4 | 4 | ||
| ... | @@ -8,8 +8,8 @@ | ... | @@ -8,8 +8,8 @@ |
| 8 | // constants | 8 | // constants |
| 9 | var detailsReq = 'driverDataRequest', | 9 | var detailsReq = 'driverDataRequest', |
| 10 | detailsResp = 'driverDataResponse', | 10 | detailsResp = 'driverDataResponse', |
| 11 | + // TODO: deal with details panel | ||
| 11 | pName = 'ov-driver-matrix-item-details-panel', | 12 | pName = 'ov-driver-matrix-item-details-panel', |
| 12 | - | ||
| 13 | propOrder = ['id', 'label', 'code'], | 13 | propOrder = ['id', 'label', 'code'], |
| 14 | friendlyProps = ['Item ID', 'Item Label', 'Special Code']; | 14 | friendlyProps = ['Item ID', 'Item Label', 'Special Code']; |
| 15 | 15 | ||
| ... | @@ -40,9 +40,11 @@ | ... | @@ -40,9 +40,11 @@ |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | function respDetailsCb(data) { | 42 | function respDetailsCb(data) { |
| 43 | - $log.debug(data); | 43 | + //$log.debug('Matrix Data', data); |
| 44 | - //$scope.panelDetails = data.details; | 44 | + $scope.behaviours = data.behaviours; |
| 45 | - //$scope.$apply(); | 45 | + $scope.drivers = data.drivers; |
| 46 | + $scope.matrix = data.matrix; | ||
| 47 | + $scope.$apply(); | ||
| 46 | } | 48 | } |
| 47 | 49 | ||
| 48 | angular.module('ovDriverMatrix', []) | 50 | angular.module('ovDriverMatrix', []) |
| ... | @@ -57,7 +59,9 @@ | ... | @@ -57,7 +59,9 @@ |
| 57 | wss = _wss_; | 59 | wss = _wss_; |
| 58 | 60 | ||
| 59 | var handlers = {}; | 61 | var handlers = {}; |
| 60 | - $scope.panelDetails = {}; | 62 | + $scope.behaviours = []; |
| 63 | + $scope.drivers = []; | ||
| 64 | + $scope.matrix = {}; | ||
| 61 | 65 | ||
| 62 | // details response handler | 66 | // details response handler |
| 63 | handlers[detailsResp] = respDetailsCb; | 67 | handlers[detailsResp] = respDetailsCb; |
| ... | @@ -75,12 +79,17 @@ | ... | @@ -75,12 +79,17 @@ |
| 75 | // $log.debug('Got a click on:', row); | 79 | // $log.debug('Got a click on:', row); |
| 76 | //} | 80 | //} |
| 77 | 81 | ||
| 78 | - //// TableBuilderService creating a table for us | 82 | + function cellHit(d, b) { |
| 79 | - //tbs.buildTable({ | 83 | + var drec = $scope.matrix[d], |
| 80 | - // scope: $scope, | 84 | + brec = drec && drec[b]; |
| 81 | - // tag: 'driverMatrix', | 85 | + return !!brec; |
| 82 | - // selCb: selCb | 86 | + } |
| 83 | - //}); | 87 | + |
| 88 | + $scope.cellMarked = cellHit; | ||
| 89 | + | ||
| 90 | + $scope.cellValue = function(d, b) { | ||
| 91 | + return cellHit(d, b) ? 'x' : ''; | ||
| 92 | + }; | ||
| 84 | 93 | ||
| 85 | // cleanup | 94 | // cleanup |
| 86 | $scope.$on('$destroy', function () { | 95 | $scope.$on('$destroy', function () { |
| ... | @@ -91,6 +100,7 @@ | ... | @@ -91,6 +100,7 @@ |
| 91 | $log.log('OvDriverMatrixCtrl has been created'); | 100 | $log.log('OvDriverMatrixCtrl has been created'); |
| 92 | }]) | 101 | }]) |
| 93 | 102 | ||
| 103 | + // TODO: implement row selection to show details panel | ||
| 94 | .directive('ovDriverMatrixItemDetailsPanel', ['PanelService', 'KeyService', | 104 | .directive('ovDriverMatrixItemDetailsPanel', ['PanelService', 'KeyService', |
| 95 | function (ps, ks) { | 105 | function (ps, ks) { |
| 96 | return { | 106 | return { | ... | ... |
-
Please register or login to post a comment