commit
91f39ef841
|
@ -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`
|
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:
|
Execute these commands on your server as a normal user to prepare the dependencies:
|
||||||
|
|
||||||
git clone https://github.com/plumpudding/hopglass
|
git clone https://github.com/plumpudding/hopglass
|
||||||
|
|
92
lib/infobox/location.js
Normal file
92
lib/infobox/location.js
Normal file
|
@ -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) + "'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -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) {
|
return function (config, sidebar, router) {
|
||||||
var self = this
|
var self = this
|
||||||
var el
|
var el
|
||||||
|
@ -41,6 +41,12 @@ define(["infobox/link", "infobox/node"], function (Link, Node) {
|
||||||
new Link(config, el, router, d)
|
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
|
return self
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -39,7 +39,7 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
||||||
function showStatus(d) {
|
function showStatus(d) {
|
||||||
return function (el) {
|
return function (el) {
|
||||||
el.classList.add(d.flags.online ? "online" : "offline")
|
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
|
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) {
|
function showRAM(d) {
|
||||||
if (!("memory_usage" in d.statistics))
|
if (!("memory_usage" in d.statistics))
|
||||||
return undefined
|
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) {
|
function showAutoupdate(d) {
|
||||||
var au = dictGet(d.nodeinfo, ["software", "autoupdater"])
|
var au = dictGet(d.nodeinfo, ["software", "autoupdater"])
|
||||||
if (!au)
|
if (!au)
|
||||||
|
@ -206,8 +271,10 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
||||||
attributeEntry(attributes, "Site", showSite(d, config))
|
attributeEntry(attributes, "Site", showSite(d, config))
|
||||||
attributeEntry(attributes, "Uptime", showUptime(d))
|
attributeEntry(attributes, "Uptime", showUptime(d))
|
||||||
attributeEntry(attributes, "Teil des Netzes", showFirstseen(d))
|
attributeEntry(attributes, "Teil des Netzes", showFirstseen(d))
|
||||||
|
attributeEntry(attributes, "Load - avg", showLOAD(d))
|
||||||
attributeEntry(attributes, "Arbeitsspeicher", showRAM(d))
|
attributeEntry(attributes, "Arbeitsspeicher", showRAM(d))
|
||||||
attributeEntry(attributes, "IP Adressen", showIPs(d))
|
attributeEntry(attributes, "IP Adressen", showIPs(d))
|
||||||
|
attributeEntry(attributes, "Webseite", showPages(d))
|
||||||
attributeEntry(attributes, "Gewähltes Gateway", dictGet(d.statistics, ["gateway"]))
|
attributeEntry(attributes, "Gewähltes Gateway", dictGet(d.statistics, ["gateway"]))
|
||||||
attributeEntry(attributes, "Autom. Updates", showAutoupdate(d))
|
attributeEntry(attributes, "Autom. Updates", showAutoupdate(d))
|
||||||
attributeEntry(attributes, "Clients", showClients(d))
|
attributeEntry(attributes, "Clients", showClients(d))
|
||||||
|
|
16
lib/map.js
16
lib/map.js
|
@ -20,7 +20,9 @@ define(["map/clientlayer", "map/labelslayer",
|
||||||
var button = L.DomUtil.create("button", "add-layer")
|
var button = L.DomUtil.create("button", "add-layer")
|
||||||
button.textContent = ""
|
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)
|
L.DomEvent.addListener(button, "click", this.f, this)
|
||||||
|
|
||||||
this.button = button
|
this.button = button
|
||||||
|
@ -233,7 +235,7 @@ define(["map/clientlayer", "map/labelslayer",
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCoordinates(e) {
|
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()
|
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")
|
var el = document.createElement("div")
|
||||||
el.classList.add("map")
|
el.classList.add("map")
|
||||||
|
|
||||||
|
@ -292,6 +299,7 @@ define(["map/clientlayer", "map/labelslayer",
|
||||||
map.on("locationfound", locationFound)
|
map.on("locationfound", locationFound)
|
||||||
map.on("locationerror", locationError)
|
map.on("locationerror", locationError)
|
||||||
map.on("dragend", saveView)
|
map.on("dragend", saveView)
|
||||||
|
map.on("contextmenu", contextMenuGotoLocation)
|
||||||
|
|
||||||
addButton(locateUserButton)
|
addButton(locateUserButton)
|
||||||
addButton(showCoordsPickerButton)
|
addButton(showCoordsPickerButton)
|
||||||
|
@ -498,6 +506,10 @@ define(["map/clientlayer", "map/labelslayer",
|
||||||
updateView()
|
updateView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.gotoLocation = function () {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
|
||||||
self.destroy = function () {
|
self.destroy = function () {
|
||||||
clearButtons()
|
clearButtons()
|
||||||
map.remove()
|
map.remove()
|
||||||
|
|
|
@ -62,6 +62,18 @@ define(function () {
|
||||||
return true
|
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) {
|
function loadState(s) {
|
||||||
if (!s)
|
if (!s)
|
||||||
return false
|
return false
|
||||||
|
@ -162,6 +174,8 @@ define(function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.gotoLocation = gotoLocation
|
||||||
|
|
||||||
self.reset = function () {
|
self.reset = function () {
|
||||||
resetView()
|
resetView()
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@ define(function () {
|
||||||
setTitle(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname)
|
setTitle(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.gotoLocation = function() {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
|
||||||
this.destroy = function () {
|
this.destroy = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue