diff options
| -rw-r--r-- | web/etc/varnish/nms.vcl | 1 | ||||
| -rw-r--r-- | web/nms.gathering.org/js/nms-data.js | 16 | ||||
| -rw-r--r-- | web/nms.gathering.org/js/nms-map.js | 111 | ||||
| -rw-r--r-- | web/nms.gathering.org/js/nms.js | 709 | 
4 files changed, 331 insertions, 506 deletions
diff --git a/web/etc/varnish/nms.vcl b/web/etc/varnish/nms.vcl index e4b4747..4f1a855 100644 --- a/web/etc/varnish/nms.vcl +++ b/web/etc/varnish/nms.vcl @@ -30,6 +30,7 @@ sub vcl_recv {          return (pass);      } +    return (pass);      # Brukes ikke. Cookies er for nubs.      unset req.http.Cookie; diff --git a/web/nms.gathering.org/js/nms-data.js b/web/nms.gathering.org/js/nms-data.js index 7ef11ba..2d7fc01 100644 --- a/web/nms.gathering.org/js/nms-data.js +++ b/web/nms.gathering.org/js/nms-data.js @@ -82,11 +82,12 @@ var nmsData = nmsData || {  	 */  	get now() { return this._now || this._last; },  	set now(val) { -		if (val == undefined) { -			this._now = undefined; +		if (val == undefined || !val) { +			nmsData._now = undefined; +		} else { +			// FIXME: Check if now is valid syntax. +			nmsData._now = val;  		} -		// FIXME: Check if now is valid syntax. -		this._now = now;  	},  	/*  	 * List of sources, name, handler, etc @@ -170,11 +171,11 @@ nmsData.addHandler = function(name, id, cb, cbdata) {   */  nmsData.unregisterHandlerWildcard = function(id) {  	for (var v in nmsData._sources) { -		this._unregisterHandler(v, id); +		this.unregisterHandler(v, id);  	}  } -nmsData._unregisterHandler = function(name, id) { +nmsData.unregisterHandler = function(name, id) {  	delete this._sources[name].cbs[id];  } @@ -227,10 +228,11 @@ nmsData._genericUpdater = function(name) {  		url: this._sources[name].target + now,  		dataType: "json",  		success: function (data, textStatus, jqXHR) { -			nmsData._last = data['time'];  			if (nmsData[name] == undefined ||  nmsData[name]['hash'] != data['hash']) { +				nmsData._last = data['time'];  				nmsData.old[name] = nmsData[name];  				nmsData[name] = data; +				nmsMap.drawNow();  				for (var i in nmsData._sources[name].cbs) {  					var tmp = nmsData._sources[name].cbs[i];  					if (tmp.cb != undefined) { diff --git a/web/nms.gathering.org/js/nms-map.js b/web/nms.gathering.org/js/nms-map.js index 65b5b68..a9731c5 100644 --- a/web/nms.gathering.org/js/nms-map.js +++ b/web/nms.gathering.org/js/nms-map.js @@ -19,7 +19,9 @@ var nmsMap = nmsMap || {  		colorSame:0,  		resizeEvents:0,  		switchInfoUpdate:0, -		switchInfoSame:0 +		switchInfoSame:0, +		nowDups:0, +		nows:0  	},  	contexts: ["bg","link","blur","switch","text","textInfo","top","input","hidden"],  	_info: {}, @@ -27,7 +29,9 @@ var nmsMap = nmsMap || {  		fontLineFactor: 3,  		textMargin: 3,  		xMargin: 10, -		yMargin: 20 +		yMargin: 20, +		fontSize: 14, +		fontFace: "Verdana"  	},  	scale: 1,  	_orig: { width:1920, height:1032 }, @@ -43,7 +47,6 @@ var nmsMap = nmsMap || {  nmsMap.init = function() {  	this._initContexts();  	this._drawBG(); -	nmsData.registerSource("switches","/api/public/switches");  	nmsData.addHandler("switches","nmsMap",function(){nmsMap._drawAllSwitches();});  	window.addEventListener('resize',nmsMap._resizeEvent,true);  	document.addEventListener('load',nmsMap._resizeEvent,true); @@ -114,9 +117,38 @@ nmsMap._resizeEvent = function() {  	}  	nmsMap._drawBG();  	nmsMap._drawAllSwitches(); +	nmsMap.drawNow();  	nmsMap.stats.resizeEvents++;  } +/* + * Draw current time-window + * + * FIXME: The math here is just wild approximation and guesswork because + * I'm lazy. + */ +nmsMap.drawNow = function () +{ +	var now = nmsData.now; +	if (nmsMap._lastNow == now) { +		nmsMap.stats.nowDups++; +		return; +	} +	nmsMap.stats.nows++; + +	var ctx = nmsMap._c.top.ctx; +	ctx.save(); +	ctx.scale(this.scale, this.scale); +	ctx.font = Math.round(2 * this._settings.fontSize) + "px " + this._settings.fontFace; +	ctx.clearRect(0,0,800,100); +	ctx.fillStyle = "white"; +	ctx.strokeStyle = "black"; +	ctx.lineWidth = nms.fontLineFactor; +	ctx.strokeText(now, 0 + this._settings.textMargin, 25); +	ctx.fillText(now, 0 + this._settings.textMargin, 25); +	ctx.restore(); +} +  nmsMap.setNightMode = function(toggle) {  	if (this._nightmode == toggle)  		return; @@ -268,3 +300,76 @@ nmsMap._connectBoxes = function(box1, box2,color1, color2) {  	ctx.stroke();  	ctx.restore();  } + +/* + * STUFF NOT YET INTEGRATED, BUT MOVED AWAY FROM nms.js TO TIDY. + * + * Consider this a TODO list. + */ + + +/* + * Draw the blur for a box. + */ +function drawBoxBlur(x,y,boxw,boxh) +{ +	var myX = Math.floor(x * canvas.scale); +	var myY = Math.floor(y * canvas.scale); +	var myX2 = Math.floor((boxw) * canvas.scale); +	var myY2 = Math.floor((boxh) * canvas.scale); +	dr.blur.ctx.fillRect(myX,myY, myX2, myY2); +} + +/* + * Draw a linknet with index i. + * + * XXX: Might have to change the index here to match backend + */ +function drawLinknet(i) +{ +	var c1 = nms.linknet_color[i] && nms.linknet_color[i].c1 ? nms.linknet_color[i].c1 : blue; +	var c2 = nms.linknet_color[i] && nms.linknet_color[i].c2 ? nms.linknet_color[i].c2 : blue; +	if (nmsData.switches.switches[nmsData.switches.linknets[i].sysname1] && nmsData.switches.switches[nmsData.switches.linknets[i].sysname2]) { +		connectSwitches(nmsData.switches.linknets[i].sysname1,nmsData.switches.linknets[i].sysname2, c1, c2); +	} +} + +/* + * Draw all linknets + */ +function drawLinknets() +{ +	if (nmsData.switches && nmsData.switches.linknets) { +		for (var i in nmsData.switches.linknets) { +			drawLinknet(i); +		} +	} +} + +/* + * Change both colors of a linknet. + * + * XXX: Probably have to change this to better match the backend data + */ +function setLinknetColors(i,c1,c2) +{ +	if (!nms.linknet_color[i] ||  + 	     nms.linknet_color[i].c1 != c1 || +	     nms.linknet_color[i].c2 != c2) { +		if (!nms.linknet_color[i]) +			nms.linknet_color[i] = {}; +		nms.linknet_color[i]['c1'] = c1; +		nms.linknet_color[i]['c2'] = c2; +		drawLinknet(i); +	} +} + +function applyBlur() +{ +	var blur = document.getElementById("shadowBlur"); +	var col = document.getElementById("shadowColor"); +	nms.shadowBlur = blur.value; +	nms.shadowColor = col.value; +	resetBlur(); +	saveSettings(); +} diff --git a/web/nms.gathering.org/js/nms.js b/web/nms.gathering.org/js/nms.js index 7564d72..a959db0 100644 --- a/web/nms.gathering.org/js/nms.js +++ b/web/nms.gathering.org/js/nms.js @@ -1,39 +1,34 @@  "use strict";  var nms = {  	stats:{}, // Various internal stats -	updater:undefined, // Active updater -	speed:0, // Current aggregated speed  	switch_showing:"", // Which switch we are displaying (if any). -	switchInfo:{}, -	repop_switch:false, // True if we need to repopulate the switch info when port state updates (e.g.: added comments); -	repop_time:false, // Timestamp in case we get a cached result -	nightMode:false,  +	get nightMode() { return this._nightMode; }, +	set nightMode(val) { if (val != this._nightMode) { this._nightMode = val; setNightMode(val); } }, +	/* +	 * FIXME: This should be slightly smarter. +	 */  	_now: false,  	get now() { return this._now }, -	set now(v) { this._now = n; nmsData.now = n; }, +	set now(v) { this._now = v; nmsData.now = v; },  	/*  	 * Various setInterval() handlers. See nmsTimer() for how they are  	 * used.  	 * -	 * Cool fact: Adding one here adds it to the 'debug timers' -	 * drop-down. +	 * FIXME: Should just stop using these.  	 */  	timers: {  		playback:false,  	}, +	  	menuShowing:true,  	/*  	 * This is a list of nms[x] variables that we store in our  	 * settings-cookie when altered and restore on load.  	 */  	settingsList:[ -		'shadowBlur', -		'shadowColor',  		'nightMode', -		'menuShowing', -		'layerVisibility' +		'menuShowing'  	], -	layerVisibility:{},  	keyBindings:{  		'?':toggleMenu,  		'n':toggleNightMode, @@ -51,16 +46,16 @@ var nms = {  		'p':moveTimeFromKey,  		'r':moveTimeFromKey  	}, -  /* -   * Playback controllers and variables -   */ -  playback:{ -    startTime: false, -    stopTime: false, -    playing: false, -    replayTime: 0, -    replayIncrement: 60 * 60 -  } +	/* +	 * Playback controllers and variables +	 */ +	playback:{ +		startTime: false, +		stopTime: false, +		playing: false, +		replayTime: 0, +		replayIncrement: 60 * 60 +	 }  };  /* @@ -117,7 +112,7 @@ function byteCount(bytes) {   */  function toggleNightMode()  { -	setNightMode(!nms.nightMode); +	nms.nightMode = !nms.nightMode;  	saveSettings();  } @@ -190,76 +185,82 @@ function epochToString(t)  	return str;  } +  function localEpochToString(t) { -  var d = new Date(parseInt(t) * parseInt(1000)); -  var timezoneOffset = d.getTimezoneOffset() * -60; -  t = t + timezoneOffset; +	var d = new Date(parseInt(t) * parseInt(1000)); +	var timezoneOffset = d.getTimezoneOffset() * -60; +	t = t + timezoneOffset; -  return epochToString(t); +	return epochToString(t);  }  /*   * Start replaying historical data.   */  nms.playback.startReplay = function(startTime,stopTime) { -  if(!startTime || !stopTime) -    return false; - -  nms.playback.pause(); -  nms.playback.startTime = stringToEpoch(startTime); -  nms.playback.stopTime = stringToEpoch(stopTime); -  nms.now = epochToString(nms.playback.startTime); -  nms.playback.play(); +	if(!startTime || !stopTime) +		return false; + +	nms.playback.pause(); +	nms.playback.startTime = stringToEpoch(startTime); +	nms.playback.stopTime = stringToEpoch(stopTime); +	nms.now = epochToString(nms.playback.startTime); +	nms.playback.play();  } +  /*   * Pause playback   */  nms.playback.pause = function() { -  nms.timers.playback.stop(); -  nms.playback.playing = false; +	nms.timers.playback.stop(); +	nms.playback.playing = false;  } +  /*   * Start playback   */  nms.playback.play = function() { -  nms.playback.tick(); -  nms.timers.playback.start(); -  nms.playback.playing = true; +	nms.playback.tick(); +	nms.timers.playback.start(); +	nms.playback.playing = true;  } +  /*   * Toggle playback   */  nms.playback.toggle = function() { -  if(nms.playback.playing) { -    nms.playback.pause(); -  } else { -    nms.playback.play(); -  } +	if(nms.playback.playing) { +		nms.playback.pause(); +	} else { +		nms.playback.play(); +	}  } +  /*   * Jump to place in time   */  nms.playback.setNow = function(now) { -  resetSwitchStates(); -  now = parseNow(now); -  nms.now = now; +	var now = parseNow(now); +	nms.now = now; -  nms.playback.stopTime = false; -  nms.playback.startTime = false; -  nms.playback.tick(); +	nms.playback.stopTime = false; +	nms.playback.startTime = false; +	nms.playback.tick();  } +  /*   * Step forwards or backwards in timer   */  nms.playback.stepTime = function(n)  { -  now = getNowEpoch(); -  newtime = parseInt(now) + parseInt(n); -  nms.now = epochToString(parseInt(newtime)); +	var now = getNowEpoch(); +	var newtime = parseInt(now) + parseInt(n); +	nms.now = epochToString(parseInt(newtime)); -  if(!nms.playback.playing) -    nms.playback.tick(); +	if(!nms.playback.playing) +		nms.playback.tick();  } +  /*   * Ticker to trigger updates, and advance time if replaying   * @@ -267,62 +268,67 @@ nms.playback.stepTime = function(n)   */  nms.playback.tick = function()  { -  nms.playback.replayTime = getNowEpoch(); - -  // If outside start-/stopTime, remove limits and pause playback -  if (nms.playback.stopTime && (nms.playback.replayTime >= nms.playback.stopTime || nms.playback.replayTime < nms.playback.startTime)) { -    nms.playback.stopTime = false; -    nms.playback.startTime = false; -    nms.playback.pause(); -    return; -  } - -  // If past actual datetime, go live -  if (nms.playback.replayTime > parseInt(Date.now() / 1000)) { -    nms.now = false; -  } - -  // If we are still replaying, advance time -  if(nms.now !== false && nms.playback.playing) { -    nms.playback.stepTime(nms.playback.replayIncrement); -  } - -  // Update data and force redraw -  // FIXME: nmsData merge -  // nms.updater.updater(); -  // FIXME: 2: This should not be necsarry. The updaters should be -  // data-driven, not time-driven. E.g.: If nmsData upates, the handlers -  // should run. +	nms.playback.replayTime = getNowEpoch(); + +	// If outside start-/stopTime, remove limits and pause playback +	if (nms.playback.stopTime && (nms.playback.replayTime >= nms.playback.stopTime || nms.playback.replayTime < nms.playback.startTime)) { +		nms.playback.stopTime = false; +		nms.playback.startTime = false; +		nms.playback.pause(); +		return; +	} + +	// If past actual datetime, go live +	if (nms.playback.replayTime > parseInt(Date.now() / 1000)) { +		nms.now = false; +	} + +	// If we are still replaying, advance time +	if(nms.now !== false && nms.playback.playing) { +		nms.playback.stepTime(nms.playback.replayIncrement); +	}  } +  /*   * Helper function for safely getting a valid now-epoch   */  function getNowEpoch() { -  if (nms.now && nms.now != 0) -    return stringToEpoch(nms.now); -  else -    return parseInt(Date.now() / 1000); +	if (nms.now && nms.now != 0) +		return stringToEpoch(nms.now); +	else +		return parseInt(Date.now() / 1000);  } +function hideSwitch() +{ +	_hideSwitch(); +	nmsData.unregisterHandler("comments","switchshower"); +} +  /*   * Hide switch info-box   */ -function hideSwitch() +function _hideSwitch()  { -		var swtop = document.getElementById("info-switch-parent"); -		var switchele = document.getElementById("info-switch-table"); -		var comments = document.getElementById("info-switch-comments-table"); -		var commentbox; -		if (switchele != undefined) -			switchele.parentNode.removeChild(switchele); -		if (comments != undefined) -			comments.parentNode.removeChild(comments); -		commentbox = document.getElementById("commentbox"); -		if (commentbox != undefined) -			commentbox.parentNode.removeChild(commentbox); -		swtop.style.display = 'none'; -		nms.switch_showing = ""; +	var swtop = document.getElementById("info-switch-parent"); +	var switchele = document.getElementById("info-switch-table"); +	var comments = document.getElementById("info-switch-comments-table"); +	var commentbox; +	if (switchele != undefined) +		switchele.parentNode.removeChild(switchele); +	if (comments != undefined) +		comments.parentNode.removeChild(comments); +	commentbox = document.getElementById("commentbox"); +	if (commentbox != undefined) +		commentbox.parentNode.removeChild(commentbox); +	swtop.style.display = 'none'; +	nms.switch_showing = ""; +} + +function showSwitch(x) { +	nmsData.addHandler("comments","switchshower",_showSwitch,x); +	_showSwitch(x);  }  /* @@ -330,159 +336,95 @@ function hideSwitch()   *   * FIXME: THIS IS A MONSTROSITY.   */ -function showSwitch(x) +function _showSwitch(x)  { -		var sw = nmsData.switches["switches"][x]; -		var swm = nmsData.smanagement.switches[x]; -		var swtop = document.getElementById("info-switch-parent"); -		var swpanel = document.getElementById("info-switch-panel-body"); -		var swtitle = document.getElementById("info-switch-title"); -		var tr; -		var td1; -		var td2; +	var sw = nmsData.switches["switches"][x]; +	var swm = nmsData.smanagement.switches[x]; +	var swtop = document.getElementById("info-switch-parent"); +	var swpanel = document.getElementById("info-switch-panel-body"); +	var swtitle = document.getElementById("info-switch-title"); +	var tr; +	var td1; +	var td2; -		hideSwitch();	 -		nms.switch_showing = x; -		document.getElementById("aboutBox").style.display = "none"; -		var switchele = document.createElement("table"); -		switchele.id = "info-switch-table"; -		switchele.className = "table"; -		switchele.classList.add("table"); -		switchele.classList.add("table-condensed"); -		 -		swtitle.innerHTML = x + '<button type="button" class="close" aria-labe="Close" onclick="hideSwitch();" style="float: right;"><span aria-hidden="true">×</span></button>'; -		var speed = 0; -		var speed2 = 0; -		for (port in nmsData.switches["switches"][x]["ports"]) { -			if (nmsData.switches["switches"][x]["ports"] == undefined || -			    nms.switches_then["switches"][x]["ports"] == undefined) { -				continue; -			} -			if (/ge-0\/0\/44$/.exec(port) || -			    /ge-0\/0\/45$/.exec(port) || -			    /ge-0\/0\/46$/.exec(port) || -			    /ge-0\/0\/47$/.exec(port)) -			 { -				 var t = nms.switches_then["switches"][x]["ports"][port]; -				 var n = nmsData.switches["switches"][x]["ports"][port]; -				 speed += (parseInt(t["ifhcoutoctets"]) - parseInt(n["ifhcoutoctets"])) / (parseInt(t["time"] - n["time"])); -				 speed2 += (parseInt(t["ifhcinoctets"]) - parseInt(n["ifhcinoctets"])) / (parseInt(t["time"] - n["time"])); -			 } -		} - -		tr = switchele.insertRow(-1); -		td1 = tr.insertCell(0); -		td2 = tr.insertCell(1); -		td1.innerHTML = "Uplink speed (out , port 44-47)"; -		td2.innerHTML = byteCount(8 * speed) + "b/s"; +	_hideSwitch();	 +	nms.switch_showing = x; +	var switchele = document.createElement("table"); +	switchele.id = "info-switch-table"; +	switchele.className = "table"; +	switchele.classList.add("table"); +	switchele.classList.add("table-condensed"); +	 +	swtitle.innerHTML = x + '<button type="button" class="close" aria-labe="Close" onclick="hideSwitch();" style="float: right;"><span aria-hidden="true">×</span></button>'; -		tr = switchele.insertRow(-1); -		td1 = tr.insertCell(0); -		td2 = tr.insertCell(1); -		td1.title = "Port 44, 45, 46 and 47 are used as uplinks."; -		td1.innerHTML = "Uplink speed (in , port 44-47)"; -		td2.innerHTML = byteCount(8 * speed2) + "b/s"; - -		speed = 0; -		for (port in nmsData.switches["switches"][x]["ports"]) { -			if (nmsData.switches["switches"][x]["ports"] == undefined || -			    nms.switches_then["switches"][x]["ports"] == undefined) { -				continue; -			} -			 var t = nms.switches_then["switches"][x]["ports"][port]; -			 var n = nmsData.switches["switches"][x]["ports"][port]; -			 speed += (parseInt(t["ifhcinoctets"]) -parseInt(n["ifhcinoctets"])) / (parseInt(t["time"] - n["time"])); +	for (var v in sw) {  +		if (v == "placement") { +			continue;  		} -  		tr = switchele.insertRow(-1);  		td1 = tr.insertCell(0);  		td2 = tr.insertCell(1); -		td1.innerHTML = "Total speed (in)"; -		td2.innerHTML = byteCount(8 * speed) + "b/s"; - -		speed = 0; -		for (port in nmsData.switches["switches"][x]["ports"]) { -			if (nmsData.switches["switches"][x]["ports"] == undefined || -			    nms.switches_then["switches"][x]["ports"] == undefined) { -				continue; -			} -			 var t = nms.switches_then["switches"][x]["ports"][port]; -			 var n = nmsData.switches["switches"][x]["ports"][port]; -			 speed += (parseInt(t["ifhcoutoctets"]) -parseInt(n["ifhcoutoctets"])) / (parseInt(t["time"] - n["time"])); -		} - +		td1.innerHTML = v; +		td2.innerHTML = sw[v]; +	} +	for (var v in swm) {   		tr = switchele.insertRow(-1);  		td1 = tr.insertCell(0);  		td2 = tr.insertCell(1); -		td1.innerHTML = "Total speed (out)"; -		td2.innerHTML = byteCount(8 * speed) + "b/s"; - -		for (var v in sw) {  -			tr = switchele.insertRow(-1); -			td1 = tr.insertCell(0); -			td2 = tr.insertCell(1); -			td1.innerHTML = v; -			td2.innerHTML = sw[v]; -		} -		for (var v in swm) {  -			tr = switchele.insertRow(-1); -			td1 = tr.insertCell(0); -			td2 = tr.insertCell(1); -			td1.innerHTML = v; -			td2.innerHTML = swm[v]; -		} +		td1.innerHTML = v; +		td2.innerHTML = swm[v]; +	} -		var comments = document.createElement("table"); -		comments.id = "info-switch-comments-table"; -		comments.className = "table table-condensed"; -		var cap = document.createElement("caption"); -		cap.textContent = "Comments"; -		comments.appendChild(cap); -	 -		var has_comment = false; -		if (nmsData.comments.comments == undefined || nmsData.comments.comments[x] == undefined) { -			console.log("blank"); -		} else { -			for (var c in nmsData.comments.comments[x]["comments"]) { -				var comment = nmsData.comments.comments[x]["comments"][c]; -				has_comment = true; -				if (comment["state"] == "active" || comment["state"] == "persist" || comment["state"] == "inactive") { -					tr = comments.insertRow(-1); -					var col; -					if (comment["state"] == "active") -						col = "danger"; -					else if (comment["state"] == "inactive") -						col = false; -					else -						col = "info"; -					tr.className = col; -					tr.id = "commentRow" + comment["id"]; -					td1 = tr.insertCell(0); -					td2 = tr.insertCell(1); -					td1.style.whiteSpace = "nowrap"; -					td1.style.width = "8em"; -					var txt =  '<div class="btn-group" role="group" aria-label="..."><button type="button" class="btn btn-xs btn-default" data-trigger="focus" data-toggle="popover" title="Info" data-content="Comment added ' + epochToString(comment["time"]) + " by user " + comment["username"] + ' and listed as ' + comment["state"] + '"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span></button>'; -					txt += '<button type="button" class="btn btn-xs btn-danger" data-trigger="focus" data-toggle="tooltip" title="Mark as deleted" onclick="commentDelete(' + comment["id"] + ');"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>'; -					txt += '<button type="button" class="btn btn-xs btn-success" data-trigger="focus" data-toggle="tooltip" title="Mark as inactive/fixed" onclick="commentInactive(' + comment["id"] + ');"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>'; -					txt += '<button type="button" class="btn btn-xs btn-info" data-trigger="focus" data-toggle="tooltip" title="Mark as persistent" onclick="commentPersist(' + comment["id"] + ');"><span class="glyphicon glyphicon-star" aria-hidden="true"></span></button></div>'; -					td1.innerHTML = txt; -					td2.textContent = comment['comment']; -				} +	var comments = document.createElement("table"); +	comments.id = "info-switch-comments-table"; +	comments.className = "table table-condensed"; +	var cap = document.createElement("caption"); +	cap.textContent = "Comments"; +	comments.appendChild(cap); + +	var has_comment = false; +	if (nmsData.comments.comments == undefined || nmsData.comments.comments[x] == undefined) { +	} else { +		for (var c in nmsData.comments.comments[x]["comments"]) { +			var comment = nmsData.comments.comments[x]["comments"][c]; +			has_comment = true; +			if (comment["state"] == "active" || comment["state"] == "persist" || comment["state"] == "inactive") { +				tr = comments.insertRow(-1); +				var col; +				if (comment["state"] == "active") +					col = "danger"; +				else if (comment["state"] == "inactive") +					col = false; +				else +					col = "info"; +				tr.className = col; +				tr.id = "commentRow" + comment["id"]; +				td1 = tr.insertCell(0); +				td2 = tr.insertCell(1); +				td1.style.whiteSpace = "nowrap"; +				td1.style.width = "8em"; +				var txt =  '<div class="btn-group" role="group" aria-label="..."><button type="button" class="btn btn-xs btn-default" data-trigger="focus" data-toggle="popover" title="Info" data-content="Comment added ' + epochToString(comment["time"]) + " by user " + comment["username"] + ' and listed as ' + comment["state"] + '"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span></button>'; +				txt += '<button type="button" class="btn btn-xs btn-danger" data-trigger="focus" data-toggle="tooltip" title="Mark as deleted" onclick="commentDelete(' + comment["id"] + ');"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>'; +				txt += '<button type="button" class="btn btn-xs btn-success" data-trigger="focus" data-toggle="tooltip" title="Mark as inactive/fixed" onclick="commentInactive(' + comment["id"] + ');"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>'; +				txt += '<button type="button" class="btn btn-xs btn-info" data-trigger="focus" data-toggle="tooltip" title="Mark as persistent" onclick="commentPersist(' + comment["id"] + ');"><span class="glyphicon glyphicon-star" aria-hidden="true"></span></button></div>'; +				td1.innerHTML = txt; +				td2.textContent = comment['comment'];  			}  		} -		 -		swtop.appendChild(switchele); -		if (has_comment) { -			swtop.appendChild(comments); -			$(function () { $('[data-toggle="popover"]').popover({placement:"top",continer:'body'}) }) -		} -		var commentbox = document.createElement("div"); -		commentbox.id = "commentbox"; -		commentbox.className = "panel-body"; -		commentbox.style.width = "100%"; -		commentbox.innerHTML = '<div class="input-group"><input type="text" class="form-control" placeholder="Comment" id="' + x + '-comment"><span class=\"input-group-btn\"><button class="btn btn-default" onclick="addComment(\'' + x + '\',document.getElementById(\'' + x + '-comment\').value); document.getElementById(\'' + x + '-comment\').value = \'\'; document.getElementById(\'' + x + '-comment\').placeholder = \'Comment added. Wait for next refresh.\';">Add comment</button></span></div>'; -		swtop.appendChild(commentbox); -		swtop.style.display = 'block'; +	} + +	swtop.appendChild(switchele); +	if (has_comment) { +		swtop.appendChild(comments); +		$(function () { $('[data-toggle="popover"]').popover({placement:"top",continer:'body'}) }) +	} +	var commentbox = document.createElement("div"); +	commentbox.id = "commentbox"; +	commentbox.className = "panel-body"; +	commentbox.style.width = "100%"; +	commentbox.innerHTML = '<div class="input-group"><input type="text" class="form-control" placeholder="Comment" id="' + x + '-comment"><span class=\"input-group-btn\"><button class="btn btn-default" onclick="addComment(\'' + x + '\',document.getElementById(\'' + x + '-comment\').value); document.getElementById(\'' + x + '-comment\').value = \'\'; document.getElementById(\'' + x + '-comment\').placeholder = \'Comment added. Wait for next refresh.\';">Add comment</button></span></div>'; +	swtop.appendChild(commentbox); +	swtop.style.display = 'block';  }  /* @@ -501,102 +443,18 @@ function setLegend(x,color,name)  }  /* - * Run periodically to trigger map updates when a handler is active - */ -function updateMap() -{ -	/* -	 * XXX: This a bit hacky: There are a bunch of links that use -	 * href="#foo" but probably shouldn't. This breaks refresh since we -	 * base this on the location hash. To circumvent that issue -	 * somewhat, we just update the location hash if it's not -	 * "correct". -	 */ -	if (nms.updater) { -		if (document.location.hash != ('#' + nms.updater.tag)) { -			document.location.hash = nms.updater.tag; -		} -	} -	if (!newerSwitches()) -		return; -	 -	if (nms.updater != undefined && nmsData.switches && nms.switches_then) { -		nms.updater.updater(); -	} -	drawNow(); -} - -/*   * Change map handler (e.g., change from uplink map to ping map)   */  function setUpdater(fo)  { -	nms.updater = undefined;  	nmsMap.reset();  	nmsData.unregisterHandlerWildcard("mapHandler");  	fo.init(); -	nms.updater = fo;  	var foo = document.getElementById("updater_name");  	foo.innerHTML = fo.name + "   ";  	document.location.hash = fo.tag;  } -/* - * Helper function for updating switch-data without overwriting existing - * data with non-existent data - */ -function updateSwitches(switchdata,target) { -	target['time'] = switchdata['time'] //Assume we always get time - -	if(switchdata.switches != undefined) { -		for(var sw in switchdata.switches) { -			if(switchdata.switches[sw]['management'] != undefined) -				updateSwitchProperty(sw,'management',switchdata.switches[sw]['management'],target); -			if(switchdata.switches[sw]['ports'] != undefined) -				updateSwitchProperty(sw,'ports',switchdata.switches[sw]['ports'],target); -			if(switchdata.switches[sw]['temp'] != undefined) -				updateSwitchProperty(sw,'temp',switchdata.switches[sw]['temp'],target); -			if(switchdata.switches[sw]['temp_time'] != undefined) -				updateSwitchProperty(sw,'temp_time',switchdata.switches[sw]['temp_time'],target); -			if(switchdata.switches[sw]['placement'] != undefined) -				updateSwitchProperty(sw,'placement',switchdata.switches[sw]['placement'],target); -		} -	} -} -/* - * Helper function for updating a limited subset of switch properties, - * while the current state of the switch data is unknown. - */ -function updateSwitchProperty(sw,property,data,target) { -  if(target.switches[sw] == undefined) -    target.switches[sw] = {}; - -  target.switches[sw][property] = data; -} - -/* - * Helper function for reseting switch state data (and keeping more permanent data) - */ -function resetSwitchStates() { -  for (var sw in nmsData.switches.switches) { -    for (var property in nmsData.switches.switches[sw]) { -      if (['ports','temp','temp_time'].indexOf(property) > -1) { -        nmsData.switches.switches[sw][property] = undefined; -      } -    } -  } -} - -function applyBlur() -{ -	var blur = document.getElementById("shadowBlur"); -	var col = document.getElementById("shadowColor"); -	nms.shadowBlur = blur.value; -	nms.shadowColor = col.value; -	resetBlur(); -	saveSettings(); -} -  function toggleLayer(layer) {         var l = document.getElementById(layer);         if (l.style.display == 'none') @@ -605,16 +463,6 @@ function toggleLayer(layer) {                 l.style.display = 'none';  } -function showBlurBox() -{ -	var blur = document.getElementById("shadowBlur"); -	var col = document.getElementById("shadowColor"); -	blur.value = nms.shadowBlur; -	col.value = nms.shadowColor; -	document.getElementById("blurManic").style.display = ''; -} - -  function commentInactive(id)  {  	commentChange(id,"inactive"); @@ -654,7 +502,7 @@ function commentChange(id,state)  		dataType: "text",  		data:myData,  		success: function (data, textStatus, jqXHR) { -			nms.repop_switch = true; +			nmsData.updateSource("comments");  		}  	});  } @@ -672,121 +520,12 @@ function addComment(sw,comment)  		dataType: "text",  		data:myData,  		success: function (data, textStatus, jqXHR) { -			nms.repop_switch = true; +			nmsData.updateSource("comments");  		}  	});  } -/* - * Returns true if we have now and then-data for switches and that the - * "now" is actually newer. Useful for basic sanity and avoiding negative - * values when rewinding time. - */ -function newerSwitches() -{ -	if (nmsData.switches.time == undefined || nms.switches_then.time == undefined) -		return false; -	var now_timestamp = stringToEpoch(nmsData.switches.time); -	var then_timestamp = stringToEpoch(nms.switches_then.time); -	if (now_timestamp == 0 || then_timestamp == 0 || then_timestamp >= now_timestamp) -		return false; -	return true; -} -/* - * Draw a linknet with index i. - * - * XXX: Might have to change the index here to match backend - */ -function drawLinknet(i) -{ -	var c1 = nms.linknet_color[i] && nms.linknet_color[i].c1 ? nms.linknet_color[i].c1 : blue; -	var c2 = nms.linknet_color[i] && nms.linknet_color[i].c2 ? nms.linknet_color[i].c2 : blue; -	if (nmsData.switches.switches[nmsData.switches.linknets[i].sysname1] && nmsData.switches.switches[nmsData.switches.linknets[i].sysname2]) { -		connectSwitches(nmsData.switches.linknets[i].sysname1,nmsData.switches.linknets[i].sysname2, c1, c2); -	} -} - -/* - * Draw all linknets - */ -function drawLinknets() -{ -	if (nmsData.switches && nmsData.switches.linknets) { -		for (var i in nmsData.switches.linknets) { -			drawLinknet(i); -		} -	} -} - -/* - * Change both colors of a linknet. - * - * XXX: Probably have to change this to better match the backend data - */ -function setLinknetColors(i,c1,c2) -{ -	if (!nms.linknet_color[i] ||  - 	     nms.linknet_color[i].c1 != c1 || -	     nms.linknet_color[i].c2 != c2) { -		if (!nms.linknet_color[i]) -			nms.linknet_color[i] = {}; -		nms.linknet_color[i]['c1'] = c1; -		nms.linknet_color[i]['c2'] = c2; -		drawLinknet(i); -	} -} - -function drawSwitchInfo() -{ -	if (!nmsData.switches || !nmsData.switches.switches) -		return; -	for (var sw in nms.switchInfo) { -		switchInfoText(sw, nms.switchInfo[sw]); -	} -	nms.drawn = true; -} - -/* - * Draw current time-window - * - * FIXME: The math here is just wild approximation and guesswork because - * I'm lazy. - */ -function drawNow() -{ -	if (!nmsData.switches) -		return; -	// XXX: Get rid of microseconds that we get from the backend. -	var now = /^[^.]*/.exec(nmsData.switches.time); -	dr.top.ctx.font = Math.round(2 * nms.fontSize * canvas.scale) + "px " + nms.fontFace; -	dr.top.ctx.clearRect(0,0,Math.floor(800 * canvas.scale),Math.floor(100 * canvas.scale)); -	dr.top.ctx.fillStyle = "white"; -	dr.top.ctx.strokeStyle = "black"; -	dr.top.ctx.lineWidth = Math.floor(nms.fontLineFactor * canvas.scale); -	if (dr.top.ctx.lineWidth == 0) { -		dr.top.ctx.lineWidth = Math.round(nms.fontLineFactor * canvas.scale); -	} -	dr.top.ctx.strokeText(now, 0 + margin.text, 25 * canvas.scale); -	dr.top.ctx.fillText(now, 0 + margin.text, 25 * canvas.scale); -} -/* - * Draw foreground/scene. - * - * FIXME: Review this! This was made before linknets and switches were - * split apart. - * - * This is used so linknets are drawn before switches. If a switch is all - * that has changed, we just need to re-draw that, but linknets require - * scene-redrawing. - */ -function drawScene() -{ -	//dr.text.ctx.font = Math.floor(nms.fontSize * canvas.scale) + "px " + nms.fontFace; -	dr.textInfo.ctx.font = Math.floor(nms.fontSize * canvas.scale) + "px " + nms.fontFace; -	drawLinknets(); -	drawSwitchInfo(); -}  /*   * Returns true if the coordinates (x,y) is inside the box defined by @@ -843,9 +582,8 @@ function canvasClick(e)  /*   * Set night mode to whatever 'toggle' is. - *  - * XXX: setScale() is a bit of a hack, but it really is the same stuff we - * need to do: Redraw "everything" (not really). + * + * Changes background and nav-bar, then leaves the rest to nmsMap.   */  function setNightMode(toggle) {  	nms.nightMode = toggle; @@ -861,30 +599,16 @@ function setNightMode(toggle) {  }  /* - * Draw the blur for a box. - */ -function drawBoxBlur(x,y,boxw,boxh) -{ -	var myX = Math.floor(x * canvas.scale); -	var myY = Math.floor(y * canvas.scale); -	var myX2 = Math.floor((boxw) * canvas.scale); -	var myY2 = Math.floor((boxh) * canvas.scale); -	dr.blur.ctx.fillRect(myX,myY, myX2, myY2); -} - -/*   * Boot up "fully fledged" NMS.   * - * If you only want parts of the functionality, then re-implement this - * (e.g., just add and start the handlers you want, don't worry about - * drawing, etc). + * This can be re-written to provide different looks and feels but using + * the same framework. Or rather: that's the goal. We're not quite there + * yet.   */  function initNMS() { -	  	nms.timers.playback = new nmsTimer(nms.playback.tick, 1000, "Playback ticker", "Handler used to advance time");  	// Public -	  	nmsData.registerSource("ping", "/api/public/ping");  	nmsData.registerSource("switches","/api/public/switches");  	nmsData.registerSource("switchstate","/api/public/switch-state"); @@ -1033,39 +757,32 @@ function restoreSettings()  		nms[v] = retrieve[v];  	}  	setMenu(); -	setNightMode(nms.nightMode); -} - -function forgetSettings() -{ -	document.cookie = 'nms=' + btoa('{}');  }  /*   * Time travel gui   */ -var datepicker;  function startNowPicker(now) { -  $.datetimepicker.setLocale('no'); -  $('#nowPicker').datetimepicker('destroy'); -  if(!now && nms.now) -    now = nms.now; -  datepicker = $('#nowPicker').datetimepicker({ -    value: now, -    mask:false, -    inline:true, -    todayButton: false, -    validateOnBlur:false, -    dayOfWeekStart:1, -    maxDate:'+1970/01/01', -    onSelectDate: function(ct,$i){ -      document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000); -    }, -    onSelectTime: function(ct,$i){ -      document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000); -    }, -    onGenerate: function(ct,$i){ -      document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000); -    } -  }); +	$.datetimepicker.setLocale('no'); +	$('#nowPicker').datetimepicker('destroy'); +	if(!now && nms.now) +		now = nms.now; +	var datepicker = $('#nowPicker').datetimepicker({ +		value: now, +		mask:false, +		inline:true, +		todayButton: false, +		validateOnBlur:false, +		dayOfWeekStart:1, +		maxDate:'+1970/01/01', +		onSelectDate: function(ct,$i){ +			document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000); +		}, +		onSelectTime: function(ct,$i){ +			document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000); +		}, +		onGenerate: function(ct,$i){ +			document.getElementById('nowPicker').dataset.iso = localEpochToString(ct.valueOf()/1000); +		} +	});  }  | 
