mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-07-10 15:16:58 +00:00
Refactoring configuration list
This commit is contained in:
parent
ccfc1ad166
commit
cd9d17ab18
@ -563,7 +563,6 @@ class WireguardConfiguration:
|
|||||||
return False, err
|
return False, err
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
|
||||||
def __parseConfigurationFile(self):
|
def __parseConfigurationFile(self):
|
||||||
with open(self.configPath, 'r') as f:
|
with open(self.configPath, 'r') as f:
|
||||||
original = [l.rstrip("\n") for l in f.readlines()]
|
original = [l.rstrip("\n") for l in f.readlines()]
|
||||||
@ -1095,7 +1094,6 @@ class WireguardConfiguration:
|
|||||||
"backupDate": datetime.now().strftime("%Y%m%d%H%M%S")
|
"backupDate": datetime.now().strftime("%Y%m%d%H%M%S")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def getBackups(self, databaseContent: bool = False) -> list[dict[str: str, str: str, str: str]]:
|
def getBackups(self, databaseContent: bool = False) -> list[dict[str: str, str: str, str: str]]:
|
||||||
backups = []
|
backups = []
|
||||||
|
|
||||||
@ -1171,9 +1169,6 @@ class WireguardConfiguration:
|
|||||||
|
|
||||||
return True, zip
|
return True, zip
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def updateConfigurationSettings(self, newData: dict) -> tuple[bool, str]:
|
def updateConfigurationSettings(self, newData: dict) -> tuple[bool, str]:
|
||||||
if self.Status:
|
if self.Status:
|
||||||
self.toggleConfiguration()
|
self.toggleConfiguration()
|
||||||
@ -1208,6 +1203,11 @@ class WireguardConfiguration:
|
|||||||
status, msg = self.toggleConfiguration()
|
status, msg = self.toggleConfiguration()
|
||||||
if not status:
|
if not status:
|
||||||
return False, msg
|
return False, msg
|
||||||
|
for i in allowEdit:
|
||||||
|
if isinstance(getattr(self, i), bool):
|
||||||
|
setattr(self, i, _strToBool(newData[i]))
|
||||||
|
else:
|
||||||
|
setattr(self, i, str(newData[i]))
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
def deleteConfiguration(self):
|
def deleteConfiguration(self):
|
||||||
@ -1274,6 +1274,29 @@ class WireguardConfiguration:
|
|||||||
break
|
break
|
||||||
return True, availableAddress
|
return True, availableAddress
|
||||||
|
|
||||||
|
def getRealtimeTrafficUsage(self):
|
||||||
|
stats = psutil.net_io_counters(pernic=True, nowrap=True)
|
||||||
|
if self.Name in stats.keys():
|
||||||
|
stat = stats[self.Name]
|
||||||
|
recv1 = stat.bytes_recv
|
||||||
|
sent1 = stat.bytes_sent
|
||||||
|
time.sleep(1)
|
||||||
|
stats = psutil.net_io_counters(pernic=True, nowrap=True)
|
||||||
|
if self.Name in stats.keys():
|
||||||
|
stat = stats[self.Name]
|
||||||
|
recv2 = stat.bytes_recv
|
||||||
|
sent2 = stat.bytes_sent
|
||||||
|
net_in = round((recv2 - recv1) / 1024 / 1024, 3)
|
||||||
|
net_out = round((sent2 - sent1) / 1024 / 1024, 3)
|
||||||
|
return {
|
||||||
|
"sent": net_out,
|
||||||
|
"recv": net_in
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return { "sent": 0, "recv": 0 }
|
||||||
|
else:
|
||||||
|
return { "sent": 0, "recv": 0 }
|
||||||
|
|
||||||
"""
|
"""
|
||||||
AmneziaWG Configuration
|
AmneziaWG Configuration
|
||||||
"""
|
"""
|
||||||
@ -2039,7 +2062,6 @@ def sqlSelect(statement: str, paramters: tuple = ()) -> sqlite3.Cursor:
|
|||||||
result = []
|
result = []
|
||||||
with sqldb:
|
with sqldb:
|
||||||
try:
|
try:
|
||||||
print("[WGDashboard] SQLite Select" + " | Statement: " + statement)
|
|
||||||
cursor = sqldb.cursor()
|
cursor = sqldb.cursor()
|
||||||
result = cursor.execute(statement, paramters)
|
result = cursor.execute(statement, paramters)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
@ -2327,6 +2349,13 @@ def API_renameWireguardConfiguration():
|
|||||||
WireguardConfigurations[data.get("NewConfigurationName")] = WireguardConfiguration(data.get("NewConfigurationName"))
|
WireguardConfigurations[data.get("NewConfigurationName")] = WireguardConfiguration(data.get("NewConfigurationName"))
|
||||||
return ResponseObject(status, message)
|
return ResponseObject(status, message)
|
||||||
|
|
||||||
|
@app.get(f'{APP_PREFIX}/api/getWireguardConfigurationRealtimeTraffic')
|
||||||
|
def API_getWireguardConfigurationRealtimeTraffic():
|
||||||
|
configurationName = request.args.get('configurationName')
|
||||||
|
if configurationName is None or configurationName not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Configuration does not exist")
|
||||||
|
return ResponseObject(data=WireguardConfigurations[configurationName].getRealtimeTrafficUsage())
|
||||||
|
|
||||||
@app.get(f'{APP_PREFIX}/api/getWireguardConfigurationBackup')
|
@app.get(f'{APP_PREFIX}/api/getWireguardConfigurationBackup')
|
||||||
def API_getWireguardConfigurationBackup():
|
def API_getWireguardConfigurationBackup():
|
||||||
configurationName = request.args.get('configurationName')
|
configurationName = request.args.get('configurationName')
|
||||||
|
@ -24,12 +24,7 @@ onBeforeUnmount(() =>{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="text-center">
|
<div style="margin-bottom: 20px; height: 1px" id="loadMore"></div>
|
||||||
<small v-if="peerListLength < showPeersCount" class="text-muted">
|
|
||||||
That's it, no more peers
|
|
||||||
</small>
|
|
||||||
<div style="margin-bottom: 20px; height: 1px" id="loadMore"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -79,7 +79,7 @@ export default {
|
|||||||
Line,
|
Line,
|
||||||
Bar
|
Bar
|
||||||
},
|
},
|
||||||
setup(){
|
async setup(){
|
||||||
const dashboardConfigurationStore = DashboardConfigurationStore();
|
const dashboardConfigurationStore = DashboardConfigurationStore();
|
||||||
const wireguardConfigurationStore = WireguardConfigurationsStore();
|
const wireguardConfigurationStore = WireguardConfigurationsStore();
|
||||||
const interval = ref(undefined)
|
const interval = ref(undefined)
|
||||||
@ -284,9 +284,6 @@ export default {
|
|||||||
this.getPeers()
|
this.getPeers()
|
||||||
}, parseInt(this.dashboardConfigurationStore.Configuration.Server.dashboard_refresh_interval))
|
}, parseInt(this.dashboardConfigurationStore.Configuration.Server.dashboard_refresh_interval))
|
||||||
},
|
},
|
||||||
disableMutationObserver(){
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
configurationSummary(){
|
configurationSummary(){
|
||||||
|
@ -0,0 +1,263 @@
|
|||||||
|
<script setup>
|
||||||
|
import {computed, defineComponent, onBeforeUnmount, onMounted, reactive, ref, useTemplateRef, watch} from "vue";
|
||||||
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
|
import { Line, Bar } from 'vue-chartjs'
|
||||||
|
import {
|
||||||
|
Chart,
|
||||||
|
LineElement,
|
||||||
|
BarElement,
|
||||||
|
BarController,
|
||||||
|
LineController,
|
||||||
|
LinearScale,
|
||||||
|
Legend,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
CategoryScale,
|
||||||
|
PointElement
|
||||||
|
} from 'chart.js';
|
||||||
|
Chart.register(
|
||||||
|
LineElement,
|
||||||
|
BarElement,
|
||||||
|
BarController,
|
||||||
|
LineController,
|
||||||
|
LinearScale,
|
||||||
|
Legend,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
CategoryScale,
|
||||||
|
PointElement
|
||||||
|
);
|
||||||
|
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
const props = defineProps({
|
||||||
|
configurationPeers: Array,
|
||||||
|
configurationInfo: Object
|
||||||
|
})
|
||||||
|
|
||||||
|
const historySentData = ref({
|
||||||
|
timestamp: [],
|
||||||
|
data: []
|
||||||
|
})
|
||||||
|
|
||||||
|
const historyReceivedData = ref({
|
||||||
|
timestamp: [],
|
||||||
|
data: []
|
||||||
|
})
|
||||||
|
|
||||||
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
|
const fetchRealtimeTrafficInterval = ref(undefined)
|
||||||
|
const fetchRealtimeTraffic = async () => {
|
||||||
|
await fetchGet("/api/getWireguardConfigurationRealtimeTraffic", {
|
||||||
|
configurationName: "wg1"
|
||||||
|
}, (res) => {
|
||||||
|
let timestamp = dayjs().format("hh:mm:ss A")
|
||||||
|
|
||||||
|
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 = () => {
|
||||||
|
clearInterval(fetchRealtimeTrafficInterval.value)
|
||||||
|
fetchRealtimeTrafficInterval.value = undefined;
|
||||||
|
if (props.configurationInfo.Status){
|
||||||
|
fetchRealtimeTrafficInterval.value = setInterval(() => {
|
||||||
|
fetchRealtimeTraffic()
|
||||||
|
}, parseInt(dashboardStore.Configuration.Server.dashboard_refresh_interval))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
toggleFetchRealtimeTraffic()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.configurationInfo.Status, () => {
|
||||||
|
toggleFetchRealtimeTraffic()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => dashboardStore.Configuration.Server.dashboard_refresh_interval, () => {
|
||||||
|
toggleFetchRealtimeTraffic()
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearInterval(fetchRealtimeTrafficInterval.value)
|
||||||
|
fetchRealtimeTrafficInterval.value = undefined;
|
||||||
|
})
|
||||||
|
const peersDataUsageChartData = computed(() => {
|
||||||
|
return {
|
||||||
|
labels: props.configurationPeers.map(x => {
|
||||||
|
if (x.name) return x.name
|
||||||
|
return `Untitled Peer - ${x.id}`
|
||||||
|
}),
|
||||||
|
datasets: [{
|
||||||
|
label: 'Total Data Usage',
|
||||||
|
data: props.configurationPeers.map(x => x.cumu_data + x.total_data),
|
||||||
|
backgroundColor: props.configurationPeers.map(x => `#ffc107`),
|
||||||
|
barThickness: 50,
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: (tooltipItem) => {
|
||||||
|
return `${tooltipItem.formattedValue} GB`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const peersRealtimeSentData = computed(() => {
|
||||||
|
return {
|
||||||
|
labels: [...historySentData.value.timestamp],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Data Sent',
|
||||||
|
data: [...historySentData.value.data],
|
||||||
|
fill: false,
|
||||||
|
borderColor: '#198754',
|
||||||
|
backgroundColor: '#198754',
|
||||||
|
tension: 0
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const peersRealtimeReceivedData = computed(() => {
|
||||||
|
return {
|
||||||
|
labels: [...historyReceivedData.value.timestamp],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Data Received',
|
||||||
|
data: [...historyReceivedData.value.data],
|
||||||
|
fill: false,
|
||||||
|
borderColor: '#0d6efd',
|
||||||
|
tension: 0
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const peersDataUsageChartOption = computed(() => {
|
||||||
|
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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const realtimePeersChartOption = computed(() => {
|
||||||
|
return {
|
||||||
|
responsive: true,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: (tooltipItem) => {
|
||||||
|
return `${tooltipItem.formattedValue} MB/s`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
ticks: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y:{
|
||||||
|
ticks: {
|
||||||
|
callback: (val, index) => {
|
||||||
|
return `${Math.round((val + Number.EPSILON) * 1000) / 1000
|
||||||
|
} MB/s`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="row gx-2 gy-2 mb-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
||||||
|
<div class="card-header bg-transparent border-0">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="Peers Data Usage"></LocaleText>
|
||||||
|
</small></div>
|
||||||
|
<div class="card-body pt-1">
|
||||||
|
<Bar
|
||||||
|
:data="peersDataUsageChartData"
|
||||||
|
:options="peersDataUsageChartOption"
|
||||||
|
style="width: 100%; height: 200px; max-height: 200px"></Bar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm col-lg-6">
|
||||||
|
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
||||||
|
<div class="card-header bg-transparent border-0"><small class="text-muted">
|
||||||
|
<LocaleText t="Real Time Received Data Usage"></LocaleText>
|
||||||
|
</small></div>
|
||||||
|
<div class="card-body pt-1">
|
||||||
|
<Line
|
||||||
|
:options="realtimePeersChartOption"
|
||||||
|
:data="peersRealtimeReceivedData"
|
||||||
|
style="width: 100%; height: 200px; max-height: 200px"
|
||||||
|
></Line>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm col-lg-6">
|
||||||
|
<div class="card rounded-3 bg-transparent " style="height: 270px">
|
||||||
|
<div class="card-header bg-transparent border-0"><small class="text-muted">
|
||||||
|
<LocaleText t="Real Time Sent Data Usage"></LocaleText>
|
||||||
|
</small></div>
|
||||||
|
<div class="card-body pt-1">
|
||||||
|
<Line
|
||||||
|
:options="realtimePeersChartOption"
|
||||||
|
:data="peersRealtimeSentData"
|
||||||
|
|
||||||
|
style="width: 100%; height: 200px; max-height: 200px"
|
||||||
|
></Line>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,23 @@
|
|||||||
|
<script setup>
|
||||||
|
import {defineAsyncComponent} from "vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
const DeleteConfigurationModal = defineAsyncComponent(() => import("@/components/configurationComponents/deleteConfiguration.vue"))
|
||||||
|
const ConfigurationBackupRestoreModal = defineAsyncComponent(() => import("@/components/configurationComponents/configurationBackupRestore.vue"))
|
||||||
|
const SelectPeersModal = defineAsyncComponent(() => import("@/components/configurationComponents/selectPeers.vue"))
|
||||||
|
const EditConfigurationModal = defineAsyncComponent(() => import("@/components/configurationComponents/editConfiguration.vue"))
|
||||||
|
const PeerShareLinkModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerShareLinkModal.vue"))
|
||||||
|
const PeerJobsLogsModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobsLogsModal.vue"))
|
||||||
|
const PeerJobsAllModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobsAllModal.vue"))
|
||||||
|
const PeerJobsModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerJobs.vue"))
|
||||||
|
const PeerQRCodeModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerQRCode.vue"))
|
||||||
|
const PeerConfigurationFileModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerConfigurationFile.vue"))
|
||||||
|
const PeerSettingsModal = defineAsyncComponent(() => import("@/components/configurationComponents/peerSettings.vue"))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,287 @@
|
|||||||
|
<script setup async>
|
||||||
|
import {computed, onBeforeUnmount, ref, watch} from "vue";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
|
import ProtocolBadge from "@/components/protocolBadge.vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
|
import PeerDataUsageCharts from "@/components/configurationComponents/peerListComponents/peerDataUsageCharts.vue";
|
||||||
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
|
const wireguardConfigurationStore = WireguardConfigurationsStore()
|
||||||
|
const route = useRoute()
|
||||||
|
const configurationInfo = ref({})
|
||||||
|
const configurationPeers = ref([])
|
||||||
|
const configurationToggling = ref(false)
|
||||||
|
const configurationModals = ref({
|
||||||
|
peerSetting: {
|
||||||
|
modalOpen: false,
|
||||||
|
},
|
||||||
|
peerScheduleJobs:{
|
||||||
|
modalOpen: false,
|
||||||
|
},
|
||||||
|
peerQRCode: {
|
||||||
|
modalOpen: false,
|
||||||
|
},
|
||||||
|
peerConfigurationFile: {
|
||||||
|
modalOpen: false,
|
||||||
|
},
|
||||||
|
peerCreate: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
peerScheduleJobsAll: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
peerScheduleJobsLogs: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
peerShare:{
|
||||||
|
modalOpen: false,
|
||||||
|
},
|
||||||
|
editConfiguration: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
selectPeers: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
backupRestore: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
deleteConfiguration: {
|
||||||
|
modalOpen: false
|
||||||
|
},
|
||||||
|
editRawConfigurationFile: {
|
||||||
|
modalOpen: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fetch Peer =====================================
|
||||||
|
const fetchPeerList = async () => {
|
||||||
|
await fetchGet("/api/getWireguardConfigurationInfo", {
|
||||||
|
configurationName: route.params.id
|
||||||
|
}, (res) => {
|
||||||
|
if (res.status){
|
||||||
|
configurationInfo.value = res.data.configurationInfo;
|
||||||
|
configurationPeers.value = res.data.configurationPeers;
|
||||||
|
|
||||||
|
configurationPeers.value.forEach(p => {
|
||||||
|
p.restricted = false
|
||||||
|
})
|
||||||
|
res.data.configurationRestrictedPeers.forEach(x => {
|
||||||
|
x.restricted = true;
|
||||||
|
configurationPeers.value.push(x)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await fetchPeerList()
|
||||||
|
|
||||||
|
// Fetch Peer Interval =====================================
|
||||||
|
const fetchPeerListInterval = ref(undefined)
|
||||||
|
const setFetchPeerListInterval = () => {
|
||||||
|
clearInterval(fetchPeerListInterval.value)
|
||||||
|
fetchPeerListInterval.value = setInterval(async () => {
|
||||||
|
await fetchPeerList()
|
||||||
|
}, parseInt(dashboardStore.Configuration.Server.dashboard_refresh_interval))
|
||||||
|
}
|
||||||
|
setFetchPeerListInterval()
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearInterval(fetchPeerListInterval.value);
|
||||||
|
fetchPeerListInterval.value = undefined;
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => {
|
||||||
|
return dashboardStore.Configuration.Server.dashboard_refresh_interval
|
||||||
|
}, () => {
|
||||||
|
setFetchPeerListInterval()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Toggle Configuration Method =====================================
|
||||||
|
const toggleConfiguration = async () => {
|
||||||
|
configurationToggling.value = true;
|
||||||
|
await fetchGet("/api/toggleWireguardConfiguration/", {
|
||||||
|
configurationName: configurationInfo.value.Name
|
||||||
|
}, (res) => {
|
||||||
|
if (res.status){
|
||||||
|
dashboardStore.newMessage("Server",
|
||||||
|
`${configurationInfo.value.Name} ${res.data ? 'is on':'is off'}`, "success")
|
||||||
|
}else{
|
||||||
|
dashboardStore.newMessage("Server", res.message, 'danger')
|
||||||
|
}
|
||||||
|
wireguardConfigurationStore.Configurations
|
||||||
|
.find(x => x.Name === configurationInfo.value.Name).Status = res.data
|
||||||
|
configurationInfo.value.Status = res.data
|
||||||
|
configurationToggling.value = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration Summary =====================================
|
||||||
|
const configurationSummary = computed(() => {
|
||||||
|
return {
|
||||||
|
connectedPeers: configurationPeers.value.filter(x => x.status === "running").length,
|
||||||
|
totalUsage: configurationPeers.value.length > 0 ?
|
||||||
|
configurationPeers.value.filter(x => !x.restricted)
|
||||||
|
.map(x => x.total_data + x.cumu_data).reduce((a, b) => a + b, 0).toFixed(4) : 0,
|
||||||
|
totalReceive: configurationPeers.value.length > 0 ?
|
||||||
|
configurationPeers.value.filter(x => !x.restricted)
|
||||||
|
.map(x => x.total_receive + x.cumu_receive).reduce((a, b) => a + b, 0).toFixed(4) : 0,
|
||||||
|
totalSent: configurationPeers.value.length > 0 ?
|
||||||
|
configurationPeers.value.filter(x => !x.restricted)
|
||||||
|
.map(x => x.total_sent + x.cumu_sent).reduce((a, b) => a + b, 0).toFixed(4) : 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="container-md" >
|
||||||
|
<div class="d-flex align-items-sm-center flex-column flex-sm-row gap-3">
|
||||||
|
<div>
|
||||||
|
<div class="text-muted d-flex align-items-center gap-2">
|
||||||
|
<h5 class="mb-0">
|
||||||
|
<ProtocolBadge :protocol="configurationInfo.Protocol"></ProtocolBadge>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<h1 class="mb-0 display-4"><samp>{{configurationInfo.Name}}</samp></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-sm-auto d-flex gap-2 flex-column">
|
||||||
|
<div class="card rounded-3 bg-transparent ">
|
||||||
|
<div class="card-body py-2 d-flex align-items-center">
|
||||||
|
<small class="text-muted">
|
||||||
|
<LocaleText t="Status"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<div class="dot ms-2" :class="{active: configurationInfo.Status}"></div>
|
||||||
|
<div class="form-check form-switch mb-0 ms-auto pe-0 me-0">
|
||||||
|
<label class="form-check-label" style="cursor: pointer" :for="'switch' + configurationInfo.id">
|
||||||
|
<LocaleText t="On" v-if="configurationInfo.Status && !configurationToggling"></LocaleText>
|
||||||
|
<LocaleText t="Off" v-else-if="!configurationInfo.Status && !configurationToggling"></LocaleText>
|
||||||
|
<span v-if="configurationToggling"
|
||||||
|
class="spinner-border spinner-border-sm ms-2" aria-hidden="true">
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input class="form-check-input"
|
||||||
|
style="cursor: pointer"
|
||||||
|
:disabled="configurationToggling"
|
||||||
|
type="checkbox" role="switch" :id="'switch' + configurationInfo.id"
|
||||||
|
@change="toggleConfiguration()"
|
||||||
|
v-model="configurationInfo.Status">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<RouterLink
|
||||||
|
to="create"
|
||||||
|
class="titleBtn py-2 text-decoration-none btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle ">
|
||||||
|
<i class="bi bi-plus-lg me-2"></i>
|
||||||
|
<LocaleText t="Peer"></LocaleText>
|
||||||
|
</RouterLink>
|
||||||
|
<button class="titleBtn py-2 text-decoration-none btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle "
|
||||||
|
@click="configurationModals.editConfiguration.modalOpen = true"
|
||||||
|
type="button" aria-expanded="false">
|
||||||
|
<i class="bi bi-gear-fill me-2"></i>
|
||||||
|
<LocaleText t="Configuration Settings"></LocaleText>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="row mt-3 gy-2 gx-2 mb-2">
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body py-2 d-flex flex-column justify-content-center">
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Address"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
{{configurationInfo.Address}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body py-2 d-flex flex-column justify-content-center">
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Listen Port"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
{{configurationInfo.ListenPort}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="word-break: break-all" class="col-12 col-lg-6">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body py-2 d-flex flex-column justify-content-center">
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Public Key"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
<samp>{{configurationInfo.PublicKey}}</samp>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row gx-2 gy-2 mb-2">
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body d-flex">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Connected Peers"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
<strong class="h4">
|
||||||
|
{{configurationSummary.connectedPeers}} / {{configurationPeers.length}}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<i class="bi bi-ethernet ms-auto h2 text-muted"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body d-flex">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Total Usage"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
<strong class="h4">{{configurationSummary.totalUsage}} GB</strong>
|
||||||
|
</div>
|
||||||
|
<i class="bi bi-arrow-down-up ms-auto h2 text-muted"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body d-flex">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Total Received"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
<strong class="h4 text-primary">{{configurationSummary.totalReceive}} GB</strong>
|
||||||
|
</div>
|
||||||
|
<i class="bi bi-arrow-down ms-auto h2 text-muted"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="card rounded-3 bg-transparent h-100">
|
||||||
|
<div class="card-body d-flex">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 text-muted"><small>
|
||||||
|
<LocaleText t="Total Sent"></LocaleText>
|
||||||
|
</small></p>
|
||||||
|
<strong class="h4 text-success">{{configurationSummary.totalSent}} GB</strong>
|
||||||
|
</div>
|
||||||
|
<i class="bi bi-arrow-up ms-auto h2 text-muted"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<PeerDataUsageCharts
|
||||||
|
:configurationPeers="configurationPeers"
|
||||||
|
:configurationInfo="configurationInfo"
|
||||||
|
></PeerDataUsageCharts>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,11 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onBeforeUnmount, onMounted, ref} from "vue";
|
import {computed, onBeforeUnmount, onMounted, ref} from "vue";
|
||||||
import {fetchGet} from "@/utilities/fetch.js";
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
import CpuCore from "@/components/systemStatusComponents/cpuCore.vue";
|
import CpuCore from "@/components/systemStatusComponents/cpuCore.vue";
|
||||||
import StorageMount from "@/components/systemStatusComponents/storageMount.vue";
|
import StorageMount from "@/components/systemStatusComponents/storageMount.vue";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
|
||||||
const data = ref(undefined)
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
|
|
||||||
|
// const data = ref(undefined)
|
||||||
let interval = null;
|
let interval = null;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -21,9 +24,13 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
const getData = () => {
|
const getData = () => {
|
||||||
fetchGet("/api/systemStatus", {}, (res) => {
|
fetchGet("/api/systemStatus", {}, (res) => {
|
||||||
data.value = res.data
|
dashboardStore.SystemStatus = res.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = computed(() => {
|
||||||
|
return dashboardStore.SystemStatus
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -91,7 +91,7 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
name: "Peers List",
|
name: "Peers List",
|
||||||
path: 'peers',
|
path: 'peers',
|
||||||
component: () => import('@/components/configurationComponents/peerList.vue')
|
component: () => import('@/components/configurationComponents/peerListNew.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Peers Create",
|
name: "Peers Create",
|
||||||
|
@ -16,6 +16,7 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
|
|||||||
Enable: false,
|
Enable: false,
|
||||||
ServerList: {}
|
ServerList: {}
|
||||||
},
|
},
|
||||||
|
SystemStatus: undefined,
|
||||||
ActiveServerConfiguration: undefined,
|
ActiveServerConfiguration: undefined,
|
||||||
IsElectronApp: false,
|
IsElectronApp: false,
|
||||||
ShowNavBar: false,
|
ShowNavBar: false,
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onBeforeUnmount, onMounted, ref} from "vue";
|
import {computed, onBeforeUnmount, onMounted, ref} from "vue";
|
||||||
import {fetchGet} from "@/utilities/fetch.js";
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
import CpuCore from "@/components/systemStatusComponents/cpuCore.vue";
|
import CpuCore from "@/components/systemStatusComponents/cpuCore.vue";
|
||||||
import StorageMount from "@/components/systemStatusComponents/storageMount.vue";
|
import StorageMount from "@/components/systemStatusComponents/storageMount.vue";
|
||||||
import Process from "@/components/systemStatusComponents/process.vue";
|
import Process from "@/components/systemStatusComponents/process.vue";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
|
||||||
const data = ref(undefined)
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
|
const data = computed(() => {
|
||||||
|
return dashboardStore.SystemStatus
|
||||||
|
})
|
||||||
let interval = null;
|
let interval = null;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -22,7 +26,7 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
const getData = () => {
|
const getData = () => {
|
||||||
fetchGet("/api/systemStatus", {}, (res) => {
|
fetchGet("/api/systemStatus", {}, (res) => {
|
||||||
data.value = res.data
|
dashboardStore.SystemStatus = res.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user