Bri Prebilic Cole

ONOS-1842 - GUI -- Tables have better resizing behavior -- column headers stay a…

…bove their columns and table cell text is constrained to one size.

Change-Id: I89ca7d25d46d895c78c41b8250ce40408fbaba85
...@@ -16,68 +16,80 @@ ...@@ -16,68 +16,80 @@
16 16
17 /* ------ for summary-list tables ------ */ 17 /* ------ for summary-list tables ------ */
18 18
19 -table.summary-list { 19 +div.summary-list {
20 - margin: 0 20px 16px 12px; 20 + margin: 0 20px 16px 10px;
21 font-size: 10pt; 21 font-size: 10pt;
22 border-spacing: 0; 22 border-spacing: 0;
23 } 23 }
24 24
25 -table.summary-list td.nodata { 25 +div.summary-list table {
26 + border-collapse: collapse;
27 + table-layout: fixed;
28 + empty-cells: show;
29 + margin: 0;
30 +}
31 +
32 +div.summary-list div.table-body {
33 + overflow-y: scroll;
34 +}
35 +
36 +div.summary-list tr.no-data td {
26 text-align: center; 37 text-align: center;
27 font-style: italic; 38 font-style: italic;
28 } 39 }
29 40
30 -.light table.summary-list tr:nth-child(even) { 41 +.light div.summary-list tr:nth-child(even) {
31 background-color: #ddd; 42 background-color: #ddd;
32 } 43 }
33 -.light table.summary-list tr:nth-child(odd) { 44 +.light div.summary-list tr:nth-child(odd) {
34 background-color: #eee; 45 background-color: #eee;
35 } 46 }
36 -.dark table.summary-list tr:nth-child(even) { 47 +.dark div.summary-list tr:nth-child(even) {
37 background-color: #333; 48 background-color: #333;
38 } 49 }
39 -.dark table.summary-list tr:nth-child(odd) { 50 +.dark div.summary-list tr:nth-child(odd) {
40 background-color: #444; 51 background-color: #444;
41 } 52 }
42 53
43 -.light table.summary-list tr.selected { 54 +.light div.summary-list tr.selected {
44 background-color: deepskyblue; 55 background-color: deepskyblue;
45 } 56 }
46 57
47 -.dark table.summary-list tr.selected { 58 +.dark div.summary-list tr.selected {
48 background-color: #304860; 59 background-color: #304860;
49 } 60 }
50 61
51 -table.summary-list td, 62 +div.summary-list td {
52 -table.summary-list th {
53 padding: 6px; 63 padding: 6px;
54 text-align: left; 64 text-align: left;
65 + word-wrap: break-word;
55 } 66 }
56 67
57 -table.summary-list th { 68 +div.summary-list .table-header td {
58 letter-spacing: 0.02em; 69 letter-spacing: 0.02em;
59 cursor: pointer; 70 cursor: pointer;
71 + font-weight: bold;
60 } 72 }
61 -table.summary-list th:first-child { 73 +div.summary-list .table-header td:first-child {
62 border-radius: 8px 0 0 0; 74 border-radius: 8px 0 0 0;
63 } 75 }
64 -table.summary-list th:last-child { 76 +div.summary-list .table-header td:last-child {
65 border-radius: 0 8px 0 0; 77 border-radius: 0 8px 0 0;
66 } 78 }
67 79
68 -.light table.summary-list th { 80 +.light div.summary-list .table-header td {
69 background-color: #bbb; 81 background-color: #bbb;
70 } 82 }
71 -.dark table.summary-list th { 83 +.dark div.summary-list .table-header td {
72 background-color: #222; 84 background-color: #222;
73 color: #ccc; 85 color: #ccc;
74 } 86 }
75 87
76 /* rows are selectable */ 88 /* rows are selectable */
77 -table.summary-list td { 89 +div.summary-list .table-body td {
78 cursor: pointer; 90 cursor: pointer;
79 } 91 }
80 92
81 -.dark table.summary-list td { 93 +.dark div.summary-list td {
82 color: #ccc; 94 color: #ccc;
83 } 95 }
......
...@@ -37,86 +37,68 @@ ...@@ -37,86 +37,68 @@
37 prevCol = {}, 37 prevCol = {},
38 sortIconAPI; 38 sortIconAPI;
39 39
40 - // Functions for creating a fixed header on a table (Angular Directive) 40 + // Functions for creating a scrolling table body with fixed table header
41 41
42 - function setElemWidth(elem, size) { 42 + function _width(elem, width) {
43 - elem.style('width', size + 'px') 43 + elem.style('width', width);
44 } 44 }
45 45
46 - function setColWidth(th, td, size) { 46 + function defaultSize(table, width) {
47 - setElemWidth(th, size); 47 + var thead = table.select('.table-header').select('table'),
48 - setElemWidth(td, size); 48 + tbody = table.select('.table-body').select('table'),
49 + wpx = width + 'px';
50 + _width(thead, wpx);
51 + _width(tbody, wpx);
49 } 52 }
50 53
51 - // count number of headers of 54 + function adjustTable(table, width, height) {
52 - // - assigned width, 55 + var thead = table.select('.table-header').select('table'),
53 - // - icon width, 56 + tbodyDiv = table.select('.table-body'),
54 - // - and default width 57 + tbody = tbodyDiv.select('table'),
55 - // assumes assigned width is not given to icons 58 + cstmWidths = {};
56 - // returns the width of all columns that are not icons
57 - // or have an assigned width
58 - function getDefaultWidth(headers) {
59 - var winWidth = fs.windowSize().width,
60 - iconCols = 0,
61 - regCols = 0,
62 - cstmColWidth = 0;
63 -
64 - headers.each(function (d, i) {
65 - var thElement = d3.select(this),
66 - cstmWidth = thElement.attr(colWidth);
67 -
68 - if (cstmWidth) {
69 - cstmColWidth += fs.noPx(cstmWidth);
70 - } else if (thElement.classed(tableIcon)) {
71 - iconCols += 1;
72 - } else {
73 - regCols += 1;
74 - }
75 - });
76 -
77 - return Math.floor((winWidth - cstmColWidth -
78 - (iconCols * tableIconTdSize)) / regCols);
79 - }
80 59
81 - function setTableWidth(t) { 60 + function findCstmWidths() {
82 - var tHeaders = t.selectAll('th'), 61 + var headers = thead.selectAll('td');
83 - defaultColWidth = getDefaultWidth(tHeaders);
84 -
85 - tHeaders.each(function (d, i) {
86 - var thElement = d3.select(this),
87 - tr = t.select('tr:nth-of-type(2)'),
88 - tdElement = tr.select('td:nth-of-type(' + (i + 1) + ')'),
89 - custWidth = thElement.attr(colWidth);
90 -
91 - if (custWidth) {
92 - setColWidth(thElement, tdElement, fs.noPx(custWidth));
93 - } else if (thElement.classed(tableIcon)) {
94 - setColWidth(thElement, tdElement, tableIconTdSize);
95 - } else {
96 - setColWidth(thElement, tdElement, defaultColWidth);
97 - }
98 - });
99 - }
100 62
101 - // get the size of the window and then subtract the extra space at the top 63 + headers.each(function (d, i) {
102 - // to get the height of the table 64 + var h = d3.select(this),
103 - function setTableHeight(thead, tbody) { 65 + index = i.toString();
104 - var ttlHgt = fs.noPxStyle(d3.select('.tabular-header'), 'height'), 66 + if (h.classed(tableIcon)) {
105 - thHgt = fs.noPxStyle(thead, 'height'), 67 + cstmWidths[index] = tableIconTdSize + 'px';
106 - totalHgt = ttlHgt + thHgt + pdg, 68 + }
107 - tbleHgt = fs.windowSize(mast.mastHeight() + totalHgt).height; 69 + if (h.attr(colWidth)) {
108 - 70 + cstmWidths[index] = h.attr(colWidth);
109 - thead.style('display', 'block'); 71 + }
110 - tbody.style({ 72 + });
111 - display: 'block', 73 + $log.debug('Headers with custom widths: ', cstmWidths);
112 - height: tbleHgt + 'px', 74 + }
113 - overflow: 'auto'
114 - });
115 - }
116 75
117 - function fixTable(t, th, tb) { 76 + function setTdWidths(elem) {
118 - setTableWidth(t); 77 + var tds = elem.selectAll('tr:not(.ignore-width)').selectAll('td');
119 - setTableHeight(th, tb); 78 + _width(elem, width + 'px');
79 +
80 + tds.each(function (d, i) {
81 + var td = d3.select(this),
82 + index = i.toString();
83 + if (cstmWidths.hasOwnProperty(index)) {
84 + _width(td, cstmWidths[index]);
85 + }
86 + });
87 + }
88 +
89 + function setHeight(body) {
90 + var h = height - (mast.mastHeight() +
91 + fs.noPxStyle(d3.select('.tabular-header'), 'height') +
92 + fs.noPxStyle(thead, 'height') + pdg);
93 + body.style('height', h + 'px');
94 + }
95 +
96 + findCstmWidths();
97 + setTdWidths(thead);
98 + setTdWidths(tbody);
99 + setHeight(tbodyDiv);
100 +
101 + cstmWidths = {};
120 } 102 }
121 103
122 // Functions for sorting table rows by header 104 // Functions for sorting table rows by header
...@@ -163,40 +145,42 @@ ...@@ -163,40 +145,42 @@
163 } 145 }
164 146
165 angular.module('onosWidget') 147 angular.module('onosWidget')
166 - .directive('onosFixedHeader', ['$window', 'FnService', 'MastService', 148 + .directive('onosFixedHeader', ['$log','$window',
167 - function (_$window_, _fs_, _mast_) { 149 + 'FnService', 'MastService',
150 +
151 + function (_$log_, _$window_, _fs_, _mast_) {
168 return function (scope, element) { 152 return function (scope, element) {
153 + $log = _$log_;
169 $window = _$window_; 154 $window = _$window_;
170 fs = _fs_; 155 fs = _fs_;
171 mast = _mast_; 156 mast = _mast_;
172 157
173 var w = angular.element($window), 158 var w = angular.element($window),
174 table = d3.select(element[0]), 159 table = d3.select(element[0]),
175 - thead = table.select('thead'),
176 - tbody = table.select('tbody'),
177 canAdjust = false; 160 canAdjust = false;
178 161
179 scope.$watch(function () { 162 scope.$watch(function () {
180 return { 163 return {
181 - h: window.innerHeight, 164 + h: $window.innerHeight,
182 - w: window.innerWidth 165 + w: $window.innerWidth
183 }; 166 };
184 - }, function (newVal) { 167 + }, function () {
185 - var wsz = fs.windowSize(0, 30); 168 + var wsz = fs.windowSize(0, 30),
186 - scope.windowHeight = newVal.h; 169 + wWidth = wsz.width,
187 - scope.windowWidth = newVal.w; 170 + wHeight = wsz.height;
188 171
189 - // default table size in case no data elements 172 + if (!scope.tableData.length) {
190 - table.style('width', wsz.width + 'px'); 173 + defaultSize(table, wWidth);
174 + }
191 175
192 scope.$on('LastElement', function () { 176 scope.$on('LastElement', function () {
193 // only adjust the table once it's completely loaded 177 // only adjust the table once it's completely loaded
194 - fixTable(table, thead, tbody); 178 + adjustTable(table, wWidth, wHeight);
195 canAdjust = true; 179 canAdjust = true;
196 }); 180 });
197 181
198 if (canAdjust) { 182 if (canAdjust) {
199 - fixTable(table, thead, tbody); 183 + adjustTable(table, wWidth, wHeight);
200 } 184 }
201 }, true); 185 }, true);
202 186
...@@ -215,16 +199,16 @@ ...@@ -215,16 +199,16 @@
215 link: function (scope, element) { 199 link: function (scope, element) {
216 $log = _$log_; 200 $log = _$log_;
217 is = _is_; 201 is = _is_;
218 - var table = d3.select(element[0]); 202 + var header = d3.select(element[0]);
219 sortIconAPI = is.sortIcons(); 203 sortIconAPI = is.sortIcons();
220 204
221 - // when a header is clicked, change its icon tag 205 + // when a header is clicked, change its sort direction
222 // and get sorting order to send to the server. 206 // and get sorting order to send to the server.
223 - table.selectAll('th').on('click', function () { 207 + header.selectAll('td').on('click', function () {
224 - var thElem = d3.select(this); 208 + var col = d3.select(this);
225 209
226 - if (thElem.attr('sortable') === '') { 210 + if (col.attr('sortable') === '') {
227 - updateSortDirection(thElem); 211 + updateSortDirection(col);
228 scope.ctrlCallback({ 212 scope.ctrlCallback({
229 requestParams: sortRequestParams() 213 requestParams: sortRequestParams()
230 }); 214 });
...@@ -234,9 +218,9 @@ ...@@ -234,9 +218,9 @@
234 }; 218 };
235 }]) 219 }])
236 220
237 - .factory('TableService', ['$log', 'IconService', 221 + .factory('TableService', ['IconService',
238 222
239 - function ($log, is) { 223 + function (is) {
240 sortIconAPI = is.sortIcons(); 224 sortIconAPI = is.sortIcons();
241 225
242 return { 226 return {
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
25 25
26 // example params to buildTable: 26 // example params to buildTable:
27 // { 27 // {
28 - // self: this, <- controller object
29 // scope: $scope, <- controller scope 28 // scope: $scope, <- controller scope
30 // tag: 'device', <- table identifier 29 // tag: 'device', <- table identifier
31 // selCb: selCb <- row selection callback (optional) 30 // selCb: selCb <- row selection callback (optional)
...@@ -43,10 +42,10 @@ ...@@ -43,10 +42,10 @@
43 resp = o.tag + 'DataResponse', 42 resp = o.tag + 'DataResponse',
44 onSel = fs.isF(o.selCb); 43 onSel = fs.isF(o.selCb);
45 44
46 - o.self.tableData = []; 45 + o.scope.tableData = [];
47 46
48 function respCb(data) { 47 function respCb(data) {
49 - o.self.tableData = data[root]; 48 + o.scope.tableData = data[root];
50 o.scope.$apply(); 49 o.scope.$apply();
51 } 50 }
52 51
......
1 <!-- app partial HTML --> 1 <!-- app partial HTML -->
2 <div id="ov-app"> 2 <div id="ov-app">
3 <div class="tabular-header"> 3 <div class="tabular-header">
4 - <h2>Applications ({{ctrl.tableData.length}} total)</h2> 4 + <h2>Applications ({{tableData.length}} total)</h2>
5 <div class="ctrl-btns"> 5 <div class="ctrl-btns">
6 <div class="refresh active" 6 <div class="refresh active"
7 icon icon-size="36" icon-id="refresh" 7 icon icon-size="36" icon-id="refresh"
...@@ -19,39 +19,44 @@ ...@@ -19,39 +19,44 @@
19 </form> 19 </form>
20 </div> 20 </div>
21 21
22 - <table class="summary-list" 22 + <div class="summary-list" onos-fixed-header>
23 - onos-fixed-header
24 - onos-sortable-header
25 - sort-callback="sortCallback(requestParams)">
26 - <thead>
27 - <tr>
28 - <th colId="state" class="table-icon" sortable></th>
29 - <th colId="id" sortable>App ID </th>
30 - <th colId="version" sortable>Version </th>
31 - <th colId="origin" sortable>Origin </th>
32 - <th colId="desc" col-width="640px">Description </th>
33 - </tr>
34 - </thead>
35 23
36 - <tbody> 24 + <div class="table-header"
37 - <tr ng-hide="ctrl.tableData.length"> 25 + onos-sortable-header sort-callback="sortCallback(requestParams)">
38 - <td class="nodata" colspan="5"> 26 + <table>
39 - No Applications found 27 + <tr>
40 - </td> 28 + <td colId="state" class="table-icon" sortable></td>
41 - </tr> 29 + <td colId="id" sortable>App ID </td>
30 + <td colId="version" sortable>Version </td>
31 + <td colId="origin" sortable>Origin </td>
32 + <td colId="desc" col-width="475px">Description </td>
33 + </tr>
34 + </table>
35 + </div>
36 +
37 + <div class="table-body">
38 + <table>
39 + <tr ng-hide="tableData.length" class="no-data ignore-width">
40 + <td colspan="5">
41 + No Applications found
42 + </td>
43 + </tr>
44 +
45 + <tr ng-repeat="app in tableData"
46 + ng-click="selectCallback($event, app)"
47 + ng-class="{selected: app === sel}"
48 + ng-repeat-done>
49 + <td class="table-icon">
50 + <div icon icon-id="{{app._iconid_state}}"></div>
51 + </td>
52 + <td>{{app.id}}</td>
53 + <td>{{app.version}}</td>
54 + <td>{{app.origin}}</td>
55 + <td>{{app.desc}}</td>
56 + </tr>
57 + </table>
58 + </div>
59 +
60 + </div>
42 61
43 - <tr ng-repeat="app in ctrl.tableData"
44 - ng-click="selectCallback($event, app)"
45 - ng-class="{selected: app === sel}"
46 - ng-repeat-done>
47 - <td class="table-icon">
48 - <div icon icon-id="{{app._iconid_state}}"></div>
49 - </td>
50 - <td>{{app.id}}</td>
51 - <td>{{app.version}}</td>
52 - <td>{{app.origin}}</td>
53 - <td>{{app.desc}}</td>
54 - </tr>
55 - </tbody>
56 - </table>
57 </div> 62 </div>
......
...@@ -71,7 +71,6 @@ ...@@ -71,7 +71,6 @@
71 d3.select('#app-deactivate').on('click', function () { appAction('deactivate'); }); 71 d3.select('#app-deactivate').on('click', function () { appAction('deactivate'); });
72 72
73 tbs.buildTable({ 73 tbs.buildTable({
74 - self: this,
75 scope: $scope, 74 scope: $scope,
76 tag: 'app', 75 tag: 'app',
77 selCb: selCb 76 selCb: selCb
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
17 <!-- Cluster partial HTML --> 17 <!-- Cluster partial HTML -->
18 <div id="ov-cluster"> 18 <div id="ov-cluster">
19 <div class="tabular-header"> 19 <div class="tabular-header">
20 - <h2>Cluster Nodes ({{ctrl.tableData.length}} total)</h2> 20 + <h2>Cluster Nodes ({{tableData.length}} total)</h2>
21 <div class="ctrl-btns"> 21 <div class="ctrl-btns">
22 <div class="refresh active" 22 <div class="refresh active"
23 icon icon-size="36" icon-id="refresh" 23 icon icon-size="36" icon-id="refresh"
...@@ -25,37 +25,42 @@ ...@@ -25,37 +25,42 @@
25 </div> 25 </div>
26 </div> 26 </div>
27 27
28 - <table class="summary-list" 28 + <div class="summary-list" onos-fixed-header>
29 - onos-fixed-header
30 - onos-sortable-header
31 - sort-callback="sortCallback(requestParams)">
32 - <thead>
33 - <tr>
34 - <th colId="_iconid_state" class="table-icon" sortable></th>
35 - <th colId="id" sortable>ID </th>
36 - <th colId="ip" sortable>IP Address </th>
37 - <th colId="tcp" sortable>TCP Port </th>
38 - <th colId="updated" sortable>Last Updated </th>
39 - </tr>
40 - </thead>
41 29
42 - <tbody> 30 + <div class="table-header"
43 - <tr ng-hide="ctrl.tableData.length"> 31 + onos-sortable-header sort-callback="sortCallback(requestParams)">
44 - <td class="nodata" colspan="5"> 32 + <table>
45 - No Cluster Nodes found 33 + <tr>
46 - </td> 34 + <td colId="_iconid_state" class="table-icon" sortable></td>
47 - </tr> 35 + <td colId="id" sortable>ID </td>
36 + <td colId="ip" sortable>IP Address </td>
37 + <td colId="tcp" sortable>TCP Port </td>
38 + <td colId="updated" sortable>Last Updated </td>
39 + </tr>
40 + </table>
41 + </div>
42 +
43 + <div class="table-body">
44 + <table>
45 + <tr ng-hide="tableData.length" class="no-data ignore-width">
46 + <td colspan="5">
47 + No Cluster Nodes found
48 + </td>
49 + </tr>
50 +
51 + <tr ng-repeat="node in tableData"
52 + ng-repeat-done>
53 + <td class="table-icon">
54 + <div icon icon-id="{{node._iconid_state}}"></div>
55 + </td>
56 + <td>{{node.id}}</td>
57 + <td>{{node.ip}}</td>
58 + <td>{{node.tcp}}</td>
59 + <td>{{node.updated}}</td>
60 + </tr>
61 + </table>
62 + </div>
63 +
64 + </div>
48 65
49 - <tr ng-repeat="node in ctrl.tableData"
50 - ng-repeat-done>
51 - <td class="table-icon">
52 - <div icon icon-id="{{node._iconid_state}}"></div>
53 - </td>
54 - <td>{{node.id}}</td>
55 - <td>{{node.ip}}</td>
56 - <td>{{node.tcp}}</td>
57 - <td>{{node.updated}}</td>
58 - </tr>
59 - </tbody>
60 - </table>
61 </div> 66 </div>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
27 27
28 function ($log, $scope, ts, tbs) { 28 function ($log, $scope, ts, tbs) {
29 tbs.buildTable({ 29 tbs.buildTable({
30 - self: this,
31 scope: $scope, 30 scope: $scope,
32 tag: 'cluster' 31 tag: 'cluster'
33 }); 32 });
......
1 <!-- Device partial HTML --> 1 <!-- Device partial HTML -->
2 <div id="ov-device"> 2 <div id="ov-device">
3 <div class="tabular-header"> 3 <div class="tabular-header">
4 - <h2>Devices ({{ctrl.tableData.length}} total)</h2> 4 + <h2>Devices ({{tableData.length}} total)</h2>
5 <div class="ctrl-btns"> 5 <div class="ctrl-btns">
6 <div class="refresh active" 6 <div class="refresh active"
7 icon icon-size="36" icon-id="refresh" 7 icon icon-size="36" icon-id="refresh"
...@@ -9,49 +9,54 @@ ...@@ -9,49 +9,54 @@
9 </div> 9 </div>
10 </div> 10 </div>
11 11
12 - <table class="summary-list" 12 + <div class="summary-list" onos-fixed-header>
13 - onos-fixed-header
14 - onos-sortable-header
15 - sort-callback="sortCallback(requestParams)">
16 - <thead>
17 - <tr>
18 - <th colId="available" class="table-icon" sortable></th>
19 - <th colId="type" class="table-icon" sortable></th>
20 - <th colId="id" sortable>Device ID </th>
21 - <th colId="masterid" sortable>Master Instance </th>
22 - <th colId="num_ports" sortable>Ports </th>
23 - <th colId="mfr" sortable>Vendor </th>
24 - <th colId="hw" sortable>H/W Version </th>
25 - <th colId="sw" sortable>S/W Version </th>
26 - <th colId="protocol" sortable>Protocol </th>
27 - </tr>
28 - </thead>
29 13
30 - <tbody> 14 + <div class="table-header"
31 - <tr ng-hide="ctrl.tableData.length"> 15 + onos-sortable-header sort-callback="sortCallback(requestParams)">
32 - <td class="nodata" colspan="9"> 16 + <table>
33 - No Devices found 17 + <tr>
34 - </td> 18 + <td colId="available" class="table-icon" sortable></td>
35 - </tr> 19 + <td colId="type" class="table-icon" sortable></td>
20 + <td colId="id" sortable>Device ID </td>
21 + <td colId="masterid" sortable>Master Instance </td>
22 + <td colId="num_ports" sortable>Ports </td>
23 + <td colId="mfr" sortable>Vendor </td>
24 + <td colId="hw" sortable>H/W Version </td>
25 + <td colId="sw" sortable>S/W Version </td>
26 + <td colId="protocol" sortable>Protocol </td>
27 + </tr>
28 + </table>
29 + </div>
30 +
31 + <div class="table-body">
32 + <table>
33 + <tr ng-hide="tableData.length" class="no-data ignore-width">
34 + <td colspan="9">
35 + No Devices found
36 + </td>
37 + </tr>
38 +
39 + <tr ng-repeat="dev in tableData"
40 + ng-click="selectCallback($event, dev)"
41 + ng-class="{selected: dev === sel}"
42 + ng-repeat-done>
43 + <td class="table-icon">
44 + <div icon icon-id="{{dev._iconid_available}}"></div>
45 + </td>
46 + <td class="table-icon">
47 + <div icon icon-id="{{dev._iconid_type}}"></div>
48 + </td>
49 + <td>{{dev.id}}</td>
50 + <td>{{dev.masterid}}</td>
51 + <td>{{dev.num_ports}}</td>
52 + <td>{{dev.mfr}}</td>
53 + <td>{{dev.hw}}</td>
54 + <td>{{dev.sw}}</td>
55 + <td>{{dev.protocol}}</td>
56 + </tr>
57 + </table>
58 + </div>
59 +
60 + </div>
36 61
37 - <tr ng-repeat="dev in ctrl.tableData"
38 - ng-click="selectCallback($event, dev)"
39 - ng-class="{selected: dev === sel}"
40 - ng-repeat-done>
41 - <td class="table-icon">
42 - <div icon icon-id="{{dev._iconid_available}}"></div>
43 - </td>
44 - <td class="table-icon">
45 - <div icon icon-id="{{dev._iconid_type}}"></div>
46 - </td>
47 - <td>{{dev.id}}</td>
48 - <td>{{dev.masterid}}</td>
49 - <td>{{dev.num_ports}}</td>
50 - <td>{{dev.mfr}}</td>
51 - <td>{{dev.hw}}</td>
52 - <td>{{dev.sw}}</td>
53 - <td>{{dev.protocol}}</td>
54 - </tr>
55 - </tbody>
56 - </table>
57 </div> 62 </div>
......
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
25 var $log, $scope, fs, mast, ps, wss, is, bns, ns, ttip; 25 var $log, $scope, fs, mast, ps, wss, is, bns, ns, ttip;
26 26
27 // internal state 27 // internal state
28 - var self, 28 + var detailsPanel,
29 - detailsPanel,
30 pStartY, pHeight, 29 pStartY, pHeight,
31 top, bottom, iconDiv, 30 top, bottom, iconDiv,
32 wSize, selRow; 31 wSize, selRow;
...@@ -183,8 +182,8 @@ ...@@ -183,8 +182,8 @@
183 } 182 }
184 183
185 function respDetailsCb(data) { 184 function respDetailsCb(data) {
186 - self.panelData = data.details; 185 + $scope.panelData = data.details;
187 - populateDetails(self.panelData); 186 + populateDetails($scope.panelData);
188 detailsPanel.show(); 187 detailsPanel.show();
189 } 188 }
190 189
...@@ -219,9 +218,8 @@ ...@@ -219,9 +218,8 @@
219 bns = _bns_; 218 bns = _bns_;
220 ns = _ns_; 219 ns = _ns_;
221 ttip = _ttip_; 220 ttip = _ttip_;
222 - self = this;
223 var handlers = {}; 221 var handlers = {};
224 - self.panelData = []; 222 + $scope.panelData = [];
225 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height') 223 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
226 + mast.mastHeight() + topPdg; 224 + mast.mastHeight() + topPdg;
227 wSize = fs.windowSize(pStartY); 225 wSize = fs.windowSize(pStartY);
...@@ -238,7 +236,6 @@ ...@@ -238,7 +236,6 @@
238 } 236 }
239 237
240 tbs.buildTable({ 238 tbs.buildTable({
241 - self: self,
242 scope: $scope, 239 scope: $scope,
243 tag: 'device', 240 tag: 'device',
244 selCb: selCb 241 selCb: selCb
......
...@@ -50,4 +50,5 @@ ...@@ -50,4 +50,5 @@
50 #ov-flow td.selector, 50 #ov-flow td.selector,
51 #ov-flow td.treatment { 51 #ov-flow td.treatment {
52 padding-left: 36px; 52 padding-left: 36px;
53 + opacity: 0.65;
53 } 54 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
2 <div id="ov-flow"> 2 <div id="ov-flow">
3 <div class="tabular-header"> 3 <div class="tabular-header">
4 <h2> 4 <h2>
5 - Flows for Device {{ctrl.devId || "(No device selected)"}} 5 + Flows for Device {{devId || "(No device selected)"}}
6 - ({{ctrl.tableData.length}} total) 6 + ({{tableData.length}} total)
7 </h2> 7 </h2>
8 <div class="ctrl-btns"> 8 <div class="ctrl-btns">
9 <div class="refresh active" 9 <div class="refresh active"
...@@ -12,46 +12,52 @@ ...@@ -12,46 +12,52 @@
12 </div> 12 </div>
13 </div> 13 </div>
14 14
15 - <table class="summary-list" 15 + <div class="summary-list" onos-fixed-header>
16 - onos-fixed-header
17 - onos-sortable-header
18 - sort-callback="sortCallback(requestParams)">
19 - <thead>
20 - <tr>
21 - <th colId="id" sortable>Flow ID </th>
22 - <th colId="appId" sortable>App ID </th>
23 - <th colId="groupId" sortable>Group ID </th>
24 - <th colId="tableId" sortable>Table ID </th>
25 - <th colId="priority" sortable>Priority </th>
26 - <th colId="timeout" sortable>Timeout </th>
27 - <th colId="permanent" sortable>Permanent </th>
28 - <th colId="state" sortable>State </th>
29 - </tr>
30 - </thead>
31 16
32 - <tbody> 17 + <div class="table-header"
33 - <tr ng-hide="ctrl.tableData.length"> 18 + onos-sortable-header sort-callback="sortCallback(requestParams)">
34 - <td class="nodata" colspan="8"> 19 + <table>
35 - No Flows found 20 + <tr>
36 - </td> 21 + <td colId="id" col-width="180px" sortable>Flow ID </td>
37 - </tr> 22 + <td colId="appId" sortable>App ID </td>
23 + <td colId="groupId" sortable>Group ID </td>
24 + <td colId="tableId" sortable>Table ID </td>
25 + <td colId="priority" sortable>Priority </td>
26 + <td colId="timeout" sortable>Timeout </td>
27 + <td colId="permanent" sortable>Permanent </td>
28 + <td colId="state" sortable>State </td>
29 + </tr>
30 + </table>
31 + </div>
32 +
33 + <div class="table-body">
34 + <table>
35 + <tr ng-hide="tableData.length" class="no-data ignore-width">
36 + <td colspan="8">
37 + No Flows found
38 + </td>
39 + </tr>
40 +
41 + <tr ng-repeat-start="flow in tableData">
42 + <td>{{flow.id}}</td>
43 + <td>{{flow.appId}}</td>
44 + <td>{{flow.groupId}}</td>
45 + <td>{{flow.tableId}}</td>
46 + <td>{{flow.priority}}</td>
47 + <td>{{flow.timeout}}</td>
48 + <td>{{flow.permanent}}</td>
49 + <td>{{flow.state}}</td>
50 + </tr>
51 + <tr class="ignore-width">
52 + <td class="selector" colspan="8">{{flow.selector}}</td>
53 + </tr>
54 + <tr class="ignore-width"
55 + ng-repeat-end ng-repeat-done>
56 + <td class="treatment" colspan="8">{{flow.treatment}}</td>
57 + </tr>
58 + </table>
59 + </div>
60 +
61 + </div>
38 62
39 - <tr ng-repeat-start="flow in ctrl.tableData">
40 - <td>{{flow.id}}</td>
41 - <td>{{flow.appId}}</td>
42 - <td>{{flow.groupId}}</td>
43 - <td>{{flow.tableId}}</td>
44 - <td>{{flow.priority}}</td>
45 - <td>{{flow.timeout}}</td>
46 - <td>{{flow.permanent}}</td>
47 - <td>{{flow.state}}</td>
48 - </tr>
49 - <tr>
50 - <td class="selector" colspan="8">{{flow.selector}}</td>
51 - </tr>
52 - <tr ng-repeat-end ng-repeat-done>
53 - <td class="treatment" colspan="8">{{flow.treatment}}</td>
54 - </tr>
55 - </tbody>
56 - </table>
57 </div> 63 </div>
......
...@@ -30,8 +30,7 @@ ...@@ -30,8 +30,7 @@
30 'FnService', 'TableService', 'TableBuilderService', 30 'FnService', 'TableService', 'TableBuilderService',
31 31
32 function (_$log_, _$scope_, _$location_, _fs_, _ts_, _tbs_) { 32 function (_$log_, _$scope_, _$location_, _fs_, _ts_, _tbs_) {
33 - var self = this, 33 + var params;
34 - params;
35 $log = _$log_; 34 $log = _$log_;
36 $scope = _$scope_; 35 $scope = _$scope_;
37 $location = _$location_; 36 $location = _$location_;
...@@ -41,11 +40,10 @@ ...@@ -41,11 +40,10 @@
41 40
42 params = $location.search(); 41 params = $location.search();
43 if (params.hasOwnProperty('devId')) { 42 if (params.hasOwnProperty('devId')) {
44 - self.devId = params['devId']; 43 + $scope.devId = params['devId'];
45 } 44 }
46 45
47 tbs.buildTable({ 46 tbs.buildTable({
48 - self: self,
49 scope: $scope, 47 scope: $scope,
50 tag: 'flow', 48 tag: 'flow',
51 query: params 49 query: params
......
1 <!-- Host partial HTML --> 1 <!-- Host partial HTML -->
2 <div id="ov-host"> 2 <div id="ov-host">
3 <div class="tabular-header"> 3 <div class="tabular-header">
4 - <h2>Hosts ({{ctrl.tableData.length}} total)</h2> 4 + <h2>Hosts ({{tableData.length}} total)</h2>
5 <div class="ctrl-btns"> 5 <div class="ctrl-btns">
6 <div class="refresh active" 6 <div class="refresh active"
7 icon icon-size="36" icon-id="refresh" 7 icon icon-size="36" icon-id="refresh"
...@@ -9,39 +9,44 @@ ...@@ -9,39 +9,44 @@
9 </div> 9 </div>
10 </div> 10 </div>
11 11
12 - <table class="summary-list" 12 + <div class="summary-list" onos-fixed-header>
13 - onos-fixed-header
14 - onos-sortable-header
15 - sort-callback="sortCallback(requestParams)">
16 - <thead>
17 - <tr>
18 - <th colId="type" class="table-icon" sortable></th>
19 - <th colId="id" sortable>Host ID </th>
20 - <th colId="mac" sortable>MAC Address </th>
21 - <th colId="vlan" sortable>VLAN ID </th>
22 - <th colId="ips" sortable>IP Addresses </th>
23 - <th colId="location" sortable>Location </th>
24 - </tr>
25 - </thead>
26 13
27 - <tbody> 14 + <div class="table-header"
28 - <tr ng-hide="ctrl.tableData.length"> 15 + onos-sortable-header sort-callback="sortCallback(requestParams)">
29 - <td class="nodata" colspan="6"> 16 + <table>
30 - No Hosts found 17 + <tr>
31 - </td> 18 + <td colId="type" class="table-icon" sortable></td>
32 - </tr> 19 + <td colId="id" sortable>Host ID </td>
20 + <td colId="mac" sortable>MAC Address </td>
21 + <td colId="vlan" sortable>VLAN ID </td>
22 + <td colId="ips" sortable>IP Addresses </td>
23 + <td colId="location" sortable>Location </td>
24 + </tr>
25 + </table>
26 + </div>
27 +
28 + <div class="table-body">
29 + <table>
30 + <tr ng-hide="tableData.length" class="no-data ignore-width">
31 + <td colspan="6">
32 + No Hosts found
33 + </td>
34 + </tr>
35 +
36 + <tr ng-repeat="host in tableData"
37 + ng-repeat-done>
38 + <td class="table-icon">
39 + <div icon icon-id="{{host._iconid_type}}"></div>
40 + </td>
41 + <td>{{host.id}}</td>
42 + <td>{{host.mac}}</td>
43 + <td>{{host.vlan}}</td>
44 + <td>{{host.ips}}</td>
45 + <td>{{host.location}}</td>
46 + </tr>
47 + </table>
48 + </div>
49 +
50 + </div>
33 51
34 - <tr ng-repeat="host in ctrl.tableData"
35 - ng-repeat-done>
36 - <td class="table-icon">
37 - <div icon icon-id="{{host._iconid_type}}"></div>
38 - </td>
39 - <td>{{host.id}}</td>
40 - <td>{{host.mac}}</td>
41 - <td>{{host.vlan}}</td>
42 - <td>{{host.ips}}</td>
43 - <td>{{host.location}}</td>
44 - </tr>
45 - </tbody>
46 - </table>
47 </div> 52 </div>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
27 27
28 function ($log, $scope, ts, tbs) { 28 function ($log, $scope, ts, tbs) {
29 tbs.buildTable({ 29 tbs.buildTable({
30 - self: this,
31 scope: $scope, 30 scope: $scope,
32 tag: 'host' 31 tag: 'host'
33 }); 32 });
...@@ -37,7 +36,7 @@ ...@@ -37,7 +36,7 @@
37 ts.resetSortIcons(); 36 ts.resetSortIcons();
38 $scope.sortCallback(); 37 $scope.sortCallback();
39 }; 38 };
40 - 39 +
41 $log.log('OvHostCtrl has been created'); 40 $log.log('OvHostCtrl has been created');
42 }]); 41 }]);
43 }()); 42 }());
......
...@@ -50,4 +50,5 @@ ...@@ -50,4 +50,5 @@
50 #ov-intent td.resources, 50 #ov-intent td.resources,
51 #ov-intent td.details { 51 #ov-intent td.details {
52 padding-left: 36px; 52 padding-left: 36px;
53 + opacity: 0.65;
53 } 54 }
......
...@@ -17,45 +17,51 @@ ...@@ -17,45 +17,51 @@
17 <!-- Intent partial HTML --> 17 <!-- Intent partial HTML -->
18 <div id="ov-intent"> 18 <div id="ov-intent">
19 <div class="tabular-header"> 19 <div class="tabular-header">
20 - <h2>Intents ({{ctrl.tableData.length}} total)</h2> 20 + <h2>Intents ({{tableData.length}} total)</h2>
21 <div class="ctrl-btns"> 21 <div class="ctrl-btns">
22 <div class="refresh active" 22 <div class="refresh active"
23 icon icon-size="36" icon-id="refresh" 23 icon icon-size="36" icon-id="refresh"
24 ng-click="refresh()"></div> 24 ng-click="refresh()"></div>
25 </div> 25 </div>
26 </div> 26 </div>
27 - <table class="summary-list"
28 - onos-fixed-header
29 - onos-sortable-header
30 - sort-callback="sortCallback(requestParams)">
31 - <thead>
32 - <tr>
33 - <th colId="appId" sortable>Application ID </th>
34 - <th colId="key" sortable>Key </th>
35 - <th colId="type" sortable>Type </th>
36 - <th colId="priority" sortable>Priority </th>
37 - </tr>
38 - </thead>
39 27
40 - <tbody> 28 + <div class="summary-list" onos-fixed-header>
41 - <tr ng-hide="ctrl.tableData.length"> 29 +
42 - <td class="nodata" colspan="4"> 30 + <div class="table-header"
43 - No Intents found 31 + onos-sortable-header sort-callback="sortCallback(requestParams)">
44 - </td> 32 + <table>
45 - </tr> 33 + <tr>
34 + <td colId="appId" sortable>Application ID </td>
35 + <td colId="key" sortable>Key </td>
36 + <td colId="type" sortable>Type </td>
37 + <td colId="priority" sortable>Priority </td>
38 + </tr>
39 + </table>
40 + </div>
41 +
42 + <div class="table-body">
43 + <table>
44 + <tr ng-hide="tableData.length" class="no-data ignore-width">
45 + <td colspan="4">
46 + No Intents found
47 + </td>
48 + </tr>
49 +
50 + <tr ng-repeat-start="intent in tableData">
51 + <td>{{intent.appId}}</td>
52 + <td>{{intent.key}}</td>
53 + <td>{{intent.type}}</td>
54 + <td>{{intent.priority}}</td>
55 + </tr>
56 + <tr>
57 + <td class="resources" colspan="4">{{intent.resources}}</td>
58 + </tr>
59 + <tr ng-repeat-end ng-repeat-done>
60 + <td class="details" colspan="4">{{intent.details}}</td>
61 + </tr>
62 + </table>
63 + </div>
64 +
65 + </div>
46 66
47 - <tr ng-repeat-start="intent in ctrl.tableData">
48 - <td>{{intent.appId}}</td>
49 - <td>{{intent.key}}</td>
50 - <td>{{intent.type}}</td>
51 - <td>{{intent.priority}}</td>
52 - </tr>
53 - <tr>
54 - <td class="resources" colspan="4">{{intent.resources}}</td>
55 - </tr>
56 - <tr ng-repeat-end ng-repeat-done>
57 - <td class="details" colspan="4">{{intent.details}}</td>
58 - </tr>
59 - </tbody>
60 - </table>
61 </div> 67 </div>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
27 27
28 function ($log, $scope, ts, tbs) { 28 function ($log, $scope, ts, tbs) {
29 tbs.buildTable({ 29 tbs.buildTable({
30 - self: this,
31 scope: $scope, 30 scope: $scope,
32 tag: 'intent' 31 tag: 'intent'
33 }); 32 });
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
17 <!-- Link partial HTML --> 17 <!-- Link partial HTML -->
18 <div id="ov-link"> 18 <div id="ov-link">
19 <div class="tabular-header"> 19 <div class="tabular-header">
20 - <h2>Links ({{ctrl.tableData.length}} total)</h2> 20 + <h2>Links ({{tableData.length}} total)</h2>
21 <div class="ctrl-btns"> 21 <div class="ctrl-btns">
22 <div class="refresh active" 22 <div class="refresh active"
23 icon icon-size="36" icon-id="refresh" 23 icon icon-size="36" icon-id="refresh"
...@@ -25,39 +25,44 @@ ...@@ -25,39 +25,44 @@
25 </div> 25 </div>
26 </div> 26 </div>
27 27
28 - <table class="summary-list" 28 + <div class="summary-list" onos-fixed-header>
29 - onos-fixed-header
30 - onos-sortable-header
31 - sort-callback="sortCallback(requestParams)">
32 - <thead>
33 - <tr>
34 - <th colId="_iconid_state" class="table-icon" sortable></th>
35 - <th colId="one" sortable>Port 1 </th>
36 - <th colId="two" sortable>Port 2 </th>
37 - <th colId="type" sortable>Type </th>
38 - <th colId="direction" sortable>Direction </th>
39 - <th colId="durable" sortable>Durable </th>
40 - </tr>
41 - </thead>
42 29
43 - <tbody> 30 + <div class="table-header"
44 - <tr ng-hide="ctrl.tableData.length"> 31 + onos-sortable-header sort-callback="sortCallback(requestParams)">
45 - <td class="nodata" colspan="6"> 32 + <table>
46 - No Links found 33 + <tr>
47 - </td> 34 + <td colId="_iconid_state" class="table-icon" sortable></td>
48 - </tr> 35 + <td colId="one" sortable>Port 1 </td>
36 + <td colId="two" sortable>Port 2 </td>
37 + <td colId="type" sortable>Type </td>
38 + <td colId="direction" sortable>Direction </td>
39 + <td colId="durable" sortable>Durable </td>
40 + </tr>
41 + </table>
42 + </div>
43 +
44 + <div class="table-body">
45 + <table>
46 + <tr ng-hide="tableData.length" class="no-data ignore-width">
47 + <td colspan="6">
48 + No Links found
49 + </td>
50 + </tr>
51 +
52 + <tr ng-repeat="link in tableData"
53 + ng-repeat-done>
54 + <td class="table-icon">
55 + <div icon icon-id="{{link._iconid_state}}"></div>
56 + </td>
57 + <td>{{link.one}}</td>
58 + <td>{{link.two}}</td>
59 + <td>{{link.type}}</td>
60 + <td>{{link.direction}}</td>
61 + <td>{{link.durable}}</td>
62 + </tr>
63 + </table>
64 + </div>
65 +
66 + </div>
49 67
50 - <tr ng-repeat="link in ctrl.tableData"
51 - ng-repeat-done>
52 - <td class="table-icon">
53 - <div icon icon-id="{{link._iconid_state}}"></div>
54 - </td>
55 - <td>{{link.one}}</td>
56 - <td>{{link.two}}</td>
57 - <td>{{link.type}}</td>
58 - <td>{{link.direction}}</td>
59 - <td>{{link.durable}}</td>
60 - </tr>
61 - </tbody>
62 - </table>
63 </div> 68 </div>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
27 27
28 function ($log, $scope, ts, tbs) { 28 function ($log, $scope, ts, tbs) {
29 tbs.buildTable({ 29 tbs.buildTable({
30 - self: this,
31 scope: $scope, 30 scope: $scope,
32 tag: 'link' 31 tag: 'link'
33 }); 32 });
...@@ -37,7 +36,7 @@ ...@@ -37,7 +36,7 @@
37 ts.resetSortIcons(); 36 ts.resetSortIcons();
38 $scope.sortCallback(); 37 $scope.sortCallback();
39 }; 38 };
40 - 39 +
41 $log.log('OvLinkCtrl has been created'); 40 $log.log('OvLinkCtrl has been created');
42 }]); 41 }]);
43 }()); 42 }());
......
...@@ -48,7 +48,6 @@ describe('factory: fw/widget/tableBuilder.js', function () { ...@@ -48,7 +48,6 @@ describe('factory: fw/widget/tableBuilder.js', function () {
48 48
49 beforeEach(function () { 49 beforeEach(function () {
50 mockObj = { 50 mockObj = {
51 - self: {},
52 scope: $rootScope.$new(), 51 scope: $rootScope.$new(),
53 tag: 'foo', 52 tag: 'foo',
54 selCb: mockSelCb 53 selCb: mockSelCb
...@@ -78,10 +77,10 @@ describe('factory: fw/widget/tableBuilder.js', function () { ...@@ -78,10 +77,10 @@ describe('factory: fw/widget/tableBuilder.js', function () {
78 }); 77 });
79 78
80 it('should set tableData', function () { 79 it('should set tableData', function () {
81 - expect(mockObj.self.tableData).not.toBeDefined(); 80 + expect(mockObj.scope.tableData).not.toBeDefined();
82 tbs.buildTable(mockObj); 81 tbs.buildTable(mockObj);
83 - expect(fs.isA(mockObj.self.tableData)).toBeTruthy(); 82 + expect(fs.isA(mockObj.scope.tableData)).toBeTruthy();
84 - expect(mockObj.self.tableData.length).toBe(0); 83 + expect(mockObj.scope.tableData.length).toBe(0);
85 }); 84 });
86 85
87 it('should unbind handlers on destroyed scope', function () { 86 it('should unbind handlers on destroyed scope', function () {
......