mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-06-16 14:15:07 +03:00
360 lines
11 KiB
JavaScript
360 lines
11 KiB
JavaScript
var $ = id => document.getElementById(id)
|
|
var $$ = clazz => document.getElementsByClassName(clazz)
|
|
|
|
function setPingValue(peer, value) {
|
|
var cellText;
|
|
var peerCell = $(peer);
|
|
if (!peerCell) return;
|
|
var peerTable = $("peer_list");
|
|
if (value === "-1") {
|
|
var peerAddress = $("label_" + peer);
|
|
peerAddress.style.color = "rgba(250,250,250,.5)";
|
|
} else {
|
|
|
|
cellText = document.createTextNode(value);
|
|
peerCell.appendChild(cellText);
|
|
|
|
var peerCellTime = $("time_" + peer);
|
|
var cellTextTime = document.createTextNode("ms");
|
|
peerCellTime.appendChild(cellTextTime);
|
|
}
|
|
peerCell.parentNode.classList.remove("is-hidden");
|
|
//sort table
|
|
moveRowToOrderPos(peerTable, 2, peerCell.parentNode)
|
|
}
|
|
|
|
function cmpTime(a, b) {
|
|
return a.textContent.trim() === "" ? 1 : (a.textContent.trim() // using `.textContent.trim()` for test
|
|
.localeCompare(b.textContent.trim(), 'en', { numeric: true }))
|
|
}
|
|
|
|
function moveRowToOrderPos(table, col, row) {
|
|
var tb = table.tBodies[0], tr = tb.rows;
|
|
var i = 0;
|
|
for (; i < tr.length && cmpTime(row.cells[col], tr[i].cells[col]) >= 0; ++i);
|
|
if (i < tr.length && i != row.rowIndex) {
|
|
tb.deleteRow(row.rowIndex);
|
|
tb.insertBefore(row, tr[i]);
|
|
}
|
|
}
|
|
|
|
function openTab(element, tabName) {
|
|
// Declare all variables
|
|
var i, tabContent, tabLinks;
|
|
|
|
// Get all elements with class="content" and hide them
|
|
tabContent = $$("tab here");
|
|
for (i = 0; i < tabContent.length; i++) {
|
|
tabContent[i].className = "tab here is-hidden";
|
|
}
|
|
|
|
// Get all elements with class="tab" and remove the class "is-active"
|
|
tabLinks = $$("tab is-active");
|
|
for (i = 0; i < tabLinks.length; i++) {
|
|
tabLinks[i].className = "tab";
|
|
}
|
|
|
|
// Show the current tab, and add an "is-active" class to the button that opened the tab
|
|
$(tabName).className = "tab here";
|
|
element.parentElement.className = "tab is-active";
|
|
//refreshRecordsList();
|
|
}
|
|
|
|
function copy2clipboard(text) {
|
|
var textArea = document.createElement("textarea");
|
|
textArea.style.position = 'fixed';
|
|
textArea.style.top = 0;
|
|
textArea.style.left = 0;
|
|
|
|
// Ensure it has a small width and height. Setting to 1px / 1em
|
|
// doesn't work as this gives a negative w/h on some browsers.
|
|
textArea.style.width = '2em';
|
|
textArea.style.height = '2em';
|
|
|
|
// We don't need padding, reducing the size if it does flash render.
|
|
textArea.style.padding = 0;
|
|
|
|
// Clean up any borders.
|
|
textArea.style.border = 'none';
|
|
textArea.style.outline = 'none';
|
|
textArea.style.boxShadow = 'none';
|
|
|
|
// Avoid flash of the white box if rendered for any reason.
|
|
textArea.style.background = 'transparent';
|
|
textArea.value = text;
|
|
|
|
document.body.appendChild(textArea);
|
|
textArea.focus();
|
|
textArea.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');
|
|
}
|
|
document.body.removeChild(textArea);
|
|
showInfo('value copied successfully!');
|
|
}
|
|
|
|
function showInfo(text) {
|
|
var info = $("notification_info");
|
|
var message = $("info_text");
|
|
message.innerHTML = text;
|
|
|
|
info.className = "notification is-primary";
|
|
var button = $("info_close");
|
|
button.onclick = function () {
|
|
message.value = "";
|
|
info.className = "notification is-primary is-hidden";
|
|
};
|
|
setTimeout(button.onclick, 2000);
|
|
}
|
|
|
|
function showWindow(text) {
|
|
var info = $("notification_window");
|
|
var message = $("info_window");
|
|
message.innerHTML = text;
|
|
|
|
info.classList.remove("is-hidden");
|
|
var button_info_close = $("info_win_close");
|
|
button_info_close.onclick = function () {
|
|
message.value = "";
|
|
info.classList.add("is-hidden");
|
|
$("peer_list").remove();
|
|
};
|
|
var button_window_close = $("window_close");
|
|
button_window_close.onclick = function () {
|
|
message.value = "";
|
|
info.classList.add("is-hidden");
|
|
$("peer_list").remove();
|
|
};
|
|
var button_window_save = $("window_save");
|
|
button_window_save.onclick = function () {
|
|
message.value = "";
|
|
info.classList.add("is-hidden");
|
|
//todo save peers
|
|
var peers = document.querySelectorAll('*[id^="peer-"]');
|
|
var peer_list = [];
|
|
for (i = 0; i < peers.length; ++i) {
|
|
var p = peers[i];
|
|
if (p.checked) {
|
|
var peerURL = p.parentElement.parentElement.children[1].innerText;
|
|
peer_list.push(peerURL);
|
|
}
|
|
}
|
|
fetch('api/peers', {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Riv-Save-Config': 'true',
|
|
},
|
|
body: JSON.stringify(peer_list),
|
|
})
|
|
.catch((error) => {
|
|
console.error('Error:', error);
|
|
});
|
|
$("peer_list").remove();
|
|
};
|
|
}
|
|
|
|
function add_table(peerList) {
|
|
|
|
var peers = [];
|
|
//const countries = Object.keys(peerList);
|
|
// get the reference for the body
|
|
var body = document.createElement("div");
|
|
// creates a <table> element and a <tbody> element
|
|
var tbl = document.createElement("table");
|
|
tbl.setAttribute('id', "peer_list");
|
|
//tbl.setAttribute('cellpadding', '10');
|
|
var tblBody = document.createElement("tbody");
|
|
|
|
// creating all cells
|
|
for (var c in peerList) {
|
|
let counter = 1;
|
|
for (let peer in peerList[c]) {
|
|
peers.push(peer);
|
|
// creates a table row
|
|
var row = document.createElement("tr");
|
|
row.className = "is-hidden";
|
|
var imgElement = document.createElement("td");
|
|
imgElement.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer);
|
|
var peerAddress = document.createElement("td");
|
|
var cellText = document.createTextNode(peer);
|
|
peerAddress.appendChild(cellText);
|
|
peerAddress.setAttribute('id', "label_" + peer);
|
|
var peerPing = document.createElement("td");
|
|
peerPing.setAttribute('id', peer);
|
|
var peerPingTime = document.createElement("td");
|
|
peerPingTime.setAttribute('id', "time_" + peer);
|
|
var peerSelect = document.createElement("td");
|
|
var chk = document.createElement('input');
|
|
chk.setAttribute('type', 'checkbox');
|
|
chk.setAttribute('id', "peer-" + counter);
|
|
peerSelect.appendChild(chk);
|
|
|
|
row.appendChild(imgElement);
|
|
row.appendChild(peerAddress);
|
|
row.appendChild(peerPing);
|
|
row.appendChild(peerPingTime);
|
|
row.appendChild(peerSelect);
|
|
tblBody.appendChild(row);
|
|
}
|
|
}
|
|
// put the <tbody> in the <table>
|
|
tbl.appendChild(tblBody);
|
|
// appends <table> into <body>
|
|
body.appendChild(tbl);
|
|
// sets the border attribute of tbl to 2;
|
|
//tbl.setAttribute("border", "0");
|
|
showWindow(body.innerHTML);
|
|
return peers;
|
|
}
|
|
|
|
function togglePrivKeyVisibility() {
|
|
if (this.classList.contains("fa-eye")) {
|
|
this.classList.remove("fa-eye");
|
|
this.classList.add("fa-eye-slash");
|
|
$("priv_key_visible").innerHTML = $("priv_key").innerHTML;
|
|
} else {
|
|
this.classList.remove("fa-eye-slash");
|
|
this.classList.add("fa-eye");
|
|
$("priv_key_visible").innerHTML = "••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••";
|
|
}
|
|
}
|
|
|
|
|
|
var ui = {
|
|
countries: []
|
|
};
|
|
|
|
ui.getAllPeers = () => {
|
|
if(! ("_allPeersPromise" in ui)) {
|
|
ui._allPeersPromise = new Promise((resolve, reject) => {
|
|
if("_allPeers" in ui) resolve(ui._allPeers);
|
|
else fetch('https://map.rivchain.org/rest/peers.json')
|
|
.then((response) => response.json())
|
|
.then((data) => {
|
|
// add country code to each peer
|
|
for (var c in data) {
|
|
let country = c.slice(0, -3);
|
|
let filtered = ui.countries.find((entry) => entry.name.toLowerCase() == country);
|
|
//let flagFile = filtered ? filtered["flag_4x3"] : "";
|
|
let flagCode = filtered ? filtered["code"] : "";
|
|
for (let peer in data[c]) {
|
|
data[c][peer].countryCode = flagCode;
|
|
}
|
|
}
|
|
ui._allPeers = data;
|
|
resolve(ui._allPeers);
|
|
})
|
|
.catch(reject);
|
|
}).finally(() => delete ui._allPeersPromise);
|
|
}
|
|
return ui._allPeersPromise;
|
|
};
|
|
|
|
ui.showAllPeers = () =>
|
|
ui.getAllPeers()
|
|
.then((peerList) => {
|
|
var peers = add_table(peerList);
|
|
//start peers test
|
|
fetch('api/ping', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(peers)
|
|
})
|
|
.catch((error) => {
|
|
console.error('Error:', error);
|
|
});
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
|
|
|
|
ui.getConnectedPeers = () =>
|
|
fetch('api/peers')
|
|
.then((response) => response.json())
|
|
|
|
ui.updateConnectedPeersHandler = (cont) => {
|
|
$("peers").innerText = "";
|
|
const regexStrip = /%[^\]]*/gm;
|
|
const regexMulticast = /:\/\/\[fe80::/;
|
|
const sorted = cont.peers.map(peer => ({"url": peer["remote"], "isMulticast": peer["remote"].match(regexMulticast)}))
|
|
.sort((a, b) => a.isMulticast > b.isMulticast);
|
|
sorted.forEach(peer => {
|
|
let row = $("peers").appendChild(document.createElement('div'));
|
|
row.className = "overflow-ellipsis"
|
|
let flag = row.appendChild(document.createElement("span"));
|
|
if(peer.isMulticast)
|
|
flag.className = "fa fa-thin fa-share-nodes peer-connected-fl";
|
|
else
|
|
flag.className = "fi fi-" + ui.lookupCountryCodeByAddress(peer.url) + " peer-connected-fl";
|
|
row.append(peer.url.replace(regexStrip, ""));
|
|
});
|
|
}
|
|
|
|
ui.updateConnectedPeers = () =>
|
|
ui.getConnectedPeers()
|
|
.then(ui.updateConnectedPeersHandler)
|
|
.catch((error) => {
|
|
$("peers").innerText = error.message;
|
|
});
|
|
|
|
ui.lookupCountryCodeByAddress = (address) => {
|
|
for (var c in ui._allPeers)
|
|
for (let peer in ui._allPeers[c])
|
|
if(peer == address)
|
|
return ui._allPeers[c][peer].countryCode;
|
|
}
|
|
|
|
ui.getSelfInfo = () =>
|
|
fetch('api/self')
|
|
.then((response) => response.json())
|
|
|
|
ui.updateSelfInfo = () =>
|
|
ui.getSelfInfo()
|
|
.then((info) => {
|
|
$("ipv6").innerText = info.address;
|
|
$("subnet").innerText = info.subnet;
|
|
$("pub_key").innerText = info.key;
|
|
$("priv_key").innerText = info.private_key;
|
|
$("ipv6").innerText = info.address;
|
|
$("version").innerText = info.build_version;
|
|
}).catch((error) => {
|
|
$("ipv6").innerText = error.message;
|
|
});
|
|
|
|
ui.sse = new EventSource('/api/sse');
|
|
|
|
function main() {
|
|
|
|
fetch('country.json')
|
|
.then((response) => response.json())
|
|
.then((data) => { ui.countries = data });
|
|
|
|
window.addEventListener("load", () => {
|
|
$("showAllPeersBtn").addEventListener("click", ui.showAllPeers);
|
|
|
|
ui.getAllPeers().then(() => ui.updateConnectedPeers());
|
|
setInterval(ui.updateConnectedPeers, 5000);
|
|
|
|
ui.updateSelfInfo();
|
|
//setInterval(ui.updateSelfInfo, 5000);
|
|
|
|
ui.sse.addEventListener("ping", (e) => {
|
|
let data = JSON.parse(e.data);
|
|
setPingValue(data.peer, data.value);
|
|
})
|
|
|
|
ui.sse.addEventListener("peers", (e) => {
|
|
ui.updateConnectedPeersHandler(JSON.parse(e.data));
|
|
})
|
|
|
|
});
|
|
}
|
|
|
|
main();
|