"use strict";
/*
* NMS info-window controller
*
* Interface: nmsInfoBox.showWindow(windowType,optionalParameter), nmsInfoBox.hide()
*
* Uses a basic hierarchy of window > views > panels, where each panel can work
* independently, but gets loaded/unloaded when needed by window or view.
*
*/
/*
*
* Currently broken or needs reimplementing:
* - Possibly: Comment CRUD, did not want to test writes on our "historic db copy"
* - Comments popover
* - Handler unloading is not working correctly, and many are never removed
* - SSH-management link, this should propably be a custom "view" of sorts
* - inventoryListing window is partially broken when first opened. Since it's
* both a window type and a panel with different modes it has some conflicts.
*
* General TODO:
* - Fix broken stuff
* - Test comments
* - Add external windows (timetravel, etc)
* - Take a critical look at what methods/variables should be marked as "_"
* - Currently argument is assumed to be a switch, this should not be the case
* - Add some basic styling to separate panels visually when in the same view
* - Add some movement/placement/size options to info window
*
*/
/*
* Basic configuration
*/
var nmsInfoBox = nmsInfoBox || {
stats: {},
_container: false, //Container window
_windowHandler: false, //Window handler
_sw: false, //Name of last switch opened, used for toggle-click
_windowTypes: [
{
'id': 'switchInfo',
'title': 'Switch info',
'views': {
'initial': {
'name': 'Switch summary',
'panels': ['switchComments','switchSummary']
},
'details': {
'name': 'Switch details',
'panels': ['switchDetails']
},
'ports': {
'name': 'SNMP - Ports',
'panels': ['switchSNMP:ports']
},
'misc': {
'name': 'SNMP - Misc',
'panels': ['switchSNMP:misc']
},
'comments': {
'name': 'Comments',
'panels': ['switchComments']
},
'edit': {
'name': 'Edit',
'panels': ['switchEdit']
}
}
},
{
'id': 'addSwitch',
'title': 'Add new switch',
'views': {
'initial': {
'name': 'Add switch',
'panels': ['switchAdd']
}
}
},
{
'id': 'inventoryListing',
'title': 'Inventory listing',
'views': {
'initial': {
'name': 'Distro names',
'panels': ['inventoryListing:distro_name']
},
'sysDescr': {
'name': 'System description',
'panels': ['inventoryListing:sysDescr']
},
'jnxBoxSerialNo': {
'name': 'Serial numbers',
'panels': ['inventoryListing:jnxBoxSerialNo']
}
}
}
],
_panelTypes: {} //Populate by using the nmsInfoBox.addPanelType method
};
/*
* Shows a window, and triggers initial load if needed
*/
nmsInfoBox.showWindow = function (windowName,argument) {
if(windowName == "switchInfo" && argument != '' && argument == this._sw) {
nmsInfoBox.hide();
return;
}
if(!this._container)
this._load();
if(!windowName)
windowName = 'switchInfo';
this._sw = argument;
this._windowHandler.showWindow(windowName,argument)
this._container.style.display = "block";
};
/*
* Internal function to load and register the initial html objects
*/
nmsInfoBox._load = function() {
var infoBox = document.createElement("div");
infoBox.classList.add("panel", "panel-default");
var title = document.createElement("div");
title.id = "info-box-title";
title.classList.add("panel-heading");
var nav = document.createElement("div");
nav.id = "info-box-nav";
nav.classList.add("panel-body");
var body = document.createElement("div");
body.id = "info-box-body";
body.classList.add("panel-body");
infoBox.appendChild(title);
infoBox.appendChild(nav);
infoBox.appendChild(body);
this._container = document.getElementById("info-box-container");
this._container.appendChild(infoBox);
this._windowHandler = new windowHandler();
this._windowHandler.setContainerObj(document.getElementById("info-box-container"));
this._windowHandler.setTitleObj(document.getElementById("info-box-title"));
this._windowHandler.setBodyObj(document.getElementById("info-box-body"));
this._windowHandler.setNavObj(document.getElementById("info-box-nav"));
this._windowHandler.setPanelTypes(this._panelTypes);
this._windowHandler.setWindowTypes(this._windowTypes);
};
/*
* Adds a panel type to _panelTypes for usage in windows and views
*/
nmsInfoBox.addPanelType = function (id, obj) {
this._panelTypes[id] = obj;
};
/*
* Hide the active window and tell it to unload
*/
nmsInfoBox.hide = function() {
this._sw = false;
this._windowHandler.hide();
this._windowHandler.unloadWindow();
};
/*
* Click a switch and display it.
*/
nmsInfoBox.click = function(sw)
{
this.showWindow("switchInfo",sw);
};
/*
* Window handler
*
* Is based on a hierarchy of objects: Window (itself) > Views > Panels. Where
* any object should not interact with any other directly. Panels are special
* nmsInfoPanel-objects that handle their own rendering, refreshing, etc. The
* window handler only makes shure these panels are loaded and unloaded when
* needed in a window or view.
*
* Does primarily rely on an imported list of panel types and window types to
* display stuff, but has methods for manual overrides if needed.
*
* Panels can use the doInPanel(panelId,functionName,arguments) method to pass
* actions to themselves if needed.
*
*/
var windowHandler = function () {
this.containerObj = false;
this.titleObj = false;
this.navObj = false;
this.bodyObj = false;
this._panels = {};
this._view = "";
this._window = {};
this.windowTypes = false;
this.panelTypes = false;
this.argument = false;
this.show = function () {
this.containerObj.classList.remove("hidden");
};
this.hide = function () {
this.containerObj.classList.add("hidden");
};
this.setContainerObj = function (containerObj) {
this.containerObj = containerObj;
};
this.setTitleObj = function (titleObj) {
this.titleObj = titleObj;
};
this.setNavObj = function (navObj) {
this.navObj = navObj;
};
this.setBodyObj = function (bodyObj) {
this.bodyObj = bodyObj;
};
this.setPanelTypes = function (panelTypes) {
this.panelTypes = panelTypes;
};
this.setWindowTypes = function (windowTypes) {
this.windowTypes = {};
for(var i in windowTypes) {
this.windowTypes[windowTypes[i].id] = windowTypes[i];
}
};
this.setArgument = function (argument) {
if(this.argument != argument) {
this.argument = argument;
this.showView(this._view);
}
};
this.showPanel = function (panelName) {
var panelArray = panelName.split(":");
var panelName = panelArray[0];
var panelMode = panelArray[1];
if(this.panelTypes[panelName]) {
var id = (Math.random().toString(36)+'00000000000000000').slice(2, 10+2);
var panel = new this.panelTypes[panelName];
panel.setId(id);
if(!!panelMode)
panel.setMode(panelMode);
panel.load(this.bodyObj,this.argument);
this._panels[id] = panel;
}
};
this.showTitle = function (title) {
this.titleObj.innerHTML = '×
' + title + ' ';
};
this.showNav = function () {
if(!this._window.views)
this.navObj.innerHTML = '';
var output = '';
var i = 0;
for(var view in this._window.views) {
var viewObj = this._window.views[view];
var active = '';
if(this._view == view)
active = ' class="active" ';
output += '' + viewObj.name + ' ';
i++;
}
output += ' ';
if(i < 2) {
this.navObj.innerHTML = '';
} else {
this.navObj.innerHTML = output;
}
};
this.addWindow = function (windowObj) {
this.windowTypes[windowObj.id] = windowObj;
};
this.showWindow = function (windowName,argument) {
if(!this.windowTypes[windowName])
return;
this.unloadWindow();
this.argument = argument;
this._window = this.windowTypes[windowName];
this.showTitle(this._window.title);
this.showView();
this.show();
};
this.showView = function (viewId) {
if(!viewId || viewId == '')
viewId = "initial";
if(!this._window.views || !this._window.views[viewId])
return;
this.unloadView();
for(var panel in this._window.views[viewId].panels) {
this.showPanel(this._window.views[viewId].panels[panel]);
}
this._view = viewId;
this.showNav();
};
this.removePanel = function (panelId) {
if(!!panelId)
this.unloadPanel(panelId);
};
this.unloadView = function () {
this.unloadPanel();
};
this.unloadWindow = function() {
this.hide();
this.unloadPanel();
};
this.unloadPanel = function (panelId) {
if(!panelId) {
for(var i in this._panels) {
this._panels[i].unload();
}
this._panels = {};
} else {
try {
this._panels[panelId].unload();
} catch (e) {}
delete this._panels[panelId];
}
};
//Method for triggering a function in an active panel
this.doInPanel = function (panelId, action, argument) {
if(!this._panels[panelId])
return;
if(typeof this._panels[panelId][action] === "function") {
if(!argument) {
this._panels[panelId][action]();
} else {
this._panels[panelId][action](argument);
}
}
};
};
/*
* Basic info-panel object
*
* Has a basic model of a stand alone panel which is intended to be extended
* upon to implement specific panels:
*
* var myNewPanel = function () {
* nmsInfoPanel.call(this,"myNewPanelId");
* this.refresh = function (reason) {
* //My custom window function
* this._render(htmlObj);
* };
* };
*
*/
var nmsInfoPanel = function nmsInfoPanel(name,id) {
this.name = name;
this.id = id;
this.sw = false;
this.container = false;
this.classList = ['info-panel'];
this.me = false;
this.handlers = [];
this.mode = "initial";
if(!this.id)
this.id = (Math.random().toString(36)+'00000000000000000').slice(2, 10+2);
//Method for loading the general panel properties
this.load = function (container,argument) {
this.container = container;
this.sw = argument;
this.me = document.createElement("div");
this.me.id = this.id;
for(var i in this.classList)
this.me.classList.add(this.classList[i]);
this.container.appendChild(this.me);
this.init(argument);
};
//Method for making this specific panel-instance ready for first refresh
//Override in children when any custom init-functionality is needed
this.init = function (argument) {
this.refresh("init");
};
//Methods for getting and setting panel id
this.setId = function (id) {
this.id = id;
};
this.getId = function () {
return this.id;
};
//Methods for setting and getting mode (default "initial")
this.setMode = function (mode) {
this.mode = mode;
};
this.getMode = function () {
return this.mode;
};
//Internal method for rendering content
this._render = function (newContent) {
if(!newContent || !this.me)
return;
this.me.innerHTML = newContent.outerHTML;
};
//Helper method for rendering error messages in a unified way
this._renderError = function (message) {
var error = document.createElement("div");
error.className = "alert alert-info";
error.innerHTML = message;
this._render(error);
};
//Method for unloading any local data
this.unload = function () {
if(!this.me)
return;
this.me.remove();
this.sw = false;
this.container = false;
this.me = false;
this.id = false;
this.removeHandlers();
};
//Method for loading new data and triggering a _render if needed
//Implemented in children only
this.refresh = function (reason) {};
//Methods for adding and removing classes
this.addClass = function (className) {
if(this.classList.indexOf(className) == -1) {
this.classList.push(className);
this.me.classList.add(className);
}
};
this.removeClass = function (className) {
var index = this.classList.indexOf(className);
if(index != -1) {
this.classList.splice(index,1);
this.me.classList.remove(className);
}
};
//Method for registering a data handler (lets us clean them up later)
this.addHandler = function (dataType,targetFunction) {
if(!targetFunction)
targetFunction = "refresh";
nmsData.addHandler(dataType,this.id,(this[targetFunction]).bind(this),"handler-"+dataType);
this.handlers.push(dataType);
};
//Method for removing all handlers we have registered
this.removeHandlers = function () {
for(var i in this.handlers) {
nmsData.unregisterHandler(this.handlers[i],this.id);
}
};
//Method for checking if we have handlers registered
this.hasHandler = function (dataType) {
for(var i in this.handlers) {
if(this.handlers[i] == dataType)
return true;
}
return false;
};
};
/*
* Panel type: Switch SNMP information
*
* Displays a list of available SNMP data from a set SNMP-group (Ex. "Ports", "Misc")
*
* TODO: Clean up html-generator code.
*
*/
var switchSNMPPanel = function () {
nmsInfoPanel.call(this,"switchSNMP");
this.init = function() {
this.addHandler("snmp");
this.refresh();
};
this.refresh = function(reason) {
var domObj = document.createElement("div");
domObj.classList.add("panel-group");
try {
var snmpJson = nmsData.snmp.snmp[this.sw][this.mode];
} catch(e) {
this._renderError("Waiting for data.");
return;
}
for(var obj in snmpJson) {
var cleanObj = obj.replace(/\W+/g, "");
var groupObj = document.createElement("div");
groupObj.classList.add("panel","panel-default");
groupObj.innerHTML = '' + obj + ' ';
var groupObjCollapse = document.createElement("div");
groupObjCollapse.id = cleanObj + "-group";
groupObjCollapse.classList.add("collapse");
var panelBodyObj = document.createElement("div");
panelBodyObj.classList.add("panel-body");
var tableObj = document.createElement("table");
tableObj.classList.add("table","table-condensed");
var tbody = document.createElement("tbody");
for(var prop in snmpJson[obj]) {
var propObj = document.createElement("tr");
propObj.innerHTML = '' + prop + ' ' + snmpJson[obj][prop] + ' ';
tbody.appendChild(propObj);
}
tableObj.appendChild(tbody);
panelBodyObj.appendChild(tableObj);
groupObjCollapse.appendChild(panelBodyObj);
groupObj.appendChild(groupObjCollapse);
domObj.appendChild(groupObj);
}
this._render(domObj);
};
};
nmsInfoBox.addPanelType("switchSNMP",switchSNMPPanel);
/*
* Panel type: Switch details
*
* Displays a table of switch information
*
*/
var switchDetailsPanel = function() {
nmsInfoPanel.call(this,"switchDetails");
this.refresh = function(reason) {
var swi = [];
var swm = [];
try {
swi = nmsData.switches["switches"][this.sw];
} catch(e) {}
try {
swm = nmsData.smanagement.switches[this.sw];
} catch(e) {}
var content = [];
for (var v in swi) {
if (v == "placement") {
var place = JSON.stringify(swi[v]);
content.push([v,place]);
continue;
}
content.push([v, swi[v]]);
}
for (var v in swm) {
content.push([v, swm[v]]);
}
content.sort();
var infotable = nmsInfoBox._makeTable(content);
this._render(infotable);
};
};
nmsInfoBox.addPanelType("switchDetails",switchDetailsPanel);
/*
* Panel type: Add switch
*
* Lets you add a new switch using the switch-add api
*
*/
var switchAddPanel = function() {
nmsInfoPanel.call(this,"switchAdd");
this.refresh = function(reason) {
var domObj = document.createElement("div");
domObj.innerHTML = 'Add switch '
this._render(domObj);
};
this.save = function () {
var sysname = document.getElementById('create-sysname').value;
var myData = JSON.stringify([{'sysname':sysname}]);
$.ajax({
type: "POST",
url: "/api/write/switch-add",
dataType: "text",
data:myData,
success: function (data, textStatus, jqXHR) {
var result = JSON.parse(data);
if(result.switches_addded.length > 0) { // FIXME unresolved variable switches_addded
nmsInfoBox.hide();
}
nmsData.invalidate("switches");
nmsData.invalidate("smanagement");
}
});
};
};
nmsInfoBox.addPanelType("switchAdd",switchAddPanel);
/*
* Panel type: Inventory listing
*
* Displays a filterable table with switch data, based on a selected mode
*
* TODO:
* - Add support for multiple columns with data
* - Add sorting
* - Add live filtering
* - Add export options?
*
*/
var inventoryListingPanel = function() {
nmsInfoPanel.call(this,"inventoryListing");
this.filter = "";
this.init = function (mode) {
if(!nmsData.snmp || !nmsData.snmp.snmp) {
if(!this.hasHandler("snmp")) {
this.addHandler("snmp","init");
this._renderError("Waiting for SNMP data.");
}
return;
} else {
this.removeHandlers();
if(!!mode && this.mode == "initial")
this.setMode(mode);
this.refresh("init");
}
};
this.setFilter = function (filter) {
this.filter = filter;
this.refresh();
};
this.refresh = function (reason) {
var targetArray = [];
var listTitle = '';
var contentObj = document.createElement("div");
var inputObj = document.createElement("div");
inputObj.innerHTML = 'Filtrer
';
contentObj.appendChild(inputObj);
switch (this.mode) {
case 'distro_name':
listTitle = 'Distro names';
break;
case 'sysDescr':
listTitle = 'System description';
break;
case 'jnxBoxSerialNo':
listTitle = 'Serial Numbers';
break;
default:
listTitle = 'Distro names';
}
var resultArray = [];
for(var sw in nmsData.switches.switches) {
var value = '';
if(this.filter != '') {
if(sw.toLowerCase().indexOf(this.filter) == -1 && !nmsInfoBox._searchSmart(this.filter,sw))
continue;
}
try {
switch (this.mode) {
case 'distro_name':
value = nmsData.switches.switches[sw]["distro_name"];
break;
case 'sysDescr':
value = nmsData.snmp.snmp[sw]["misc"]["sysDescr"][0];
break;
case 'jnxBoxSerialNo':
value = nmsData.snmp.snmp[sw]["misc"]["jnxBoxSerialNo"][0];
break;
}
} catch (e) {}
resultArray.push([sw, value]);
}
resultArray.sort();
var infotable = nmsInfoBox._makeTable(resultArray,listTitle);
infotable.id = "inventory-table";
contentObj.appendChild(infotable);
this._render(contentObj);
};
};
nmsInfoBox.addPanelType("inventoryListing",inventoryListingPanel);
/*
* Panel type: Edit switch
*
* Lets you edit basic switch and switch management data through the switch-update api
*
*/
var switchEditPanel = function () {
nmsInfoPanel.call(this,"switchEdit");
this.refresh = function (reason) {
var swi = [];
var swm = [];
try {
swi = nmsData.switches["switches"][this.sw];
} catch(e) {}
try {
swm = nmsData.smanagement.switches[this.sw];
} catch(e) {}
var domObj = document.createElement("div");
var template = {};
nmsInfoBox._editValues = {};
var place;
for (var v in swi) {
if (v == "placement") {
place = JSON.stringify(swi[v]);
template[v] = place;
continue;
}
template[v] = nmsInfoBox._nullBlank(swi[v]);
}
for (var v in swm) {
template[v] = nmsInfoBox._nullBlank(swm[v]);
}
var content = [];
for (v in template) {
var tmpsw = '\'' + this.sw + '\'';
var tmpv = '\'' + v + '\'';
var tmphandler = '"nmsInfoBox._editChange(' + tmpsw + ',' + tmpv + ');"';
var html = ' ';
content.push([v, html]);
}
content.sort();
var table = nmsInfoBox._makeTable(content, "edit");
domObj.appendChild(table);
var submit = document.createElement("button");
submit.innerHTML = "Save changes";
submit.classList.add("btn", "btn-primary");
submit.id = "edit-submit-" + this.sw;
submit.setAttribute("onclick","nmsInfoBox._windowHandler.doInPanel('" + this.id + "','save');");
domObj.appendChild(submit);
var output = document.createElement("output");
output.id = "edit-output";
domObj.appendChild(output);
if (place) {
var pval = document.getElementById("edit-" + this.sw + "-placement");
if (pval) {
pval.value = place;
}
}
this._render(domObj);
};
this.save = function () {
var myData = nmsInfoBox._editStringify(this.sw);
$.ajax({
type: "POST",
url: "/api/write/switch-update",
dataType: "text",
data:myData,
success: function (data, textStatus, jqXHR) {
var result = JSON.parse(data);
if(result.switches_updated.length > 0) { // FIXME unresolved variable switches_addded
nmsInfoBox.hide();
}
nmsData.invalidate("switches");
nmsData.invalidate("smanagement");
}
});
};
};
nmsInfoBox.addPanelType("switchEdit",switchEditPanel);
/*
* Panel type: Switch comments
*
* Displays the current comments and lets you interact with them or add new ones
*
* TODO: Test with a dummy-db to make sure everything still works properly
*
*/
var switchCommentsPanel = function () {
nmsInfoPanel.call(this,"switchComments");
this.commentsHash = false;
this.refresh = function (reason) {
var domObj = document.createElement("div");
var comments = [];
var commentbox = document.createElement("div");
commentbox.id = "commentbox";
commentbox.className = "panel-body";
commentbox.style.width = "100%";
commentbox.innerHTML = 'Add comment
';
// We have data
if(!(!nmsData.comments || !nmsData.comments.comments)) {
this.commentsHash = nmsData.comments.hash;
// We have data for this switch
if(nmsData.comments.comments[this.sw]) {
this.commentsHash = nmsData.comments.hash;
for (var c in nmsData.comments.comments[this.sw]["comments"]) {
var comment = nmsData.comments.comments[this.sw]["comments"][c];
if (comment["state"] == "active" || comment["state"] == "persist" || comment["state"] == "inactive") {
comments.push(comment);
}
}
if (comments.length > 0) {
var commenttable = nmsInfoBox._makeCommentTable(comments);
commenttable.id = "info-switch-comments-table";
domObj.appendChild(commenttable);
}
}
}
domObj.appendChild(commentbox);
this._render(domObj);
};
};
nmsInfoBox.addPanelType("switchComments",switchCommentsPanel);
/*
* Panel type: Switch summary
*
* Display a live summary of key metrics
*
*/
var switchSummaryPanel = function() {
nmsInfoPanel.call(this,"switchSummary");
this.init = function() {
this.addHandler("ticker");
this.refresh();
};
this.refresh = function(reason) {
var content = [];
//Get DHCP info
var lastDhcp = undefined;
try {
var tempDhcp = nmsData.dhcp.dhcp[this.sw];
var now = Date.now();
now = Math.floor(now / 1000);
tempDhcp = now - parseInt(tempDhcp);
tempDhcp = tempDhcp + " s";
} catch(e) {}
//Get SNMP status
var snmpStatus = undefined;
try {
if (nmsData.snmp.snmp[this.sw].misc.sysName[0] != sw) {
snmpStatus = "Sysname mismatch";
} else {
snmpStatus = "OK";
}
} catch(e) {}
//Get CPU usage
var cpuUsage = undefined;
try {
var cpu = 0;
for (var u in nmsData.snmp.snmp[this.sw].misc.jnxOperatingCPU) {
var local = nmsData.snmp.snmp[this.sw].misc['jnxOperatingCPU'][u];
cpu = Math.max(nmsData.snmp.snmp[this.sw].misc.jnxOperatingCPU[u],cpu);
}
cpuUsage = cpu + " %";
} catch (e) {}
//Get traffic data
var uplinkTraffic = undefined;
try {
var speed = 0;
var t = parseInt(nmsData.switchstate.then[this.sw].uplinks.ifHCOutOctets);
var n = parseInt(nmsData.switchstate.switches[this.sw].uplinks.ifHCOutOctets);
var tt = parseInt(nmsData.switchstate.then[this.sw].time);
var nt = parseInt(nmsData.switchstate.switches[this.sw].time);
var tdiff = nt - tt;
var diff = n - t;
speed = diff / tdiff;
if(!isNaN(speed)) {
uplinkTraffic = byteCount(speed*8,0);
}
} catch (e) {};
//Get uptime data
var uptime = "";
try {
uptime = nmsData.snmp.snmp[this.sw]["misc"]["sysUpTimeInstance"][""] / 60 / 60 / 100;
uptime = Math.floor(uptime) + " t";
} catch(e) {}
//Get temperature data
var temp = "";
try {
temp = nmsData.switchstate.switches[this.sw].temp + " °C";
} catch(e) {}
//Get management data
var mgmtV4 = "";
var mgmtV6 = "";
var subnetV4 = "";
var subnetV6 = "";
try {
mgmtV4 = nmsData.smanagement.switches[this.sw].mgmt_v4_addr;
mgmtV6 = nmsData.smanagement.switches[this.sw].mgmt_v6_addr;
subnetV4 = nmsData.smanagement.switches[this.sw].subnet4;
subnetV6 = nmsData.smanagement.switches[this.sw].subnet6;
} catch(e) {}
//Get ping data
var ping = undefined;
try {
nmsData.ping.switches[this.sw].latency + " ms";
} catch (e) {}
content.push(["Ping latency:",ping]);
content.push(["Last DHCP lease:",lastDhcp]);
content.push(["SNMP status:",snmpStatus]);
content.push(["CPU usage:",cpuUsage]);
content.push(["Uplink traffic:",uplinkTraffic]);
content.push(["System uptime:",uptime]);
content.push(["Temperature",temp]);
content.push(["Management (v4):",mgmtV4]);
content.push(["Management (v6):",mgmtV6]);
content.push(["Subnet (v4):",subnetV4]);
content.push(["Subnet (v6):",subnetV6]);
var contentCleaned = [];
for(var i in content) {
if(content[i][1] == '' || content[i][1] == null)
continue;
if(content[i][1] == undefined || content[i][1])
content[i][1] == "No data";
contentCleaned.push(content[i]);
}
var table = nmsInfoBox._makeTable(contentCleaned);
this._render(table);
};
};
nmsInfoBox.addPanelType("switchSummary",switchSummaryPanel);
/*
* General-purpose table-maker?
*
* Takes an array of arrays as input, and an optional caption.
*
* E.g.: _makeTable([["name","Kjell"],["Age","five"]], "Age list");
*/
nmsInfoBox._makeTable = function(content, caption) {
var table = document.createElement("table");
var tr;
var td1;
var td2;
table.className = "table";
table.classList.add("table");
table.classList.add("table-condensed");
if (caption != undefined) {
var cap = document.createElement("caption");
cap.textContent = caption;
table.appendChild(cap);
}
for (var v in content) {
tr = table.insertRow(-1);
tr.className = content[v][0].toLowerCase();
td1 = tr.insertCell(0);
td2 = tr.insertCell(1);
td1.innerHTML = content[v][0];
td2.innerHTML = content[v][1];
}
return table;
};
/*
* Create and return a table for comments.
*
* Input is an array of comments.
*/
nmsInfoBox._makeCommentTable = function(content) {
var table = document.createElement("table");
table.className = "table";
table.classList.add("table");
table.classList.add("table-condensed");
var cap = document.createElement("caption");
cap.textContent = "Comments"
table.appendChild(cap);
for (var commentid in content) {
var tr;
var td1;
var td2;
var comment = content[commentid];
var col;
if (comment["state"] == "active")
col = "danger";
else if (comment["state"] == "inactive")
col = false;
else
col = "info";
tr = table.insertRow(-1);
tr.id = "commentRow" + comment["id"];
tr.className = col;
td1 = tr.insertCell(0);
td1.style.whiteSpace = "nowrap";
td1.style.width = "8em";
td2 = tr.insertCell(1);
var txt = ' ';
txt += ' ';
txt += ' ';
txt += '
';
td1.innerHTML = txt;
td2.innerHTML = comment["comment"];
}
return table;
};
nmsInfoBox._searchSmart = function(id, sw) {
try {
try {
if (nmsData.switches.switches[sw].distro_name.toLowerCase() == id) {
return true;
}
} catch (e) {}
try {
if (id.match("active")) {
var limit = id;
limit = limit.replace("active>","");
limit = limit.replace("active<","");
limit = limit.replace("active=","");
var operator = id.replace("active","")[0];
if (limit == parseInt(limit)) {
var ports = parseInt(nmsData.switchstate.switches[sw].ifs.ge.live);
limit = parseInt(limit);
if (operator == ">" ) {
if (ports > limit) {
return true;
}
} else if (operator == "<") {
if (ports < limit) {
return true;
}
} else if (operator == "=") {
if (ports == limit) {
return true;
}
}
}
}
} catch (e) {}
try {
if (nmsData.smanagement.switches[sw].mgmt_v4_addr.match(id)) {
return true;
}
if (nmsData.smanagement.switches[sw].mgmt_v6_addr.match(id)) {
return true;
}
} catch (e) {}
try {
if (nmsData.smanagement.switches[sw].subnet4.match(id)) {
return true;
}
if (nmsData.smanagement.switches[sw].subnet6.match(id)) {
return true;
}
} catch (e) {}
if (nmsData.snmp.snmp[sw].misc.sysDescr[0].toLowerCase().match(id)) {
return true;
}
} catch (e) {
return false;
}
return false;
};
/*
* FIXME: Not sure this belongs here, it's really part of the "Core" ui,
* not just the infobox.
*/
nmsInfoBox._search = function() {
var el = document.getElementById("searchbox");
var id = false;
var matches = [];
if (el) {
id = el.value.toLowerCase();
}
if(id) {
nmsMap.enableHighlights();
for(var sw in nmsData.switches.switches) {
if(sw.toLowerCase().indexOf(id) > -1) {
matches.push(sw);
nmsMap.setSwitchHighlight(sw,true);
} else if (nmsInfoBox._searchSmart(id,sw)) {
matches.push(sw);
nmsMap.setSwitchHighlight(sw,true);
} else {
nmsMap.setSwitchHighlight(sw,false);
}
}
} else {
nmsMap.disableHighlights();
}
if(matches.length == 1) {
document.getElementById("searchbox-submit").classList.add("btn-primary");
document.getElementById("searchbox").dataset.match = matches[0];
} else {
document.getElementById("searchbox-submit").classList.remove("btn-primary");
document.getElementById("searchbox").dataset.match = '';
}
};
nmsInfoBox._searchKeyListener = function(e) {
switch (e.keyCode) {
case 13:
var sw = document.getElementById("searchbox").dataset.match;
if(sw != '') {
nmsInfoBox.showWindow("switchInfo",sw);
}
break;
case 27:
document.getElementById("searchbox").dataset.match = '';
document.getElementById("searchbox").value = '';
nmsInfoBox._search();
nmsInfoBox.hide();
break;
}
};
nmsInfoBox._nullBlank = function(x) {
if (x == null || x == false || x == undefined)
return "";
return x;
};
nmsInfoBox._editChange = function(sw, v) {
var el = document.getElementById("edit-" + sw + "-" + v);
var val = el.value;
if (v == "placement") {
try {
val = JSON.parse(val);
el.parentElement.classList.remove("has-error");
el.parentElement.classList.add("has-success");
} catch (e) {
el.parentElement.classList.add("has-error");
return;
}
}
nmsInfoBox._editValues[v] = val;
el.classList.add("has-warning");
var myData = nmsInfoBox._editStringify(sw);
var out = document.getElementById("edit-output");
out.value = myData;
};
nmsInfoBox._editStringify = function(sw) {
nmsInfoBox._editValues['sysname'] = sw;
return JSON.stringify([nmsInfoBox._editValues]);
};