Finished some building blocks on the new version

This commit is contained in:
Donald Zou
2024-02-26 10:22:33 -05:00
parent 1e88491ca1
commit ed3bb6429b
6 changed files with 627 additions and 146 deletions

View File

@@ -11,10 +11,12 @@
"bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.2",
"cidr-tools": "^7.0.4",
"dayjs": "^1.11.10",
"pinia": "^2.1.7",
"qrcode": "^1.5.3",
"uuid": "^9.0.1",
"vue": "^3.3.11",
"vue-chartjs": "^5.3.0",
"vue-router": "^4.2.5"
},
"devDependencies": {
@@ -406,6 +408,12 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@kurkle/color": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==",
"peer": true
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
@@ -756,6 +764,18 @@
"node": ">=6"
}
},
"node_modules/chart.js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
"integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
"peer": true,
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=7"
}
},
"node_modules/cidr-tools": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cidr-tools/-/cidr-tools-7.0.4.tgz",
@@ -798,6 +818,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
},
"node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
@@ -1278,6 +1303,15 @@
}
}
},
"node_modules/vue-chartjs": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.0.tgz",
"integrity": "sha512-8XqX0JU8vFZ+WA2/knz4z3ThClduni2Nm0BMe2u0mXgTfd9pXrmJ07QBI+WAij5P/aPmPMX54HCE1seWL37ZdQ==",
"peerDependencies": {
"chart.js": "^4.1.1",
"vue": "^3.0.0-0 || ^2.7.0"
}
},
"node_modules/vue-router": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz",

View File

@@ -12,10 +12,12 @@
"bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.2",
"cidr-tools": "^7.0.4",
"dayjs": "^1.11.10",
"pinia": "^2.1.7",
"qrcode": "^1.5.3",
"uuid": "^9.0.1",
"vue": "^3.3.11",
"vue-chartjs": "^5.3.0",
"vue-router": "^4.2.5"
},
"devDependencies": {

View File

@@ -0,0 +1,47 @@
<script>
export default {
name: "peer",
props: {
Peer: Object
}
}
</script>
<template>
<div class="card shadow rounded-3">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0">
<div class="dot ms-0" :class="{active: Peer.status === 'running'}"></div>
<div style="font-size: 0.8rem" class="ms-auto d-flex gap-2">
<span class="text-primary">
<i class="bi bi-arrow-down"></i><strong>
{{(Peer.cumu_receive + Peer.total_receive).toFixed(4)}}</strong> GB
</span>
<span class="text-success">
<i class="bi bi-arrow-up"></i><strong>
{{(Peer.cumu_sent + Peer.total_sent).toFixed(4)}}</strong> GB
</span>
<span class="text-secondary" v-if="Peer.latest_handshake !== 'No Handshake'">
<i class="bi bi-arrows-angle-contract"></i>
{{Peer.latest_handshake}} ago
</span>
</div>
</div>
<div class="card-body pt-1" style="font-size: 0.9rem">
<h5>
{{Peer.name ? Peer.name : 'Untitled Peer'}}
</h5>
<div class="mb-2">
<small class="text-muted">Public Key</small>
<p class="mb-0"><samp>{{Peer.id}}</samp></p>
</div>
<div>
<small class="text-muted">Allowed IP</small>
<p class="mb-0"><samp>{{Peer.allowed_ip}}</samp></p>
</div>
</div>
</div>
</template>
<style scoped>
</style>

View File

@@ -1,12 +1,368 @@
<script>
import {fetchGet} from "@/utilities/fetch.js";
import Peer from "@/components/configurationComponents/peer.vue";
import { Line, Bar } from 'vue-chartjs'
import {
Chart,
ArcElement,
LineElement,
BarElement,
PointElement,
BarController,
BubbleController,
DoughnutController,
LineController,
PieController,
PolarAreaController,
RadarController,
ScatterController,
CategoryScale,
LinearScale,
LogarithmicScale,
RadialLinearScale,
TimeScale,
TimeSeriesScale,
Decimation,
Filler,
Legend,
Title,
Tooltip
} from 'chart.js';
Chart.register(
ArcElement,
LineElement,
BarElement,
PointElement,
BarController,
BubbleController,
DoughnutController,
LineController,
PieController,
PolarAreaController,
RadarController,
ScatterController,
CategoryScale,
LinearScale,
LogarithmicScale,
RadialLinearScale,
TimeScale,
TimeSeriesScale,
Decimation,
Filler,
Legend,
Title,
Tooltip
);
import dayjs from "dayjs";
export default {
name: "configuration"
name: "configuration",
components: {Peer, Line, Bar},
data(){
return {
loading: false,
error: null,
configurationInfo: [],
configurationPeers: [],
historyDataSentDifference: [],
historyDataReceivedDifference: [],
historySentData: {
labels: [],
datasets: [
{
label: 'Data Sent',
data: [],
fill: false,
borderColor: '#198754',
tension: 0
},
],
},
historyReceiveData: {
labels: [],
datasets: [
{
label: 'Data Received',
data: [],
fill: false,
borderColor: '#0d6efd',
tension: 0
},
],
},
}
},
watch: {
'$route.params': {
immediate: true,
handler(){
clearInterval(this.interval)
this.loading = true;
let id = this.$route.params.id;
this.configurationInfo = [];
this.configurationPeers = [];
if (id){
this.getPeers(id)
this.interval = setInterval(() => {
this.getPeers(id)
}, 2000)
}
}
}
},
beforeRouteLeave(){
clearInterval(this.interval)
},
methods:{
getPeers(id){
fetchGet("/api/getWireguardConfigurationInfo",
{
configurationName: id
}, (res) => {
this.configurationInfo = res.data.configurationInfo;
this.configurationPeers = res.data.configurationPeers;
this.loading = false;
if (this.configurationPeers.length > 0){
const sent = this.configurationPeers.map(x => x.total_sent + x.cumu_sent).reduce((x,y) => x + y).toFixed(4);
const receive = this.configurationPeers.map(x => x.total_receive + x.cumu_receive).reduce((x,y) => x + y).toFixed(4);
if (
this.historyDataSentDifference[this.historyDataSentDifference.length - 1] !== sent
){
if (this.historyDataSentDifference.length > 0){
this.historySentData = {
labels: [...this.historySentData.labels, dayjs().format("HH:mm:ss A")],
datasets: [
{
label: 'Data Sent',
data: [...this.historySentData.datasets[0].data,
((sent - this.historyDataSentDifference[this.historyDataSentDifference.length - 1])*1000).toFixed(4)],
fill: false,
borderColor: ' #198754',
tension: 0
}
],
}
}
this.historyDataSentDifference.push(sent)
}
if (
this.historyDataReceivedDifference[this.historyDataReceivedDifference.length - 1] !== receive
){
if (this.historyDataReceivedDifference.length > 0){
this.historyReceiveData = {
labels: [...this.historyReceiveData.labels, dayjs().format("HH:mm:ss A")],
datasets: [
{
label: 'Data Received',
data: [...this.historyReceiveData.datasets[0].data,
((receive - this.historyDataReceivedDifference[this.historyDataReceivedDifference.length - 1])*1000).toFixed(4)],
fill: false,
borderColor: '#0d6efd',
tension: 0
}
],
}
}
this.historyDataReceivedDifference.push(receive)
}
}
});
}
},
computed: {
configurationSummary(){
return {
connectedPeers: this.configurationPeers.filter(x => x.status === "running").length,
totalUsage: this.configurationPeers.length > 0 ? this.configurationPeers.map(x => x.total_data + x.cumu_data).reduce((a, b) => a + b) : 0,
totalReceive: this.configurationPeers.length > 0 ? this.configurationPeers.map(x => x.total_receive + x.cumu_receive).reduce((a, b) => a + b) : 0,
totalSent: this.configurationPeers.length > 0 ? this.configurationPeers.map(x => x.total_sent + x.cumu_sent).reduce((a, b) => a + b) : 0
}
},
receiveData(){
return this.historyReceiveData
},
sentData(){
return this.historySentData
},
individualDataUsage(){
return {
labels: this.configurationPeers.map(x => {
if (x.name) return x.name
return `Untitled Peer - ${x.id}`
}),
datasets: [{
label: 'Total Data Usage',
data: this.configurationPeers.map(x => x.cumu_data + x.total_data),
backgroundColor: this.configurationPeers.map(x => `#0dcaf0`),
tooltip: {
callbacks: {
label: (tooltipItem) => {
console.log(tooltipItem)
return `${tooltipItem.formattedValue} GB`
}
}
}
}]
}
},
individualDataUsageChartOption(){
return {
responsive: true,
plugins: {
legend: {
display: false
}
},
scales: {
x: {
ticks: {
display: false,
},
grid: {
display: false
},
},
y:{
ticks: {
callback: (val, index) => {
return `${val} GB`
}
},
grid: {
display: false
},
}
}
}
},
chartOptions() {
return {
responsive: true,
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: (tooltipItem) => {
console.log(tooltipItem)
return `${tooltipItem.formattedValue} MB/s`
}
}
}
},
scales: {
x: {
ticks: {
display: false,
},
grid: {
display: false
},
},
y:{
ticks: {
callback: (val, index) => {
return `${val} MB/s`
}
},
grid: {
display: false
},
}
}
}
}
}
}
</script>
<template>
<div class="text-body">
hiiii
<div class="mt-5 text-body" v-if="!loading">
<div>
<small CLASS="text-muted">CONFIGURATION</small>
<div class="d-flex align-items-center gap-3">
<h1 class="mb-0"><samp>{{this.configurationInfo.Name}}</samp></h1>
<div class="dot active ms-0"></div>
</div>
</div>
<div class="row mt-3 gy-2">
<div class="col-sm-3">
<p class="mb-0 text-muted"><small>Address</small></p>
{{this.configurationInfo.Address}}
</div>
<div class="col-sm-3">
<p class="mb-0 text-muted"><small>Listen Port</small></p>
{{this.configurationInfo.ListenPort}}
</div>
<div style="word-break: break-all" class="col-sm-6">
<p class="mb-0 text-muted"><small>Public Key</small></p>
<samp>{{this.configurationInfo.PublicKey}}</samp>
</div>
<div class="col-sm-3">
<p class="mb-1 text-muted"><small>Connected Peers</small></p>
<i class="bi bi-ethernet me-2"></i><strong>{{configurationSummary.connectedPeers}}</strong>
</div>
<div class="col-sm-3">
<p class="mb-0 text-muted"><small>Total Usage</small></p>
<i class="bi bi-arrow-down-up me-2"></i><strong>{{configurationSummary.totalUsage.toFixed(4)}}</strong> GB
</div>
<div class="col-sm-3">
<p class="mb-0 text-muted"><small>Total Received</small></p>
<i class="bi bi-arrow-down me-2"></i><strong>{{configurationSummary.totalReceive.toFixed(4)}}</strong> GB
</div>
<div class="col-sm-3">
<p class="mb-0 text-muted"><small>Total Sent</small></p>
<i class="bi bi-arrow-up me-2"></i><strong>{{configurationSummary.totalSent.toFixed(4)}}</strong> GB
</div>
</div>
<div class="row mt-3 gx-2 gy-2 mb-2">
<div class="col-sm ">
<div class="card rounded-3 bg-transparent">
<div class="card-header bg-transparent border-0"><small>Peers Total Data Usage</small></div>
<div class="card-body pt-1">
<Bar
:data="individualDataUsage"
:options="individualDataUsageChartOption"
style="height: 150px; width: 100%"></Bar>
</div>
</div>
</div>
<div class="col-sm">
<div class="card rounded-3 bg-transparent">
<div class="card-header bg-transparent border-0"><small>Real Time Received Data Usage</small></div>
<div class="card-body pt-1">
<Line
:options="chartOptions"
:data="receiveData"
style="width: 100%; height: 150px"
></Line>
</div>
</div>
</div>
<div class="col-sm">
<div class="card rounded-3 bg-transparent">
<div class="card-header bg-transparent border-0"><small>Real Time Sent Data Usage</small></div>
<div class="card-body pt-1">
<Line
:options="chartOptions"
:data="sentData"
style="width: 100%; height: 150px"
></Line>
</div>
</div>
</div>
</div>
<hr>
<div class="row gx-2 gy-2">
<div class="col-12 col-lg-6 col-xl-4" v-for="peer in this.configurationPeers">
<Peer :Peer="peer"></Peer>
</div>
</div>
</div>
</template>