diff --git a/README.md b/README.md index 4ff1959..424b63a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Install npm and Sass with your package-manager. On Debian-like systems run: or if you have bundler you can install ruby-sass simply via `bundle install` +On Mac you have to install only npm via brew and sass + + /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + brew install node + sudo gem install sass + Execute these commands on your server as a normal user to prepare the dependencies: git clone https://github.com/plumpudding/hopglass diff --git a/lib/infobox/location.js b/lib/infobox/location.js new file mode 100644 index 0000000..216a6e5 --- /dev/null +++ b/lib/infobox/location.js @@ -0,0 +1,92 @@ +define(function () { + return function (config, el, router, d) { + var h2 = document.createElement("h2") + h2.textContent = "Location: " + d.toString() + el.appendChild(h2) + + getJSON("https://nominatim.openstreetmap.org/reverse?format=json&lat=" + d.lat + "&lon=" + d.lng + "&zoom=18&addressdetail=0") + .then(function(result) { + h2.textContent = result.display_name + }) + + var h3lat = document.createElement("h3") + h3lat.textContent = "Breitengrad" + el.appendChild(h3lat) + var txt1 = document.createElement("textarea") + txt1.id = "location-latitude" + txt1.value = d.lat.toFixed(9) + var p = document.createElement("p") + p.appendChild(txt1) + p.appendChild(createCopyButton(txt1.id)) + el.appendChild(p) + + var h3lng = document.createElement("h3") + h3lng.textContent = "Längengrad" + el.appendChild(h3lng) + var txt2 = document.createElement("textarea") + txt2.id = "location-longitude" + txt2.value = d.lng.toFixed(9) + var p2 = document.createElement("p") + p2.appendChild(txt2) + p2.appendChild(createCopyButton(txt2.id)) + el.appendChild(p2) + + var a1 = document.createElement("a") + a1.textContent = "plain" + a1.onclick = function() { + switch2plain() + return false + } + a1.href = config.siteURL + var a2 = document.createElement("a") + a2.textContent = "uci" + a2.onclick = function() { + switch2uci() + return false + } + a2.href = config.siteURL + + var p3 = document.createElement("p") + p3.textContent = "Du kannst zwischen " + p3.appendChild(a1) + var t1 = document.createTextNode(" und ") + p3.appendChild(t1) + p3.appendChild(a2) + var t2 = document.createTextNode(" wechseln.") + p3.appendChild(t2) + el.appendChild(p3) + + function createCopyButton(id) { + var btn = document.createElement("button") + btn.className = "ion-ios-copy" + btn.title = "Kopiere" + btn.onclick = function() { + copy2clip(id) + } + return btn + } + function copy2clip(id) { + var copyTextarea = document.querySelector("#" + id) + copyTextarea.select() + try { + var successful = document.execCommand("copy") + var msg = successful ? "successful" : "unsuccessful" + console.log("Copying text command was " + msg) + } catch (err) { + console.log("Oops, unable to copy") + } + } + function switch2plain() { + var box1 = document.getElementById("location-latitude") + box1.value = d.lat.toFixed(9) + var box2 = document.getElementById("location-longitude") + box2.value = d.lng.toFixed(9) + } + function switch2uci() { + var box1 = document.getElementById("location-latitude") + box1.value = "uci set gluon-node-info.@location[0].latitude='" + d.lat.toFixed(9) + "'" + var box2 = document.getElementById("location-longitude") + box2.value = "uci set gluon-node-info.@location[0].longitude='" + d.lng.toFixed(9) + "'" + } + } +}) diff --git a/lib/infobox/main.js b/lib/infobox/main.js index 14590a0..70b6a6e 100644 --- a/lib/infobox/main.js +++ b/lib/infobox/main.js @@ -1,4 +1,4 @@ -define(["infobox/link", "infobox/node"], function (Link, Node) { +define(["infobox/link", "infobox/node", "infobox/location"], function (Link, Node, Location) { return function (config, sidebar, router) { var self = this var el @@ -41,6 +41,12 @@ define(["infobox/link", "infobox/node"], function (Link, Node) { new Link(config, el, router, d) } + self.gotoLocation = function (d) { + console.log("goto location called with ", d) + create() + new Location(config, el, router, d) + } + return self } }) diff --git a/lib/infobox/node.js b/lib/infobox/node.js index 98e7dff..508bb26 100644 --- a/lib/infobox/node.js +++ b/lib/infobox/node.js @@ -39,7 +39,7 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], function showStatus(d) { return function (el) { el.classList.add(d.flags.online ? "online" : "offline") - el.textContent = d.flags.online ? "online" : "offline, " + d.lastseen.fromNow(true) + el.textContent = d.flags.online ? "online" : "offline, " + d.lastseen.fromNow(true) + " " + d.lastseen.format("(DD.MM.YYYY, H:mm:ss)") } } @@ -134,6 +134,40 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], return span } + function showLoadBar(className, v) { + var span = document.createElement("span") + span.classList.add("bar") + span.classList.add(className) + + var bar = document.createElement("span") + if (v >= 1) { + bar.style.width = ((v * 100) % 100) + "%" + bar.style.background = "rgba(255, 50, 50, 0.9)" + span.style.background = "rgba(255, 50, 50, 0.6)" + span.appendChild(bar) + } + else + { + bar.style.width = (v * 100) + "%" + span.appendChild(bar) + } + + var label = document.createElement("label") + label.textContent = (v) + span.appendChild(label) + + return span + } + + function showLOAD(d) { + if (!("loadavg" in d.statistics)) + return undefined + + return function (el) { + el.appendChild(showLoadBar("load-avg", d.statistics.loadavg)) + } + } + function showRAM(d) { if (!("memory_usage" in d.statistics)) return undefined @@ -143,6 +177,37 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], } } + function showPages(d) { + var webpages = dictGet(d.nodeinfo, ["pages"]) + if (webpages === null) + return undefined + + webpages.sort() + + return function (el) { + webpages.forEach( function (webpage, i) { + if (i > 0) + el.appendChild(document.createElement("br")) + + var a = document.createElement("span") + var link = document.createElement("a") + link.href = webpage + if (webpage.search(/^https:\/\//i) !== -1) { + var lock = document.createElement("span") + lock.className = "ion-android-lock" + a.appendChild(lock) + var t1 = document.createTextNode(" ") + a.appendChild(t1) + link.textContent = webpage.replace(/^https:\/\//i, "") + } + else + link.textContent = webpage.replace(/^http:\/\//i, "") + a.appendChild(link) + el.appendChild(a) + }) + } + } + function showAutoupdate(d) { var au = dictGet(d.nodeinfo, ["software", "autoupdater"]) if (!au) @@ -206,8 +271,10 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], attributeEntry(attributes, "Site", showSite(d, config)) attributeEntry(attributes, "Uptime", showUptime(d)) attributeEntry(attributes, "Teil des Netzes", showFirstseen(d)) + attributeEntry(attributes, "Load - avg", showLOAD(d)) attributeEntry(attributes, "Arbeitsspeicher", showRAM(d)) attributeEntry(attributes, "IP Adressen", showIPs(d)) + attributeEntry(attributes, "Webseite", showPages(d)) attributeEntry(attributes, "Gewähltes Gateway", dictGet(d.statistics, ["gateway"])) attributeEntry(attributes, "Autom. Updates", showAutoupdate(d)) attributeEntry(attributes, "Clients", showClients(d)) diff --git a/lib/map.js b/lib/map.js index f3e18d2..d9c9f3c 100644 --- a/lib/map.js +++ b/lib/map.js @@ -20,7 +20,9 @@ define(["map/clientlayer", "map/labelslayer", var button = L.DomUtil.create("button", "add-layer") button.textContent = "" - L.DomEvent.disableClickPropagation(button) + // L.DomEvent.disableClickPropagation(button) + // Click propagation isn't disabled as this causes problems with the + // location picking mode; instead propagation is stopped in onClick(). L.DomEvent.addListener(button, "click", this.f, this) this.button = button @@ -233,7 +235,7 @@ define(["map/clientlayer", "map/labelslayer", } function showCoordinates(e) { - window.prompt("Koordinaten (Lat, Lng)", e.latlng.lat.toFixed(6) + ", " + e.latlng.lng.toFixed(6)) + window.prompt("Koordinaten (Lat, Lng)", e.latlng.lat.toFixed(9) + ", " + e.latlng.lng.toFixed(9)) disableCoords() } @@ -271,6 +273,11 @@ define(["map/clientlayer", "map/labelslayer", } } + function contextMenuGotoLocation(e) { + console.log("context menu called at ", e) + router.gotoLocation(e.latlng) + } + var el = document.createElement("div") el.classList.add("map") @@ -292,6 +299,7 @@ define(["map/clientlayer", "map/labelslayer", map.on("locationfound", locationFound) map.on("locationerror", locationError) map.on("dragend", saveView) + map.on("contextmenu", contextMenuGotoLocation) addButton(locateUserButton) addButton(showCoordsPickerButton) @@ -498,6 +506,10 @@ define(["map/clientlayer", "map/labelslayer", updateView() } + self.gotoLocation = function () { + //ignore + } + self.destroy = function () { clearButtons() map.remove() diff --git a/lib/router.js b/lib/router.js index 51b9e0e..7aa6aae 100644 --- a/lib/router.js +++ b/lib/router.js @@ -62,6 +62,18 @@ define(function () { return true } + function gotoLocation(d) { + if (!d) + return false + + targets.forEach( function (t) { + if(!t.gotoLocation)console.warn("has no gotoLocation", t) + t.gotoLocation(d) + }) + + return true + } + function loadState(s) { if (!s) return false @@ -162,6 +174,8 @@ define(function () { } } + self.gotoLocation = gotoLocation + self.reset = function () { resetView() } diff --git a/lib/title.js b/lib/title.js index d285cbe..372dd75 100644 --- a/lib/title.js +++ b/lib/title.js @@ -23,6 +23,10 @@ define(function () { setTitle(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname) } + this.gotoLocation = function() { + //ignore + } + this.destroy = function () { }