mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-06 16:00:28 +01:00
Added line graph using chart.js & Improving websocket.
Added line graph to show total receive & total sent changes per refresh interval, using chart.js line chart to show the changes. Switching configuration don't need to refresh anymore, by using websocket.
This commit is contained in:
parent
264a050360
commit
8fe8209580
115
src/dashboard.py
115
src/dashboard.py
@ -120,7 +120,7 @@ def get_conf_running_peer_number(config_name):
|
|||||||
data_usage = subprocess.check_output(f"wg show {config_name} latest-handshakes",
|
data_usage = subprocess.check_output(f"wg show {config_name} latest-handshakes",
|
||||||
shell=True, stderr=subprocess.STDOUT)
|
shell=True, stderr=subprocess.STDOUT)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return "stopped"
|
return 0
|
||||||
data_usage = data_usage.decode("UTF-8").split()
|
data_usage = data_usage.decode("UTF-8").split()
|
||||||
count = 0
|
count = 0
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
@ -143,16 +143,19 @@ def read_conf_file_interface(config_name):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
conf_location = WG_CONF_PATH + "/" + config_name + ".conf"
|
conf_location = WG_CONF_PATH + "/" + config_name + ".conf"
|
||||||
with open(conf_location, 'r', encoding='utf-8') as file_object:
|
try:
|
||||||
file = file_object.read().split("\n")
|
with open(conf_location, 'r', encoding='utf-8') as file_object:
|
||||||
data = {}
|
file = file_object.read().split("\n")
|
||||||
for i in file:
|
data = {}
|
||||||
if not regex_match("#(.*)", i):
|
for i in file:
|
||||||
if len(i) > 0:
|
if not regex_match("#(.*)", i):
|
||||||
if i != "[Interface]":
|
if len(i) > 0:
|
||||||
tmp = re.split(r'\s*=\s*', i, 1)
|
if i != "[Interface]":
|
||||||
if len(tmp) == 2:
|
tmp = re.split(r'\s*=\s*', i, 1)
|
||||||
data[tmp[0]] = tmp[1]
|
if len(tmp) == 2:
|
||||||
|
data[tmp[0]] = tmp[1]
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
return {}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@ -1013,49 +1016,59 @@ def get_conf(data):
|
|||||||
@type config_name: str
|
@type config_name: str
|
||||||
@return: TODO
|
@return: TODO
|
||||||
"""
|
"""
|
||||||
|
result = {
|
||||||
|
"status": True,
|
||||||
|
"message": "",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
if not session:
|
||||||
|
result["status"] = False
|
||||||
|
result["message"] = "Oops! <br> You're not signed in. Please refresh your page."
|
||||||
|
socketio.emit("get_config", result, json=True)
|
||||||
|
return
|
||||||
|
|
||||||
if getattr(g, 'db', None) is None:
|
if getattr(g, 'db', None) is None:
|
||||||
g.db = connect_db()
|
g.db = connect_db()
|
||||||
g.cur = g.db.cursor()
|
g.cur = g.db.cursor()
|
||||||
print(data)
|
|
||||||
config_name = data['config']
|
config_name = data['config']
|
||||||
print(config_name)
|
|
||||||
|
|
||||||
config_interface = read_conf_file_interface(config_name)
|
config_interface = read_conf_file_interface(config_name)
|
||||||
search = data['search']
|
|
||||||
print(search)
|
if config_interface != {}:
|
||||||
# search = request.args.get('search')
|
search = data['search']
|
||||||
if len(search) == 0:
|
if len(search) == 0:
|
||||||
search = ""
|
search = ""
|
||||||
search = urllib.parse.unquote(search)
|
search = urllib.parse.unquote(search)
|
||||||
config = get_dashboard_conf()
|
config = get_dashboard_conf()
|
||||||
sort = config.get("Server", "dashboard_sort")
|
sort = config.get("Server", "dashboard_sort")
|
||||||
peer_display_mode = config.get("Peers", "peer_display_mode")
|
peer_display_mode = config.get("Peers", "peer_display_mode")
|
||||||
wg_ip = config.get("Peers", "remote_endpoint")
|
wg_ip = config.get("Peers", "remote_endpoint")
|
||||||
if "Address" not in config_interface:
|
if "Address" not in config_interface:
|
||||||
conf_address = "N/A"
|
conf_address = "N/A"
|
||||||
|
else:
|
||||||
|
conf_address = config_interface['Address']
|
||||||
|
result['data'] = {
|
||||||
|
"peer_data": get_peers(config_name, search, sort),
|
||||||
|
"name": config_name,
|
||||||
|
"status": get_conf_status(config_name),
|
||||||
|
"total_data_usage": get_conf_total_data(config_name),
|
||||||
|
"public_key": get_conf_pub_key(config_name),
|
||||||
|
"listen_port": get_conf_listen_port(config_name),
|
||||||
|
"running_peer": get_conf_running_peer_number(config_name),
|
||||||
|
"conf_address": conf_address,
|
||||||
|
"wg_ip": wg_ip,
|
||||||
|
"sort_tag": sort,
|
||||||
|
"dashboard_refresh_interval": int(config.get("Server", "dashboard_refresh_interval")),
|
||||||
|
"peer_display_mode": peer_display_mode
|
||||||
|
}
|
||||||
|
if result['data']['status'] == "stopped":
|
||||||
|
result['data']['checked'] = "nope"
|
||||||
|
else:
|
||||||
|
result['data']['checked'] = "checked"
|
||||||
|
config.clear()
|
||||||
else:
|
else:
|
||||||
conf_address = config_interface['Address']
|
result['status'] = False
|
||||||
conf_data = {
|
result['message'] = "I cannot find this configuration. <br> Please refresh and try again"
|
||||||
"peer_data": get_peers(config_name, search, sort),
|
socketio.emit("get_config", result, json=True)
|
||||||
"name": config_name,
|
|
||||||
"status": get_conf_status(config_name),
|
|
||||||
"total_data_usage": get_conf_total_data(config_name),
|
|
||||||
"public_key": get_conf_pub_key(config_name),
|
|
||||||
"listen_port": get_conf_listen_port(config_name),
|
|
||||||
"running_peer": get_conf_running_peer_number(config_name),
|
|
||||||
"conf_address": conf_address,
|
|
||||||
"wg_ip": wg_ip,
|
|
||||||
"sort_tag": sort,
|
|
||||||
"dashboard_refresh_interval": int(config.get("Server", "dashboard_refresh_interval")),
|
|
||||||
"peer_display_mode": peer_display_mode
|
|
||||||
}
|
|
||||||
if conf_data['status'] == "stopped":
|
|
||||||
conf_data['checked'] = "nope"
|
|
||||||
else:
|
|
||||||
conf_data['checked'] = "checked"
|
|
||||||
config.clear()
|
|
||||||
socketio.emit("get_config", conf_data, json=True)
|
|
||||||
# return jsonify(conf_data)
|
|
||||||
|
|
||||||
|
|
||||||
# Turn on / off a configuration
|
# Turn on / off a configuration
|
||||||
@ -1334,7 +1347,11 @@ def get_peer_name(config_name):
|
|||||||
# Return available IPs
|
# Return available IPs
|
||||||
@app.route('/available_ips/<config_name>', methods=['GET'])
|
@app.route('/available_ips/<config_name>', methods=['GET'])
|
||||||
def available_ips(config_name):
|
def available_ips(config_name):
|
||||||
return jsonify(f_available_ips(config_name))
|
result = {"status": True, "message":"", "data": f_available_ips(config_name)}
|
||||||
|
if len(result["data"]) == 0:
|
||||||
|
result['status'] = False
|
||||||
|
result['message'] = f"No more available IP for {config_name}."
|
||||||
|
return jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
# Check if both key match
|
# Check if both key match
|
||||||
|
@ -9,6 +9,10 @@ body {
|
|||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-primary{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sidebar
|
* Sidebar
|
||||||
*/
|
*/
|
||||||
@ -23,12 +27,6 @@ body {
|
|||||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@media (max-width: 767.98px) {*/
|
|
||||||
/* .sidebar {*/
|
|
||||||
/* top: 5rem;*/
|
|
||||||
/* }*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
.sidebar-sticky {
|
.sidebar-sticky {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -369,6 +367,7 @@ main{
|
|||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rotating::before {
|
.rotating::before {
|
||||||
-webkit-animation: rotating 0.75s linear infinite;
|
-webkit-animation: rotating 0.75s linear infinite;
|
||||||
-moz-animation: rotating 0.75s linear infinite;
|
-moz-animation: rotating 0.75s linear infinite;
|
||||||
@ -385,7 +384,7 @@ main{
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#peer_private_key_textbox, #private_key, #public_key{
|
#peer_private_key_textbox, #private_key, #public_key, #peer_preshared_key_textbox{
|
||||||
font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
|
font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,4 +569,32 @@ pre.index-alert{
|
|||||||
|
|
||||||
.peerLightContainer{
|
.peerLightContainer{
|
||||||
text-transform: uppercase; margin: 0; margin-left: auto !important;
|
text-transform: uppercase; margin: 0; margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conf_card .dot, .info .dot {
|
||||||
|
transform: translateX(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#config_body{
|
||||||
|
transition: 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#config_body.firstLoading{
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chartTitle{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chartControl{
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chartTitle h6{
|
||||||
|
margin-bottom: 0;
|
||||||
|
line-height: 1;
|
||||||
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
2
src/static/css/dashboard.min.css
vendored
2
src/static/css/dashboard.min.css
vendored
File diff suppressed because one or more lines are too long
@ -50,6 +50,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let firstLoading = true;
|
||||||
|
$(".nav-conf-link").on("click", function(e){
|
||||||
|
if(socket.connected){
|
||||||
|
e.preventDefault();
|
||||||
|
firstLoading = true;
|
||||||
|
$("#config_body").addClass("firstLoading");
|
||||||
|
|
||||||
|
conf_name = $(this).data("conf-id");
|
||||||
|
configurations.loadPeers($('#search_peer_textbox').val());
|
||||||
|
|
||||||
|
$(".nav-conf-link").removeClass("active");
|
||||||
|
$(`.sb-${conf_name}-url`).addClass("active");
|
||||||
|
|
||||||
|
window.history.pushState(null,null,`/configuration/${conf_name}`);
|
||||||
|
$("title").text(`${conf_name} | WGDashboard`);
|
||||||
|
|
||||||
|
totalDataUsageChartObj.data.labels = [];
|
||||||
|
totalDataUsageChartObj.data.datasets[0].data = [];
|
||||||
|
totalDataUsageChartObj.data.datasets[1].data = [];
|
||||||
|
totalDataUsageChartObj.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse all responded information onto the configuration header
|
* Parse all responded information onto the configuration header
|
||||||
* @param response
|
* @param response
|
||||||
@ -61,6 +84,45 @@
|
|||||||
}else{
|
}else{
|
||||||
$conf_status_btn.innerHTML = `<a href="#" id="${response.name}" ${response.checked} class="switch text-primary"><i class="bi bi-toggle2-off"></i> OFF</a>`;
|
$conf_status_btn.innerHTML = `<a href="#" id="${response.name}" ${response.checked} class="switch text-primary"><i class="bi bi-toggle2-off"></i> OFF</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.running_peer > 0){
|
||||||
|
let d = new Date();
|
||||||
|
let time = d.toLocaleString("en-us",
|
||||||
|
{hour: '2-digit', minute: '2-digit', second: "2-digit", hourCycle: 'h23'});
|
||||||
|
totalDataUsageChartObj.data.labels.push(`${time}`);
|
||||||
|
|
||||||
|
if (totalDataUsageChartObj.data.datasets[0].data.length === 0){
|
||||||
|
totalDataUsageChartObj.data.datasets[1].lastData = response.total_data_usage[2];
|
||||||
|
totalDataUsageChartObj.data.datasets[0].lastData = response.total_data_usage[1];
|
||||||
|
totalDataUsageChartObj.data.datasets[0].data.push(0);
|
||||||
|
totalDataUsageChartObj.data.datasets[1].data.push(0);
|
||||||
|
}else{
|
||||||
|
if (totalDataUsageChartObj.data.datasets[0].data.length === 50 && totalDataUsageChartObj.data.datasets[1].data.length === 50){
|
||||||
|
totalDataUsageChartObj.data.labels.shift();
|
||||||
|
totalDataUsageChartObj.data.datasets[0].data.shift();
|
||||||
|
totalDataUsageChartObj.data.datasets[1].data.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
let newTotalReceive = response.total_data_usage[2] - totalDataUsageChartObj.data.datasets[1].lastData;
|
||||||
|
let newTotalSent = response.total_data_usage[1] - totalDataUsageChartObj.data.datasets[0].lastData;
|
||||||
|
let k = 0;
|
||||||
|
if (chartUnit === "MB"){
|
||||||
|
k = 1024;
|
||||||
|
}
|
||||||
|
else if (chartUnit === "KB"){
|
||||||
|
k = 1048576;
|
||||||
|
}else{
|
||||||
|
k = 1;
|
||||||
|
}
|
||||||
|
totalDataUsageChartObj.data.datasets[1].data.push(newTotalReceive*k);
|
||||||
|
totalDataUsageChartObj.data.datasets[0].data.push(newTotalSent*k);
|
||||||
|
totalDataUsageChartObj.data.datasets[0].lastData = response.total_data_usage[1];
|
||||||
|
totalDataUsageChartObj.data.datasets[1].lastData = response.total_data_usage[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDataUsageChartObj.update();
|
||||||
|
}
|
||||||
|
|
||||||
$conf_status_btn.classList.remove("info_loading");
|
$conf_status_btn.classList.remove("info_loading");
|
||||||
document.querySelectorAll("#sort_by_dropdown option").forEach(ele => ele.removeAttribute("selected"));
|
document.querySelectorAll("#sort_by_dropdown option").forEach(ele => ele.removeAttribute("selected"));
|
||||||
document.querySelector(`#sort_by_dropdown option[value="${response.sort_tag}"]`).setAttribute("selected", "selected");
|
document.querySelector(`#sort_by_dropdown option[value="${response.sort_tag}"]`).setAttribute("selected", "selected");
|
||||||
@ -164,7 +226,7 @@
|
|||||||
let data_list = [$new_add_DNS, $new_add_endpoint_allowed_ip,$new_add_MTU, $new_add_keep_alive];
|
let data_list = [$new_add_DNS, $new_add_endpoint_allowed_ip,$new_add_MTU, $new_add_keep_alive];
|
||||||
if ($new_add_amount.val() > 0 && !$new_add_amount.hasClass("is-invalid")){
|
if ($new_add_amount.val() > 0 && !$new_add_amount.hasClass("is-invalid")){
|
||||||
if ($new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
|
if ($new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
|
||||||
let conf = $add_peer.getAttribute('conf_id');
|
let conf = conf_name;
|
||||||
let keys = [];
|
let keys = [];
|
||||||
for (let i = 0; i < $new_add_amount.val(); i++) {
|
for (let i = 0; i < $new_add_amount.val(); i++) {
|
||||||
keys.push(window.wireguard.generateKeypair());
|
keys.push(window.wireguard.generateKeypair());
|
||||||
@ -262,12 +324,13 @@
|
|||||||
/**
|
/**
|
||||||
* Handle when the server is not responding
|
* Handle when the server is not responding
|
||||||
*/
|
*/
|
||||||
function noResponding(){
|
function noResponding(message = "Opps! <br> I can't connect to the server."){
|
||||||
document.querySelectorAll(".no-response").forEach(ele => ele.classList.add("active"));
|
document.querySelectorAll(".no-response").forEach(ele => ele.classList.add("active"));
|
||||||
setTimeout(function (){
|
setTimeout(function (){
|
||||||
document.querySelectorAll(".no-response").forEach(ele => ele.classList.add("show"));
|
document.querySelectorAll(".no-response").forEach(ele => ele.classList.add("show"));
|
||||||
document.querySelector("#right_body").classList.add("no-responding");
|
document.querySelector("#right_body").classList.add("no-responding");
|
||||||
document.querySelector(".navbar").classList.add("no-responding");
|
document.querySelector(".navbar").classList.add("no-responding");
|
||||||
|
document.querySelector(".no-response .container h4").innerHTML = message;
|
||||||
},10);
|
},10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,53 +412,38 @@
|
|||||||
let time = 0;
|
let time = 0;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
|
||||||
let d1 = new Date();
|
let d1 = new Date();
|
||||||
function loadPeers(searchString){
|
function loadPeers(searchString){
|
||||||
d1 = new Date();
|
d1 = new Date();
|
||||||
startProgressBar();
|
|
||||||
socket.emit('get_config', {"config": conf_name, "search": searchString});
|
socket.emit('get_config', {"config": conf_name, "search": searchString});
|
||||||
|
|
||||||
// let d1 = new Date();
|
|
||||||
// $.ajax({
|
|
||||||
// method: "GET",
|
|
||||||
// url: `/get_config/${conf_name}?search=${encodeURIComponent(searchString)}`,
|
|
||||||
// headers:{"Content-Type": "application/json"}
|
|
||||||
// }).done(function(response){
|
|
||||||
// removeNoResponding();
|
|
||||||
// peers = response.peer_data;
|
|
||||||
// configurationAlert(response);
|
|
||||||
// configurationHeader(response);
|
|
||||||
// configurationPeers(response);
|
|
||||||
// $(".dot.dot-running").attr("title","Peer Connected").tooltip();
|
|
||||||
// $(".dot.dot-stopped").attr("title","Peer Disconnected").tooltip();
|
|
||||||
// $("i[data-toggle='tooltip']").tooltip();
|
|
||||||
// endProgressBar();
|
|
||||||
// let d2 = new Date();
|
|
||||||
// let seconds = (d2 - d1);
|
|
||||||
// $("#peer_loading_time").html(`Peer Loading Time: ${seconds}ms`);
|
|
||||||
// }).fail(function(){
|
|
||||||
// noResponding();
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parsePeers(response){
|
function parsePeers(response){
|
||||||
let d2 = new Date();
|
if (response.status){
|
||||||
let seconds = (d2 - d1);
|
let d2 = new Date();
|
||||||
time += seconds
|
let seconds = (d2 - d1);
|
||||||
count += 1
|
time += seconds;
|
||||||
window.console.log(`Average time: ${time/count}ms`);
|
count += 1;
|
||||||
$("#peer_loading_time").html(`Peer Loading Time: ${seconds}ms`);
|
window.console.log(`Average time: ${time/count}ms`);
|
||||||
removeNoResponding();
|
$("#peer_loading_time").html(`Peer Loading Time: ${seconds}ms`);
|
||||||
peers = response.peer_data;
|
removeNoResponding();
|
||||||
configurationAlert(response);
|
peers = response.data.peer_data;
|
||||||
configurationHeader(response);
|
configurationAlert(response.data);
|
||||||
configurationPeers(response);
|
configurationHeader(response.data);
|
||||||
$(".dot.dot-running").attr("title","Peer Connected").tooltip();
|
configurationPeers(response.data);
|
||||||
$(".dot.dot-stopped").attr("title","Peer Disconnected").tooltip();
|
$(".dot.dot-running").attr("title","Peer Connected").tooltip();
|
||||||
$("i[data-toggle='tooltip']").tooltip();
|
$(".dot.dot-stopped").attr("title","Peer Disconnected").tooltip();
|
||||||
endProgressBar();
|
$("i[data-toggle='tooltip']").tooltip();
|
||||||
|
$("#conf_name").text(conf_name);
|
||||||
|
if (firstLoading){
|
||||||
|
firstLoading = false;
|
||||||
|
$("#config_body").removeClass("firstLoading");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
noResponding(response.message);
|
||||||
|
removeConfigurationInterval();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -513,16 +561,21 @@
|
|||||||
*/
|
*/
|
||||||
function getAvailableIps(){
|
function getAvailableIps(){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
"url": `/available_ips/${$add_peer.getAttribute("conf_id")}`,
|
"url": `/available_ips/${conf_name}`,
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
}).done(function (res) {
|
}).done(function (res) {
|
||||||
available_ips = res;
|
if (res.status === true){
|
||||||
let $list_group = document.querySelector("#available_ip_modal .modal-body .list-group");
|
available_ips = res.data;
|
||||||
$list_group.innerHTML = "";
|
let $list_group = document.querySelector("#available_ip_modal .modal-body .list-group");
|
||||||
document.querySelector("#allowed_ips").value = available_ips[0];
|
$list_group.innerHTML = "";
|
||||||
available_ips.forEach((ip) =>
|
document.querySelector("#allowed_ips").value = available_ips[0];
|
||||||
$list_group.innerHTML +=
|
available_ips.forEach((ip) =>
|
||||||
`<a class="list-group-item list-group-item-action available-ip-item" style="cursor: pointer" data-ip="${ip}">${ip}</a>`);
|
$list_group.innerHTML +=
|
||||||
|
`<a class="list-group-item list-group-item-action available-ip-item" style="cursor: pointer" data-ip="${ip}">${ip}</a>`);
|
||||||
|
}else{
|
||||||
|
document.querySelector("#allowed_ips").value = res.message;
|
||||||
|
document.querySelector("#search_available_ip").setAttribute("disabled", "disabled");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,6 +586,7 @@
|
|||||||
ipModal: () => { return ipModal; },
|
ipModal: () => { return ipModal; },
|
||||||
qrcodeModal: () => { return qrcodeModal; },
|
qrcodeModal: () => { return qrcodeModal; },
|
||||||
settingModal: () => { return settingModal; },
|
settingModal: () => { return settingModal; },
|
||||||
|
configurationTimeout: () => { return configuration_timeout;},
|
||||||
|
|
||||||
loadPeers: (searchString) => { loadPeers(searchString); },
|
loadPeers: (searchString) => { loadPeers(searchString); },
|
||||||
addPeersByBulk: () => { addPeersByBulk(); },
|
addPeersByBulk: () => { addPeersByBulk(); },
|
||||||
@ -663,7 +717,7 @@ $add_peer.addEventListener("click",function(){
|
|||||||
$add_peer.setAttribute("disabled","disabled");
|
$add_peer.setAttribute("disabled","disabled");
|
||||||
$add_peer.innerHTML = "Adding...";
|
$add_peer.innerHTML = "Adding...";
|
||||||
if ($allowed_ips.val() !== "" && $public_key.val() !== "" && $new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
|
if ($allowed_ips.val() !== "" && $public_key.val() !== "" && $new_add_DNS.val() !== "" && $new_add_endpoint_allowed_ip.val() !== ""){
|
||||||
let conf = $add_peer.getAttribute('conf_id');
|
let conf = conf_name;
|
||||||
let data_list = [$private_key, $allowed_ips, $new_add_name, $new_add_DNS, $new_add_endpoint_allowed_ip,$new_add_MTU, $new_add_keep_alive];
|
let data_list = [$private_key, $allowed_ips, $new_add_name, $new_add_DNS, $new_add_endpoint_allowed_ip,$new_add_MTU, $new_add_keep_alive];
|
||||||
data_list.forEach((ele) => ele.attr("disabled", "disabled"));
|
data_list.forEach((ele) => ele.attr("disabled", "disabled"));
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -739,7 +793,7 @@ $("#new_add_amount").on("keyup", function(){
|
|||||||
* Handle when user toggled add peers by bulk
|
* Handle when user toggled add peers by bulk
|
||||||
*/
|
*/
|
||||||
$("#bulk_add").on("change", function (){
|
$("#bulk_add").on("change", function (){
|
||||||
let hide = $(".non-bulk").find("input");
|
let hide = $(".non-bulk");
|
||||||
let amount = $("#new_add_amount");
|
let amount = $("#new_add_amount");
|
||||||
if ($(this).prop("checked") === true){
|
if ($(this).prop("checked") === true){
|
||||||
for(let i = 0; i < hide.length; i++){
|
for(let i = 0; i < hide.length; i++){
|
||||||
@ -854,7 +908,7 @@ $body.on("click", ".btn-qrcode-peer", function (){
|
|||||||
*/
|
*/
|
||||||
$body.on("click", ".btn-delete-peer", function(){
|
$body.on("click", ".btn-delete-peer", function(){
|
||||||
let peer_id = $(this).attr("id");
|
let peer_id = $(this).attr("id");
|
||||||
$("#delete_peer").attr("peer_id", peer_id);
|
$("#delete_peer").data("peer-id", peer_id);
|
||||||
window.configurations.deleteModal().toggle();
|
window.configurations.deleteModal().toggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -864,9 +918,8 @@ $body.on("click", ".btn-delete-peer", function(){
|
|||||||
$("#delete_peer").on("click",function(){
|
$("#delete_peer").on("click",function(){
|
||||||
$(this).attr("disabled","disabled");
|
$(this).attr("disabled","disabled");
|
||||||
$(this).html("Deleting...");
|
$(this).html("Deleting...");
|
||||||
let peer_id = $(this).attr("peer_id");
|
let config = conf_name;
|
||||||
let config = $(this).attr("conf_id");
|
let peer_ids = [$(this).data("peer-id")];
|
||||||
let peer_ids = [peer_id];
|
|
||||||
window.configurations.deletePeers(config, peer_ids);
|
window.configurations.deletePeers(config, peer_ids);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -880,12 +933,12 @@ $("#delete_peer").on("click",function(){
|
|||||||
* Handle when setting button got clicked for each peer
|
* Handle when setting button got clicked for each peer
|
||||||
*/
|
*/
|
||||||
$body.on("click", ".btn-setting-peer", function(){
|
$body.on("click", ".btn-setting-peer", function(){
|
||||||
window.configurations.startProgressBar();
|
// window.configurations.startProgressBar();
|
||||||
let peer_id = $(this).attr("id");
|
let peer_id = $(this).attr("id");
|
||||||
$("#save_peer_setting").attr("peer_id", peer_id);
|
$("#save_peer_setting").attr("peer_id", peer_id);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/get_peer_data/"+$("#setting_modal").attr("conf_id"),
|
url: "/get_peer_data/"+conf_name,
|
||||||
headers:{
|
headers:{
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
@ -921,7 +974,7 @@ $("#peer_private_key_textbox").on("change",function(){
|
|||||||
let $save_peer_setting = $("#save_peer_setting");
|
let $save_peer_setting = $("#save_peer_setting");
|
||||||
if ($(this).val().length > 0){
|
if ($(this).val().length > 0){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
"url": "/check_key_match/"+$save_peer_setting.attr("conf_id"),
|
"url": "/check_key_match/"+conf_name,
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"headers":{"Content-Type": "application/json"},
|
"headers":{"Content-Type": "application/json"},
|
||||||
"data": JSON.stringify({
|
"data": JSON.stringify({
|
||||||
@ -1233,7 +1286,7 @@ $("#confirm_delete_bulk_peers").on("click", function(){
|
|||||||
btn.attr("disabled", "disabled");
|
btn.attr("disabled", "disabled");
|
||||||
let ips = [];
|
let ips = [];
|
||||||
$selected_peer_list.childNodes.forEach((ele) => ips.push(ele.dataset.id));
|
$selected_peer_list.childNodes.forEach((ele) => ips.push(ele.dataset.id));
|
||||||
window.configurations.deletePeers(btn.data("conf"), ips);
|
window.configurations.deletePeers(conf_name, ips);
|
||||||
clearInterval(confirm_delete_bulk_peers_interval);
|
clearInterval(confirm_delete_bulk_peers_interval);
|
||||||
confirm_delete_bulk_peers_interval = undefined;
|
confirm_delete_bulk_peers_interval = undefined;
|
||||||
}
|
}
|
||||||
@ -1289,7 +1342,7 @@ $body.on("click", ".btn-download-peer", function(e){
|
|||||||
*/
|
*/
|
||||||
$("#download_all_peers").on("click", function(){
|
$("#download_all_peers").on("click", function(){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
"url": $(this).data("url"),
|
"url": `/download_all/${conf_name}`,
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
success: function(res){
|
success: function(res){
|
||||||
if (res.peers.length > 0){
|
if (res.peers.length > 0){
|
||||||
|
4
src/static/js/configuration.min.js
vendored
4
src/static/js/configuration.min.js
vendored
File diff suppressed because one or more lines are too long
@ -74,6 +74,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">
|
||||||
|
<div class="chartTitle">
|
||||||
|
<h6>Data Usage / Refresh Interval</h6>
|
||||||
|
<div class="chartControl" style="margin-left: auto">
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button class="btn btn-outline-primary btn-sm switchUnit active" data-unit="GB">GB</button>
|
||||||
|
<button class="btn btn-outline-primary btn-sm switchUnit" data-unit="MB">MB</button>
|
||||||
|
<button class="btn btn-outline-primary btn-sm switchUnit" data-unit="KB">KB</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 100%; max-height: 300px">
|
||||||
|
<canvas id="myChart" width="100" height="100"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
<div class="button-div mb-3">
|
<div class="button-div mb-3">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
@ -154,35 +172,35 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<form id="add_peer_form">
|
<form id="add_peer_form">
|
||||||
<div class="form-group non-bulk">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<label for="private_key">Private Key</label>
|
<label for="private_key">Private Key</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" id="private_key" aria-describedby="private_key">
|
<input type="text" class="form-control non-bulk" id="private_key" aria-describedby="private_key">
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button type="button" class="btn btn-danger" id="re_generate_key" data-toggle="tooltip" data-placement="top" title="Regenerate Key"><i class="bi bi-arrow-repeat"></i></button>
|
<button type="button" class="btn btn-danger non-bulk" id="re_generate_key" data-toggle="tooltip" data-placement="top" title="Regenerate Key"><i class="bi bi-arrow-repeat"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group non-bulk">
|
<div class="form-group">
|
||||||
<label for="public_key">Public Key <code>(Required)</code></label>
|
<label for="public_key">Public Key <code>(Required)</code></label>
|
||||||
<input type="text" class="form-control" id="public_key" aria-describedby="public_key" disabled>
|
<input type="text" class="form-control non-bulk" id="public_key" aria-describedby="public_key" disabled>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 non-bulk">
|
<div class="col-sm-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new_add_name">Name</label>
|
<label for="new_add_name">Name</label>
|
||||||
<input type="text" class="form-control" id="new_add_name">
|
<input type="text" class="form-control non-bulk" id="new_add_name">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 non-bulk">
|
<div class="col-sm-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="allowed_ips">Allowed IPs <code>(Required)</code></label>
|
<label for="allowed_ips">Allowed IPs <code>(Required)</code></label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" id="allowed_ips">
|
<input type="text" class="form-control non-bulk" id="allowed_ips">
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button type="button" class="btn btn-primary" id="search_available_ip" data-toggle="tooltip" data-placement="top" title="Search Available IPs">
|
<button type="button" class="btn btn-primary non-bulk" id="search_available_ip" data-toggle="tooltip" data-placement="top" title="Search Available IPs">
|
||||||
<i class="bi bi-search"></i>
|
<i class="bi bi-search"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -281,7 +299,6 @@
|
|||||||
<input type="text" class="form-control" id="peer_preshared_key_textbox">
|
<input type="text" class="form-control" id="peer_preshared_key_textbox">
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
@ -418,17 +435,102 @@
|
|||||||
let load_interval = 0;
|
let load_interval = 0;
|
||||||
let conf_name = "{{ conf_data['name'] }}"
|
let conf_name = "{{ conf_data['name'] }}"
|
||||||
let peers = [];
|
let peers = [];
|
||||||
$(".sb-"+conf_name+"-url").addClass("active");
|
$(`.sb-${conf_name}-url`).addClass("active");
|
||||||
let socket = io();
|
let socket = io();
|
||||||
$(function(){
|
socket.on('connect', function() {
|
||||||
socket.on('connect', function() {
|
configurations.loadPeers($('#search_peer_textbox').val());
|
||||||
configurations.loadPeers($('#search_peer_textbox').val());
|
});
|
||||||
});
|
socket.on('get_config', function(res){
|
||||||
socket.on('get_config', function(res){
|
window.console.log(res);
|
||||||
window.console.log(res);
|
configurations.parsePeers(res);
|
||||||
configurations.parsePeers(res);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
});
|
let chartUnit = $(".switchUnit.active").data('unit');
|
||||||
|
const totalDataUsageChart = document.getElementById('myChart').getContext('2d');
|
||||||
|
const totalDataUsageChartObj = new Chart(totalDataUsageChart, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Total Sent',
|
||||||
|
data: [],
|
||||||
|
fill: false,
|
||||||
|
borderColor: '#28a745',
|
||||||
|
tension: 0.1,
|
||||||
|
borderWidth: 1
|
||||||
|
},{
|
||||||
|
label: 'Total Received',
|
||||||
|
data: [],
|
||||||
|
fill: false,
|
||||||
|
borderColor: '#007bff',
|
||||||
|
tension: 0.1,
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive:false,
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
ticks: {
|
||||||
|
callback: function(value, index, ticks) {
|
||||||
|
return `${value} ${chartUnit}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#myChart").css("width", "100%");
|
||||||
|
totalDataUsageChartObj.width = $("#myChart").parent().width();
|
||||||
|
totalDataUsageChartObj.resize();
|
||||||
|
$(window).on("resize", function() {
|
||||||
|
totalDataUsageChartObj.width = $("#myChart").parent().width();
|
||||||
|
totalDataUsageChartObj.resize();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let mul = 1;
|
||||||
|
$(".switchUnit").on("click", function(){
|
||||||
|
$(".switchUnit").removeClass("active");
|
||||||
|
$(this).addClass("active");
|
||||||
|
if ($(this).data('unit') !== chartUnit){
|
||||||
|
switch ($(this).data('unit')) {
|
||||||
|
case "GB":
|
||||||
|
if (chartUnit === "MB"){
|
||||||
|
mul = 1/1024;
|
||||||
|
}
|
||||||
|
if (chartUnit === "KB"){
|
||||||
|
mul = 1/1048576;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "MB":
|
||||||
|
if (chartUnit === "GB"){
|
||||||
|
mul = 1024
|
||||||
|
}
|
||||||
|
if (chartUnit === "KB"){
|
||||||
|
mul = 1/1024
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "KB":
|
||||||
|
if (chartUnit === "GB"){
|
||||||
|
mul = 1048576
|
||||||
|
}
|
||||||
|
if (chartUnit === "MB"){
|
||||||
|
mul = 1024
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chartUnit = $(this).data('unit');
|
||||||
|
totalDataUsageChartObj.data.datasets[0].data = totalDataUsageChartObj.data.datasets[0].data.map(x => x * mul);
|
||||||
|
totalDataUsageChartObj.data.datasets[1].data = totalDataUsageChartObj.data.datasets[1].data.map(x => x * mul);
|
||||||
|
|
||||||
|
totalDataUsageChartObj.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
@ -15,4 +15,5 @@
|
|||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
|
||||||
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='css/dashboard.css') }}">
|
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='css/dashboard.css') }}">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
</head>
|
</head>
|
@ -19,7 +19,7 @@
|
|||||||
</h6>
|
</h6>
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
{% for i in conf%}
|
{% for i in conf%}
|
||||||
<li class="nav-item"><a class="nav-link sb-{{i['conf']}}-url" href="/configuration/{{i['conf']}}"><samp>{{i['conf']}}</samp></a></li>
|
<li class="nav-item"><a class="nav-link nav-conf-link sb-{{i['conf']}}-url" href="/configuration/{{i['conf']}}" data-conf-id="{{i['conf']}}"><samp>{{i['conf']}}</samp></a></li>
|
||||||
{%endfor%}
|
{%endfor%}
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
<hr>
|
||||||
|
Loading…
Reference in New Issue
Block a user