GUI -- TableService can take a div, config object, and data object in order to programmatically render and load data into a table. Test functions added.
Change-Id: I95f82108d7bb4f84a701b49e0e419afbdbac6f14
diff --git a/web/gui/src/main/webapp/_bripc/practice-table.js b/web/gui/src/main/webapp/_bripc/practice-table.js
index 858494d..b2b892c 100644
--- a/web/gui/src/main/webapp/_bripc/practice-table.js
+++ b/web/gui/src/main/webapp/_bripc/practice-table.js
@@ -21,6 +21,54 @@
(function () {
'use strict';
+ var config = {
+ colIds: ['_iconid_available', 'id', 'mfr', 'hw', 'sw', 'serial',
+ 'annotations.protocol'],
+ colText: ['', 'URI', 'Vendor', 'Hardware Version', 'Software Version',
+ 'Serial Number', 'Protocol']
+ },
+ deviceData = {
+ "devices": [{
+ "id": "of:0000000000000001",
+ "available": true,
+ "_iconid_available": "deviceOnline",
+ "role": "MASTER",
+ "mfr": "Nicira, Inc.",
+ "hw": "Open vSwitch",
+ "sw": "2.0.1",
+ "serial": "None",
+ "annotations": {
+ "protocol": "OF_10"
+ }
+ },
+ {
+ "id": "of:0000000000000004",
+ "available": false,
+ "_iconid_available": "deviceOffline",
+ "role": "MASTER",
+ "mfr": "Nicira, Inc.",
+ "hw": "Open vSwitch",
+ "sw": "2.0.1",
+ "serial": "None",
+ "annotations": {
+ "protocol": "OF_10"
+ }
+ },
+ {
+ "id": "of:0000000000000092",
+ "available": false,
+ "_iconid_available": "deviceOffline",
+ "role": "MASTER",
+ "mfr": "Nicira, Inc.",
+ "hw": "Open vSwitch",
+ "sw": "2.0.1",
+ "serial": "None",
+ "annotations": {
+ "protocol": "OF_10"
+ }
+ }]
+ };
+
function setColWidth(t) {
var tHeaders, tdElement, colWidth;
@@ -84,4 +132,4 @@
}
};
}]);
-}());
\ No newline at end of file
+}());
diff --git a/web/gui/src/main/webapp/app/fw/widget/table.js b/web/gui/src/main/webapp/app/fw/widget/table.js
index 833c42c..bd20b9c 100644
--- a/web/gui/src/main/webapp/app/fw/widget/table.js
+++ b/web/gui/src/main/webapp/app/fw/widget/table.js
@@ -22,12 +22,68 @@
var $log;
+ function renderTable(div, config) {
+ var table = div.append('table').attr('fixed-header', true),
+ thead, tr, numTableCols, i;
+ table.append('thead');
+ table.append('tbody');
+
+ thead = table.select('thead');
+ tr = thead.append('tr');
+ numTableCols = config.colIds.length;
+
+ for(i = 0; i < numTableCols; i += 1) {
+ tr.append('th').html(config.colText[i]);
+ }
+
+ return config.colIds;
+ }
+
+ // I can delete these comments later...
+ // loadTableData needs to know which IDs are used to create the table...
+ // Potentially, there will be some rows in the JSON that the server is
+ // sending back that will be unused. We don't want to create unneeded rows.
+ // For example, in device view, we aren't displaying "role" or
+ // "available" properties, but they would be displayed if we took it
+ // directly from the data being sent in.
+ function loadTableData(data, div, colIds) {
+ // let me know if you have suggestions for this function
+
+ var numTableCols = colIds.length,
+ tbody, tr, td, i;
+ tbody = div.select('tbody');
+
+ // get the array associated with the first object, such as "devices"
+ // in fakeData
+ // (for some reason it doesn't like the data.keys() function, saying
+ // "undefined is not a function"
+ // Object.keys(data) works though)
+ // loop through every object in the array, and every property in the object
+ // put their property in the td of the table
+ (data[Object.keys(data)[0]]).forEach(function (item) {
+ tr = tbody.append('tr');
+ for(var key in item) {
+ for(i = 0; i < numTableCols; i += 1) {
+ if(key === colIds[i]) {
+ td = tr.append('td').html(item[key]);
+ }
+ }
+ }
+ });
+ }
+
+ function renderAndLoadTable(div, config, data) {
+ loadTableData(data, div, (renderTable(div, config)));
+ }
+
angular.module('onosWidget')
.factory('TableService', ['$log', function (_$log_) {
$log = _$log_;
return {
-
+ renderTable: renderTable,
+ loadTableData: loadTableData,
+ renderAndLoadTable: renderAndLoadTable
};
}]);
diff --git a/web/gui/src/main/webapp/app/view/device/device.html b/web/gui/src/main/webapp/app/view/device/device.html
index a83f5e7..a6fb8b9 100644
--- a/web/gui/src/main/webapp/app/view/device/device.html
+++ b/web/gui/src/main/webapp/app/view/device/device.html
@@ -1,7 +1,6 @@
<!-- Device partial HTML -->
<div id="ov-device">
<h2>Device View</h2>
-<!-- TODO: uncomment and test the thead and tbody tags for CSS styling -->
<table class="summary-list">
<tbody>
<tr>
diff --git a/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js b/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js
index 12d0390..688897c 100644
--- a/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js
@@ -18,7 +18,54 @@
ONOS GUI -- Widget -- Table Service - Unit Tests
*/
describe('factory: fw/widget/table.js', function() {
- var ts, $log;
+ var ts, $log, d3Elem;
+
+ var config = {
+ colIds: ['id', 'mfr', 'hw', 'sw', 'serial', 'annotations.protocol'],
+ colText: ['URI', 'Vendor', 'Hardware Version', 'Software Version',
+ 'Serial Number', 'Protocol']
+ },
+ fakeData = {
+ "devices": [{
+ "id": "of:0000000000000001",
+ "available": true,
+ "_iconid_available": "deviceOnline",
+ "role": "MASTER",
+ "mfr": "Nicira, Inc.",
+ "hw": "Open vSwitch",
+ "sw": "2.0.1",
+ "serial": "None",
+ "annotations": {
+ "protocol": "OF_10"
+ }
+ },
+ {
+ "id": "of:0000000000000004",
+ "available": false,
+ "_iconid_available": "deviceOffline",
+ "role": "MASTER",
+ "mfr": "Nicira, Inc.",
+ "hw": "Open vSwitch",
+ "sw": "2.0.1",
+ "serial": "None",
+ "annotations": {
+ "protocol": "OF_10"
+ }
+ },
+ {
+ "id": "of:0000000000000092",
+ "available": false,
+ "_iconid_available": "deviceOffline",
+ "role": "MASTER",
+ "mfr": "Nicira, Inc.",
+ "hw": "Open vSwitch",
+ "sw": "2.0.1",
+ "serial": "None",
+ "annotations": {
+ "protocol": "OF_10"
+ }
+ }]
+ };
beforeEach(module('onosWidget'));
@@ -30,4 +77,58 @@
it('should define TableService', function () {
expect(ts).toBeDefined();
});
-});
\ No newline at end of file
+
+ function verifyTableTags(div) {
+ var table = div.select('table'),
+ tableHeaders;
+ expect(table).toBeTruthy();
+ expect(table.attr('fixed-header')).toBeTruthy();
+ expect(table.select('thead')).toBeTruthy();
+ expect(table.select('tbody')).toBeTruthy();
+
+ tableHeaders = table.select('thead').selectAll('th');
+ tableHeaders.each(function(thElement, i) {
+ thElement = d3.select(this);
+ expect(thElement).toBeTruthy();
+ expect(thElement.html()).toBe(config.colText[i]);
+ });
+ }
+
+ function verifyData(div) {
+ var tbody = div.select('tbody'),
+ tableBoxes = tbody.selectAll('td');
+ expect(tbody).toBeTruthy();
+ expect(tbody.select('tr')).toBeTruthy();
+
+ tableBoxes.each(function(tdElement, i){
+ tdElement = d3.select(this);
+ if(i === 0) {
+ expect(tdElement.html()).toBe('of:0000000000000001');
+ }
+ if(i === 1) {
+ expect(tdElement.html()).toBe('Nicira, Inc.');
+ }
+ if(i === 2) {
+ expect(tdElement.html()).toBe('Open vSwitch');
+ }
+ expect(tdElement).toBeTruthy();
+ });
+ }
+
+ it('should create table tags', function () {
+ ts.renderTable(d3Elem, config);
+ verifyTableTags(d3Elem);
+ });
+
+ it('should load data into table', function () {
+ var colIds = ts.renderTable(d3Elem, config);
+ ts.loadTableData(fakeData, d3Elem, colIds);
+ verifyData(d3Elem);
+ });
+
+ it('should render table and load data', function () {
+ ts.renderAndLoadTable(d3Elem, config, fakeData);
+ verifyData(d3Elem);
+ });
+
+});