mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-06-28 01:06:58 +00:00
Update
This commit is contained in:
parent
85d4b8c487
commit
d80eb03707
@ -101,4 +101,9 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
|
||||
def ClientAPI_Configurations():
|
||||
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
|
@ -63,7 +63,9 @@ class DashboardClients:
|
||||
def GetClientProfile(self, ClientID):
|
||||
with self.engine.connect() as conn:
|
||||
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
|
||||
)
|
||||
).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
|
||||
if (data){
|
||||
if (data.status){
|
||||
console.log(data.data)
|
||||
store.clientProfile = data.data;
|
||||
router.push('/')
|
||||
}else{
|
||||
store.newNotification(data.message, "danger")
|
||||
|
@ -5,6 +5,7 @@ import SignUp from "@/views/signup.vue";
|
||||
import axios from "axios";
|
||||
import {axiosGet, requestURl} from "@/utilities/request.js";
|
||||
import {clientStore} from "@/stores/clientStore.js";
|
||||
import Settings from "@/views/settings.vue";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
@ -17,6 +18,14 @@ const router = createRouter({
|
||||
},
|
||||
name: "Home"
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
component: Settings,
|
||||
meta: {
|
||||
auth: true
|
||||
},
|
||||
name: "Settings"
|
||||
},
|
||||
{
|
||||
path: '/signin',
|
||||
component: SignIn,
|
||||
@ -35,10 +44,7 @@ const router = createRouter({
|
||||
})
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const store = clientStore()
|
||||
|
||||
if (to.path === '/signout'){
|
||||
|
||||
|
||||
await axios.get(requestURl('/api/signout')).then(() => {
|
||||
next('/signin')
|
||||
}).catch(() => {
|
||||
@ -58,8 +64,6 @@ router.beforeEach(async (to, from, next) => {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
router.afterEach((to, from, next) => {
|
||||
|
@ -4,35 +4,40 @@ import {v4} from "uuid"
|
||||
import dayjs from "dayjs";
|
||||
import {axiosGet} from "@/utilities/request.js";
|
||||
|
||||
|
||||
export const clientStore = defineStore('clientStore', () => {
|
||||
const notifications = ref([])
|
||||
const configurations = ref([])
|
||||
const clientProfile = reactive({
|
||||
export const clientStore = defineStore('clientStore', {
|
||||
state: () => ({
|
||||
notifications: [],
|
||||
configurations: [],
|
||||
clientProfile: {
|
||||
Email: "",
|
||||
Profile: {}
|
||||
})
|
||||
|
||||
|
||||
function newNotification(content, status) {
|
||||
notifications.value.push({
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
newNotification(content, status){
|
||||
this.notifications.push({
|
||||
id: v4().toString(),
|
||||
status: status,
|
||||
content: content,
|
||||
time: dayjs(),
|
||||
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")
|
||||
if (data){
|
||||
configurations.value = data.data
|
||||
this.configurations = data.data
|
||||
}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>
|
||||
</a>
|
||||
<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>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
</RouterLink>
|
||||
<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>
|
||||
<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