mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-06-28 09:16:55 +00:00
Update
This commit is contained in:
parent
85d4b8c487
commit
d80eb03707
@ -101,4 +101,9 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
|||||||
def ClientAPI_Configurations():
|
def ClientAPI_Configurations():
|
||||||
return ResponseObject(True, data=DashboardClients.GetClientAssignedPeers(session['ClientID']))
|
return ResponseObject(True, data=DashboardClients.GetClientAssignedPeers(session['ClientID']))
|
||||||
|
|
||||||
|
@client.get(f'{prefix}/api/settings/getClientProfile')
|
||||||
|
@login_required
|
||||||
|
def ClientAPI_Settings_GetClientProfile():
|
||||||
|
return ResponseObject(data=DashboardClients.GetClientProfile(session['ClientID']))
|
||||||
|
|
||||||
return client
|
return client
|
@ -63,7 +63,9 @@ class DashboardClients:
|
|||||||
def GetClientProfile(self, ClientID):
|
def GetClientProfile(self, ClientID):
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
return dict(conn.execute(
|
return dict(conn.execute(
|
||||||
self.dashboardClientsInfoTable.select().where(
|
db.select(
|
||||||
|
*[c for c in self.dashboardClientsInfoTable.c if c.name != 'ClientID']
|
||||||
|
).where(
|
||||||
self.dashboardClientsInfoTable.c.ClientID == ClientID
|
self.dashboardClientsInfoTable.c.ClientID == ClientID
|
||||||
)
|
)
|
||||||
).mappings().fetchone())
|
).mappings().fetchone())
|
||||||
|
72
src/static/client/src/components/Settings/profile.vue
Normal file
72
src/static/client/src/components/Settings/profile.vue
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<script setup>
|
||||||
|
import {clientStore} from "@/stores/clientStore.js";
|
||||||
|
import {reactive} from "vue";
|
||||||
|
const store = clientStore()
|
||||||
|
const ProfileLabels = {
|
||||||
|
Firstname: "First Name",
|
||||||
|
Lastname: "Last Name"
|
||||||
|
}
|
||||||
|
const Password = reactive({
|
||||||
|
CurrentPassword: "",
|
||||||
|
NewPassword: "",
|
||||||
|
RepeatNewPassword: ""
|
||||||
|
})
|
||||||
|
|
||||||
|
const ResetPasswordFields = () => {
|
||||||
|
Password.CurrentPassword = ""
|
||||||
|
Password.NewPassword = ""
|
||||||
|
Password.RepeatNewPassword = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="d-flex flex-column gap-4 p-3">
|
||||||
|
<div>
|
||||||
|
<h5>
|
||||||
|
Profile
|
||||||
|
</h5>
|
||||||
|
<div class="row g-2">
|
||||||
|
<div class="col-sm-6" v-for="(val, key) in store.clientProfile.Profile">
|
||||||
|
<label :for="key" class="text-muted form-label">
|
||||||
|
<small>{{ ProfileLabels[key] }}</small>
|
||||||
|
</label>
|
||||||
|
<input :id="key" class="form-control rounded-3" v-model="store.clientProfile.Profile[key]">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form @submit="undefined" @reset="ResetPasswordFields()">
|
||||||
|
<h5>
|
||||||
|
Update Password
|
||||||
|
</h5>
|
||||||
|
<div class="row g-2 mb-3">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label class="text-muted form-label" for="CurrentPassword">
|
||||||
|
<small>Current Password</small>
|
||||||
|
</label>
|
||||||
|
<input class="form-control rounded-3" type="password" autocomplete="current-password" id="CurrentPassword" v-model="Password.CurrentPassword">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<label class="text-muted form-label" for="NewPassword">
|
||||||
|
<small>New Password</small>
|
||||||
|
</label>
|
||||||
|
<input class="form-control rounded-3" type="password" id="NewPassword" autocomplete="new-password" v-model="Password.NewPassword">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<label class="text-muted form-label" for="RepeatNewPassword">
|
||||||
|
<small>Repeat New Password</small>
|
||||||
|
</label>
|
||||||
|
<input class="form-control rounded-3" type="password" id="RepeatNewPassword" autocomplete="new-password" v-model="Password.RepeatNewPassword">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button class="btn btn-sm btn-secondary rounded-3 ms-auto" type="reset">Clear</button>
|
||||||
|
<button class="btn btn-sm btn-danger rounded-3" type="submit">Update</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -56,7 +56,7 @@ const verify = async (e) => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
if (data){
|
if (data){
|
||||||
if (data.status){
|
if (data.status){
|
||||||
console.log(data.data)
|
store.clientProfile = data.data;
|
||||||
router.push('/')
|
router.push('/')
|
||||||
}else{
|
}else{
|
||||||
store.newNotification(data.message, "danger")
|
store.newNotification(data.message, "danger")
|
||||||
|
@ -5,6 +5,7 @@ import SignUp from "@/views/signup.vue";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {axiosGet, requestURl} from "@/utilities/request.js";
|
import {axiosGet, requestURl} from "@/utilities/request.js";
|
||||||
import {clientStore} from "@/stores/clientStore.js";
|
import {clientStore} from "@/stores/clientStore.js";
|
||||||
|
import Settings from "@/views/settings.vue";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
@ -17,6 +18,14 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
name: "Home"
|
name: "Home"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/settings',
|
||||||
|
component: Settings,
|
||||||
|
meta: {
|
||||||
|
auth: true
|
||||||
|
},
|
||||||
|
name: "Settings"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/signin',
|
path: '/signin',
|
||||||
component: SignIn,
|
component: SignIn,
|
||||||
@ -35,10 +44,7 @@ const router = createRouter({
|
|||||||
})
|
})
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
const store = clientStore()
|
const store = clientStore()
|
||||||
|
|
||||||
if (to.path === '/signout'){
|
if (to.path === '/signout'){
|
||||||
|
|
||||||
|
|
||||||
await axios.get(requestURl('/api/signout')).then(() => {
|
await axios.get(requestURl('/api/signout')).then(() => {
|
||||||
next('/signin')
|
next('/signin')
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -58,8 +64,6 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
router.afterEach((to, from, next) => {
|
router.afterEach((to, from, next) => {
|
||||||
|
@ -4,35 +4,40 @@ import {v4} from "uuid"
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {axiosGet} from "@/utilities/request.js";
|
import {axiosGet} from "@/utilities/request.js";
|
||||||
|
|
||||||
|
export const clientStore = defineStore('clientStore', {
|
||||||
export const clientStore = defineStore('clientStore', () => {
|
state: () => ({
|
||||||
const notifications = ref([])
|
notifications: [],
|
||||||
const configurations = ref([])
|
configurations: [],
|
||||||
const clientProfile = reactive({
|
clientProfile: {
|
||||||
Email: "",
|
Email: "",
|
||||||
Profile: {}
|
Profile: {}
|
||||||
})
|
}
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
function newNotification(content, status) {
|
newNotification(content, status){
|
||||||
notifications.value.push({
|
this.notifications.push({
|
||||||
id: v4().toString(),
|
id: v4().toString(),
|
||||||
status: status,
|
status: status,
|
||||||
content: content,
|
content: content,
|
||||||
time: dayjs(),
|
time: dayjs(),
|
||||||
show: true
|
show: true
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
async getClientProfile(){
|
||||||
|
const data = await axiosGet('/api/settings/getClientProfile')
|
||||||
|
if (data){
|
||||||
|
this.clientProfile.Profile = data.data
|
||||||
|
}else{
|
||||||
|
this.newNotification("Failed to fetch client profile", "danger")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
async function getConfigurations(){
|
async getConfigurations(){
|
||||||
const data = await axiosGet("/api/configurations")
|
const data = await axiosGet("/api/configurations")
|
||||||
if (data){
|
if (data){
|
||||||
configurations.value = data.data
|
this.configurations = data.data
|
||||||
}else{
|
}else{
|
||||||
newNotification("Failed to fetch configurations", "danger")
|
this.newNotification("Failed to fetch configurations", "danger")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
notifications, newNotification, getConfigurations, configurations, clientProfile
|
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -29,10 +29,10 @@ onMounted(async () => {
|
|||||||
<strong>WGDashboard Client</strong>
|
<strong>WGDashboard Client</strong>
|
||||||
</a>
|
</a>
|
||||||
<div class="ms-auto px-3 d-flex gap-2 nav-links">
|
<div class="ms-auto px-3 d-flex gap-2 nav-links">
|
||||||
<a class=" text-body btn btn-outline-body rounded-3 ms-auto btn-sm" aria-current="page" href="#">
|
<RouterLink to="/settings" class=" text-body btn btn-outline-body rounded-3 ms-auto btn-sm" aria-current="page" href="#">
|
||||||
<i class="bi bi-gear-fill me-sm-2"></i>
|
<i class="bi bi-gear-fill me-sm-2"></i>
|
||||||
<span>Settings</span>
|
<span>Settings</span>
|
||||||
</a>
|
</RouterLink>
|
||||||
<RouterLink to="/signout" class="btn btn-outline-danger rounded-3 btn-sm" aria-current="page">
|
<RouterLink to="/signout" class="btn btn-outline-danger rounded-3 btn-sm" aria-current="page">
|
||||||
<i class="bi bi-box-arrow-left me-sm-2"></i>
|
<i class="bi bi-box-arrow-left me-sm-2"></i>
|
||||||
<span>Sign Out</span>
|
<span>Sign Out</span>
|
||||||
|
24
src/static/client/src/views/settings.vue
Normal file
24
src/static/client/src/views/settings.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<script setup async>
|
||||||
|
import {clientStore} from "@/stores/clientStore.js";
|
||||||
|
import Profile from "@/components/Settings/profile.vue";
|
||||||
|
const store = clientStore()
|
||||||
|
|
||||||
|
await store.getClientProfile();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-sm-3">
|
||||||
|
<div class="w-100 d-flex align-items-center p-3">
|
||||||
|
<RouterLink to="/" class=" text-body btn btn-outline-body rounded-3 btn-sm" aria-current="page" href="#">
|
||||||
|
<i class="bi bi-chevron-left me-sm-2"></i>
|
||||||
|
<span>Back</span>
|
||||||
|
</RouterLink>
|
||||||
|
<strong class="ms-auto">Settings</strong>
|
||||||
|
</div>
|
||||||
|
<Profile></Profile>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user