452 lines
17 KiB
HTML
452 lines
17 KiB
HTML
<!doctype html>
|
||
<!--
|
||
* Tabler - Premium and Open Source dashboard template with responsive and high quality UI.
|
||
* @version 1.0.0-alpha.7
|
||
* @link https://github.com/tabler/tabler
|
||
* Copyright 2018-2019 The Tabler Authors
|
||
* Copyright 2018-2019 codecalm.net Paweł Kuna
|
||
* Licensed under MIT (https://tabler.io/license)
|
||
-->
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||
<title>OLBS Dashboard</title>
|
||
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
|
||
<meta name="msapplication-TileColor" content="#206bc4" />
|
||
<meta name="theme-color" content="#206bc4" />
|
||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||
<meta name="mobile-web-app-capable" content="yes" />
|
||
<meta name="HandheldFriendly" content="True" />
|
||
<meta name="MobileOptimized" content="320" />
|
||
<meta name="robots" content="noindex,nofollow,noarchive" />
|
||
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
|
||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||
<!-- CSS files -->
|
||
<link href="./dist/libs/jqvmap/dist/jqvmap.min.css" rel="stylesheet" />
|
||
<link href="./dist/css/tabler.min.css" rel="stylesheet" />
|
||
<link href="./dist/css/demo.min.css" rel="stylesheet" />
|
||
<style>
|
||
body {
|
||
display: none;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body class="antialiased">
|
||
<div class="page">
|
||
<div class="content">
|
||
<div class="container-xl">
|
||
<!-- Page title -->
|
||
<div class="page-header">
|
||
<div class="row align-items-center">
|
||
<div class="col-auto">
|
||
<h2 class="page-title">
|
||
Openvpn Load Balancing Socks5 Server
|
||
</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row row-deck row-cards">
|
||
<div class="col-lg-12">
|
||
<div class="card card-sm">
|
||
<div class="card-body d-flex align-items-center">
|
||
<div class="mr-3 lh-sm">
|
||
<button type="button" class="btn btn-outline-success" onclick="add_new_instance()">Add New
|
||
Instance</button>
|
||
</div>
|
||
<div class="mr-3 lh-sm">
|
||
<button type="button" class="btn btn-outline-secondary" onclick="start_all()">Start All</button>
|
||
</div>
|
||
<div class="mr-3 lh-sm">
|
||
<div class="strong">
|
||
<button type="button" class="btn btn-outline-secondary" onclick="stop_all()">Stop All</button>
|
||
</div>
|
||
</div>
|
||
<div class="mr-3 lh-sm">
|
||
<div class="strong">
|
||
<button type="button" class="btn btn-outline-danger" onclick="remove_all()">Remove All</button>
|
||
</div>
|
||
</div>
|
||
<div class="mr-3 lh-sm">
|
||
<div class="strong">
|
||
<button type="button" class="btn btn-outline-info" onclick="save_current_config()">Save Current
|
||
Config</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-12">
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<div class="d-flex align-items-center">
|
||
<div class="subheader">
|
||
<h3>Traffic summary</h3>
|
||
</div>
|
||
<div class="ml-auto lh-1">
|
||
<div class="dropdown">
|
||
<a class="dropdown-toggle text-muted" href="#" data-toggle="dropdown" aria-haspopup="true"
|
||
aria-expanded="false">
|
||
Last 7 days
|
||
</a>
|
||
<div class="dropdown-menu dropdown-menu-right">
|
||
<a class="dropdown-item active" href="#">Last 7 days</a>
|
||
<a class="dropdown-item" href="#">Last 30 days</a>
|
||
<a class="dropdown-item" href="#">Last 3 months</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<canvas id="chart-traffic" class="chart-lg"></canvas>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="col-lg-12">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h4 class="card-title">Most Visited Pages</h4>
|
||
</div>
|
||
<div id="ovpn_table_container" class="table-responsive">
|
||
<table id="ovpn_table" class="table card-table table-vcenter">
|
||
<!-- <thead>
|
||
<tr>
|
||
<th>Connection name</th>
|
||
<th>Visitors</th>
|
||
<th>Unique</th>
|
||
<th>Alive</th>
|
||
</tr>
|
||
</thead>
|
||
<tr>
|
||
<td>
|
||
name
|
||
</td>
|
||
<td class="text-muted"></td>
|
||
<td class="text-muted"></td>
|
||
<td class="text-right">
|
||
<div class="chart-sparkline" id="sparkline-69"></div>
|
||
</td>
|
||
</tr> -->
|
||
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<footer class="footer footer-transparent">
|
||
<div class="container">
|
||
<div class="row text-center align-items-center flex-row-reverse">
|
||
<div class="col-lg-auto ml-lg-auto">
|
||
|
||
</div>
|
||
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
</div>
|
||
<!-- Libs JS -->
|
||
<script src="./dist/libs/jquery/dist/jquery-3.5.1.min.js"></script>
|
||
<!-- <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> -->
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
|
||
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous">
|
||
</script>
|
||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
|
||
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous">
|
||
</script>
|
||
|
||
|
||
<script src="./dist/libs/apexcharts/dist/apexcharts.min.js"></script>
|
||
<script src="./dist/libs/jqvmap/dist/jquery.vmap.min.js"></script>
|
||
<script src="./dist/libs/jqvmap/dist/maps/jquery.vmap.world.js"></script>
|
||
<script src="./dist/libs/peity/jquery.peity.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.bundle.min.js"
|
||
integrity="sha256-TQq84xX6vkwR0Qs1qH5ADkP+MvH0W+9E7TdHJsoIQiM=" crossorigin="anonymous"></script>
|
||
<!-- Tabler Core -->
|
||
<script src="./dist/js/tabler.min.js"></script>
|
||
|
||
<script>
|
||
var bytesToString = function (bytes) {
|
||
// One way to write it, not the prettiest way to write it.
|
||
|
||
var fmt = parseInt;
|
||
if (bytes < 1024) {
|
||
return fmt(bytes) + 'B';
|
||
} else if (bytes < 1024 * 1024) {
|
||
return fmt(bytes / 1024) + 'kB';
|
||
} else if (bytes < 1024 * 1024 * 1024) {
|
||
return fmt(bytes / 1024 / 1024) + 'MB';
|
||
} else {
|
||
return fmt(bytes / 1024 / 1024 / 1024) + 'GB';
|
||
}
|
||
}
|
||
var ctx = document.getElementById('chart-traffic').getContext('2d');
|
||
var config = {
|
||
type: 'line',
|
||
data: {
|
||
datasets: []
|
||
},
|
||
options: {
|
||
responsive: true,
|
||
title: {
|
||
display: false,
|
||
},
|
||
animation: {
|
||
duration: 0
|
||
},
|
||
scales: {
|
||
xAxes: [{
|
||
type: 'time',
|
||
display: true,
|
||
scaleLabel: {
|
||
display: true,
|
||
labelString: 'Time'
|
||
},
|
||
ticks: {
|
||
source: "auto",
|
||
major: {
|
||
fontStyle: 'bold',
|
||
fontColor: '#FF0000'
|
||
}
|
||
}
|
||
}],
|
||
yAxes: [{
|
||
display: true,
|
||
scaleLabel: {
|
||
display: true,
|
||
labelString: 'Link Speed'
|
||
},
|
||
ticks: {
|
||
callback: function (value, index, values) {
|
||
return bytesToString(parseInt(value)) + "/s";
|
||
}
|
||
}
|
||
}]
|
||
}
|
||
}
|
||
};
|
||
var traffic_chart = new Chart(ctx, config);
|
||
|
||
function uuidv4() {
|
||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||
var r = Math.random() * 16 | 0,
|
||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||
return v.toString(16);
|
||
});
|
||
}
|
||
var random = (function () {
|
||
var seed = 0x2F6E2BC; // 0x2F6E2B1
|
||
return function () {
|
||
// Robert Jenkins’ 32 bit integer hash function
|
||
seed = ((seed + 0x7ED55D16) + (seed << 12)) & 0xFFFFFFFF;
|
||
seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
|
||
seed = ((seed + 0x165667B1) + (seed << 5)) & 0xFFFFFFFF;
|
||
seed = ((seed + 0xD3A2646C) ^ (seed << 9)) & 0xFFFFFFFF;
|
||
seed = ((seed + 0xFD7046C5) + (seed << 3)) & 0xFFFFFFFF;
|
||
seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
|
||
return (seed & 0xFFFFFFF) / 0x10000000;
|
||
};
|
||
}());
|
||
random();
|
||
colors = Array.from(Array(100), () => "#" + random().toString(16).substr(-6))
|
||
var color = Chart.helpers.color;
|
||
|
||
$('body').tooltip({
|
||
selector: '[data-toggle="tooltip"]'
|
||
});
|
||
var update_stat = function () {
|
||
$.getJSON("/stat", function (data) {
|
||
// update top chart
|
||
var datasets = data.instances.map((value, index) => {
|
||
return {
|
||
label: value.name,
|
||
backgroundColor: color(colors[index]).alpha(0.5).rgbString(),
|
||
borderColor: color(colors[index]).alpha(0.8).rgbString(),
|
||
fill: false,
|
||
data: value.io_mean.map((value, index) => {
|
||
return {
|
||
x: data.time[index],
|
||
y: value,
|
||
}
|
||
}),
|
||
}
|
||
})
|
||
traffic_chart.data.datasets = datasets;
|
||
traffic_chart.update();
|
||
|
||
// update table
|
||
var ovpn_table = $("#ovpn_table");
|
||
$('[data-toggle="tooltip"]').tooltip('hide');
|
||
ovpn_table.empty();
|
||
ovpn_table.append($(`<thead>
|
||
<tr>
|
||
<th>Connection name</th>
|
||
<th>Status</th>
|
||
<th>Weight</th>
|
||
<th>Alive</th>
|
||
<th>Ping</th>
|
||
<th>Actions</th>
|
||
</tr>
|
||
</thead>`))
|
||
data.instances.forEach((instance, index) => {
|
||
var tr = $(`<tr>
|
||
<td>
|
||
${instance.name}
|
||
</td>
|
||
<td class="text-muted">${instance.status}</td>
|
||
<td class="text-muted">${instance.weight}</td>
|
||
<td class="text-muted">
|
||
<div class="chart-sparkline" id="alive-${index}"></div>
|
||
</td>
|
||
<td class="text-muted">
|
||
<div class="chart-sparkline" id="ping-${index}"></div>
|
||
</td>
|
||
<td class="text-muted">
|
||
<a id="start_button_${instance.idx}" href="#!" data-placement="top" data-toggle="tooltip" title="start"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-md" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"></path><path d="M18 15l-6-6l-6 6h12" transform="rotate(90 12 12)"></path></svg></a>
|
||
<a id="stop_button_${instance.idx}" href="#!" data-placement="top" data-toggle="tooltip" title="stop"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-md" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"></path><rect x="4" y="4" width="16" height="16" rx="2"></rect></svg></a>
|
||
<a id="delete_button_${instance.idx}" href="#!" data-placement="top" data-toggle="tooltip" title="delete"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-md" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"></path><line x1="4" y1="7" x2="20" y2="7"></line><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line><path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12"></path><path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"></path></svg></a>
|
||
</td>
|
||
</tr>`);
|
||
ovpn_table.append(tr);
|
||
tr.find(`#delete_button_${instance.idx}`).click(() => {
|
||
$.get(`/remove?i=${instance.idx}`, update_stat);
|
||
})
|
||
tr.find(`#start_button_${instance.idx}`).click(() => {
|
||
$.get(`/start?i=${instance.idx}`, update_stat);
|
||
})
|
||
tr.find(`#stop_button_${instance.idx}`).click(() => {
|
||
$.get(`/stop?i=${instance.idx}`, update_stat);
|
||
})
|
||
$().peity && $(`#alive-${index}`).text(instance.ping_rate.join(", ")).peity("line", {
|
||
width: 64,
|
||
height: 40,
|
||
stroke: "#206bc4",
|
||
strokeWidth: 2,
|
||
fill: ["#d2e1f3"],
|
||
padding: .2,
|
||
});
|
||
$().peity && $(`#ping-${index}`).text(instance.ping_mean.join(", ")).peity("bar", {
|
||
width: 64,
|
||
height: 40,
|
||
stroke: "#206bc4",
|
||
strokeWidth: 2,
|
||
fill: function (_, i, all) {
|
||
if (instance.ping_rate[i] == 0) {
|
||
return "#ee1111"
|
||
} else {
|
||
return "#27a16c"
|
||
}
|
||
},
|
||
padding: .2,
|
||
max: 200
|
||
});
|
||
});
|
||
|
||
$("#ovpn_table_container").height($("#ovpn_table").height()); // set fixed height for table container to prevent page from scrolling to top
|
||
});
|
||
}
|
||
update_stat();
|
||
setInterval(update_stat, 1000);
|
||
|
||
function save_current_config(){
|
||
$.get("/save_instance", (data, textStatus)=>{
|
||
if(textStatus=="success"){
|
||
alert("saved")
|
||
}
|
||
});
|
||
}
|
||
|
||
</script>
|
||
|
||
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
$().peity && $('#sparkline-67').text("56/100").peity("pie", {
|
||
width: 40,
|
||
height: 40,
|
||
stroke: "#cd201f",
|
||
strokeWidth: 2,
|
||
fill: ["#cd201f", "rgba(110, 117, 130, 0.2)"],
|
||
padding: .2,
|
||
innerRadius: 17,
|
||
});
|
||
});
|
||
</script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
$().peity && $('#sparkline-68').text("22/100").peity("pie", {
|
||
width: 40,
|
||
height: 40,
|
||
stroke: "#fab005",
|
||
strokeWidth: 2,
|
||
fill: ["#fab005", "rgba(110, 117, 130, 0.2)"],
|
||
padding: .2,
|
||
innerRadius: 17,
|
||
});
|
||
});
|
||
</script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
$().peity && $('#sparkline-69').text("17, 24, 20, 10, 5, 1, 4, 18, 13").peity("line", {
|
||
width: 64,
|
||
height: 40,
|
||
stroke: "#206bc4",
|
||
strokeWidth: 2,
|
||
fill: ["#d2e1f3"],
|
||
padding: .2,
|
||
});
|
||
});
|
||
</script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
$().peity && $('#sparkline-70').text("13, 11, 19, 22, 12, 7, 14, 3, 21").peity("line", {
|
||
width: 64,
|
||
height: 40,
|
||
stroke: "#206bc4",
|
||
strokeWidth: 2,
|
||
fill: ["#d2e1f3"],
|
||
padding: .2,
|
||
});
|
||
});
|
||
</script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
$().peity && $('#sparkline-71').text("10, 13, 10, 4, 17, 3, 23, 22, 19").peity("line", {
|
||
width: 64,
|
||
height: 40,
|
||
stroke: "#206bc4",
|
||
strokeWidth: 2,
|
||
fill: ["#d2e1f3"],
|
||
padding: .2,
|
||
});
|
||
});
|
||
</script>
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
$().peity && $('#sparkline-72').text("9, 6, 14, 11, 8, 24, 2, 16, 15").peity("line", {
|
||
width: 64,
|
||
height: 40,
|
||
stroke: "#206bc4",
|
||
strokeWidth: 2,
|
||
fill: ["#d2e1f3"],
|
||
padding: .2,
|
||
});
|
||
});
|
||
</script>
|
||
<script>
|
||
document.body.style.display = "block"
|
||
</script>
|
||
</body>
|
||
|
||
</html> |