Final testing for client side

This commit is contained in:
Donald Zou
2025-09-16 14:59:57 +08:00
parent 4ea3aa0a58
commit d526deb826
15 changed files with 120 additions and 70 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -10,11 +10,11 @@ fetch("/client/api/serverInformation")
</script> </script>
<template> <template>
<div data-bs-theme="dark" class="text-body bg-body vw-100 vh-100 bg-body-tertiary"> <div data-bs-theme="dark" class="text-body bg-body vw-100 vh-100 bg-body">
<div class="d-flex vh-100 vw-100 p-sm-4 overflow-y-scroll"> <div class="d-flex vw-100 p-sm-4 overflow-y-scroll innerContainer d-flex flex-column">
<div class="mx-auto my-sm-auto position-relative" <div class="mx-auto my-sm-auto position-relative"
id="listContainer" id="listContainer"
style="width: 700px"> >
<Suspense> <Suspense>
<RouterView v-slot="{ Component }"> <RouterView v-slot="{ Component }">
<Transition name="app" type="transition" mode="out-in"> <Transition name="app" type="transition" mode="out-in">
@@ -23,16 +23,40 @@ fetch("/client/api/serverInformation")
</RouterView> </RouterView>
</Suspense> </Suspense>
</div> </div>
<div style="font-size: 0.8rem" class="text-center text-muted">
<small>
Background image by <a href="https://unsplash.com/photos/body-of-water-aExT3y92x5o">Fabrizio Conti</a>
</small><br>
</div>
</div> </div>
<NotificationList></NotificationList> <NotificationList></NotificationList>
</div> </div>
</template> </template>
<style scoped> <style scoped>
@media screen and (max-width: 576px) {
#listContainer{
width: 100%;
}
@media screen and (min-width: 992px) {
#listContainer{ #listContainer{
border-radius: 0 !important; width: 700px;
} }
} }
.innerContainer{
height: 100vh;
}
@supports(height: 100dvh) {
.innerContainer { height: 100dvh; }
}
.bg-body[data-bs-theme="dark"]{
background: linear-gradient(rgba(48, 48, 48, 0.5), rgba(0, 0, 0, 0.5)), url("/img/fabrizio-conti-aExT3y92x5o-unsplash.jpg") fixed;
background-size: cover;
background-position: top;
}
</style> </style>

View File

@@ -141,3 +141,8 @@
background: rgb(125,32,32); background: rgb(125,32,32);
background: linear-gradient(90deg, rgba(125,32,32,1) 0%, rgba(255,56,56,1) 100%); background: linear-gradient(90deg, rgba(125,32,32,1) 0%, rgba(255,56,56,1) 100%);
} }
.form-control{
background-color: rgba(0, 0, 0, 0.25) !important;
backdrop-filter: blur(8px) !important;
}

View File

@@ -45,6 +45,8 @@ const totalDataPercentage = computed(() => {
return ( props.config.data / totalDataLimit.value ) * 100 return ( props.config.data / totalDataLimit.value ) * 100
}) })
window.dayjs = dayjs window.dayjs = dayjs
const emits = defineEmits(['select'])
</script> </script>
<template> <template>
@@ -85,18 +87,11 @@ window.dayjs = dayjs
</div> </div>
</div> </div>
<button class="btn btn-outline-body rounded-3 flex-grow-1 fw-bold w-100" @click="showQRCode = true"> <button class="btn btn-outline-body rounded-3 flex-grow-1 fw-bold w-100" @click="emits('select')">
<i class="bi bi-link-45deg me-2"></i><small>Connect</small> <i class="bi bi-link-45deg me-2"></i><small>Connect</small>
</button> </button>
</div> </div>
<Transition name="app">
<ConfigurationQRCode
v-if="showQRCode"
:config="props.config"
:protocol="props.config.protocol"
@back="showQRCode = false"
:qrcode-data="config.peer_configuration_data"></ConfigurationQRCode>
</Transition>
</div> </div>
</template> </template>

View File

