ONOS-2876 -- GUI - first cut at client-side code for device friendly name setting (still WIP).
Change-Id: I531a2f1fef698cb72a5529f732bb2a0a97e2acc4
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
index fb83cdd..45c42b6 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
@@ -153,6 +153,10 @@
ObjectNode data = MAPPER.createObjectNode();
data.put(ID, deviceId.toString());
+
+ // TODO: get friendly name from the device
+ data.put(NAME, deviceId.toString());
+
data.put(TYPE, capitalizeFully(device.type().toString()));
data.put(TYPE_IID, getTypeIconId(device));
data.put(MFR, device.manufacturer());
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 fc08f68..a2ff2a1 100644
--- a/web/gui/src/main/webapp/app/view/device/device.css
+++ b/web/gui/src/main/webapp/app/view/device/device.css
@@ -75,6 +75,30 @@
margin: 8px 0;
}
+#device-details-panel .name-div {
+ height: 20px;
+ padding: 8px 0 0 8px;
+}
+
+#device-details-panel .name-div span {
+ display: inline-block;
+}
+
+#device-details-panel .name-div .label {
+ font-style: italic;
+ padding-right: 12px;
+ /* works for both light and dark themes ... */
+ color: #777;
+}
+
+#device-details-panel .name-div .value {
+}
+
+#device-details-panel .editable {
+ cursor: pointer;
+ border-bottom: 1px dashed darkgreen;
+}
+
#device-details-panel .top div.left {
float: left;
padding: 0 18px 0 0;
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 7a2dc4f..76c0d03 100644
--- a/web/gui/src/main/webapp/app/view/device/device.js
+++ b/web/gui/src/main/webapp/app/view/device/device.js
@@ -26,9 +26,13 @@
// internal state
var detailsPanel,
- pStartY, pHeight,
- top, bottom, iconDiv,
- wSize;
+ pStartY,
+ pHeight,
+ top,
+ bottom,
+ iconDiv,
+ wSize,
+ editingName = false;
// constants
var topPdg = 13,
@@ -59,7 +63,9 @@
if (detailsPanel.isVisible()) {
$scope.selId = null;
detailsPanel.hide();
+ return true;
}
+ return false;
}
function addCloseBtn(div) {
@@ -68,6 +74,72 @@
div.on('click', closePanel);
}
+ function getNameSpan() {
+ return top.select('.name-div').select('.value');
+ }
+
+ function nameValid(name) {
+ // TODO: guard against empty strings etc.
+ return true;
+ }
+
+ function editNameSave() {
+ var span = getNameSpan(),
+ newVal;
+ if (editingName) {
+ newVal = span.select('input').property('value');
+
+ $log.debug("TODO: Saving name change... to '" + newVal + "'");
+ if (!nameValid(newVal)) {
+ return editNameCancel();
+ }
+
+ // TODO: send event to server to set friendly name for device
+ $scope.panelData.name = newVal;
+
+ span.html(newVal);
+ span.classed('editable', true);
+ editingName = false;
+ }
+ }
+
+ function editNameCancel() {
+ var span = getNameSpan();
+ if (editingName) {
+ $log.debug("Canceling name change...");
+ span.html($scope.panelData.name);
+ span.classed('editable', true);
+ editingName = false;
+ return true;
+ }
+ return false;
+ }
+
+ function editName() {
+ $log.log('editName() .. editing=' + editingName);
+ var span = getNameSpan();
+ if (!editingName) {
+ editingName = true;
+ span.classed('editable', false);
+ span.html('');
+ span.append('input').classed('name-input', true)
+ .attr('type', 'text')
+ .attr('value', $scope.panelData.name);
+ }
+ }
+
+ function handleEscape() {
+ return editNameCancel() || closePanel();
+ }
+
+ function setUpEditableName(top) {
+ var div = top.append('div').classed('name-div', true);
+
+ div.append('span').classed('label', true);
+ div.append('span').classed('value editable', true)
+ .on('click', editName);
+ }
+
function setUpPanel() {
var container, closeBtn, tblDiv;
detailsPanel.empty();
@@ -80,6 +152,8 @@
iconDiv = top.append('div').classed('dev-icon', true);
top.append('h2');
+ setUpEditableName(top);
+
tblDiv = top.append('div').classed('top-tables', true);
tblDiv.append('div').classed('left', true).append('table');
tblDiv.append('div').classed('right', true).append('table');
@@ -156,14 +230,23 @@
detailsPanel.width(tbWidth + ctnrPdg);
}
+ function populateName(div, name) {
+ var lab = div.select('.label'),
+ val = div.select('.value');
+ lab.html('Friendly Name:');
+ val.html(name);
+ }
+
function populateDetails(details) {
- var topTbs, btmTbl, ports;
+ var nameDiv, topTbs, btmTbl, ports;
setUpPanel();
+ nameDiv = top.select('.name-div');
topTbs = top.select('.top-tables');
btmTbl = bottom.select('table');
ports = details.ports;
+ populateName(nameDiv, details.name);
populateTop(topTbs, details);
populateBottom(btmTbl, ports);
@@ -278,7 +361,8 @@
}
// create key bindings to handle panel
ks.keyBindings({
- esc: [closePanel, 'Close the details panel'],
+ enter: editNameSave,
+ esc: [handleEscape, 'Close the details panel'],
_helpFormat: ['esc']
});
ks.gestureNotes([