Bri Prebilic Cole
Committed by Ray Milkey

GUI -- TableService can take a div, config object, and data object in order to p…

…rogrammatically render and load data into a table. Test functions added.

Change-Id: I95f82108d7bb4f84a701b49e0e419afbdbac6f14
...@@ -21,6 +21,54 @@ ...@@ -21,6 +21,54 @@
21 (function () { 21 (function () {
22 'use strict'; 22 'use strict';
23 23
24 + var config = {
25 + colIds: ['_iconid_available', 'id', 'mfr', 'hw', 'sw', 'serial',
26 + 'annotations.protocol'],
27 + colText: ['', 'URI', 'Vendor', 'Hardware Version', 'Software Version',
28 + 'Serial Number', 'Protocol']
29 + },
30 + deviceData = {
31 + "devices": [{
32 + "id": "of:0000000000000001",
33 + "available": true,
34 + "_iconid_available": "deviceOnline",
35 + "role": "MASTER",
36 + "mfr": "Nicira, Inc.",
37 + "hw": "Open vSwitch",
38 + "sw": "2.0.1",
39 + "serial": "None",
40 + "annotations": {
41 + "protocol": "OF_10"
42 + }
43 + },
44 + {
45 + "id": "of:0000000000000004",
46 + "available": false,
47 + "_iconid_available": "deviceOffline",
48 + "role": "MASTER",
49 + "mfr": "Nicira, Inc.",
50 + "hw": "Open vSwitch",
51 + "sw": "2.0.1",
52 + "serial": "None",
53 + "annotations": {
54 + "protocol": "OF_10"
55 + }
56 + },
57 + {
58 + "id": "of:0000000000000092",
59 + "available": false,
60 + "_iconid_available": "deviceOffline",
61 + "role": "MASTER",
62 + "mfr": "Nicira, Inc.",
63 + "hw": "Open vSwitch",
64 + "sw": "2.0.1",
65 + "serial": "None",
66 + "annotations": {
67 + "protocol": "OF_10"
68 + }
69 + }]
70 + };
71 +
24 function setColWidth(t) { 72 function setColWidth(t) {
25 var tHeaders, tdElement, colWidth; 73 var tHeaders, tdElement, colWidth;
26 74
...@@ -84,4 +132,4 @@ ...@@ -84,4 +132,4 @@
84 } 132 }
85 }; 133 };
86 }]); 134 }]);
87 -}());
...\ No newline at end of file ...\ No newline at end of file
135 +}());
......
...@@ -22,12 +22,68 @@ ...@@ -22,12 +22,68 @@
22 22
23 var $log; 23 var $log;
24 24
25 + function renderTable(div, config) {
26 + var table = div.append('table').attr('fixed-header', true),
27 + thead, tr, numTableCols, i;
28 + table.append('thead');
29 + table.append('tbody');
30 +
31 + thead = table.select('thead');
32 + tr = thead.append('tr');
33 + numTableCols = config.colIds.length;
34 +
35 + for(i = 0; i < numTableCols; i += 1) {
36 + tr.append('th').html(config.colText[i]);
37 + }
38 +
39 + return config.colIds;
40 + }
41 +
42 + // I can delete these comments later...
43 + // loadTableData needs to know which IDs are used to create the table...
44 + // Potentially, there will be some rows in the JSON that the server is
45 + // sending back that will be unused. We don't want to create unneeded rows.
46 + // For example, in device view, we aren't displaying "role" or
47 + // "available" properties, but they would be displayed if we took it
48 + // directly from the data being sent in.
49 + function loadTableData(data, div, colIds) {
50 + // let me know if you have suggestions for this function
51 +
52 + var numTableCols = colIds.length,
53 + tbody, tr, td, i;
54 + tbody = div.select('tbody');
55 +
56 + // get the array associated with the first object, such as "devices"
57 + // in fakeData
58 + // (for some reason it doesn't like the data.keys() function, saying
59 + // "undefined is not a function"
60 + // Object.keys(data) works though)
61 + // loop through every object in the array, and every property in the object
62 + // put their property in the td of the table
63 + (data[Object.keys(data)[0]]).forEach(function (item) {
64 + tr = tbody.append('tr');
65 + for(var key in item) {
66 + for(i = 0; i < numTableCols; i += 1) {
67 + if(key === colIds[i]) {
68 + td = tr.append('td').html(item[key]);
69 + }
70 + }
71 + }
72 + });
73 + }
74 +
75 + function renderAndLoadTable(div, config, data) {
76 + loadTableData(data, div, (renderTable(div, config)));
77 + }
78 +
25 angular.module('onosWidget') 79 angular.module('onosWidget')
26 .factory('TableService', ['$log', function (_$log_) { 80 .factory('TableService', ['$log', function (_$log_) {
27 $log = _$log_; 81 $log = _$log_;
28 82
29 return { 83 return {
30 - 84 + renderTable: renderTable,
85 + loadTableData: loadTableData,
86 + renderAndLoadTable: renderAndLoadTable
31 }; 87 };
32 }]); 88 }]);
33 89
......
1 <!-- Device partial HTML --> 1 <!-- Device partial HTML -->
2 <div id="ov-device"> 2 <div id="ov-device">
3 <h2>Device View</h2> 3 <h2>Device View</h2>
4 -<!-- TODO: uncomment and test the thead and tbody tags for CSS styling -->
5 <table class="summary-list"> 4 <table class="summary-list">
6 <tbody> 5 <tbody>
7 <tr> 6 <tr>
......
...@@ -18,7 +18,54 @@ ...@@ -18,7 +18,54 @@
18 ONOS GUI -- Widget -- Table Service - Unit Tests 18 ONOS GUI -- Widget -- Table Service - Unit Tests
19 */ 19 */
20 describe('factory: fw/widget/table.js', function() { 20 describe('factory: fw/widget/table.js', function() {
21 - var ts, $log; 21 + var ts, $log, d3Elem;
22 +
23 + var config = {
24 + colIds: ['id', 'mfr', 'hw', 'sw', 'serial', 'annotations.protocol'],
25 + colText: ['URI', 'Vendor', 'Hardware Version', 'Software Version',
26 + 'Serial Number', 'Protocol']
27 + },
28 + fakeData = {
29 + "devices": [{
30 + "id": "of:0000000000000001",
31 + "available": true,
32 + "_iconid_available": "deviceOnline",
33 + "role": "MASTER",
34 + "mfr": "Nicira, Inc.",
35 + "hw": "Open vSwitch",
36 + "sw": "2.0.1",
37 + "serial": "None",
38 + "annotations": {
39 + "protocol": "OF_10"
40 + }
41 + },
42 + {
43 + "id": "of:0000000000000004",
44 + "available": false,
45 + "_iconid_available": "deviceOffline",
46 + "role": "MASTER",
47 + "mfr": "Nicira, Inc.",
48 + "hw": "Open vSwitch",
49 + "sw": "2.0.1",
50 + "serial": "None",
51 + "annotations": {
52 + "protocol": "OF_10"
53 + }
54 + },
55 + {
56 + "id": "of:0000000000000092",
57 + "available": false,
58 + "_iconid_available": "deviceOffline",
59 + "role": "MASTER",
60 + "mfr": "Nicira, Inc.",
61 + "hw": "Open vSwitch",
62 + "sw": "2.0.1",
63 + "serial": "None",
64 + "annotations": {
65 + "protocol": "OF_10"
66 + }
67 + }]
68 + };
22 69
23 beforeEach(module('onosWidget')); 70 beforeEach(module('onosWidget'));
24 71
...@@ -30,4 +77,58 @@ describe('factory: fw/widget/table.js', function() { ...@@ -30,4 +77,58 @@ describe('factory: fw/widget/table.js', function() {
30 it('should define TableService', function () { 77 it('should define TableService', function () {
31 expect(ts).toBeDefined(); 78 expect(ts).toBeDefined();
32 }); 79 });
33 -});
...\ No newline at end of file ...\ No newline at end of file
80 +
81 + function verifyTableTags(div) {
82 + var table = div.select('table'),
83 + tableHeaders;
84 + expect(table).toBeTruthy();
85 + expect(table.attr('fixed-header')).toBeTruthy();
86 + expect(table.select('thead')).toBeTruthy();
87 + expect(table.select('tbody')).toBeTruthy();
88 +
89 + tableHeaders = table.select('thead').selectAll('th');
90 + tableHeaders.each(function(thElement, i) {
91 + thElement = d3.select(this);
92 + expect(thElement).toBeTruthy();
93 + expect(thElement.html()).toBe(config.colText[i]);
94 + });
95 + }
96 +
97 + function verifyData(div) {
98 + var tbody = div.select('tbody'),
99 + tableBoxes = tbody.selectAll('td');
100 + expect(tbody).toBeTruthy();
101 + expect(tbody.select('tr')).toBeTruthy();
102 +
103 + tableBoxes.each(function(tdElement, i){
104 + tdElement = d3.select(this);
105 + if(i === 0) {
106 + expect(tdElement.html()).toBe('of:0000000000000001');
107 + }
108 + if(i === 1) {
109 + expect(tdElement.html()).toBe('Nicira, Inc.');
110 + }
111 + if(i === 2) {
112 + expect(tdElement.html()).toBe('Open vSwitch');
113 + }
114 + expect(tdElement).toBeTruthy();
115 + });
116 + }
117 +
118 + it('should create table tags', function () {
119 + ts.renderTable(d3Elem, config);
120 + verifyTableTags(d3Elem);
121 + });
122 +
123 + it('should load data into table', function () {
124 + var colIds = ts.renderTable(d3Elem, config);
125 + ts.loadTableData(fakeData, d3Elem, colIds);
126 + verifyData(d3Elem);
127 + });
128 +
129 + it('should render table and load data', function () {
130 + ts.renderAndLoadTable(d3Elem, config, fakeData);
131 + verifyData(d3Elem);
132 + });
133 +
134 +});
......