@@ -64,7 +64,7 @@ const download = computed(() => {
.qrcodeContainer{ .qrcodeContainer{
background-color: #00000050; background-color: #00000050;
backdrop-filter: blur(8px) brightness(0.8); backdrop-filter: blur(8px) brightness(0.7);
z-index: 9999; z-index: 9999;
} }
</style> </style>

View File

@@ -80,22 +80,22 @@ watch(formFilled, () => {
<i class="me-2 bi bi-chevron-left"></i> Back <i class="me-2 bi bi-chevron-left"></i> Back
</a> </a>
</div> </div>
<div class=""> <div>
<h1 class="mb-3">Multi-Factor Authentication (MFA)</h1> <h1 class="mb-3 text-center">Multi-Factor Authentication (MFA)</h1>
<div class="card rounded-3" v-if="totpKey"> <div class="card rounded-3 text-center" v-if="totpKey">
<div class="card-body d-flex gap-3 flex-column"> <div class="card-body d-flex gap-3 flex-column align-items-center">
<h2 class="mb-0">Initial Setup</h2> <h2 class="mb-0">Initial Setup</h2>
<p class="mb-0">Please scan the following QR Code to generate TOTP with your choice of authenticator</p> <p class="mb-0">Please scan the following QR Code to generate TOTP with your choice of authenticator</p>
<Qrcode :content="totpKey"></Qrcode> <Qrcode :content="totpKey"></Qrcode>
<p class="mb-0">Or you can click the link below:</p> <p class="mb-0">Or you can click the link below:</p>
<div class="card rounded-3 "> <div class="card rounded-3 w-100">
<div class="card-body"> <div class="card-body">
<a :href="totpKey"> <a :href="totpKey" style="text-wrap: auto">
{{ totpKey }} {{ totpKey }}
</a> </a>
</div> </div>
</div> </div>
<div class="alert alert-warning mb-0"> <div class="alert alert-warning mb-0 rounded-3">
<strong> <strong>
Please note: You won't be able to see this QR Code again, so please save it somewhere safe in case you need to recover your TOTP key Please note: You won't be able to see this QR Code again, so please save it somewhere safe in case you need to recover your TOTP key
</strong> </strong>
@@ -104,7 +104,7 @@ watch(formFilled, () => {
</div> </div>
</div> </div>
<hr v-if="totpKey"> <hr v-if="totpKey">
<div class="d-flex flex-column gap-3"> <div class="d-flex flex-column gap-3 text-center">
<label for="totp">Enter the TOTP generated by your authenticator to verify</label> <label for="totp">Enter the TOTP generated by your authenticator to verify</label>
<input class="form-control form-control-lg rounded-3 text-center" <input class="form-control form-control-lg rounded-3 text-center"
id="totp" id="totp"
@@ -132,5 +132,8 @@ watch(formFilled, () => {
</template> </template>
<style scoped> <style scoped>
.card{
background-color: rgba(0, 0, 0, 0.25);
backdrop-filter: blur(8px);
}
</style> </style>

View File

@@ -5,6 +5,7 @@ import {clientStore} from "@/stores/clientStore.js";
import Configuration from "@/components/Configuration/configuration.vue"; import Configuration from "@/components/Configuration/configuration.vue";
import {onBeforeRouteLeave, useRouter} from "vue-router"; import {onBeforeRouteLeave, useRouter} from "vue-router";
import axios from "axios"; import axios from "axios";
import ConfigurationQRCode from "@/components/Configuration/configurationQRCode.vue";
const store = clientStore() const store = clientStore()
const loading = ref(true) const loading = ref(true)
@@ -37,6 +38,9 @@ const signOut = async () => {
}); });
store.newNotification("Sign out successful", "success") store.newNotification("Sign out successful", "success")
} }
const selectedConfig = ref(undefined)
</script> </script>
<template> <template>
@@ -50,6 +54,8 @@ const signOut = async () => {
<div class="ms-auto px-3 d-flex gap-2 nav-links"> <div class="ms-auto px-3 d-flex gap-2 nav-links">
<RouterLink to="/settings" 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>
</RouterLink> </RouterLink>
<a role="button" @click="signOut()" class="btn btn-outline-danger rounded-3 btn-sm" <a role="button" @click="signOut()" class="btn btn-outline-danger rounded-3 btn-sm"
@@ -66,7 +72,9 @@ const signOut = async () => {
<Transition name="app" mode="out-in"> <Transition name="app" mode="out-in">
<div class="d-flex flex-column gap-3" v-if="!loading"> <div class="d-flex flex-column gap-3" v-if="!loading">
<div class="p-3 d-flex flex-column gap-3" v-if="configurations.length > 0"> <div class="p-3 d-flex flex-column gap-3" v-if="configurations.length > 0">
<Configuration v-for="config in configurations" :config="config"></Configuration> <Configuration
@select="selectedConfig = config"
v-for="config in configurations" :config="config"></Configuration>
</div> </div>
<div class="text-center text-muted" v-else> <div class="text-center text-muted" v-else>
<small>No configuration available</small> <small>No configuration available</small>
@@ -78,6 +86,17 @@ const signOut = async () => {
</div> </div>
</div> </div>
</Transition> </Transition>
<Transition name="app">
<ConfigurationQRCode
v-if="selectedConfig !== undefined"
:config="selectedConfig.config"
:protocol="selectedConfig.protocol"
@back="selectedConfig = undefined"
:qrcode-data="selectedConfig.peer_configuration_data"
>
</ConfigurationQRCode>
</Transition>
</div> </div>
</template> </template>
@@ -91,4 +110,9 @@ const signOut = async () => {
display: none; display: none;
} }
} }
.card{
background-color: rgba(0, 0, 0, 0.25);
backdrop-filter: blur(8px);
}
</style> </style>

View File

@@ -15,7 +15,6 @@ await store.getClientProfile();
</RouterLink> </RouterLink>
<strong class="ms-auto">Settings</strong> <strong class="ms-auto">Settings</strong>
</div> </div>
<Profile></Profile>
<UpdatePassword v-if="store.clientProfile.SignInMethod === 'local'"></UpdatePassword> <UpdatePassword v-if="store.clientProfile.SignInMethod === 'local'"></UpdatePassword>
</div> </div>
</template> </template>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -28,8 +28,8 @@
} }
} }
</style> </style>
<script type="module" crossorigin src="/static/dist/WGDashboardClient/assets/index-C_3A0sda.js"></script> <script type="module" crossorigin src="/static/dist/WGDashboardClient/assets/index-C_FweDYM.js"></script>
<link rel="stylesheet" crossorigin href="/static/dist/WGDashboardClient/assets/index-Bsd6VTEn.css"> <link rel="stylesheet" crossorigin href="/static/dist/WGDashboardClient/assets/index-CyU4Qwd1.css">
</head> </head>
<body> <body>
<div id="app"> <div id="app">

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB