mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-07-08 06:06:59 +00:00
Commit
This commit is contained in:
parent
cd9d17ab18
commit
93cfc482b8
@ -2060,7 +2060,7 @@ def sqlSelect(statement: str, paramters: tuple = ()) -> sqlite3.Cursor:
|
|||||||
# sqldb.row_factory = sqlite3.Row
|
# sqldb.row_factory = sqlite3.Row
|
||||||
# cursor = sqldb.cursor()
|
# cursor = sqldb.cursor()
|
||||||
result = []
|
result = []
|
||||||
with sqldb:
|
# with sqldb:
|
||||||
try:
|
try:
|
||||||
cursor = sqldb.cursor()
|
cursor = sqldb.cursor()
|
||||||
result = cursor.execute(statement, paramters)
|
result = cursor.execute(statement, paramters)
|
||||||
|
@ -54,12 +54,21 @@ const fetchRealtimeTraffic = async () => {
|
|||||||
}, (res) => {
|
}, (res) => {
|
||||||
let timestamp = dayjs().format("hh:mm:ss A")
|
let timestamp = dayjs().format("hh:mm:ss A")
|
||||||
|
|
||||||
|
if (res.data.sent !== 0 && res.data.recv !== 0){
|
||||||
historySentData.value.timestamp.push(timestamp)
|
historySentData.value.timestamp.push(timestamp)
|
||||||
historySentData.value.data.push(res.data.sent)
|
historySentData.value.data.push(res.data.sent)
|
||||||
|
|
||||||
historyReceivedData.value.timestamp.push(timestamp)
|
historyReceivedData.value.timestamp.push(timestamp)
|
||||||
historyReceivedData.value.data.push(res.data.recv)
|
historyReceivedData.value.data.push(res.data.recv)
|
||||||
|
}else{
|
||||||
|
if (historySentData.value.data.length > 0 && historyReceivedData.value.data.length > 0){
|
||||||
|
historySentData.value.timestamp.push(timestamp)
|
||||||
|
historySentData.value.data.push(res.data.sent)
|
||||||
|
|
||||||
|
historyReceivedData.value.timestamp.push(timestamp)
|
||||||
|
historyReceivedData.value.data.push(res.data.recv)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const toggleFetchRealtimeTraffic = () => {
|
const toggleFetchRealtimeTraffic = () => {
|
||||||
@ -89,16 +98,17 @@ onBeforeUnmount(() => {
|
|||||||
fetchRealtimeTrafficInterval.value = undefined;
|
fetchRealtimeTrafficInterval.value = undefined;
|
||||||
})
|
})
|
||||||
const peersDataUsageChartData = computed(() => {
|
const peersDataUsageChartData = computed(() => {
|
||||||
|
let data = props.configurationPeers.filter(x => (x.cumu_data + x.total_data) > 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
labels: props.configurationPeers.map(x => {
|
labels: data.map(x => {
|
||||||
if (x.name) return x.name
|
if (x.name) return x.name
|
||||||
return `Untitled Peer - ${x.id}`
|
return `Untitled Peer - ${x.id}`
|
||||||
}),
|
}),
|
||||||
datasets: [{
|
datasets: [{
|
||||||
label: 'Total Data Usage',
|
label: 'Total Data Usage',
|
||||||
data: props.configurationPeers.map(x => x.cumu_data + x.total_data),
|
data: data.map(x => x.cumu_data + x.total_data),
|
||||||
backgroundColor: props.configurationPeers.map(x => `#ffc107`),
|
backgroundColor: data.map(x => `#ffc107`),
|
||||||
barThickness: 50,
|
|
||||||
tooltip: {
|
tooltip: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label: (tooltipItem) => {
|
label: (tooltipItem) => {
|
||||||
@ -133,6 +143,7 @@ const peersRealtimeReceivedData = computed(() => {
|
|||||||
data: [...historyReceivedData.value.data],
|
data: [...historyReceivedData.value.data],
|
||||||
fill: false,
|
fill: false,
|
||||||
borderColor: '#0d6efd',
|
borderColor: '#0d6efd',
|
||||||
|
backgroundColor: '#0d6efd',
|
||||||
tension: 0
|
tension: 0
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -160,7 +171,7 @@ const peersDataUsageChartOption = computed(() => {
|
|||||||
y:{
|
y:{
|
||||||
ticks: {
|
ticks: {
|
||||||
callback: (val, index) => {
|
callback: (val, index) => {
|
||||||
return `${val} GB`
|
return `${Math.round((val + Number.EPSILON) * 1000) / 1000} GB`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
@ -191,18 +202,17 @@ const realtimePeersChartOption = computed(() => {
|
|||||||
display: false,
|
display: false,
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
display: false
|
display: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
y:{
|
y:{
|
||||||
ticks: {
|
ticks: {
|
||||||
callback: (val, index) => {
|
callback: (val, index) => {
|
||||||
return `${Math.round((val + Number.EPSILON) * 1000) / 1000
|
return `${Math.round((val + Number.EPSILON) * 1000) / 1000} MB/s`
|
||||||
} MB/s`
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
display: false
|
display: true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,9 +238,14 @@ const realtimePeersChartOption = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm col-lg-6">
|
<div class="col-sm col-lg-6">
|
||||||
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
||||||
<div class="card-header bg-transparent border-0"><small class="text-muted">
|
<div class="card-header bg-transparent border-0 d-flex align-items-center">
|
||||||
|
<small class="text-muted">
|
||||||
<LocaleText t="Real Time Received Data Usage"></LocaleText>
|
<LocaleText t="Real Time Received Data Usage"></LocaleText>
|
||||||
</small></div>
|
</small>
|
||||||
|
<small class="text-primary fw-bold ms-auto" v-if="historyReceivedData.data.length > 0">
|
||||||
|
{{historyReceivedData.data[historyReceivedData.data.length - 1]}} MB/s
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
<div class="card-body pt-1">
|
<div class="card-body pt-1">
|
||||||
<Line
|
<Line
|
||||||
:options="realtimePeersChartOption"
|
:options="realtimePeersChartOption"
|
||||||
@ -242,14 +257,18 @@ const realtimePeersChartOption = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm col-lg-6">
|
<div class="col-sm col-lg-6">
|
||||||
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
||||||
<div class="card-header bg-transparent border-0"><small class="text-muted">
|
<div class="card-header bg-transparent border-0 d-flex align-items-center">
|
||||||
|
<small class="text-muted">
|
||||||
<LocaleText t="Real Time Sent Data Usage"></LocaleText>
|
<LocaleText t="Real Time Sent Data Usage"></LocaleText>
|
||||||
</small></div>
|
</small>
|
||||||
|
<small class="text-success fw-bold ms-auto" v-if="historySentData.data.length > 0">
|
||||||
|
{{historySentData.data[historySentData.data.length - 1]}} MB/s
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
<div class="card-body pt-1">
|
<div class="card-body pt-1">
|
||||||
<Line
|
<Line
|
||||||
:options="realtimePeersChartOption"
|
:options="realtimePeersChartOption"
|
||||||
:data="peersRealtimeSentData"
|
:data="peersRealtimeSentData"
|
||||||
|
|
||||||
style="width: 100%; height: 200px; max-height: 200px"
|
style="width: 100%; height: 200px; max-height: 200px"
|
||||||
></Line>
|
></Line>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {defineAsyncComponent} from "vue";
|
import {defineAsyncComponent} from "vue";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
const props = defineProps({
|
||||||
|
configurationModals: Object,
|
||||||
|
configurationModalSelectedPeer: Object
|
||||||
|
})
|
||||||
|
const emits = defineEmits(["refresh"])
|
||||||
|
|
||||||
|
|
||||||
const DeleteConfigurationModal = defineAsyncComponent(() => import("@/components/configurationComponents/deleteConfiguration.vue"))
|
const DeleteConfigurationModal = defineAsyncComponent(() => import("@/components/configurationComponents/deleteConfiguration.vue"))
|
||||||
const ConfigurationBackupRestoreModal = defineAsyncComponent(() => import("@/components/configurationComponents/configurationBackupRestore.vue"))
|
const ConfigurationBackupRestoreModal = defineAsyncComponent(() => import("@/components/configurationComponents/configurationBackupRestore.vue"))
|
||||||
const SelectPeersModal = defineAsyncComponent(() => import("@/components/configurationComponents/selectPeers.vue"))
|
const SelectPeersModal = defineAsyncComponent(() => import("@/components/configurationComponents/selectPeers.vue"))
|
||||||
@ -15,7 +21,14 @@ const PeerSettingsModal = defineAsyncComponent(() => import("@/components/config
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<Transition name="zoom">
|
||||||
|
<PeerSettingsModal v-if="configurationModals.peerSetting.modalOpen"
|
||||||
|
key="settings"
|
||||||
|
:selectedPeer="configurationModalSelectedPeer"
|
||||||
|
@refresh="emits('refresh')"
|
||||||
|
@close="configurationModals.peerSetting.modalOpen = false">
|
||||||
|
</PeerSettingsModal>
|
||||||
|
</Transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup async>
|
<script setup async>
|
||||||
import {computed, onBeforeUnmount, ref, watch} from "vue";
|
import {computed, defineAsyncComponent, onBeforeUnmount, ref, watch} from "vue";
|
||||||
import {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
import {fetchGet} from "@/utilities/fetch.js";
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
import ProtocolBadge from "@/components/protocolBadge.vue";
|
import ProtocolBadge from "@/components/protocolBadge.vue";
|
||||||
@ -7,12 +7,20 @@ import LocaleText from "@/components/text/localeText.vue";
|
|||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
import PeerDataUsageCharts from "@/components/configurationComponents/peerListComponents/peerDataUsageCharts.vue";
|
import PeerDataUsageCharts from "@/components/configurationComponents/peerListComponents/peerDataUsageCharts.vue";
|
||||||
|
import PeerSearch from "@/components/configurationComponents/peerSearch.vue";
|
||||||
|
import Peer from "@/components/configurationComponents/peer.vue";
|
||||||
|
import PeerListModals from "@/components/configurationComponents/peerListComponents/peerListModals.vue";
|
||||||
|
|
||||||
|
// Async Components
|
||||||
|
const PeerSearchBar = defineAsyncComponent(() => import("@/components/configurationComponents/peerSearchBar.vue"))
|
||||||
|
|
||||||
const dashboardStore = DashboardConfigurationStore()
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
const wireguardConfigurationStore = WireguardConfigurationsStore()
|
const wireguardConfigurationStore = WireguardConfigurationsStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const configurationInfo = ref({})
|
const configurationInfo = ref({})
|
||||||
const configurationPeers = ref([])
|
const configurationPeers = ref([])
|
||||||
const configurationToggling = ref(false)
|
const configurationToggling = ref(false)
|
||||||
|
const configurationModalSelectedPeer = ref("")
|
||||||
const configurationModals = ref({
|
const configurationModals = ref({
|
||||||
peerSetting: {
|
peerSetting: {
|
||||||
modalOpen: false,
|
modalOpen: false,
|
||||||
@ -54,6 +62,7 @@ const configurationModals = ref({
|
|||||||
modalOpen: false
|
modalOpen: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const peerSearchBar = ref(false)
|
||||||
|
|
||||||
// Fetch Peer =====================================
|
// Fetch Peer =====================================
|
||||||
const fetchPeerList = async () => {
|
const fetchPeerList = async () => {
|
||||||
@ -130,10 +139,46 @@ const configurationSummary = computed(() => {
|
|||||||
.map(x => x.total_sent + x.cumu_sent).reduce((a, b) => a + b, 0).toFixed(4) : 0
|
.map(x => x.total_sent + x.cumu_sent).reduce((a, b) => a + b, 0).toFixed(4) : 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const showPeersCount = ref(10)
|
||||||
|
const searchPeers = computed(() => {
|
||||||
|
const result = wireguardConfigurationStore.searchString ?
|
||||||
|
configurationPeers.value.filter(x => {
|
||||||
|
return x.name.includes(wireguardConfigurationStore.searchString) ||
|
||||||
|
x.id.includes(wireguardConfigurationStore.searchString) ||
|
||||||
|
x.allowed_ip.includes(wireguardConfigurationStore.searchString)
|
||||||
|
}) : configurationPeers.value;
|
||||||
|
|
||||||
|
if (dashboardStore.Configuration.Server.dashboard_sort === "restricted"){
|
||||||
|
return result.sort((a, b) => {
|
||||||
|
if ( a[dashboardStore.Configuration.Server.dashboard_sort]
|
||||||
|
< b[dashboardStore.Configuration.Server.dashboard_sort] ){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ( a[dashboardStore.Configuration.Server.dashboard_sort]
|
||||||
|
> b[dashboardStore.Configuration.Server.dashboard_sort]){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}).slice(0, showPeersCount.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.sort((a, b) => {
|
||||||
|
if ( a[dashboardStore.Configuration.Server.dashboard_sort]
|
||||||
|
< b[dashboardStore.Configuration.Server.dashboard_sort] ){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ( a[dashboardStore.Configuration.Server.dashboard_sort]
|
||||||
|
> b[dashboardStore.Configuration.Server.dashboard_sort]){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}).slice(0, showPeersCount.value)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container-md" >
|
<div class="container-fluid" >
|
||||||
<div class="d-flex align-items-sm-center flex-column flex-sm-row gap-3">
|
<div class="d-flex align-items-sm-center flex-column flex-sm-row gap-3">
|
||||||
<div>
|
<div>
|
||||||
<div class="text-muted d-flex align-items-center gap-2">
|
<div class="text-muted d-flex align-items-center gap-2">
|
||||||
@ -279,6 +324,40 @@ const configurationSummary = computed(() => {
|
|||||||
:configurationPeers="configurationPeers"
|
:configurationPeers="configurationPeers"
|
||||||
:configurationInfo="configurationInfo"
|
:configurationInfo="configurationInfo"
|
||||||
></PeerDataUsageCharts>
|
></PeerDataUsageCharts>
|
||||||
|
<hr>
|
||||||
|
<div style="margin-bottom: 80px">
|
||||||
|
<PeerSearch
|
||||||
|
@search="peerSearchBar = true"
|
||||||
|
@jobsAll="configurationModals.peerScheduleJobsAll.modalOpen = true"
|
||||||
|
@jobLogs="configurationModals.peerScheduleJobsLogs.modalOpen = true"
|
||||||
|
@editConfiguration="configurationModals.editConfiguration.modalOpen = true"
|
||||||
|
@selectPeers="configurationModals.selectPeers.modalOpen = true"
|
||||||
|
@backupRestore="configurationModals.backupRestore.modalOpen = true"
|
||||||
|
@deleteConfiguration="configurationModals.deleteConfiguration.modalOpen = true"
|
||||||
|
:configuration="configurationInfo">
|
||||||
|
</PeerSearch>
|
||||||
|
<TransitionGroup name="peerList" tag="div" class="row gx-2 gy-2 z-0 position-relative">
|
||||||
|
<div class="col-12 col-lg-6 col-xl-4"
|
||||||
|
:key="peer.id"
|
||||||
|
v-for="peer in searchPeers">
|
||||||
|
<Peer :Peer="peer"
|
||||||
|
@share="configurationModals.peerShare.selectedPeer = peer.id; this.peerShare.modalOpen = true;"
|
||||||
|
@refresh="fetchPeerList()"
|
||||||
|
@jobs="configurationModals.peerScheduleJobs.modalOpen = true; configurationModals.peerScheduleJobs.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)"
|
||||||
|
@setting="configurationModals.peerSetting.modalOpen = true; configurationModalSelectedPeer = peer"
|
||||||
|
@qrcode="(file) => {configurationModals.peerQRCode.peerConfigData = file; configurationModals.peerQRCode.modalOpen = true;}"
|
||||||
|
@configurationFile="(file) => {configurationModals.peerConfigurationFile.peerConfigData = file; configurationModals.peerConfigurationFile.modalOpen = true;}"
|
||||||
|
></Peer>
|
||||||
|
</div>
|
||||||
|
</TransitionGroup>
|
||||||
|
</div>
|
||||||
|
<Transition name="slideUp">
|
||||||
|
<PeerSearchBar @close="peerSearchBar = false" v-if="peerSearchBar"></PeerSearchBar>
|
||||||
|
</Transition>
|
||||||
|
<PeerListModals
|
||||||
|
:configurationModals="configurationModals"
|
||||||
|
:configurationModalSelectedPeer="configurationModalSelectedPeer"
|
||||||
|
></PeerListModals>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user