Finished job logs :)

This commit is contained in:
Donald Zou 2024-07-29 18:40:07 -04:00
parent b65828416f
commit 63e8553a09
16 changed files with 479 additions and 135 deletions

17
package-lock.json generated Normal file
View file

@ -0,0 +1,17 @@
{
"name": "Wireguard-Dashboard",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"dayjs": "^1.11.12"
}
},
"node_modules/dayjs": {
"version": "1.11.12",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz",
"integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg=="
}
}
}

5
package.json Normal file
View file

@ -0,0 +1,5 @@
{
"dependencies": {
"dayjs": "^1.11.12"
}
}

View file

@ -76,7 +76,7 @@ class CustomJsonEncoder(DefaultJSONProvider):
super().__init__(app) super().__init__(app)
def default(self, o): def default(self, o):
if isinstance(o, WireguardConfiguration) or isinstance(o, Peer) or isinstance(o, PeerJob): if isinstance(o, WireguardConfiguration) or isinstance(o, Peer) or isinstance(o, PeerJob) or isinstance(o, Log):
return o.toJson() return o.toJson()
return super().default(self, o) return super().default(self, o)
@ -99,6 +99,10 @@ class Log:
"Status": self.Status, "Status": self.Status,
"Message": self.Message "Message": self.Message
} }
def __dict__(self):
return self.toJson()
class Logger: class Logger:
def __init__(self): def __init__(self):
self.loggerdb = sqlite3.connect(os.path.join(CONFIGURATION_PATH, 'db', 'wgdashboard_log.db'), self.loggerdb = sqlite3.connect(os.path.join(CONFIGURATION_PATH, 'db', 'wgdashboard_log.db'),
@ -120,21 +124,26 @@ class Logger:
self.loggerdbCursor.execute(f"INSERT INTO JobLog (LogID, JobID, Status, Message) VALUES (?, ?, ?, ?)", self.loggerdbCursor.execute(f"INSERT INTO JobLog (LogID, JobID, Status, Message) VALUES (?, ?, ?, ?)",
(str(uuid.uuid4()), JobID, Status, Message,)) (str(uuid.uuid4()), JobID, Status, Message,))
self.loggerdb.commit() self.loggerdb.commit()
self.getLogs()
except Exception as e: except Exception as e:
print(e) print(e)
return False return False
return True return True
def getLogs(self, all: bool = False): def getLogs(self, all: bool = False, configName = None) -> list[Log]:
logs: list[Log] = []
try: try:
table = self.loggerdb.execute(f"SELECT * FROM JobLog ORDER BY LogDate DESC {'LIMIT 5' if not all else ''}").fetchall() allJobs = AllPeerJobs.getAllJobs(configName)
allJobsID = ", ".join([f"'{x.JobID}'" for x in allJobs])
table = self.loggerdb.execute(f"SELECT * FROM JobLog WHERE JobID IN ({allJobsID}) ORDER BY LogDate DESC").fetchall()
self.logs.clear() self.logs.clear()
for l in table: for l in table:
self.logs.append( logs.append(
Log(l["LogID"], l["JobID"], l["LogDate"], l["Status"], l["Message"])) Log(l["LogID"], l["JobID"], l["LogDate"], l["Status"], l["Message"]))
except Exception as e: except Exception as e:
pass return logs
return logs
@ -186,7 +195,18 @@ class PeerJobs:
self.Jobs.append(PeerJob( self.Jobs.append(PeerJob(
job['JobID'], job['Configuration'], job['Peer'], job['Field'], job['Operator'], job['Value'], job['JobID'], job['Configuration'], job['Peer'], job['Field'], job['Operator'], job['Value'],
job['CreationDate'], job['ExpireDate'], job['Action'])) job['CreationDate'], job['ExpireDate'], job['Action']))
# print(self.Jobs)
def getAllJobs(self, configuration: str = None):
if configuration is not None:
jobs = self.jobdbCursor.execute(
f"SELECT * FROM PeerJobs WHERE Configuration = ?", (configuration, )).fetchall()
j = []
for job in jobs:
j.append(PeerJob(
job['JobID'], job['Configuration'], job['Peer'], job['Field'], job['Operator'], job['Value'],
job['CreationDate'], job['ExpireDate'], job['Action']))
return j
return []
def __createPeerJobsDatabase(self): def __createPeerJobsDatabase(self):
existingTable = self.jobdbCursor.execute("SELECT name from sqlite_master where type='table'").fetchall() existingTable = self.jobdbCursor.execute("SELECT name from sqlite_master where type='table'").fetchall()
@ -239,21 +259,6 @@ class PeerJobs:
except Exception as e: except Exception as e:
return False, str(e) return False, str(e)
# def finishJob(self, Job: PeerJob) -> tuple[bool, list] | tuple[bool, str]:
# try:
# if (len(str(Job.CreationDate))) == 0:
# return False, "Job does not exist"
# self.jobdbCursor.execute('''
# UPDATE PeerJobs SET ExpireDate = strftime('%Y-%m-%d %H:%M:%S','now') WHERE JobId = ?
# ''', (Job.JobID,))
# self.jobdb.commit()
# self.__getJobs()
# return True, list(
# filter(lambda x: x.Configuration == Job.Configuration and x.Peer == Job.Peer and x.JobID == Job.JobID,
# self.Jobs))
# except Exception as e:
# return False, str(e)
def runJob(self): def runJob(self):
needToDelete = [] needToDelete = []
for job in self.Jobs: for job in self.Jobs:
@ -1555,6 +1560,17 @@ def API_deletePeerScheduleJob():
return ResponseObject(s, data=p) return ResponseObject(s, data=p)
return ResponseObject(s, message=p) return ResponseObject(s, message=p)
@app.route('/api/getPeerScheduleJobLogs/<configName>', methods=['GET'])
def API_getPeerScheduleJobLogs(configName):
if configName not in WireguardConfigurations.keys():
return ResponseObject(False, "Configuration does not exist")
data = request.args.get("requestAll")
requestAll = False
if data is not None and data == "true":
requestAll = True
return ResponseObject(data=JobLogger.getLogs(requestAll, configName))
''' '''
Tools Tools

View file

@ -14,7 +14,7 @@
"bootstrap": "^5.3.2", "bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.2", "bootstrap-icons": "^1.11.2",
"cidr-tools": "^7.0.4", "cidr-tools": "^7.0.4",
"dayjs": "^1.11.10", "dayjs": "^1.11.12",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"i": "^0.3.7", "i": "^0.3.7",
"is-cidr": "^5.0.3", "is-cidr": "^5.0.3",
@ -938,9 +938,9 @@
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
}, },
"node_modules/dayjs": { "node_modules/dayjs": {
"version": "1.11.10", "version": "1.11.12",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg=="
}, },
"node_modules/decamelize": { "node_modules/decamelize": {
"version": "1.2.0", "version": "1.2.0",

View file

@ -15,7 +15,7 @@
"bootstrap": "^5.3.2", "bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.2", "bootstrap-icons": "^1.11.2",
"cidr-tools": "^7.0.4", "cidr-tools": "^7.0.4",
"dayjs": "^1.11.10", "dayjs": "^1.11.12",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"i": "^0.3.7", "i": "^0.3.7",
"is-cidr": "^5.0.3", "is-cidr": "^5.0.3",

View file

@ -61,9 +61,9 @@ export default {
</div> </div>
</div> </div>
<div class="card-body pt-1" style="font-size: 0.9rem"> <div class="card-body pt-1" style="font-size: 0.9rem">
<h5> <h6>
{{Peer.name ? Peer.name : 'Untitled Peer'}} {{Peer.name ? Peer.name : 'Untitled Peer'}}
</h5> </h6>
<div class="mb-2"> <div class="mb-2">
<small class="text-muted">Public Key</small> <small class="text-muted">Public Key</small>
<p class="mb-0"><samp>{{Peer.id}}</samp></p> <p class="mb-0"><samp>{{Peer.id}}</samp></p>
@ -100,13 +100,14 @@ export default {
<style scoped> <style scoped>
.slide-fade-leave-active, .slide-fade-enter-active{ .slide-fade-leave-active, .slide-fade-enter-active{
transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1); transition: all 0.2s cubic-bezier(0.82, 0.58, 0.17, 0.9);
} }
.slide-fade-enter-from, .slide-fade-enter-from,
.slide-fade-leave-to { .slide-fade-leave-to {
transform: translateY(20px); transform: translateY(20px);
opacity: 0; opacity: 0;
filter: blur(3px);
} }
.subMenuBtn.active{ .subMenuBtn.active{
@ -114,7 +115,7 @@ export default {
} }
.peerCard{ .peerCard{
transition: box-shadow 0.1s cubic-bezier(1, 0.5, 0.8, 1); transition: box-shadow 0.1s cubic-bezier(0.82, 0.58, 0.17, 0.9);
} }
.peerCard:hover{ .peerCard:hover{

View file

@ -1,9 +1,13 @@
<script> <script>
import ScheduleDropdown from "@/components/configurationComponents/peerScheduleJobsComponents/scheduleDropdown.vue"; import ScheduleDropdown from "@/components/configurationComponents/peerScheduleJobsComponents/scheduleDropdown.vue";
import SchedulePeerJob from "@/components/configurationComponents/peerScheduleJobsComponents/schedulePeerJob.vue"; import SchedulePeerJob from "@/components/configurationComponents/peerScheduleJobsComponents/schedulePeerJob.vue";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
export default { export default {
name: "peerJobs", name: "peerJobs",
setup(){
const store = WireguardConfigurationsStore();
return {store}
},
props:{ props:{
selectedPeer: Object selectedPeer: Object
}, },
@ -13,78 +17,24 @@ export default {
}, },
data(){ data(){
return { return {
dropdowns: {
Field: [
{
display: "Total Received",
value: "total_receive",
unit: "GB",
type: 'number'
},
{
display: "Total Sent",
value: "total_sent",
unit: "GB",
type: 'number'
},
{
display: "Total Data",
value: "total_data",
unit: "GB",
type: 'number'
},
{
display: "Date",
value: "date",
type: 'date'
}
],
Operator: [
{
display: "equal",
value: "eq"
},
{
display: "not equal",
value: "neq"
},
{
display: "larger than",
value: "lgt"
},
{
display: "less than",
value: "lst"
},
],
Action: [
{
display: "Restrict Peer",
value: "restrict"
},
{
display: "Delete Peer",
value: "delete"
}
]
},
} }
}, },
methods:{ methods:{
deleteJob(j){ deleteJob(j){
this.selectedPeer.jobs = this.selectedPeer.jobs.filter(x => x.JobID !== j.JobID) this.selectedPeer.jobs = this.selectedPeer.jobs.filter(x => x.JobID !== j.JobID);
}, },
addJob(){ addJob(){
this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({ this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({
JobID: crypto.randomUUID(), JobID: crypto.randomUUID(),
Configuration: this.selectedPeer.configuration.Name, Configuration: this.selectedPeer.configuration.Name,
Peer: this.selectedPeer.id, Peer: this.selectedPeer.id,
Field: this.dropdowns.Field[0].value, Field: this.store.PeerScheduleJobs.dropdowns.Field[0].value,
Operator: this.dropdowns.Operator[0].value, Operator: this.store.PeerScheduleJobs.dropdowns.Operator[0].value,
Value: "", Value: "",
CreationDate: "", CreationDate: "",
ExpireDate: "", ExpireDate: "",
Action: this.dropdowns.Action[0].value Action: this.store.PeerScheduleJobs.dropdowns.Action[0].value
})) }))
) )
} }
@ -96,7 +46,7 @@ export default {
<template> <template>
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"> <div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
<div class="container d-flex h-100 w-100"> <div class="container d-flex h-100 w-100">
<div class="m-auto modal-dialog-centered dashboardModal mt-0"> <div class="m-auto modal-dialog-centered dashboardModal">
<div class="card rounded-3 shadow" style="width: 700px"> <div class="card rounded-3 shadow" style="width: 700px">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"> <div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
<h4 class="mb-0 fw-normal">Schedule Jobs <h4 class="mb-0 fw-normal">Schedule Jobs
@ -106,25 +56,26 @@ export default {
</div> </div>
<div class="card-body px-4 pb-4 pt-2 position-relative"> <div class="card-body px-4 pb-4 pt-2 position-relative">
<div class="d-flex align-items-center mb-3"> <div class="d-flex align-items-center mb-3">
<button class="btn btn-sm btn-primary rounded-3" @click="this.addJob()"> <button class="btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow"
@click="this.addJob()">
<i class="bi bi-plus-lg me-2"></i> Job <i class="bi bi-plus-lg me-2"></i> Job
</button> </button>
</div> </div>
<TransitionGroup name="schedulePeerJobTransition" tag="div" class="position-relative"> <TransitionGroup name="schedulePeerJobTransition" tag="div" class="position-relative">
<SchedulePeerJob <SchedulePeerJob
@refresh="(j) => this.selectedPeer.jobs[index] = j" @refresh="this.$emit('refresh')"
@delete="this.deleteJob(job)" @delete="this.deleteJob(job)"
:dropdowns="this.dropdowns" :dropdowns="this.store.PeerScheduleJobs.dropdowns"
:key="job.JobID" :key="job.JobID"
:pjob="job" v-for="(job, index) in this.selectedPeer.jobs"> :pjob="job" v-for="(job, index) in this.selectedPeer.jobs">
</SchedulePeerJob> </SchedulePeerJob>
<div class="card" key="none" v-if="this.selectedPeer.jobs.length === 0"> <div class="card shadow-sm" key="none"
<div class="card-body text-muted text-center"> style="height: 153px"
<h1><i class="bi bi-emoji-frown-fill"></i></h1> v-if="this.selectedPeer.jobs.length === 0">
<h6 class="mb-0">This peer does not have any job yet.</h6> <div class="card-body text-muted text-center d-flex">
<h6 class="m-auto">This peer does not have any job yet.</h6>
</div> </div>
</div> </div>
</TransitionGroup> </TransitionGroup>

View file

@ -0,0 +1,86 @@
<script>
import SchedulePeerJob from "@/components/configurationComponents/peerScheduleJobsComponents/schedulePeerJob.vue";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
import {v4} from "uuid";
export default {
name: "peerJobsAllModal",
setup(){
const store = WireguardConfigurationsStore();
return {store}
},
components: {SchedulePeerJob},
props: {
configurationPeers: Array[Object]
},
methods:{
getuuid(){
return v4();
}
},
computed:{
getAllJobs(){
return this.configurationPeers.filter(x => x.jobs.length > 0)
}
}
}
</script>
<template>
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
<div class="container d-flex h-100 w-100">
<div class="m-auto modal-dialog-centered dashboardModal">
<div class="card rounded-3 shadow" style="width: 700px">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
<h4 class="mb-0 fw-normal">All Active Jobs
</h4>
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
</div>
<div class="card-body px-4 pb-4 pt-2 ">
<div class="accordion" id="peerJobsLogsModalAccordion" v-if="this.getAllJobs.length > 0">
<div class="accordion-item" v-for="(p, index) in this.getAllJobs" :key="p.id">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
:data-bs-target="'#collapse_' + index">
<small>
<strong>
<span v-if="p.name">
{{p.name}} &#x2022;
</span>
<samp class="text-muted">{{p.id}}</samp>
</strong>
</small>
</button>
</h2>
<div :id="'collapse_' + index" class="accordion-collapse collapse"
data-bs-parent="#peerJobsLogsModalAccordion">
<div class="accordion-body">
<SchedulePeerJob
@delete="this.$emit('refresh')"
@refresh="this.$emit('refresh')"
:dropdowns="this.store.PeerScheduleJobs.dropdowns"
:viewOnly="true"
:key="job.JobID"
:pjob="job" v-for="job in p.jobs">
</SchedulePeerJob>
</div>
</div>
</div>
</div>
<div class="card shadow-sm"
style="height: 153px"
v-else>
<div class="card-body text-muted text-center d-flex">
<h6 class="m-auto">No active job at the moment.</h6>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
</style>

View file

@ -0,0 +1,162 @@
<script>
import dayjs from "dayjs";
import {fetchGet} from "@/utilities/fetch.js";
export default {
name: "peerJobsLogsModal",
props: {
configurationInfo: Object
},
data(){
return {
dataLoading: true,
data: [],
logFetchTime: undefined,
showLogID: false,
showJobID: true,
showSuccessJob: true,
showFailedJob: true,
showLogAmount: 10
}
},
async mounted(){
await this.fetchLog();
},
methods: {
async fetchLog(){
this.dataLoading = true;
await fetchGet(`/api/getPeerScheduleJobLogs/${this.configurationInfo.Name}`, {}, (res) => {
this.data = res.data;
this.logFetchTime = dayjs().format("YYYY-MM-DD HH:mm:ss")
this.dataLoading = false;
});
}
},
computed: {
getLogs(){
return this.data
.filter(x => {
return (this.showSuccessJob && x.Status === "1") || (this.showFailedJob && x.Status === "0")
})
},
showLogs(){
return this.getLogs.slice(0, this.showLogAmount);
}
}
}
</script>
<template>
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
<div class="container-fluid d-flex h-100 w-100">
<div class="m-auto mt-0 modal-dialog-centered dashboardModal" style="width: 100%">
<div class="card rounded-3 shadow w-100" >
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0">
<h4 class="mb-0">Jobs Logs</h4>
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
</div>
<div class="card-body px-4 pb-4 pt-2">
<div v-if="!this.dataLoading">
<p>Updated at: {{this.logFetchTime}}</p>
<div class="mb-2 d-flex gap-3">
<button @click="this.fetchLog()"
class="btn btn-sm rounded-3 shadow-sm
text-info-emphasis bg-info-subtle border-1 border-info-subtle me-1">
<i class="bi bi-arrow-clockwise me-2"></i>
Refresh
</button>
<div class="d-flex gap-3 align-items-center">
<span class="text-muted">Filter</span>
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="this.showSuccessJob"
id="jobLogsShowSuccessCheck">
<label class="form-check-label" for="jobLogsShowSuccessCheck">
<span class="badge text-success-emphasis bg-success-subtle">Success</span>
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="this.showFailedJob"
id="jobLogsShowFailedCheck">
<label class="form-check-label" for="jobLogsShowFailedCheck">
<span class="badge text-danger-emphasis bg-danger-subtle">Failed</span>
</label>
</div>
</div>
<div class="d-flex gap-3 align-items-center ms-auto">
<span class="text-muted">Display</span>
<div class="form-check">
<input class="form-check-input" type="checkbox"
v-model="showJobID"
id="jobLogsShowJobIDCheck">
<label class="form-check-label" for="jobLogsShowJobIDCheck">
Job ID
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox"
v-model="showLogID"
id="jobLogsShowLogIDCheck">
<label class="form-check-label" for="jobLogsShowLogIDCheck">
Log ID
</label>
</div>
</div>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">Date</th>
<th scope="col" v-if="showLogID">Log ID</th>
<th scope="col" v-if="showJobID">Job ID</th>
<th scope="col">Status</th>
<th scope="col">Message</th>
</tr>
</thead>
<tbody>
<tr v-for="log in this.showLogs" style="font-size: 0.875rem">
<th scope="row">{{log.LogDate}}</th>
<td v-if="showLogID"><samp class="text-muted">{{log.LogID}}</samp></td>
<td v-if="showJobID"><samp class="text-muted">{{log.JobID}}</samp></td>
<td>
<span class="badge" :class="[log.Status === '1' ? 'text-success-emphasis bg-success-subtle':'text-danger-emphasis bg-danger-subtle']">
{{log.Status === "1" ? 'Success': 'Failed'}}
</span>
</td>
<td>{{log.Message}}</td>
</tr>
</tbody>
</table>
<div class="d-flex gap-2">
<button v-if="this.getLogs.length > this.showLogAmount"
@click="this.showLogAmount += 20"
class="btn btn-sm rounded-3 shadow-sm
text-primary-emphasis bg-primary-subtle border-1 border-primary-subtle">
<i class="bi bi-chevron-down me-2"></i>
Show More
</button>
<button v-if="this.showLogAmount > 20"
@click="this.showLogAmount = 20"
class="btn btn-sm rounded-3 shadow-sm
text-primary-emphasis bg-primary-subtle border-1 border-primary-subtle">
<i class="bi bi-chevron-up me-2"></i>
Collapse
</button>
</div>
</div>
<div class="d-flex align-items-center flex-column" v-else>
<div class="spinner-border text-body" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
</style>

View file

@ -37,6 +37,8 @@ import PeerSettings from "@/components/configurationComponents/peerSettings.vue"
import PeerQRCode from "@/components/configurationComponents/peerQRCode.vue"; import PeerQRCode from "@/components/configurationComponents/peerQRCode.vue";
import PeerCreate from "@/components/configurationComponents/peerCreate.vue"; import PeerCreate from "@/components/configurationComponents/peerCreate.vue";
import PeerJobs from "@/components/configurationComponents/peerJobs.vue"; import PeerJobs from "@/components/configurationComponents/peerJobs.vue";
import PeerJobsAllModal from "@/components/configurationComponents/peerJobsAllModal.vue";
import PeerJobsLogsModal from "@/components/configurationComponents/peerJobsLogsModal.vue";
Chart.register( Chart.register(
ArcElement, ArcElement,
@ -66,7 +68,9 @@ Chart.register(
export default { export default {
name: "peerList", name: "peerList",
components: {PeerJobs, PeerCreate, PeerQRCode, PeerSettings, PeerSearch, Peer, Line, Bar}, components: {
PeerJobsLogsModal,
PeerJobsAllModal, PeerJobs, PeerCreate, PeerQRCode, PeerSettings, PeerSearch, Peer, Line, Bar},
setup(){ setup(){
const dashboardConfigurationStore = DashboardConfigurationStore(); const dashboardConfigurationStore = DashboardConfigurationStore();
const wireguardConfigurationStore = WireguardConfigurationsStore(); const wireguardConfigurationStore = WireguardConfigurationsStore();
@ -119,6 +123,12 @@ export default {
}, },
peerCreate: { peerCreate: {
modalOpen: false modalOpen: false
},
peerScheduleJobsAll: {
modalOpen: false
},
peerScheduleJobsLogs: {
modalOpen: false
} }
} }
}, },
@ -173,19 +183,6 @@ export default {
}, (res) => { }, (res) => {
this.configurationInfo = res.data.configurationInfo; this.configurationInfo = res.data.configurationInfo;
this.configurationPeers = res.data.configurationPeers; this.configurationPeers = res.data.configurationPeers;
// let modals = [this.peerSetting, this.peerScheduleJobs, this.peerQRCode]
// modals.forEach(x => {
//
// if (x.modalOpen && this.configurationPeers.find(p => p.id === x.selectedPeer.id)){
// x.selectedPeer = this.configurationPeers.find(p => p.id === x.selectedPeer.id)
// console.log(this.configurationPeers.find(p => p.id === x.selectedPeer.id))
// }else{
// x.modalOpen = false
// }
// })
this.configurationPeers.forEach(x => { this.configurationPeers.forEach(x => {
x.restricted = false; x.restricted = false;
}) })
@ -534,12 +531,16 @@ export default {
<!-- <div class="d-flex align-items-center gap-3 mb-2">--> <!-- <div class="d-flex align-items-center gap-3 mb-2">-->
<!-- <h3>Peers</h3>--> <!-- <h3>Peers</h3>-->
<!-- </div>--> <!-- </div>-->
<PeerSearch :configuration="this.configurationInfo"></PeerSearch> <PeerSearch
@jobsAll="this.peerScheduleJobsAll.modalOpen = true"
@jobLogs="this.peerScheduleJobsLogs.modalOpen = true"
:configuration="this.configurationInfo"></PeerSearch>
<TransitionGroup name="list" tag="div" class="row gx-2 gy-2 z-0"> <TransitionGroup name="list" tag="div" class="row gx-2 gy-2 z-0">
<div class="col-12 col-lg-6 col-xl-4" <div class="col-12 col-lg-6 col-xl-4"
:key="peer.id" :key="peer.id"
v-for="peer in this.searchPeers"> v-for="peer in this.searchPeers">
<Peer :Peer="peer" <Peer :Peer="peer"
@refresh="this.getPeers()" @refresh="this.getPeers()"
@jobs="peerScheduleJobs.modalOpen = true; peerScheduleJobs.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)" @jobs="peerScheduleJobs.modalOpen = true; peerScheduleJobs.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)"
@setting="peerSetting.modalOpen = true; peerSetting.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)" @setting="peerSetting.modalOpen = true; peerSetting.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)"
@ -548,7 +549,7 @@ export default {
</div> </div>
</TransitionGroup> </TransitionGroup>
</div> </div>
<Transition name="fade"> <Transition name="zoom">
<PeerSettings v-if="this.peerSetting.modalOpen" <PeerSettings v-if="this.peerSetting.modalOpen"
key="settings" key="settings"
:selectedPeer="this.peerSetting.selectedPeer" :selectedPeer="this.peerSetting.selectedPeer"
@ -556,13 +557,13 @@ export default {
@close="this.peerSetting.modalOpen = false"> @close="this.peerSetting.modalOpen = false">
</PeerSettings> </PeerSettings>
</Transition> </Transition>
<Transition name="fade"> <Transition name="zoom">
<PeerQRCode :peerConfigData="this.peerQRCode.peerConfigData" <PeerQRCode :peerConfigData="this.peerQRCode.peerConfigData"
key="qrcode" key="qrcode"
@close="this.peerQRCode.modalOpen = false" @close="this.peerQRCode.modalOpen = false"
v-if="peerQRCode.modalOpen"></PeerQRCode> v-if="peerQRCode.modalOpen"></PeerQRCode>
</Transition> </Transition>
<Transition name="fade"> <Transition name="zoom">
<PeerJobs <PeerJobs
@refresh="this.getPeers()" @refresh="this.getPeers()"
v-if="this.peerScheduleJobs.modalOpen" v-if="this.peerScheduleJobs.modalOpen"
@ -570,13 +571,22 @@ export default {
@close="this.peerScheduleJobs.modalOpen = false"> @close="this.peerScheduleJobs.modalOpen = false">
</PeerJobs> </PeerJobs>
</Transition> </Transition>
<Transition name="zoom">
<!-- <Transition name="fade">--> <PeerJobsAllModal
<!-- --> v-if="this.peerScheduleJobsAll.modalOpen"
<!-- </Transition>--> @refresh="this.getPeers()"
<!-- <Transition name="fade">--> @close="this.peerScheduleJobsAll.modalOpen = false"
<!-- --> :configurationPeers="this.configurationPeers"
<!-- </Transition>--> >
</PeerJobsAllModal>
</Transition>
<Transition name="zoom">
<PeerJobsLogsModal v-if="this.peerScheduleJobsLogs.modalOpen"
@close="this.peerScheduleJobsLogs.modalOpen = false"
:configurationInfo="this.configurationInfo"
>
</PeerJobsLogsModal>
</Transition>
</div> </div>
</template> </template>

View file

@ -6,7 +6,8 @@ export default {
peerConfigData: String peerConfigData: String
}, },
mounted() { mounted() {
QRCode.toCanvas(document.querySelector("#qrcode"), this.peerConfigData , function (error) { QRCode.toCanvas(document.querySelector("#qrcode"), this.peerConfigData , (error) => {
console.log(this.peerConfigData)
if (error) console.error(error) if (error) console.error(error)
}) })
} }
@ -14,10 +15,10 @@ export default {
</script> </script>
<template> <template>
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"> <div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0">
<div class="container d-flex h-100 w-100 m-auto"> <div class="container d-flex h-100 w-100">
<div class="modal-dialog-centered dashboardModal"> <div class="m-auto modal-dialog-centered dashboardModal justify-content-center">
<div class="card m-auto rounded-3 shadow"> <div class="card rounded-3 shadow">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"> <div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0">
<h4 class="mb-0">QR Code</h4> <h4 class="mb-0">QR Code</h4>
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button> <button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>

View file

@ -9,7 +9,8 @@ export default {
components: {ScheduleDropdown}, components: {ScheduleDropdown},
props: { props: {
dropdowns: Array[Object], dropdowns: Array[Object],
pjob: Object pjob: Object,
viewOnly: false
}, },
setup(props){ setup(props){
const job = ref({}) const job = ref({})

View file

@ -137,6 +137,28 @@ export default {
</a></li> </a></li>
</ul> </ul>
</div> </div>
<div class="dropdown">
<button class="btn dropdown-toggle text-secondary-emphasis bg-secondary-subtle rounded-3 border-1 border-secondary-subtle shadow-sm"
type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-three-dots me-2"></i>More
</button>
<ul class="dropdown-menu shadow mt-2 rounded-3">
<li>
<h6 class="dropdown-header">Peer Jobs</h6>
</li>
<li>
<a role="button" class="dropdown-item" @click="this.$emit('jobsAll')">
All Active Jobs
</a>
</li>
<li>
<a role="button" class="dropdown-item" @click="this.$emit('jobLogs')">
Logs
</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
</template> </template>

View file

@ -53,7 +53,7 @@ export default {
</script> </script>
<template> <template>
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0"> <div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
<div class="container d-flex h-100 w-100"> <div class="container d-flex h-100 w-100">
<div class="m-auto modal-dialog-centered dashboardModal"> <div class="m-auto modal-dialog-centered dashboardModal">
<div class="card rounded-3 shadow flex-grow-1"> <div class="card rounded-3 shadow flex-grow-1">

View file

@ -5,7 +5,64 @@ import isCidr from "is-cidr";
export const WireguardConfigurationsStore = defineStore('WireguardConfigurationsStore', { export const WireguardConfigurationsStore = defineStore('WireguardConfigurationsStore', {
state: () => ({ state: () => ({
Configurations: undefined, Configurations: undefined,
searchString: "" searchString: "",
PeerScheduleJobs: {
dropdowns: {
Field: [
{
display: "Total Received",
value: "total_receive",
unit: "GB",
type: 'number'
},
{
display: "Total Sent",
value: "total_sent",
unit: "GB",
type: 'number'
},
{
display: "Total Data",
value: "total_data",
unit: "GB",
type: 'number'
},
{
display: "Date",
value: "date",
type: 'date'
}
],
Operator: [
{
display: "equal",
value: "eq"
},
{
display: "not equal",
value: "neq"
},
{
display: "larger than",
value: "lgt"
},
{
display: "less than",
value: "lst"
},
],
Action: [
{
display: "Restrict Peer",
value: "restrict"
},
{
display: "Delete Peer",
value: "delete"
}
]
}
}
}), }),
actions: { actions: {
async getConfigurations(){ async getConfigurations(){

View file

@ -1119,6 +1119,7 @@ pre.index-alert {
.peerSettingContainer { .peerSettingContainer {
background-color: #00000060; background-color: #00000060;
z-index: 9999; z-index: 9999;
backdrop-filter: blur(1px);
} }
.dashboardModal{ .dashboardModal{
@ -1128,4 +1129,18 @@ pre.index-alert {
.dashboardModal > .card{ .dashboardModal > .card{
margin: 1.75rem; margin: 1.75rem;
} }
.zoom-enter-active,
.zoom-leave-active {
transition: all 0.3s cubic-bezier(0.82, 0.58, 0.17, 0.9);
/*position: absolute;*/
/*padding-top: 50px*/
}
.zoom-enter-from,
.zoom-leave-to {
transform: scale(1.1);
filter: blur(3px);
opacity: 0;
}