Simon Hunt

Cleaned up Driver Matrix View.

- now implements proper resizing and scrolling.

Change-Id: Ideabb86ed3db44ed1827de15e49216d107053189
...@@ -5,29 +5,19 @@ ...@@ -5,29 +5,19 @@
5 } 5 }
6 6
7 #ov-driver-matrix .driver-matrix { 7 #ov-driver-matrix .driver-matrix {
8 - /* FIXME: demo only, need a proper scrolling solution */ 8 + background-color: white;
9 - height: 600px;
10 - overflow: scroll;
11 } 9 }
12 10
13 #ov-driver-matrix table { 11 #ov-driver-matrix table {
14 margin-left: 20px; 12 margin-left: 20px;
15 } 13 }
16 14
17 -#ov-driver-matrix .table-header-rotated { 15 +#ov-driver-matrix .table-header-rotated table {
18 border-collapse: collapse; 16 border-collapse: collapse;
19 } 17 }
20 #ov-driver-matrix .table-header-rotated td { 18 #ov-driver-matrix .table-header-rotated td {
21 width: 24px; 19 width: 24px;
22 } 20 }
23 -#ov-driver-matrix .table-header-rotated td.xmark {
24 - background-color: rgba(200, 85, 85, 0.5);
25 -}
26 -#ov-driver-matrix .table-header-rotated td {
27 - text-align: center;
28 - padding: 2px 5px;
29 - border: 1px solid #ccc;
30 -}
31 #ov-driver-matrix .table-header-rotated th.rotate { 21 #ov-driver-matrix .table-header-rotated th.rotate {
32 height: 140px; 22 height: 140px;
33 white-space: nowrap; 23 white-space: nowrap;
...@@ -36,19 +26,43 @@ ...@@ -36,19 +26,43 @@
36 #ov-driver-matrix .table-header-rotated th.rotate > div { 26 #ov-driver-matrix .table-header-rotated th.rotate > div {
37 -webkit-transform: translate(25px, 51px) rotate(-45deg); 27 -webkit-transform: translate(25px, 51px) rotate(-45deg);
38 transform: translate(25px, 51px) rotate(-45deg); 28 transform: translate(25px, 51px) rotate(-45deg);
39 - width: 30px; 29 + width: 33px;
40 } 30 }
41 #ov-driver-matrix .table-header-rotated th.rotate > div > span { 31 #ov-driver-matrix .table-header-rotated th.rotate > div > span {
42 border-bottom: 1px solid #ccc; 32 border-bottom: 1px solid #ccc;
43 padding: 5px 10px; 33 padding: 5px 10px;
34 + background-color: rgb(249, 225, 193);
44 } 35 }
45 -#ov-driver-matrix .table-header-rotated th.row-header { 36 +
37 +#ov-driver-matrix .table-grid {
38 + overflow: scroll;
39 + color: white;
40 +}
41 +#ov-driver-matrix .table-grid table {
42 + border-collapse: collapse;
43 +}
44 +#ov-driver-matrix .table-grid th.row-header {
46 padding: 0 10px; 45 padding: 0 10px;
47 border-bottom: 1px solid #ccc; 46 border-bottom: 1px solid #ccc;
48 text-align: right; 47 text-align: right;
48 + color: black;
49 + font-size: 10pt;
50 + background-color: rgb(249, 225, 193);
51 +}
52 +#ov-driver-matrix .table-grid td {
53 + width: 24px;
54 +}
55 +#ov-driver-matrix .table-grid td.xmark {
56 + background-color: rgb(249, 225, 193);
57 + color: rgb(88,70,14);
58 +}
59 +#ov-driver-matrix .table-grid td {
60 + text-align: center;
61 + padding: 2px 5px;
62 + border: 1px solid #ccc;
49 } 63 }
50 64
51 - 65 +/* === NOT YET IMPLEMENTED === */
52 /* Panel Styling */ 66 /* Panel Styling */
53 #ov-driver-matrix-item-details-panel.floatpanel { 67 #ov-driver-matrix-item-details-panel.floatpanel {
54 position: absolute; 68 position: absolute;
......
...@@ -11,36 +11,34 @@ ...@@ -11,36 +11,34 @@
11 </div> 11 </div>
12 </div> 12 </div>
13 13
14 - <!-- TODO: handle resizing / scrolling -->
15 <div class="driver-matrix"> 14 <div class="driver-matrix">
16 - <table class="table-header-rotated"> 15 + <div class="table-header-rotated">
17 - <thead> 16 + <table>
17 + <thead>
18 <tr> 18 <tr>
19 <!-- first column header is not rotated --> 19 <!-- first column header is not rotated -->
20 - <th></th> 20 + <th class="first"></th>
21 <!-- following headers are rotated --> 21 <!-- following headers are rotated -->
22 <th class="rotate" ng-repeat="beh in behaviours track by $index"> 22 <th class="rotate" ng-repeat="beh in behaviours track by $index">
23 <div><span>{{beh}}</span></div> 23 <div><span>{{beh}}</span></div>
24 </th> 24 </th>
25 </tr> 25 </tr>
26 - 26 + </thead>
27 - </thead> 27 + <tbody></tbody>
28 - 28 + </table>
29 - <tbody> 29 + </div>
30 - <tr ng-repeat="drv in drivers track by $index"> 30 + <div class="table-grid">
31 - <!--ng-click="selectCallback($event, item)"--> 31 + <table>
32 - <!--ng-class="{selected: item.id === selId}">--> 32 + <thead></thead>
33 - <th class="row-header"> 33 + <tbody>
34 - {{drv}} 34 + <tr ng-repeat="drv in drivers track by $index">
35 - </th> 35 + <th class="row-header"> {{drv}} </th>
36 - <td ng-repeat="beh in behaviours track by $index" 36 + <td ng-repeat="beh in behaviours track by $index"
37 - ng-class="{'xmark':cellMarked(drv, beh)}"> 37 + ng-class="{'xmark':cellMarked(drv, beh)}"
38 - {{cellValue(drv, beh)}} 38 + ng-bind-html="checkmark"></td>
39 - </td> 39 + </tr>
40 - </tr> 40 + </tbody>
41 - </tbody> 41 + </table>
42 - </table> 42 + </div>
43 </div> 43 </div>
44 -
45 - <ov-driver-matrix-item-details-panel></ov-driver-matrix-item-details-panel>
46 </div> 44 </div>
......
...@@ -3,48 +3,37 @@ ...@@ -3,48 +3,37 @@
3 'use strict'; 3 'use strict';
4 4
5 // injected refs 5 // injected refs
6 - var $log, $scope, fs, wss; 6 + var $log, $scope, fs, wss, mast;
7 7
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 + topPad = 13,
12 - pName = 'ov-driver-matrix-item-details-panel', 12 + labelFudge = 14;
13 - propOrder = ['id', 'label', 'code'], 13 +
14 - friendlyProps = ['Item ID', 'Item Label', 'Special Code']; 14 + // d3 selections
15 - 15 + var tabular, dMatrix, tabHdRot, tabGrid, first;
16 - 16 +
17 - function addProp(tbody, index, value) { 17 + function fixSizes() {
18 - var tr = tbody.append('tr'); 18 + var dy = fs.noPxStyle(tabular, 'height') +
19 - 19 + fs.noPxStyle(tabHdRot, 'height') + mast.mastHeight() + topPad,
20 - function addCell(cls, txt) { 20 + tHeight = fs.windowSize(dy).height + 'px',
21 - tr.append('td').attr('class', cls).html(txt); 21 + rowHdr = tabGrid.select('.row-header'),
22 + w;
23 +
24 + tabGrid.style('height', tHeight);
25 + if (!rowHdr.empty()) {
26 + w = fs.noPxStyle(rowHdr, 'width') + labelFudge;
27 + first.style('width', w + 'px');
22 } 28 }
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 } 29 }
41 30
42 function respDetailsCb(data) { 31 function respDetailsCb(data) {
43 - //$log.debug('Matrix Data', data);
44 $scope.behaviours = data.behaviours; 32 $scope.behaviours = data.behaviours;
45 $scope.drivers = data.drivers; 33 $scope.drivers = data.drivers;
46 $scope.matrix = data.matrix; 34 $scope.matrix = data.matrix;
47 $scope.$apply(); 35 $scope.$apply();
36 + fixSizes();
48 } 37 }
49 38
50 angular.module('ovDriverMatrix', []) 39 angular.module('ovDriverMatrix', [])
...@@ -53,106 +42,60 @@ ...@@ -53,106 +42,60 @@
53 is.registerIconMapping('nav_drivers', 'cog'); 42 is.registerIconMapping('nav_drivers', 'cog');
54 }]) 43 }])
55 .controller('OvDriverMatrixCtrl', 44 .controller('OvDriverMatrixCtrl',
56 - ['$log', '$scope', 'TableBuilderService', 45 + ['$rootScope', '$window', '$log', '$scope', '$sce',
57 - 'FnService', 'WebSocketService', 46 + 'FnService', 'WebSocketService', 'MastService',
58 - 47 +
59 - function (_$log_, _$scope_, tbs, _fs_, _wss_) { 48 + function ($rootScope, $window, _$log_, _$scope_, $sce,
60 - $log = _$log_; 49 + _fs_, _wss_, _mast_) {
61 - $scope = _$scope_; 50 + $log = _$log_;
62 - fs = _fs_; 51 + $scope = _$scope_;
63 - wss = _wss_; 52 + fs = _fs_;
64 - 53 + wss = _wss_;
65 - var handlers = {}; 54 + mast = _mast_;
66 - $scope.behaviours = []; 55 +
67 - $scope.drivers = []; 56 + var handlers = {},
68 - $scope.matrix = {}; 57 + unbindWatch;
69 - 58 +
70 - // details response handler 59 + tabular = d3.select('.tabular-header');
71 - handlers[detailsResp] = respDetailsCb; 60 + dMatrix = d3.select('.driver-matrix');
72 - wss.bindHandlers(handlers); 61 + tabHdRot = d3.select('.table-header-rotated');
73 - 62 + tabGrid = d3.select('.table-grid');
74 - wss.sendEvent(detailsReq); 63 + first = tabHdRot.select('.first');
75 - 64 +
76 - //// custom selection callback 65 + unbindWatch = $rootScope.$watchCollection(
77 - //function selCb($event, row) { 66 + function () {
78 - // if ($scope.selId) { 67 + return {
79 - // wss.sendEvent(detailsReq, { id: row.id }); 68 + h: $window.innerHeight,
80 - // } else { 69 + w: $window.innerWidth
81 - // $scope.hidePanel(); 70 + };
82 - // } 71 + }, fixSizes
83 - // $log.debug('Got a click on:', row); 72 + );
84 - //} 73 +
85 - 74 + $scope.behaviours = [];
86 - function cellHit(d, b) { 75 + $scope.drivers = [];
87 - var drec = $scope.matrix[d], 76 + $scope.matrix = {};
88 - brec = drec && drec[b]; 77 +
89 - return !!brec; 78 + handlers[detailsResp] = respDetailsCb;
90 - } 79 + wss.bindHandlers(handlers);
91 - 80 +
92 - $scope.cellMarked = cellHit; 81 + wss.sendEvent(detailsReq);
93 - 82 +
94 - $scope.cellValue = function(d, b) { 83 + function cellHit(d, b) {
95 - return cellHit(d, b) ? 'x' : ''; 84 + var drec = $scope.matrix[d],
96 - }; 85 + brec = drec && drec[b];
97 - 86 + return !!brec;
98 - // cleanup 87 + }
99 - $scope.$on('$destroy', function () { 88 +
100 - wss.unbindHandlers(handlers); 89 + $scope.cellMarked = cellHit;
101 - $log.log('OvDriverMatrixCtrl has been destroyed'); 90 + $scope.checkmark = $sce.trustAsHtml("&check;");
102 - }); 91 +
103 - 92 + // cleanup
104 - $log.log('OvDriverMatrixCtrl has been created'); 93 + $scope.$on('$destroy', function () {
105 - }]) 94 + unbindWatch();
106 - 95 + wss.unbindHandlers(handlers);
107 - // TODO: implement row selection to show details panel 96 + $log.log('OvDriverMatrixCtrl has been destroyed');
108 - .directive('ovDriverMatrixItemDetailsPanel', ['PanelService', 'KeyService', 97 + });
109 - function (ps, ks) { 98 +
110 - return { 99 + $log.log('OvDriverMatrixCtrl has been created');
111 - restrict: 'E',
112 - link: function (scope, element, attrs) {
113 - // insert details panel with PanelService
114 - // create the panel
115 - var panel = ps.createPanel(pName, {
116 - width: 200,
117 - margin: 20,
118 - hideMargin: 0
119 - });
120 - panel.hide();
121 - scope.hidePanel = function () { panel.hide(); };
122 -
123 - function closePanel() {
124 - if (panel.isVisible()) {
125 - $scope.selId = null;
126 - panel.hide();
127 - return true;
128 - }
129 - return false;
130 - }
131 -
132 - // create key bindings to handle panel
133 - ks.keyBindings({
134 - esc: [closePanel, 'Close the details panel'],
135 - _helpFormat: ['esc']
136 - });
137 - ks.gestureNotes([
138 - ['click', 'Select a row to show item details']
139 - ]);
140 -
141 - // update the panel's contents when the data is changed
142 - scope.$watch('panelDetails', function () {
143 - if (!fs.isEmptyObject(scope.panelDetails)) {
144 - panel.empty();
145 - populatePanel(panel);
146 - panel.show();
147 - }
148 - });
149 -
150 - // cleanup on destroyed scope
151 - scope.$on('$destroy', function () {
152 - ks.unbindKeys();
153 - ps.destroyPanel(pName);
154 - });
155 - }
156 - };
157 }]); 100 }]);
158 }()); 101 }());
......