GUI -- Finished Device Details Panel.
- Cleaned up front and backend
- modified table row select callback to take the click $event (in app and device view)
- panel has device glyph
- closing panel deselects clicked on row
Change-Id: I42c372c74fd9fd417ceff01e424f754ea2559595
diff --git a/web/gui/src/main/webapp/app/view/device/device.css b/web/gui/src/main/webapp/app/view/device/device.css
index 4b11f21..09b729b 100644
--- a/web/gui/src/main/webapp/app/view/device/device.css
+++ b/web/gui/src/main/webapp/app/view/device/device.css
@@ -26,10 +26,10 @@
}
.light #device-details-panel.floatpanel {
- background-color: rgb(226, 248, 255);
+ background-color: rgb(229, 234, 237);
}
.dark #device-details-panel.floatpanel {
- background-color: #444;
+ background-color: #3A4042;
}
#device-details-panel .container {
@@ -40,13 +40,29 @@
position: absolute;
right: 10px;
top: 0;
+ cursor: pointer;
}
-.close-btn svg.embeddedIcon .icon.appPlus .glyph {
- /* works for both dark and light themes */
+.light .close-btn svg.embeddedIcon .icon.appPlus .glyph {
+ fill: #aaa;
+}
+.dark .close-btn svg.embeddedIcon .icon.appPlus .glyph {
fill: #ccc;
}
+#device-details-panel .dev-icon {
+ display: inline-block;
+ padding: 0 6px 0 0;
+ vertical-align: middle;
+}
+.light .dev-icon svg.embeddedIcon .glyph {
+ fill: rgb(0, 172, 229);
+}
+.dark .dev-icon svg.embeddedIcon .glyph {
+ fill: #486D91;
+}
+
#device-details-panel h2 {
+ display: inline-block;
margin: 8px 0;
}
@@ -78,11 +94,11 @@
}
.light #device-details-panel .bottom th {
- background-color: #D0E1ED;
+ background-color: #CCC;
/* default text color */
}
.dark #device-details-panel .bottom th {
- background-color: #2b2b2b;
+ background-color: #131313;
color: #ccc;
}
@@ -101,3 +117,6 @@
.dark #device-details-panel .bottom tr:nth-child(odd) {
background-color: #333;
}
+.dark #device-details-panel .bottom tr:nth-child(even) {
+ background-color: #555;
+}
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 4cc1e3d..9cfa091 100644
--- a/web/gui/src/main/webapp/app/view/device/device.html
+++ b/web/gui/src/main/webapp/app/view/device/device.html
@@ -27,7 +27,7 @@
</tr>
<tr ng-repeat="dev in ctrl.tableData"
- ng-click="selectCallback(dev)"
+ ng-click="selectCallback($event, dev)"
ng-class="{selected: dev === sel}"
ng-repeat-done>
<td class="table-icon">
diff --git a/web/gui/src/main/webapp/app/view/device/device.js b/web/gui/src/main/webapp/app/view/device/device.js
index fbe5dbb..29567bc 100644
--- a/web/gui/src/main/webapp/app/view/device/device.js
+++ b/web/gui/src/main/webapp/app/view/device/device.js
@@ -26,11 +26,13 @@
// internal state
var self,
- detailsPane,
- container, top, bottom, closeBtn;
+ detailsPanel,
+ container, top, bottom, iconDiv,
+ selRow;
// constants
// TODO: consider having a set y height that all tables start at
+ // to make calculations easier
var h2Pdg = 40,
mastPdg = 8,
tbodyPdg = 5,
@@ -53,14 +55,26 @@
'Enabled', 'ID', 'Speed', 'Type', 'Egress Links'
];
- function setUpPanel() {
- detailsPane.empty();
+ function addCloseBtn(div) {
+ is.loadEmbeddedIcon(div, 'appPlus', 30);
+ div.select('g').attr('transform', 'translate(25, 0) rotate(45)');
- container = detailsPane.append('div').classed('container', true);
+ div.on('click', function () {
+ detailsPanel.hide();
+ selRow.removeClass('selected');
+ });
+ }
+
+ function setUpPanel() {
+ var closeBtn;
+ detailsPanel.empty();
+
+ container = detailsPanel.append('div').classed('container', true);
top = container.append('div').classed('top', true);
closeBtn = top.append('div').classed('close-btn', true);
addCloseBtn(closeBtn);
+ iconDiv = top.append('div').classed('dev-icon', true);
top.append('h2');
top.append('table');
@@ -76,70 +90,20 @@
panelTop = headerHeight + tbodyPdg + mast.mastHeight() + mastPdg,
wSize = fs.windowSize(panelTop);
- detailsPane = ps.createPanel(pName, {
+ detailsPanel = ps.createPanel(pName, {
height: wSize.height,
- width: wSize.width / 2,
margin: 0,
hideMargin: 0
});
- detailsPane.el().style({
+ detailsPanel.el().style({
position: 'absolute',
top: panelTop + 'px'
});
setUpPanel();
- detailsPane.hide();
- }
-
- function addCloseBtn(div) {
- is.loadEmbeddedIcon(div, 'appPlus', 30);
- div.select('g').attr('transform', 'translate(25, 0) rotate(45)');
- div.on('click', function () {
- detailsPane.hide();
- // TODO: deselect the table row when button is clicked
- //$scope.sel = null;
- });
- }
-
- function populateTopHalf(tbody, details) {
- top.select('h2').text(details['id']);
-
- propOrder.forEach(function (prop, i) {
- addProp(tbody, i, details[prop]);
- });
- }
-
- function populateBottomHalf(table, ports) {
- var theader = table.append('thead').append('tr'),
- tbody = table.append('tbody'),
- tbWidth, tbHeight,
- scrollSize = 20,
- btmPdg = 50;
-
- friendlyPortCols.forEach(function (header) {
- theader.append('th').html(header);
- });
- ports.forEach(function (port) {
- addPortRow(tbody, port);
- });
-
- tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
- tbHeight = detailsPane.height()
- - (fs.noPxStyle(detailsPane.el().select('.top'), 'height')
- + fs.noPxStyle(detailsPane.el().select('hr'), 'height')
- + fs.noPxStyle(detailsPane.el().select('h2'), 'height')
- + btmPdg);
-
- table.style({
- height: tbHeight + 'px',
- width: tbWidth + 'px',
- overflow: 'auto',
- display: 'block'
- });
-
- detailsPane.width(tbWidth + cntrPdg);
+ detailsPanel.hide();
}
function addProp(tbody, index, value) {
@@ -152,6 +116,15 @@
addCell('value', value);
}
+ function populateTop(tbody, details) {
+ is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
+ top.select('h2').text(details.id);
+
+ propOrder.forEach(function (prop, i) {
+ addProp(tbody, i, details[prop]);
+ });
+ }
+
function addPortRow(tbody, port) {
var tr = tbody.append('tr');
@@ -163,21 +136,52 @@
});
}
+ function populateBottom(table, ports) {
+ var theader = table.append('thead').append('tr'),
+ tbody = table.append('tbody'),
+ tbWidth, tbHeight,
+ scrollSize = 20,
+ padding = 55;
+
+ friendlyPortCols.forEach(function (col) {
+ theader.append('th').html(col);
+ });
+ ports.forEach(function (port) {
+ addPortRow(tbody, port);
+ });
+
+ tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
+ tbHeight = detailsPanel.height()
+ - (fs.noPxStyle(detailsPanel.el().select('.top'), 'height')
+ + fs.noPxStyle(detailsPanel.el().select('hr'), 'height')
+ + fs.noPxStyle(detailsPanel.el().select('h2'), 'height')
+ + padding);
+
+ table.style({
+ height: tbHeight + 'px',
+ width: tbWidth + 'px',
+ overflow: 'auto',
+ display: 'block'
+ });
+
+ detailsPanel.width(tbWidth + cntrPdg);
+ }
+
function populateDetails(details) {
setUpPanel();
- var toptbody = top.select('table').append('tbody'),
- btmTable = bottom.select('table'),
+ var topTb = top.select('table').append('tbody'),
+ btmTbl = bottom.select('table'),
ports = details.ports;
- populateTopHalf(toptbody, details);
- populateBottomHalf(btmTable, ports);
+ populateTop(topTb, details);
+ populateBottom(btmTbl, ports);
}
function respDetailsCb(data) {
- self.panelData = data['details'];
+ self.panelData = data.details;
populateDetails(self.panelData);
- detailsPane.show();
+ detailsPanel.show();
}
angular.module('ovDevice', [])
@@ -197,13 +201,13 @@
var handlers = {};
self.panelData = [];
- function selCb(row) {
- // request the server for more information
- // get the id from the row to request details with
+ function selCb($event, row) {
+ selRow = angular.element($event.currentTarget);
+
if ($scope.sel) {
wss.sendEvent(detailsReq, { id: row.id });
} else {
- detailsPane.hide();
+ detailsPanel.hide();
}
$log.debug('Got a click on:', row);
}
@@ -217,7 +221,6 @@
createDetailsPane();
- // bind websocket handlers
handlers[detailsResp] = respDetailsCb;
wss.bindHandlers(handlers);