Simon Hunt

Cleaned up Driver Matrix View.

- now implements proper resizing and scrolling.

Change-Id: Ideabb86ed3db44ed1827de15e49216d107053189
......@@ -5,29 +5,19 @@
}
#ov-driver-matrix .driver-matrix {
/* FIXME: demo only, need a proper scrolling solution */
height: 600px;
overflow: scroll;
background-color: white;
}
#ov-driver-matrix table {
margin-left: 20px;
}
#ov-driver-matrix .table-header-rotated {
#ov-driver-matrix .table-header-rotated table {
border-collapse: collapse;
}
#ov-driver-matrix .table-header-rotated td {
width: 24px;
}
#ov-driver-matrix .table-header-rotated td.xmark {
background-color: rgba(200, 85, 85, 0.5);
}
#ov-driver-matrix .table-header-rotated td {
text-align: center;
padding: 2px 5px;
border: 1px solid #ccc;
}
#ov-driver-matrix .table-header-rotated th.rotate {
height: 140px;
white-space: nowrap;
......@@ -36,19 +26,43 @@
#ov-driver-matrix .table-header-rotated th.rotate > div {
-webkit-transform: translate(25px, 51px) rotate(-45deg);
transform: translate(25px, 51px) rotate(-45deg);
width: 30px;
width: 33px;
}
#ov-driver-matrix .table-header-rotated th.rotate > div > span {
border-bottom: 1px solid #ccc;
padding: 5px 10px;
background-color: rgb(249, 225, 193);
}
#ov-driver-matrix .table-header-rotated th.row-header {
#ov-driver-matrix .table-grid {
overflow: scroll;
color: white;
}
#ov-driver-matrix .table-grid table {
border-collapse: collapse;
}
#ov-driver-matrix .table-grid th.row-header {
padding: 0 10px;
border-bottom: 1px solid #ccc;
text-align: right;
color: black;
font-size: 10pt;
background-color: rgb(249, 225, 193);
}
#ov-driver-matrix .table-grid td {
width: 24px;
}
#ov-driver-matrix .table-grid td.xmark {
background-color: rgb(249, 225, 193);
color: rgb(88,70,14);
}
#ov-driver-matrix .table-grid td {
text-align: center;
padding: 2px 5px;
border: 1px solid #ccc;
}
/* === NOT YET IMPLEMENTED === */
/* Panel Styling */
#ov-driver-matrix-item-details-panel.floatpanel {
position: absolute;
......
......@@ -11,36 +11,34 @@
</div>
</div>
<!-- TODO: handle resizing / scrolling -->
<div class="driver-matrix">
<table class="table-header-rotated">
<thead>
<div class="table-header-rotated">
<table>
<thead>
<tr>
<!-- first column header is not rotated -->
<th></th>
<th class="first"></th>
<!-- following headers are rotated -->
<th class="rotate" ng-repeat="beh in behaviours track by $index">
<div><span>{{beh}}</span></div>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="drv in drivers track by $index">
<!--ng-click="selectCallback($event, item)"-->
<!--ng-class="{selected: item.id === selId}">-->
<th class="row-header">
{{drv}}
</th>
<td ng-repeat="beh in behaviours track by $index"
ng-class="{'xmark':cellMarked(drv, beh)}">
{{cellValue(drv, beh)}}
</td>
</tr>
</tbody>
</table>
</thead>
<tbody></tbody>
</table>
</div>
<div class="table-grid">
<table>
<thead></thead>
<tbody>
<tr ng-repeat="drv in drivers track by $index">
<th class="row-header"> {{drv}} </th>
<td ng-repeat="beh in behaviours track by $index"
ng-class="{'xmark':cellMarked(drv, beh)}"
ng-bind-html="checkmark"></td>
</tr>
</tbody>
</table>
</div>
</div>
<ov-driver-matrix-item-details-panel></ov-driver-matrix-item-details-panel>
</div>
......
......@@ -3,48 +3,37 @@
'use strict';
// injected refs
var $log, $scope, fs, wss;
var $log, $scope, fs, wss, mast;
// constants
var detailsReq = 'driverDataRequest',
detailsResp = 'driverDataResponse',
// TODO: deal with details panel
pName = 'ov-driver-matrix-item-details-panel',
propOrder = ['id', 'label', 'code'],
friendlyProps = ['Item ID', 'Item Label', 'Special Code'];
function addProp(tbody, index, value) {
var tr = tbody.append('tr');
function addCell(cls, txt) {
tr.append('td').attr('class', cls).html(txt);
topPad = 13,
labelFudge = 14;
// d3 selections
var tabular, dMatrix, tabHdRot, tabGrid, first;
function fixSizes() {
var dy = fs.noPxStyle(tabular, 'height') +
fs.noPxStyle(tabHdRot, 'height') + mast.mastHeight() + topPad,
tHeight = fs.windowSize(dy).height + 'px',
rowHdr = tabGrid.select('.row-header'),
w;
tabGrid.style('height', tHeight);
if (!rowHdr.empty()) {
w = fs.noPxStyle(rowHdr, 'width') + labelFudge;
first.style('width', w + 'px');
}
addCell('label', friendlyProps[index] + ' :');
addCell('value', value);
}
function populatePanel(panel) {
var title = panel.append('h3'),
tbody = panel.append('table').append('tbody');
title.text('Item Details');
propOrder.forEach(function (prop, i) {
addProp(tbody, i, $scope.panelDetails[prop]);
});
panel.append('hr');
panel.append('h4').text('Comments');
panel.append('p').text($scope.panelDetails.comment);
}
function respDetailsCb(data) {
//$log.debug('Matrix Data', data);
$scope.behaviours = data.behaviours;
$scope.drivers = data.drivers;
$scope.matrix = data.matrix;
$scope.$apply();
fixSizes();
}
angular.module('ovDriverMatrix', [])
......@@ -53,106 +42,60 @@
is.registerIconMapping('nav_drivers', 'cog');
}])
.controller('OvDriverMatrixCtrl',
['$log', '$scope', 'TableBuilderService',
'FnService', 'WebSocketService',
function (_$log_, _$scope_, tbs, _fs_, _wss_) {
$log = _$log_;
$scope = _$scope_;
fs = _fs_;
wss = _wss_;
var handlers = {};
$scope.behaviours = [];
$scope.drivers = [];
$scope.matrix = {};
// details response handler
handlers[detailsResp] = respDetailsCb;
wss.bindHandlers(handlers);
wss.sendEvent(detailsReq);
//// custom selection callback
//function selCb($event, row) {
// if ($scope.selId) {
// wss.sendEvent(detailsReq, { id: row.id });
// } else {
// $scope.hidePanel();
// }
// $log.debug('Got a click on:', row);
//}
function cellHit(d, b) {
var drec = $scope.matrix[d],
brec = drec && drec[b];
return !!brec;
}
$scope.cellMarked = cellHit;
$scope.cellValue = function(d, b) {
return cellHit(d, b) ? 'x' : '';
};
// cleanup
$scope.$on('$destroy', function () {
wss.unbindHandlers(handlers);
$log.log('OvDriverMatrixCtrl has been destroyed');
});
$log.log('OvDriverMatrixCtrl has been created');
}])
// TODO: implement row selection to show details panel
.directive('ovDriverMatrixItemDetailsPanel', ['PanelService', 'KeyService',
function (ps, ks) {
return {
restrict: 'E',
link: function (scope, element, attrs) {
// insert details panel with PanelService
// create the panel
var panel = ps.createPanel(pName, {
width: 200,
margin: 20,
hideMargin: 0
});
panel.hide();
scope.hidePanel = function () { panel.hide(); };
function closePanel() {
if (panel.isVisible()) {
$scope.selId = null;
panel.hide();
return true;
}
return false;
}
// create key bindings to handle panel
ks.keyBindings({
esc: [closePanel, 'Close the details panel'],
_helpFormat: ['esc']
});
ks.gestureNotes([
['click', 'Select a row to show item details']
]);
// update the panel's contents when the data is changed
scope.$watch('panelDetails', function () {
if (!fs.isEmptyObject(scope.panelDetails)) {
panel.empty();
populatePanel(panel);
panel.show();
}
});
// cleanup on destroyed scope
scope.$on('$destroy', function () {
ks.unbindKeys();
ps.destroyPanel(pName);
});
}
};
['$rootScope', '$window', '$log', '$scope', '$sce',
'FnService', 'WebSocketService', 'MastService',
function ($rootScope, $window, _$log_, _$scope_, $sce,
_fs_, _wss_, _mast_) {
$log = _$log_;
$scope = _$scope_;
fs = _fs_;
wss = _wss_;
mast = _mast_;
var handlers = {},
unbindWatch;
tabular = d3.select('.tabular-header');
dMatrix = d3.select('.driver-matrix');
tabHdRot = d3.select('.table-header-rotated');
tabGrid = d3.select('.table-grid');
first = tabHdRot.select('.first');
unbindWatch = $rootScope.$watchCollection(
function () {
return {
h: $window.innerHeight,
w: $window.innerWidth
};
}, fixSizes
);
$scope.behaviours = [];
$scope.drivers = [];
$scope.matrix = {};
handlers[detailsResp] = respDetailsCb;
wss.bindHandlers(handlers);
wss.sendEvent(detailsReq);
function cellHit(d, b) {
var drec = $scope.matrix[d],
brec = drec && drec[b];
return !!brec;
}
$scope.cellMarked = cellHit;
$scope.checkmark = $sce.trustAsHtml("&check;");
// cleanup
$scope.$on('$destroy', function () {
unbindWatch();
wss.unbindHandlers(handlers);
$log.log('OvDriverMatrixCtrl has been destroyed');
});
$log.log('OvDriverMatrixCtrl has been created');
}]);
}());
......