mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-11-03 01:31:21 +01:00
ONOS-5579 Refactoring Details Panel
Added an Editable Textfield Component Refactored Device View Refactored Host View Change-Id: I7ca423f6c198f8e09b20ed4e57e352de04b797e9
This commit is contained in:
parent
a441074299
commit
f50a1775a7
16
web/gui/src/main/webapp/app/fw/layer/details-panel.css
Normal file
16
web/gui/src/main/webapp/app/fw/layer/details-panel.css
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
178
web/gui/src/main/webapp/app/fw/layer/details-panel.js
Normal file
178
web/gui/src/main/webapp/app/fw/layer/details-panel.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
var ps, fs, mast, wss, is, EditableTextComponent;
|
||||||
|
|
||||||
|
var panel,
|
||||||
|
pStartY,
|
||||||
|
wSize,
|
||||||
|
wssHandlers = {},
|
||||||
|
options;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
var topPdg = 28,
|
||||||
|
defaultLabelWidth = 110,
|
||||||
|
defaultValueWidth = 80;
|
||||||
|
|
||||||
|
// Elements
|
||||||
|
var container,
|
||||||
|
top,
|
||||||
|
bottom;
|
||||||
|
|
||||||
|
function createDetailsPanel(name, _options) {
|
||||||
|
options = _options;
|
||||||
|
scope = options.scope;
|
||||||
|
|
||||||
|
panel = ps.createPanel(name, options);
|
||||||
|
|
||||||
|
calculatePositions();
|
||||||
|
|
||||||
|
panel.el().style({
|
||||||
|
position: 'absolute',
|
||||||
|
top: pStartY + 'px',
|
||||||
|
});
|
||||||
|
|
||||||
|
hide();
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculatePositions() {
|
||||||
|
pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
|
||||||
|
+ mast.mastHeight() + topPdg;
|
||||||
|
wSize = fs.windowSize(pStartY);
|
||||||
|
pHeight = wSize.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide() {
|
||||||
|
panel.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setResponse(name, callback) {
|
||||||
|
var additionalHandler = {};
|
||||||
|
additionalHandler[name] = callback;
|
||||||
|
|
||||||
|
wss.bindHandlers(additionalHandler);
|
||||||
|
wssHandlers = _.extend({}, wssHandlers, additionalHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addContainers() {
|
||||||
|
container = panel.append('div').classed('container', true);
|
||||||
|
top = container.append('div').classed('top', true);
|
||||||
|
bottom = container.append('div').classed('bottom', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCloseButton(onClose) {
|
||||||
|
var closeBtn = top.append('div').classed('close-btn', true);
|
||||||
|
|
||||||
|
is.loadEmbeddedIcon(closeBtn, 'close', 20);
|
||||||
|
closeBtn.on('click', onClose || function () {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHeading(icon) {
|
||||||
|
top.append('div').classed('iconDiv ' + icon, true);
|
||||||
|
new EditableTextComponent(top.append('h2'), {
|
||||||
|
scope: options.scope,
|
||||||
|
nameChangeRequest: options.nameChangeRequest,
|
||||||
|
keyBindings: options.keyBindings,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTable(parent, className) {
|
||||||
|
return parent.append('div').classed(className, true).append('table');
|
||||||
|
}
|
||||||
|
|
||||||
|
function addProp(tbody, key, value) {
|
||||||
|
console.log(tbody);
|
||||||
|
var tr = tbody.append('tr');
|
||||||
|
|
||||||
|
function addCell(cls, txt, width) {
|
||||||
|
tr.append('td').attr('class', cls).attr('width', width).text(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCell('label', key + ' :', defaultLabelWidth);
|
||||||
|
addCell('value', value, defaultValueWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPropsList(el, props) {
|
||||||
|
var tblDiv = el.append('div').classed('top-tables', true);
|
||||||
|
var left = addTable(tblDiv, 'left').append('tbody');
|
||||||
|
var right = addTable(tblDiv, 'right').append('tbody');
|
||||||
|
|
||||||
|
var keys = _.keys(props);
|
||||||
|
|
||||||
|
_.each(props, function (value, key) {
|
||||||
|
var index = keys.indexOf(key);
|
||||||
|
|
||||||
|
if (index < keys.length / 2) {
|
||||||
|
addProp(left, key, value);
|
||||||
|
} else {
|
||||||
|
addProp(right, key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function empty() {
|
||||||
|
panel.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(id) {
|
||||||
|
return panel.el().select(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function destroy() {
|
||||||
|
wss.unbindHandlers(wssHandlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module('onosLayer')
|
||||||
|
.factory('DetailsPanelService', [
|
||||||
|
|
||||||
|
'PanelService', 'FnService', 'MastService', 'WebSocketService',
|
||||||
|
'IconService', 'EditableTextComponent',
|
||||||
|
|
||||||
|
function (_ps_, _fs_, _mast_, _wss_, _is_, _etc_) {
|
||||||
|
|
||||||
|
ps = _ps_;
|
||||||
|
fs = _fs_;
|
||||||
|
mast = _mast_;
|
||||||
|
wss = _wss_;
|
||||||
|
is = _is_;
|
||||||
|
EditableTextComponent = _etc_;
|
||||||
|
|
||||||
|
return {
|
||||||
|
create: createDetailsPanel,
|
||||||
|
setResponse: setResponse,
|
||||||
|
|
||||||
|
addContainers: addContainers,
|
||||||
|
addCloseButton: addCloseButton,
|
||||||
|
addHeading: addHeading,
|
||||||
|
addPropsList: addPropsList,
|
||||||
|
|
||||||
|
// Elements
|
||||||
|
container: function () { return container; },
|
||||||
|
top: function () { return top; },
|
||||||
|
bottom: function () { return bottom; },
|
||||||
|
select: select,
|
||||||
|
|
||||||
|
empty: empty,
|
||||||
|
hide: hide,
|
||||||
|
destroy: destroy,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
})();
|
||||||
119
web/gui/src/main/webapp/app/fw/layer/editable-text.js
Normal file
119
web/gui/src/main/webapp/app/fw/layer/editable-text.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
var ks, wss;
|
||||||
|
|
||||||
|
var EditableText = function (el, options) {
|
||||||
|
// constructor
|
||||||
|
this.el = el;
|
||||||
|
this.scope = options.scope;
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
this.el.classed('editable clickable', true).on('click', this.onEdit.bind(this));
|
||||||
|
this.editingName = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
EditableText.prototype = {
|
||||||
|
|
||||||
|
bindHandlers: function () {
|
||||||
|
ks.keyBindings({
|
||||||
|
'enter': this.save.bind(this),
|
||||||
|
'esc': [this.cancel.bind(this), 'Close the details panel']
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
unbindHandlers: function () {
|
||||||
|
ks.unbindKeys();
|
||||||
|
|
||||||
|
if (this.options.keyBindings) {
|
||||||
|
// Reset to original bindings before editable text
|
||||||
|
ks.keyBindings(this.options.keyBindings);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addTextField: function () {
|
||||||
|
return this.el.append('input').classed('name-input', true)
|
||||||
|
.attr('type', 'text')
|
||||||
|
.attr('value', this.scope.panelData.name)[0][0];
|
||||||
|
},
|
||||||
|
|
||||||
|
onEdit: function () {
|
||||||
|
if (!this.editingName) {
|
||||||
|
this.el.classed('editable clickable', false);
|
||||||
|
this.el.text('');
|
||||||
|
|
||||||
|
var el = this.addTextField();
|
||||||
|
el.focus();
|
||||||
|
el.select();
|
||||||
|
this.editingName = true;
|
||||||
|
|
||||||
|
this.bindHandlers();
|
||||||
|
|
||||||
|
ks.enableGlobalKeys(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
exit: function (name) {
|
||||||
|
this.el.text(name);
|
||||||
|
this.el.classed('editable clickable', true);
|
||||||
|
this.editingName = false;
|
||||||
|
ks.enableGlobalKeys(true);
|
||||||
|
this.unbindHandlers();
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel: function (a, b, ev) {
|
||||||
|
|
||||||
|
if (this.editingName) {
|
||||||
|
this.exit(this.scope.panelData.name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
save: function () {
|
||||||
|
var id = this.scope.panelData.id,
|
||||||
|
val,
|
||||||
|
newVal;
|
||||||
|
|
||||||
|
if (this.editingName) {
|
||||||
|
val = this.el.select('input').property('value').trim();
|
||||||
|
newVal = val || id;
|
||||||
|
|
||||||
|
this.exit(newVal);
|
||||||
|
this.scope.panelData.name = newVal;
|
||||||
|
wss.sendEvent(this.options.nameChangeRequest, { id: id, name: val });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
angular.module('onosLayer')
|
||||||
|
.factory('EditableTextComponent', [
|
||||||
|
|
||||||
|
'KeyService', 'WebSocketService',
|
||||||
|
|
||||||
|
function (_ks_, _wss_) {
|
||||||
|
ks = _ks_;
|
||||||
|
wss = _wss_;
|
||||||
|
|
||||||
|
return EditableText;
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
||||||
@ -22,17 +22,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// injected refs
|
// injected refs
|
||||||
var $log, $scope, $loc, fs, mast, ps, wss, is, ns, ks;
|
var $log, $scope, $loc, fs, mast, ps, wss, is, ns, ks, dps;
|
||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
var detailsPanel,
|
var detailsPanel,
|
||||||
pStartY,
|
pStartY,
|
||||||
pHeight,
|
pHeight,
|
||||||
top,
|
top,
|
||||||
bottom,
|
|
||||||
iconDiv,
|
|
||||||
wSize,
|
wSize,
|
||||||
editingName = false,
|
|
||||||
device;
|
device;
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
@ -40,19 +37,12 @@
|
|||||||
ctnrPdg = 24,
|
ctnrPdg = 24,
|
||||||
scrollSize = 17,
|
scrollSize = 17,
|
||||||
portsTblPdg = 50,
|
portsTblPdg = 50,
|
||||||
defaultLabelWidth = 110,
|
|
||||||
defaultValueWidth = 80,
|
|
||||||
|
|
||||||
pName = 'device-details-panel',
|
pName = 'device-details-panel',
|
||||||
detailsReq = 'deviceDetailsRequest',
|
detailsReq = 'deviceDetailsRequest',
|
||||||
detailsResp = 'deviceDetailsResponse',
|
detailsResp = 'deviceDetailsResponse',
|
||||||
nameChangeReq = 'deviceNameChangeRequest',
|
nameChangeReq = 'deviceNameChangeRequest',
|
||||||
nameChangeResp = 'deviceNameChangeResponse',
|
nameChangeResp = 'deviceNameChangeResponse',
|
||||||
friendlyProps = [
|
|
||||||
'URI', 'Type', 'Master ID', 'Chassis ID',
|
|
||||||
'Vendor', 'H/W Version', 'S/W Version', 'Protocol', 'Serial #',
|
|
||||||
'Pipeconf',
|
|
||||||
],
|
|
||||||
portCols = [
|
portCols = [
|
||||||
'enabled', 'id', 'speed', 'type', 'elinks_dest', 'name',
|
'enabled', 'id', 'speed', 'type', 'elinks_dest', 'name',
|
||||||
],
|
],
|
||||||
@ -60,6 +50,11 @@
|
|||||||
'Enabled', 'ID', 'Speed', 'Type', 'Egress Links', 'Name',
|
'Enabled', 'ID', 'Speed', 'Type', 'Egress Links', 'Name',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var keyBindings = {
|
||||||
|
esc: [closePanel, 'Close the details panel'],
|
||||||
|
_helpFormat: ['esc'],
|
||||||
|
};
|
||||||
|
|
||||||
function closePanel() {
|
function closePanel() {
|
||||||
if (detailsPanel.isVisible()) {
|
if (detailsPanel.isVisible()) {
|
||||||
$scope.selId = null;
|
$scope.selId = null;
|
||||||
@ -69,119 +64,44 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCloseBtn(div) {
|
|
||||||
is.loadEmbeddedIcon(div, 'close', 20);
|
|
||||||
div.on('click', closePanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
function exitEditMode(nameH2, name) {
|
|
||||||
nameH2.text(name);
|
|
||||||
nameH2.classed('editable clickable', true);
|
|
||||||
editingName = false;
|
|
||||||
ks.enableGlobalKeys(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function editNameSave() {
|
|
||||||
var nameH2 = top.select('h2'),
|
|
||||||
id = $scope.panelData.id,
|
|
||||||
val,
|
|
||||||
newVal;
|
|
||||||
|
|
||||||
if (editingName) {
|
|
||||||
val = nameH2.select('input').property('value').trim();
|
|
||||||
newVal = val || id;
|
|
||||||
|
|
||||||
exitEditMode(nameH2, newVal);
|
|
||||||
$scope.panelData.name = newVal;
|
|
||||||
wss.sendEvent(nameChangeReq, { id: id, name: val });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function editNameCancel() {
|
|
||||||
if (editingName) {
|
|
||||||
exitEditMode(top.select('h2'), $scope.panelData.name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function editName() {
|
|
||||||
var nameH2 = top.select('h2'),
|
|
||||||
tf, el;
|
|
||||||
|
|
||||||
if (!editingName) {
|
|
||||||
nameH2.classed('editable clickable', false);
|
|
||||||
nameH2.text('');
|
|
||||||
tf = nameH2.append('input').classed('name-input', true)
|
|
||||||
.attr('type', 'text')
|
|
||||||
.attr('value', $scope.panelData.name);
|
|
||||||
el = tf[0][0];
|
|
||||||
el.focus();
|
|
||||||
el.select();
|
|
||||||
editingName = true;
|
|
||||||
ks.enableGlobalKeys(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEscape() {
|
|
||||||
return editNameCancel() || closePanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setUpPanel() {
|
function setUpPanel() {
|
||||||
var container, closeBtn, tblDiv;
|
// var container, closeBtn, tblDiv;
|
||||||
detailsPanel.empty();
|
|
||||||
|
|
||||||
container = detailsPanel.append('div').classed('container', true);
|
dps.empty();
|
||||||
|
dps.addContainers();
|
||||||
|
dps.addCloseButton(closePanel);
|
||||||
|
|
||||||
top = container.append('div').classed('top', true);
|
var top = dps.top();
|
||||||
closeBtn = top.append('div').classed('close-btn', true);
|
var bottom = dps.bottom();
|
||||||
addCloseBtn(closeBtn);
|
|
||||||
iconDiv = top.append('div').classed('dev-icon', true);
|
|
||||||
top.append('h2').classed('editable clickable', true).on('click', editName);
|
|
||||||
|
|
||||||
tblDiv = top.append('div').classed('top-tables', true);
|
dps.addHeading('dev-icon');
|
||||||
tblDiv.append('div').classed('left', true).append('table');
|
top.append('div').classed('top-content', true);
|
||||||
tblDiv.append('div').classed('right', true).append('table');
|
|
||||||
|
|
||||||
top.append('hr');
|
top.append('hr');
|
||||||
|
|
||||||
bottom = container.append('div').classed('bottom', true);
|
|
||||||
bottom.append('h2').classed('ports-title', true).text('Ports');
|
bottom.append('h2').classed('ports-title', true).text('Ports');
|
||||||
bottom.append('table');
|
bottom.append('table');
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProp(tbody, index, value) {
|
function friendlyPropsList(details) {
|
||||||
var tr = tbody.append('tr');
|
return {
|
||||||
|
'URI': device.id,
|
||||||
function addCell(cls, txt, width) {
|
'Type': device.type,
|
||||||
tr.append('td').attr('class', cls).attr('width', width).text(txt);
|
'Master ID': details['masterid'],
|
||||||
}
|
'Chassis ID': details['chassid'],
|
||||||
addCell('label', friendlyProps[index] + ' :', defaultLabelWidth);
|
'Vendor': device.mfr,
|
||||||
addCell('value', value, defaultValueWidth);
|
'H/W Version': device.hw,
|
||||||
|
'S/W Version': device.sw,
|
||||||
|
'Protocol': details['protocol'],
|
||||||
|
'Serial #': device.serial,
|
||||||
|
'Pipeconf': details['pipeconf'],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateTop(tblDiv, details) {
|
function populateTop(tblDiv, details) {
|
||||||
var leftTbl = tblDiv.select('.left')
|
is.loadEmbeddedIcon(dps.select('.iconDiv'), details._iconid_type, 40);
|
||||||
.select('table')
|
dps.top().select('h2').text(details.name);
|
||||||
.append('tbody'),
|
dps.addPropsList(tblDiv, friendlyPropsList(details));
|
||||||
rightTbl = tblDiv.select('.right')
|
|
||||||
.select('table')
|
|
||||||
.append('tbody');
|
|
||||||
|
|
||||||
is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
|
|
||||||
top.select('h2').text(details.name);
|
|
||||||
|
|
||||||
// === demonstrate use of JsonCodec object see ONOS-5976
|
|
||||||
addProp(leftTbl, 0, device.id);
|
|
||||||
addProp(leftTbl, 1, device.type);
|
|
||||||
addProp(leftTbl, 2, details['masterid']);
|
|
||||||
addProp(leftTbl, 3, details['chassid']);
|
|
||||||
addProp(leftTbl, 4, device.mfr);
|
|
||||||
addProp(rightTbl, 5, device.hw);
|
|
||||||
addProp(rightTbl, 6, device.sw);
|
|
||||||
addProp(rightTbl, 7, details['protocol']);
|
|
||||||
addProp(rightTbl, 8, device.serial);
|
|
||||||
addProp(rightTbl, 9, details['pipeconf']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPortRow(tbody, port) {
|
function addPortRow(tbody, port) {
|
||||||
@ -193,6 +113,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function populateBottom(table, ports) {
|
function populateBottom(table, ports) {
|
||||||
|
|
||||||
var theader = table.append('thead').append('tr'),
|
var theader = table.append('thead').append('tr'),
|
||||||
tbody = table.append('tbody'),
|
tbody = table.append('tbody'),
|
||||||
tbWidth, tbHeight;
|
tbWidth, tbHeight;
|
||||||
@ -200,16 +121,15 @@
|
|||||||
friendlyPortCols.forEach(function (col) {
|
friendlyPortCols.forEach(function (col) {
|
||||||
theader.append('th').text(col);
|
theader.append('th').text(col);
|
||||||
});
|
});
|
||||||
|
|
||||||
ports.forEach(function (port) {
|
ports.forEach(function (port) {
|
||||||
addPortRow(tbody, port);
|
addPortRow(tbody, port);
|
||||||
});
|
});
|
||||||
|
|
||||||
tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
|
tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
|
||||||
tbHeight = pHeight
|
tbHeight = pHeight
|
||||||
- (fs.noPxStyle(detailsPanel.el()
|
- (fs.noPxStyle(detailsPanel.el().select('.top'), 'height')
|
||||||
.select('.top'), 'height')
|
+ fs.noPxStyle(detailsPanel.el().select('.ports-title'), 'height')
|
||||||
+ fs.noPxStyle(detailsPanel.el()
|
|
||||||
.select('.ports-title'), 'height')
|
|
||||||
+ portsTblPdg);
|
+ portsTblPdg);
|
||||||
|
|
||||||
table.style({
|
table.style({
|
||||||
@ -223,15 +143,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function populateDetails(details) {
|
function populateDetails(details) {
|
||||||
var topTbs, btmTbl, ports;
|
var btmTbl, ports;
|
||||||
|
|
||||||
setUpPanel();
|
setUpPanel();
|
||||||
|
|
||||||
topTbs = top.select('.top-tables');
|
btmTbl = dps.bottom().select('table');
|
||||||
btmTbl = bottom.select('table');
|
|
||||||
ports = details.ports;
|
ports = details.ports;
|
||||||
|
|
||||||
populateTop(topTbs, details);
|
populateTop(dps.select('.top-content'), details);
|
||||||
populateBottom(btmTbl, ports);
|
populateBottom(btmTbl, ports);
|
||||||
|
|
||||||
detailsPanel.height(pHeight);
|
detailsPanel.height(pHeight);
|
||||||
@ -250,18 +169,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDetailsPane() {
|
function createDetailsPanel() {
|
||||||
detailsPanel = ps.createPanel(pName, {
|
detailsPanel = dps.create(pName, {
|
||||||
width: wSize.width,
|
width: wSize.width,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
hideMargin: 0,
|
hideMargin: 0,
|
||||||
|
scope: $scope,
|
||||||
|
keyBindings: keyBindings,
|
||||||
|
nameChangeRequest: nameChangeReq,
|
||||||
});
|
});
|
||||||
detailsPanel.el().style({
|
|
||||||
position: 'absolute',
|
dps.setResponse(detailsResp, respDetailsCb);
|
||||||
top: pStartY + 'px',
|
|
||||||
});
|
|
||||||
$scope.hidePanel = function () { detailsPanel.hide(); };
|
$scope.hidePanel = function () { detailsPanel.hide(); };
|
||||||
detailsPanel.hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample functions for detail panel creation
|
// Sample functions for detail panel creation
|
||||||
@ -283,10 +203,10 @@
|
|||||||
['$log', '$scope', '$location', 'TableBuilderService',
|
['$log', '$scope', '$location', 'TableBuilderService',
|
||||||
'TableDetailService', 'FnService',
|
'TableDetailService', 'FnService',
|
||||||
'MastService', 'PanelService', 'WebSocketService', 'IconService',
|
'MastService', 'PanelService', 'WebSocketService', 'IconService',
|
||||||
'NavService', 'KeyService',
|
'NavService', 'KeyService', 'DetailsPanelService',
|
||||||
|
|
||||||
function (_$log_, _$scope_, _$location_,
|
function (_$log_, _$scope_, _$location_,
|
||||||
tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_, _ns_, _ks_) {
|
tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_, _ns_, _ks_, _dps_) {
|
||||||
var params,
|
var params,
|
||||||
handlers = {};
|
handlers = {};
|
||||||
|
|
||||||
@ -300,6 +220,7 @@
|
|||||||
is = _is_;
|
is = _is_;
|
||||||
ns = _ns_;
|
ns = _ns_;
|
||||||
ks = _ks_;
|
ks = _ks_;
|
||||||
|
dps = _dps_;
|
||||||
|
|
||||||
params = $loc.search();
|
params = $loc.search();
|
||||||
|
|
||||||
@ -310,7 +231,7 @@
|
|||||||
$scope.meterTip = 'Show meter view for selected device';
|
$scope.meterTip = 'Show meter view for selected device';
|
||||||
|
|
||||||
// details panel handlers
|
// details panel handlers
|
||||||
handlers[detailsResp] = respDetailsCb;
|
// handlers[detailsResp] = respDetailsCb;
|
||||||
handlers[nameChangeResp] = respNameCb;
|
handlers[nameChangeResp] = respNameCb;
|
||||||
wss.bindHandlers(handlers);
|
wss.bindHandlers(handlers);
|
||||||
|
|
||||||
@ -352,6 +273,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
|
dps.destroy();
|
||||||
wss.unbindHandlers(handlers);
|
wss.unbindHandlers(handlers);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -373,7 +295,7 @@
|
|||||||
|
|
||||||
function initPanel() {
|
function initPanel() {
|
||||||
heightCalc();
|
heightCalc();
|
||||||
createDetailsPane();
|
createDetailsPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safari has a bug where it renders the fixed-layout table wrong
|
// Safari has a bug where it renders the fixed-layout table wrong
|
||||||
@ -384,11 +306,8 @@
|
|||||||
initPanel();
|
initPanel();
|
||||||
}
|
}
|
||||||
// create key bindings to handle panel
|
// create key bindings to handle panel
|
||||||
ks.keyBindings({
|
ks.keyBindings(keyBindings);
|
||||||
enter: editNameSave,
|
|
||||||
esc: [handleEscape, 'Close the details panel'],
|
|
||||||
_helpFormat: ['esc'],
|
|
||||||
});
|
|
||||||
ks.gestureNotes([
|
ks.gestureNotes([
|
||||||
['click', 'Select a row to show device details'],
|
['click', 'Select a row to show device details'],
|
||||||
['scroll down', 'See more devices'],
|
['scroll down', 'See more devices'],
|
||||||
|
|||||||
@ -22,16 +22,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// injected refs
|
// injected refs
|
||||||
var $log, $scope, $loc, fs, mast, ps, wss, is, ns, ks;
|
var $log, $scope, $loc, fs, mast, ps, wss, is, ns, ks, dps;
|
||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
var detailsPanel,
|
var detailsPanel,
|
||||||
pStartY,
|
pStartY,
|
||||||
pHeight,
|
pHeight,
|
||||||
top,
|
top,
|
||||||
iconDiv,
|
wSize;
|
||||||
wSize,
|
|
||||||
editingName = false;
|
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
var topPdg = 28,
|
var topPdg = 28,
|
||||||
@ -41,13 +39,10 @@
|
|||||||
nameChangeReq = 'hostNameChangeRequest',
|
nameChangeReq = 'hostNameChangeRequest',
|
||||||
nameChangeResp = 'hostNameChangeResponse';
|
nameChangeResp = 'hostNameChangeResponse';
|
||||||
|
|
||||||
var propOrder = [
|
var keyBindings = {
|
||||||
'id', 'ip', 'mac', 'vlan', 'configured', 'location',
|
esc: [closePanel, 'Close the details panel'],
|
||||||
],
|
_helpFormat: ['esc'],
|
||||||
friendlyProps = [
|
};
|
||||||
'Host ID', 'IP Address', 'MAC Address', 'VLAN',
|
|
||||||
'Configured', 'Location',
|
|
||||||
];
|
|
||||||
|
|
||||||
function closePanel() {
|
function closePanel() {
|
||||||
if (detailsPanel.isVisible()) {
|
if (detailsPanel.isVisible()) {
|
||||||
@ -58,105 +53,41 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCloseBtn(div) {
|
|
||||||
is.loadEmbeddedIcon(div, 'close', 20);
|
|
||||||
div.on('click', closePanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
function exitEditMode(nameH2, name) {
|
|
||||||
nameH2.text(name);
|
|
||||||
nameH2.classed('editable clickable', true);
|
|
||||||
editingName = false;
|
|
||||||
ks.enableGlobalKeys(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function editNameSave() {
|
|
||||||
var nameH2 = top.select('h2'),
|
|
||||||
id = $scope.panelData.id,
|
|
||||||
ip = $scope.panelData.ip,
|
|
||||||
val,
|
|
||||||
newVal;
|
|
||||||
|
|
||||||
if (editingName) {
|
|
||||||
val = nameH2.select('input').property('value').trim();
|
|
||||||
newVal = val || ip;
|
|
||||||
|
|
||||||
exitEditMode(nameH2, newVal);
|
|
||||||
$scope.panelData.name = newVal;
|
|
||||||
wss.sendEvent(nameChangeReq, { id: id, name: val });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function editNameCancel() {
|
|
||||||
if (editingName) {
|
|
||||||
exitEditMode(top.select('h2'), $scope.panelData.name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function editName() {
|
|
||||||
var nameH2 = top.select('h2'),
|
|
||||||
tf, el;
|
|
||||||
|
|
||||||
if (!editingName) {
|
|
||||||
nameH2.classed('editable clickable', false);
|
|
||||||
nameH2.text('');
|
|
||||||
tf = nameH2.append('input').classed('name-input', true)
|
|
||||||
.attr('type', 'text')
|
|
||||||
.attr('value', $scope.panelData.name);
|
|
||||||
el = tf[0][0];
|
|
||||||
el.focus();
|
|
||||||
el.select();
|
|
||||||
editingName = true;
|
|
||||||
ks.enableGlobalKeys(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEscape() {
|
|
||||||
return editNameCancel() || closePanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setUpPanel() {
|
function setUpPanel() {
|
||||||
var container, closeBtn;
|
|
||||||
detailsPanel.empty();
|
|
||||||
|
|
||||||
container = detailsPanel.append('div').classed('container', true);
|
dps.empty();
|
||||||
|
dps.addContainers();
|
||||||
|
dps.addCloseButton(closePanel);
|
||||||
|
|
||||||
top = container.append('div').classed('top', true);
|
var top = dps.top();
|
||||||
closeBtn = top.append('div').classed('close-btn', true);
|
|
||||||
addCloseBtn(closeBtn);
|
dps.addHeading('host-icon');
|
||||||
iconDiv = top.append('div').classed('host-icon', true);
|
top.append('div').classed('top-content', true);
|
||||||
top.append('h2').classed('editable clickable', true).on('click', editName);
|
|
||||||
|
|
||||||
top.append('div').classed('top-tables', true);
|
|
||||||
top.append('hr');
|
top.append('hr');
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProp(tbody, index, value) {
|
function friendlyPropsList(details) {
|
||||||
var tr = tbody.append('tr');
|
return {
|
||||||
|
'Host ID': details.id,
|
||||||
function addCell(cls, txt) {
|
'IP Address': details.ip[0],
|
||||||
tr.append('td').attr('class', cls).text(txt);
|
'MAC Address': details.mac,
|
||||||
}
|
'VLAN': details.vlan,
|
||||||
addCell('label', friendlyProps[index] + ' :');
|
'Configured': details.configured,
|
||||||
addCell('value', value);
|
'Location': details.location,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateTop(details) {
|
function populateTop(tblDiv, details) {
|
||||||
var tab = top.select('.top-tables').append('table').append('tbody');
|
is.loadEmbeddedIcon(dps.select('.iconDiv'), details._iconid_type, 40);
|
||||||
|
dps.top().select('h2').text(details.name);
|
||||||
is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
|
dps.addPropsList(tblDiv, friendlyPropsList(details));
|
||||||
top.select('h2').text(details.name);
|
|
||||||
|
|
||||||
propOrder.forEach(function (prop, i) {
|
|
||||||
addProp(tab, i, details[prop]);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateDetails(details) {
|
function populateDetails(details) {
|
||||||
setUpPanel();
|
setUpPanel();
|
||||||
populateTop(details);
|
populateTop(dps.select('.top-content'), details);
|
||||||
detailsPanel.height(pHeight);
|
detailsPanel.height(pHeight);
|
||||||
// configure width based on content.. for now hardcoded
|
// configure width based on content.. for now hardcoded
|
||||||
detailsPanel.width(400);
|
detailsPanel.width(400);
|
||||||
@ -174,18 +105,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDetailsPane() {
|
function createDetailsPanel() {
|
||||||
detailsPanel = ps.createPanel(pName, {
|
detailsPanel = dps.create(pName, {
|
||||||
width: wSize.width,
|
width: wSize.width,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
hideMargin: 0,
|
hideMargin: 0,
|
||||||
|
scope: $scope,
|
||||||
|
keyBindings: keyBindings,
|
||||||
|
nameChangeRequest: nameChangeReq,
|
||||||
});
|
});
|
||||||
detailsPanel.el().style({
|
|
||||||
position: 'absolute',
|
dps.setResponse(detailsResp, respDetailsCb);
|
||||||
top: pStartY + 'px',
|
|
||||||
});
|
|
||||||
$scope.hidePanel = function () { detailsPanel.hide(); };
|
$scope.hidePanel = function () { detailsPanel.hide(); };
|
||||||
detailsPanel.hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -196,12 +128,12 @@
|
|||||||
'$location',
|
'$location',
|
||||||
'TableBuilderService',
|
'TableBuilderService',
|
||||||
'FnService', 'MastService', 'PanelService', 'WebSocketService',
|
'FnService', 'MastService', 'PanelService', 'WebSocketService',
|
||||||
'IconService', 'NavService', 'KeyService',
|
'IconService', 'NavService', 'KeyService', 'DetailsPanelService',
|
||||||
|
|
||||||
function (_$log_, _$scope_, _$location_,
|
function (_$log_, _$scope_, _$location_,
|
||||||
tbs,
|
tbs,
|
||||||
_fs_, _mast_, _ps_, _wss_,
|
_fs_, _mast_, _ps_, _wss_,
|
||||||
_is_, _ns_, _ks_) {
|
_is_, _ns_, _ks_, _dps_) {
|
||||||
|
|
||||||
var params,
|
var params,
|
||||||
handlers = {};
|
handlers = {};
|
||||||
@ -216,13 +148,13 @@
|
|||||||
is = _is_;
|
is = _is_;
|
||||||
ns = _ns_;
|
ns = _ns_;
|
||||||
ks = _ks_;
|
ks = _ks_;
|
||||||
|
dps = _dps_;
|
||||||
|
|
||||||
params = $loc.search();
|
params = $loc.search();
|
||||||
|
|
||||||
$scope.panelData = {};
|
$scope.panelData = {};
|
||||||
|
|
||||||
// details panel handlers
|
// details panel handlers
|
||||||
handlers[detailsResp] = respDetailsCb;
|
|
||||||
handlers[nameChangeResp] = respNameCb;
|
handlers[nameChangeResp] = respNameCb;
|
||||||
wss.bindHandlers(handlers);
|
wss.bindHandlers(handlers);
|
||||||
|
|
||||||
@ -254,6 +186,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
|
dps.destroy();
|
||||||
wss.unbindHandlers(handlers);
|
wss.unbindHandlers(handlers);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -261,7 +194,7 @@
|
|||||||
}])
|
}])
|
||||||
|
|
||||||
.directive('hostDetailsPanel',
|
.directive('hostDetailsPanel',
|
||||||
['$rootScope', '$window', '$timeout', 'KeyService',
|
['$rootScope', '$window', '$timeout', 'KeyService', 'DetailsPanelService',
|
||||||
function ($rootScope, $window, $timeout, ks) {
|
function ($rootScope, $window, $timeout, ks) {
|
||||||
return function (scope) {
|
return function (scope) {
|
||||||
var unbindWatch;
|
var unbindWatch;
|
||||||
@ -275,7 +208,7 @@
|
|||||||
|
|
||||||
function initPanel() {
|
function initPanel() {
|
||||||
heightCalc();
|
heightCalc();
|
||||||
createDetailsPane();
|
createDetailsPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safari has a bug where it renders the fixed-layout table wrong
|
// Safari has a bug where it renders the fixed-layout table wrong
|
||||||
@ -286,11 +219,7 @@
|
|||||||
initPanel();
|
initPanel();
|
||||||
}
|
}
|
||||||
// create key bindings to handle panel
|
// create key bindings to handle panel
|
||||||
ks.keyBindings({
|
ks.keyBindings(keyBindings);
|
||||||
enter: editNameSave,
|
|
||||||
esc: [handleEscape, 'Close the details panel'],
|
|
||||||
_helpFormat: ['esc'],
|
|
||||||
});
|
|
||||||
ks.gestureNotes([
|
ks.gestureNotes([
|
||||||
['click', 'Select a row to show device details'],
|
['click', 'Select a row to show device details'],
|
||||||
['scroll down', 'See more devices'],
|
['scroll down', 'See more devices'],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user