1
0
mirror of https://github.com/donaldzou/WGDashboard.git synced 2024-11-22 07:10:09 +01:00

Still working on translation...

This commit is contained in:
Donald Zou 2024-09-09 23:43:55 +08:00
parent d458a28337
commit a3a312e3db
32 changed files with 399 additions and 171 deletions

View File

@ -399,7 +399,6 @@ class PeerShareLinks:
"""
)
self.__getSharedLinks()
# print(self.Links)
def __getSharedLinks(self):
self.Links.clear()
allLinks = sqlSelect("SELECT * FROM PeerShareLinks WHERE ExpireDate IS NULL OR ExpireDate > datetime('now', 'localtime')").fetchall()
@ -503,7 +502,6 @@ class WireguardConfiguration:
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1],
f"{self.Name}.conf"), "w+") as configFile:
# print(self.__parser.sections())
self.__parser.write(configFile)
self.Peers: list[Peer] = []
@ -613,7 +611,6 @@ class WireguardConfiguration:
if regex_match("#Name# = (.*)", i):
split = re.split(r'\s*=\s*', i, 1)
print(split)
if len(split) == 2:
p[pCounter]["name"] = split[1]
@ -1283,8 +1280,6 @@ def _regexMatch(regex, text):
def _getConfigurationList():
# configurations = {}
print(DashboardConfig.GetConfig("Server", "wg_conf_path")[1])
for i in os.listdir(DashboardConfig.GetConfig("Server", "wg_conf_path")[1]):
if _regexMatch("^(.{1,}).(conf)$", i):
i = i.replace('.conf', '')
@ -1478,6 +1473,7 @@ def auth_req():
and "getDashboardVersion" not in request.path
and "sharePeer/get" not in request.path
and "isTotpEnabled" not in request.path
and "locale" not in request.path
):
response = Flask.make_response(app, {
"status": False,
@ -2132,6 +2128,24 @@ def API_Welcome_Finish():
DashboardConfig.SetConfig("Other", "welcome_session", False)
return ResponseObject()
@app.get(f'{APP_PREFIX}/api/locale')
def API_Local_CurrentLang():
# if param is None or len(param) == 0:
# with open(os.path.join("./static/locale/active_languages.json"), "r") as f:
# return ResponseObject(data=''.join(f.readlines()))
_, param = DashboardConfig.GetConfig("Server", "dashboard_language")
if param == "en":
return ResponseObject()
if os.path.exists(os.path.join(f"./static/locale/{param}.json")):
with open(os.path.join(f"./static/locale/{param}.json"), "r") as f:
return ResponseObject(data=''.join(f.readlines()))
@app.route(f'{APP_PREFIX}/', methods=['GET'])
def index():
@ -2148,8 +2162,6 @@ def backGroundThread():
time.sleep(10)
while True:
with app.app_context():
print(DashboardConfig.GetConfig("Server", "wg_conf_path")[1])
print(id(WireguardConfigurations))
for c in WireguardConfigurations.values():
if c.getStatus():
try:
@ -2176,11 +2188,6 @@ def gunicornConfig():
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
return app_ip, app_port
def clearWireguardConfigurations():
WireguardConfigurations = {}
WireguardConfigurations.clear()
print(WireguardConfigurations.keys())
AllPeerShareLinks: PeerShareLinks = PeerShareLinks()
AllPeerJobs: PeerJobs = PeerJobs()

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
<script setup>
<script setup async>
import { RouterView } from 'vue-router'
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {computed, watch} from "vue";
@ -21,7 +21,6 @@ const getActiveCrossServer = computed(() => {
}
return undefined
})
</script>
<template>

View File

@ -2,10 +2,11 @@
import {wgdashboardStore} from "@/stores/wgdashboardStore.js";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
import ConfigurationCard from "@/components/configurationListComponents/configurationCard.vue";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "configurationList",
components: {ConfigurationCard},
components: {LocaleText, ConfigurationCard},
async setup(){
const wireguardConfigurationsStore = WireguardConfigurationsStore();
return {wireguardConfigurationsStore}
@ -36,16 +37,18 @@ export default {
<div class="d-flex mb-4 configurationListTitle">
<h3 class="text-body d-flex">
<i class="bi bi-body-text me-2"></i>
<span>WireGuard Configurations</span></h3>
<span>
<LocaleText t="WireGuard Configurations"></LocaleText>
</span></h3>
<RouterLink to="/new_configuration" class="btn btn-dark btn-brand rounded-3 px-3 py-2 shadow ms-auto rounded-3">
<i class="bi bi-plus-circle-fill me-2"></i>
Configuration
<LocaleText t="Configuration"></LocaleText>
</RouterLink>
</div>
<Transition name="fade" mode="out-in">
<div v-if="this.configurationLoaded">
<p class="text-muted" v-if="this.wireguardConfigurationsStore.Configurations.length === 0">
You don't have any WireGuard configurations yet. Please check the configuration folder or change it in "Settings". By default the folder is "/etc/wireguard".
<LocaleText t="You don't have any WireGuard configurations yet. Please check the configuration folder or change it in Settings. By default the folder is /etc/wireguard."></LocaleText>
</p>
<div class="d-flex gap-3 flex-column mb-3" v-else>
<ConfigurationCard v-for="c in this.wireguardConfigurationsStore.Configurations" :key="c.Name" :c="c"></ConfigurationCard>

View File

@ -3,9 +3,11 @@ import {wgdashboardStore} from "@/stores/wgdashboardStore.js";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {fetchGet} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "navbar",
components: {LocaleText},
setup(){
const wireguardConfigurationsStore = WireguardConfigurationsStore();
const dashboardConfigurationStore = DashboardConfigurationStore();
@ -47,17 +49,19 @@ export default {
<RouterLink class="nav-link rounded-3"
to="/" exact-active-class="active">
<i class="bi bi-house me-2"></i>
Home</RouterLink></li>
<LocaleText t="Home"></LocaleText>
</RouterLink></li>
<li class="nav-item">
<RouterLink class="nav-link rounded-3" to="/settings"
exact-active-class="active">
<i class="bi bi-gear me-2"></i>
Settings</RouterLink></li>
<LocaleText t="Settings"></LocaleText>
</RouterLink></li>
</ul>
<hr class="text-body">
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">
<i class="bi bi-body-text me-2"></i>
Configurations
<LocaleText t="WireGuard Configurations"></LocaleText>
</h6>
<ul class="nav flex-column px-2">
<li class="nav-item">
@ -72,7 +76,7 @@ export default {
<hr class="text-body">
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">
<i class="bi bi-tools me-2"></i>
Tools
<LocaleText t="Tools"></LocaleText>
</h6>
<ul class="nav flex-column px-2">
<li class="nav-item">
@ -87,16 +91,18 @@ export default {
@click="this.dashboardConfigurationStore.signOut()"
role="button" style="font-weight: bold">
<i class="bi bi-box-arrow-left me-2"></i>
Sign Out</a>
<LocaleText t="Sign Out"></LocaleText>
</a>
</li>
<li class="nav-item" style="font-size: 0.8rem">
<a :href="this.updateUrl" v-if="this.updateAvailable" class="text-decoration-none" target="_blank">
<small class="nav-link text-muted rounded-3" >
{{ this.updateMessage }}
<LocaleText :t="this.updateMessage"></LocaleText>
</small>
</a>
<small class="nav-link text-muted" v-else>
{{ this.updateMessage }}
<LocaleText :t="this.updateMessage"></LocaleText>
({{ dashboardConfigurationStore.Configuration.Server.version}})
</small>
</li>
</ul>

View File

@ -2,9 +2,11 @@
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {v4} from "uuid";
import {fetchPost} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "accountSettingsInputPassword",
components: {LocaleText},
props:{
targetData: String,
warning: false,
@ -81,7 +83,9 @@ export default {
<div class="col-sm">
<div class="form-group mb-2">
<label :for="'currentPassword_' + this.uuid" class="text-muted mb-1">
<strong><small>Current Password</small></strong>
<strong><small>
<LocaleText t="Current Password"></LocaleText>
</small></strong>
</label>
<input type="password" class="form-control mb-2"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
@ -93,7 +97,9 @@ export default {
<div class="col-sm">
<div class="form-group mb-2">
<label :for="'newPassword_' + this.uuid" class="text-muted mb-1">
<strong><small>New Password</small></strong>
<strong><small>
<LocaleText t="New Password"></LocaleText>
</small></strong>
</label>
<input type="password" class="form-control mb-2"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
@ -105,7 +111,9 @@ export default {
<div class="col-sm">
<div class="form-group mb-2">
<label :for="'repeatNewPassword_' + this.uuid" class="text-muted mb-1">
<strong><small>Repeat New Password</small></strong>
<strong><small>
<LocaleText t="Repeat New Password"></LocaleText>
</small></strong>
</label>
<input type="password" class="form-control mb-2"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
@ -117,7 +125,8 @@ export default {
<button
:disabled="!this.passwordValid"
class="ms-auto btn bg-success-subtle text-success-emphasis border-1 border-success-subtle rounded-3 shadow-sm" @click="this.useValidation()">
<i class="bi bi-save2-fill me-2"></i>Update Password
<i class="bi bi-save2-fill me-2"></i>
<LocaleText t="Update Password"></LocaleText>
</button>
</div>
</template>

View File

@ -2,14 +2,14 @@
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {v4} from "uuid";
import {fetchPost} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "accountSettingsInputUsername",
components: {LocaleText},
props:{
targetData: String,
title: String,
warning: false,
warningText: ""
},
setup(){
const store = DashboardConfigurationStore();
@ -62,7 +62,9 @@ export default {
<template>
<div class="form-group mb-2">
<label :for="this.uuid" class="text-muted mb-1">
<strong><small>{{this.title}}</small></strong>
<strong><small>
<LocaleText :t="this.title"></LocaleText>
</small></strong>
</label>
<input type="text" class="form-control"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
@ -73,11 +75,6 @@ export default {
:disabled="this.updating"
>
<div class="invalid-feedback">{{this.invalidFeedback}}</div>
<div class="px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1"
v-if="warning"
>
<small><i class="bi bi-exclamation-triangle-fill me-2"></i><span v-html="warningText"></span></small>
</div>
</div>
</template>

View File

@ -2,9 +2,11 @@
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {v4} from "uuid";
import {fetchPost} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "accountSettingsMFA",
components: {LocaleText},
setup(){
const store = DashboardConfigurationStore();
const uuid = `input_${v4()}`;
@ -43,7 +45,9 @@ export default {
<template>
<div>
<div class="d-flex align-items-center">
<strong>Multi-Factor Authentication</strong>
<strong>
<LocaleText t="Multi-Factor Authentication (MFA)"></LocaleText>
</strong>
<div class="form-check form-switch ms-3">
<input class="form-check-input" type="checkbox"
v-model="this.status"
@ -52,7 +56,9 @@ export default {
<button class="btn bg-warning-subtle text-warning-emphasis border-1 border-warning-subtle ms-auto rounded-3 shadow-sm"
v-if="this.status" @click="this.resetMFA()">
<i class="bi bi-shield-lock-fill me-2"></i>
{{this.store.Configuration.Account["totp_verified"] ? "Reset" : "Setup" }} MFA
<LocaleText t="Reset" v-if='this.store.Configuration.Account["totp_verified"]'></LocaleText>
<LocaleText t="Setup" v-else></LocaleText>
MFA
</button>
</div>
</div>

View File

@ -4,10 +4,11 @@ import {v4} from "uuid";
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
import NewDashboardAPIKey from "@/components/settingsComponent/dashboardAPIKeysComponents/newDashboardAPIKey.vue";
import DashboardAPIKey from "@/components/settingsComponent/dashboardAPIKeysComponents/dashboardAPIKey.vue";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "dashboardAPIKeys",
components: {DashboardAPIKey, NewDashboardAPIKey},
components: {LocaleText, DashboardAPIKey, NewDashboardAPIKey},
setup(){
const store = DashboardConfigurationStore();
return {store};
@ -64,14 +65,17 @@ export default {
<template>
<div class="card mb-4 shadow rounded-3">
<div class="card-header d-flex">
API Keys
<LocaleText t="API Keys"></LocaleText>
<div class="form-check form-switch ms-auto" v-if="!this.store.getActiveCrossServer()">
<input class="form-check-input" type="checkbox"
v-model="this.value"
@change="this.toggleDashboardAPIKeys()"
role="switch" id="allowAPIKeysSwitch">
<label class="form-check-label" for="allowAPIKeysSwitch">
{{this.value ? 'Enabled':'Disabled'}}
<LocaleText t="Enabled" v-if="this.value"></LocaleText>
<LocaleText t="Disabled" v-else></LocaleText>
</label>
</div>
</div>
@ -80,12 +84,13 @@ export default {
@click="this.newDashboardAPIKey = true"
v-if="!this.store.getActiveCrossServer()"
>
<i class="bi bi-key me-2"></i> Create
<i class="bi bi-plus-circle-fill me-2"></i>
<LocaleText t="API Key"></LocaleText>
</button>
<div class="card" style="height: 300px" v-if="this.apiKeys.length === 0">
<div class="card-body d-flex text-muted">
<span class="m-auto">
No Dashboard API Key
<LocaleText t="No WGDashboard API Key"></LocaleText>
</span>
</div>
</div>

View File

@ -1,9 +1,11 @@
<script>
import {fetchPost} from "@/utilities/fetch.js";
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "dashboardAPIKey",
components: {LocaleText},
props: {
apiKey: Object
},
@ -37,11 +39,15 @@ export default {
<div class="card rounded-3 shadow-sm">
<div class="card-body d-flex gap-3 align-items-center apiKey-card-body" v-if="!this.confirmDelete">
<div class="d-flex align-items-center gap-2">
<small class="text-muted">Key</small>
<small class="text-muted">
<LocaleText t="Key"></LocaleText>
</small>
<span style="word-break: break-all">{{this.apiKey.Key}}</span>
</div>
<div class="d-flex align-items-center gap-2 ms-auto">
<small class="text-muted">Expire At</small>
<small class="text-muted">
<LocaleText t="Expire At"></LocaleText>
</small>
{{this.apiKey.ExpiredAt ? this.apiKey.ExpiredAt : 'Never'}}
</div>
<a role="button" class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3"
@ -52,7 +58,7 @@ export default {
</div>
<div v-else class="card-body d-flex gap-3 align-items-center justify-content-end"
v-if="!this.store.getActiveCrossServer()">
Are you sure to delete this API key?
<LocaleText t="Are you sure to delete this API key?"></LocaleText>
<a role="button" class="btn btn-sm bg-success-subtle text-success-emphasis rounded-3"
@click="this.deleteAPIKey()"
>

View File

@ -3,9 +3,11 @@ import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.
import {v4} from "uuid";
import {fetchPost} from "@/utilities/fetch.js";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "dashboardSettingsInputWireguardConfigurationPath",
components: {LocaleText},
props:{
targetData: String,
title: String,
@ -66,7 +68,9 @@ export default {
<template>
<div class="form-group">
<label :for="this.uuid" class="text-muted mb-1">
<strong><small>{{this.title}}</small></strong>
<strong><small>
<LocaleText :t="this.title"></LocaleText>
</small></strong>
</label>
<div class="d-flex gap-2 align-items-start mb-2">
<div class="flex-grow-1">
@ -90,7 +94,9 @@ export default {
<div class="px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1 mb-2"
v-if="warning"
>
<small><i class="bi bi-exclamation-triangle-fill me-2"></i><span v-html="warningText"></span></small>
<small><i class="bi bi-exclamation-triangle-fill me-2"></i>
<LocaleText :t="warningText"></LocaleText>
</small>
</div>
</div>

View File

@ -1,9 +1,11 @@
<script>
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {fetchPost} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "dashboardTheme",
components: {LocaleText},
setup(){
const dashboardConfigurationStore = DashboardConfigurationStore();
return {dashboardConfigurationStore}
@ -26,19 +28,21 @@ export default {
<template>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">Dashboard Theme</p>
<p class="card-header">
<LocaleText t="Dashboard Theme"></LocaleText>
</p>
<div class="card-body d-flex gap-2">
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
@click="this.switchTheme('light')"
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'light'}">
<i class="bi bi-sun-fill"></i>
Light
<i class="bi bi-sun-fill me-2"></i>
<LocaleText t="Light"></LocaleText>
</button>
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
@click="this.switchTheme('dark')"
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'dark'}">
<i class="bi bi-moon-fill"></i>
Dark
<i class="bi bi-moon-fill me-2"></i>
<LocaleText t="Dark"></LocaleText>
</button>
</div>
</div>

View File

@ -2,8 +2,10 @@
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {v4} from "uuid";
import {fetchPost} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
components: {LocaleText},
props:{
targetData: String,
title: String,
@ -61,7 +63,9 @@ export default {
<template>
<div class="form-group mb-2">
<label :for="this.uuid" class="text-muted mb-1">
<strong><small>{{this.title}}</small></strong>
<strong><small>
<LocaleText :t="this.title"></LocaleText>
</small></strong>
</label>
<input type="text" class="form-control"
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
@ -75,7 +79,9 @@ export default {
<div class="px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1"
v-if="warning"
>
<small><i class="bi bi-exclamation-triangle-fill me-2"></i><span v-html="warningText"></span></small>
<small><i class="bi bi-exclamation-triangle-fill me-2"></i>
<LocaleText :t="warningText"></LocaleText>
</small>
</div>
</div>
</template>

View File

@ -0,0 +1,30 @@
<script>
import {GetLocale} from "@/utilities/locale.js";
export default {
name: "signInInput",
methods: {GetLocale},
props: {
id: "",
data: "",
type: "",
placeholder: ""
},
computed: {
getLocaleText(){
return GetLocale(this.placeholder)
}
}
}
</script>
<template>
<input :type="type" v-model="this.data[this.id]" class="form-control"
:id="this.id" :name="this.id"
autocomplete="on"
:placeholder="this.getLocaleText" required>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,29 @@
<script>
import {GetLocale} from "@/utilities/locale.js";
export default {
name: "signInTOTP",
methods: {GetLocale},
props: {
data: "",
},
computed: {
getLocaleText(){
return GetLocale(this.placeholder)
}
}
}
</script>
<template>
<input class="form-control totp"
required
id="totp" maxlength="6" type="text" inputmode="numeric" autocomplete="one-time-code"
:placeholder="this.getLocaleText('OTP from your authenticator')"
v-model="this.data.totp"
>
</template>
<style scoped>
</style>

View File

@ -1,5 +1,6 @@
<script>
import dayjs from "dayjs";
import {GetLocale} from "@/utilities/locale.js";
export default {
name: "RemoteServer",
@ -73,7 +74,7 @@ export default {
return `${dayjs().subtract(this.startTime).millisecond()}ms`
}else{
if (this.refreshing){
return `Pinging...`
return GetLocale(`Pinging...`)
}
return this.errorMsg ? this.errorMsg : "N/A"
}

View File

@ -1,6 +1,7 @@
<script>
import RemoteServer from "@/components/signInComponents/RemoteServer.vue";
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "RemoteServerList",
@ -8,18 +9,21 @@ export default {
const store = DashboardConfigurationStore();
return {store}
},
components: {RemoteServer}
components: {LocaleText, RemoteServer}
}
</script>
<template>
<div class="w-100 mt-3">
<div class="d-flex align-items-center mb-3">
<h5 class="mb-0">Server List</h5>
<h5 class="mb-0">
<LocaleText t="Server List"></LocaleText>
</h5>
<button
@click="this.store.addCrossServerConfiguration()"
class="btn bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle shadow-sm ms-auto">
<i class="bi bi-plus-circle-fill me-2"></i>Server
<i class="bi bi-plus-circle-fill me-2"></i>
<LocaleText t="Server"></LocaleText>
</button>
</div>
<div class="w-100 d-flex gap-3 flex-column p-3 border border-1 border-secondary-subtle rounded-3"
@ -30,7 +34,10 @@ export default {
:key="key"
:server="server"></RemoteServer>
<h6 class="text-muted m-auto" v-if="Object.keys(this.store.CrossServerConfiguration.ServerList).length === 0">
Click<i class="bi bi-plus-circle-fill mx-1"></i>to add your server</h6>
<LocaleText t="Click"></LocaleText>
<i class="bi bi-plus-circle-fill mx-1"></i>
<LocaleText t="to add your server"></LocaleText>
</h6>
</div>
</div>
</template>

View File

@ -0,0 +1,23 @@
<script>
import {GetLocale} from "@/utilities/locale.js";
export default {
name: "localeText",
props: {
t: ""
},
computed: {
getLocaleText(){
return GetLocale(this.t)
}
}
}
</script>
<template>
{{ this.getLocaleText }}
</template>
<style scoped>
</style>

View File

@ -10,17 +10,24 @@ import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {fetchGet} from "@/utilities/fetch.js";
let Locale;
await fetch("/api/locale").then(res => res.json()).then(res => Locale = JSON.parse(res.data))
const app = createApp(App)
app.use(router)
const pinia = createPinia();
app.use(router)
const pinia = createPinia();
pinia.use(({ store }) => {
store.$router = markRaw(router)
})
app.use(pinia)
const store = DashboardConfigurationStore()
window.Locale = Locale;
app.mount('#app')

View File

@ -1,6 +1,7 @@
import {defineStore} from "pinia";
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
import {v4} from "uuid";
import {GetLocale} from "@/utilities/locale.js";
export const DashboardConfigurationStore = defineStore('DashboardConfigurationStore', {
state: () => ({
@ -17,7 +18,8 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
},
ActiveServerConfiguration: undefined,
IsElectronApp: false,
ShowNavBar: false
ShowNavBar: false,
Locale: undefined
}),
actions: {
initCrossServerConfiguration(){
@ -57,19 +59,11 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
this.ActiveServerConfiguration = undefined;
localStorage.removeItem('ActiveCrossServerConfiguration')
},
async getConfiguration(){
await fetchGet("/api/getDashboardConfiguration", {}, (res) => {
if (res.status) this.Configuration = res.data
});
},
// async updateConfiguration(){
// await fetchPost("/api/updateDashboardConfiguration", {
// DashboardConfiguration: this.Configuration
// }, (res) => {
// console.log(res)
// })
// },
async signOut(){
await fetchGet("/api/signout", {}, (res) => {
this.removeActiveCrossServer();
@ -79,11 +73,25 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
newMessage(from, content, type){
this.Messages.push({
id: v4(),
from: from,
content: content,
from: GetLocale(from),
content: GetLocale(content),
type: type,
show: true
})
},
applyLocale(key){
if (this.Locale === null)
return key
const reg = Object.keys(this.Locale)
const match = reg.filter(x => {
return key.match(new RegExp('^' + x + '$', 'g')) !== null
})
console.log(match)
if (match.length === 0 || match.length > 1){
return key
}
return this.Locale[match[0]]
}
}
});

View File

@ -0,0 +1,16 @@
export const GetLocale = (key) => {
console.log(key)
if (window.Locale === null)
return key
const reg = Object.keys(window.Locale)
const match = reg.filter(x => {
return key.match(new RegExp('^' + x + '$', 'g')) !== null
})
console.log(match)
if (match.length === 0 || match.length > 1){
return key
}
return window.Locale[match[0]]
}

View File

@ -12,11 +12,13 @@ import DashboardSettingsInputIPAddressAndPort
from "@/components/settingsComponent/dashboardSettingsInputIPAddressAndPort.vue";
import DashboardAPIKeys from "@/components/settingsComponent/dashboardAPIKeys.vue";
import AccountSettingsMFA from "@/components/settingsComponent/accountSettingsMFA.vue";
import LocaleText from "@/components/text/localeText.vue";
export default {
name: "settings",
methods: {ipV46RegexCheck},
components: {
LocaleText,
AccountSettingsMFA,
DashboardAPIKeys,
DashboardSettingsInputIPAddressAndPort,
@ -27,24 +29,20 @@ export default {
const dashboardConfigurationStore = DashboardConfigurationStore()
return {dashboardConfigurationStore}
},
watch: {
// 'dashboardConfigurationStore.Configuration': {
// deep: true,
// handler(){
// this.dashboardConfigurationStore.updateConfiguration();
// }
// }
}
}
</script>
<template>
<div class="mt-md-5 mt-3">
<div class="container-md">
<h3 class="mb-3 text-body">Settings</h3>
<h3 class="mb-3 text-body">
<LocaleText t="Settings"></LocaleText>
</h3>
<DashboardTheme></DashboardTheme>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">Peers Default Settings</p>
<p class="card-header">
<LocaleText t="Peers Default Settings"></LocaleText>
</p>
<div class="card-body">
<PeersDefaultSettingsInput targetData="peer_global_dns" title="DNS"></PeersDefaultSettingsInput>
<PeersDefaultSettingsInput targetData="peer_endpoint_allowed_ip" title="Peer Endpoint Allowed IPs"></PeersDefaultSettingsInput>
@ -56,19 +54,23 @@ export default {
</div>
</div>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">WireGuard Configurations Settings</p>
<p class="card-header">
<LocaleText t="WireGuard Configurations Settings"></LocaleText>
</p>
<div class="card-body">
<DashboardSettingsInputWireguardConfigurationPath
targetData="wg_conf_path"
title="Configurations Directory"
:warning="true"
warning-text="Remember to remove <code>/</code> at the end of your path. e.g <code>/etc/wireguard</code>"
warning-text="Remember to remove / at the end of your path. e.g /etc/wireguard"
>
</DashboardSettingsInputWireguardConfigurationPath>
</div>
</div>
<div class="card mb-4 shadow rounded-3">
<p class="card-header">Account Settings</p>
<p class="card-header">
<LocaleText t="WGDashboard Account Settings"></LocaleText>
</p>
<div class="card-body d-flex gap-4 flex-column">
<AccountSettingsInputUsername targetData="username"
title="Username"

View File

@ -3,10 +3,14 @@ import {fetchGet, fetchPost} from "../utilities/fetch.js";
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import Message from "@/components/messageCentreComponent/message.vue";
import RemoteServerList from "@/components/signInComponents/RemoteServerList.vue";
import {GetLocale} from "@/utilities/locale.js";
import LocaleText from "@/components/text/localeText.vue";
import SignInInput from "@/components/signIn/signInInput.vue";
import SignInTOTP from "@/components/signIn/signInTOTP.vue";
export default {
name: "signin",
components: {RemoteServerList, Message},
components: {SignInTOTP, SignInInput, LocaleText, RemoteServerList, Message},
async setup(){
const store = DashboardConfigurationStore()
let theme = "dark"
@ -22,6 +26,7 @@ export default {
}),
fetchGet("/api/getDashboardVersion", {}, (res) => {
version = res.data
})
]);
}
@ -30,9 +35,11 @@ export default {
},
data(){
return {
username: "",
password: "",
totp: "",
data: {
username: "",
password: "",
totp: "",
},
loginError: false,
loginErrorMessage: "",
loading: false
@ -41,17 +48,17 @@ export default {
computed: {
getMessages(){
return this.store.Messages.filter(x => x.show)
},
applyLocale(key){
return GetLocale(key)
}
},
methods: {
GetLocale,
async auth(){
if (this.username && this.password && ((this.totpEnabled && this.totp) || !this.totpEnabled)){
if (this.data.username && this.data.password && ((this.totpEnabled && this.data.totp) || !this.totpEnabled)){
this.loading = true
await fetchPost("/api/authenticate", {
username: this.username,
password: this.password,
totp: this.totp
}, (response) => {
await fetchPost("/api/authenticate", this.data, (response) => {
if (response.status){
this.loginError = false;
this.$refs["signInBtn"].classList.add("signedIn")
@ -97,45 +104,38 @@ export default {
:data-bs-theme="this.theme">
<div class="login-box m-auto" >
<div class="m-auto" style="width: 700px;">
<h4 class="mb-0 text-body">Welcome to</h4>
<h4 class="mb-0 text-body">
<LocaleText t="Welcome to"></LocaleText>
</h4>
<span class="dashboardLogo display-3"><strong>WGDashboard</strong></span>
<div class="alert alert-danger mt-2 mb-0" role="alert" v-if="loginError">
{{this.loginErrorMessage}}
<LocaleText :t="this.loginErrorMessage"></LocaleText>
</div>
<form @submit="(e) => {e.preventDefault(); this.auth();}"
v-if="!this.store.CrossServerConfiguration.Enable">
<div class="form-group text-body">
<label for="username" class="text-left" style="font-size: 1rem">
<i class="bi bi-person-circle"></i></label>
<input type="text" v-model="username" class="form-control" id="username" name="username"
autocomplete="on"
placeholder="Username" required>
<SignInInput id="username" :data="this.data"
type="text" placeholder="Username"></SignInInput>
</div>
<div class="form-group text-body">
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i></label>
<input type="password"
v-model="password" class="form-control" id="password" name="password"
autocomplete="on"
placeholder="Password" required>
<SignInInput id="password" :data="this.data"
type="password" placeholder="Password"></SignInInput>
</div>
<div class="form-group text-body" v-if="totpEnabled">
<label for="totp" class="text-left" style="font-size: 1rem"><i class="bi bi-lock-fill"></i></label>
<input class="form-control totp"
required
id="totp" maxlength="6" type="text" inputmode="numeric" autocomplete="one-time-code"
placeholder="OTP from your authenticator"
v-model="this.totp"
>
<SignInTOTP :data="this.data"></SignInTOTP>
</div>
<button class="btn btn-lg btn-dark ms-auto mt-4 w-100 d-flex btn-brand signInBtn" ref="signInBtn">
<span v-if="!this.loading" class="d-flex w-100">
Sign In<i class="ms-auto bi bi-chevron-right"></i>
<LocaleText t="Sign In"></LocaleText>
<i class="ms-auto bi bi-chevron-right"></i>
</span>
<span v-else class="d-flex w-100 align-items-center">
Signing In...
<span class="spinner-border ms-auto spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</span>
<LocaleText t="Signing In..."></LocaleText>
<span class="spinner-border ms-auto spinner-border-sm" role="status"></span>
</span>
</button>
</form>
@ -146,7 +146,9 @@ export default {
<input
v-model="this.store.CrossServerConfiguration.Enable"
class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckChecked">
<label class="form-check-label" for="flexSwitchCheckChecked">Access Remote Server</label>
<label class="form-check-label" for="flexSwitchCheckChecked">
<LocaleText t="Access Remote Server"></LocaleText>
</label>
</div>
</div>
</div>

View File

@ -21,6 +21,7 @@ export default defineConfig(({mode}) => {
}
},
build: {
target: "es2022",
outDir: '../../../../WGDashboard-Desktop',
rollupOptions: {
output: {
@ -50,6 +51,7 @@ export default defineConfig(({mode}) => {
host: '0.0.0.0'
},
build: {
target: "es2022",
outDir: 'dist',
rollupOptions: {
output: {

View File

@ -1,8 +0,0 @@
{
"Index": {
"configurationList": {
"mainTitle": "WireGuard Configurations",
"addConfigurationBtn": "Configuration"
}
}
}

View File

@ -1,8 +0,0 @@
{
"Index": {
"configurationList": {
"mainTitle": "WireGuard 配置",
"addConfigurationBtn": "配置"
}
}
}

View File

@ -4,7 +4,11 @@
"lang_name": "English"
},
{
"lang_id": "zh-cn",
"lang_id": "zh-CN",
"lang_name": "Chinese (Simplified)"
},
{
"lang_id": "zh-HK",
"lang_name": "Chinese (Traditional)"
}
]

View File

@ -0,0 +1,10 @@
{
"WireGuard Configurations": {
"zh-CN": "WireGuard 配置",
"zh-HK": "WireGuard 配置"
},
"Configuration": {
"zh-CN": "配置",
"zh-HK": "配置"
}
}

View File

@ -0,0 +1,49 @@
{
"Welcome to": "欢迎来到",
"Username": "用户名",
"Password": "密码",
"OTP from your authenticator": "您双因素身份验证的一次性验证码",
"Sign In": "登录",
"Signing In\\.\\.\\.": "正在登录...",
"Access Remote Server": "访问远程服务器",
"Server": "服务器",
"Click": "点击",
"Pinging...": "尝试连接中...",
"to add your server": "添加您的服务器",
"Server List": "服务器列表",
"Sorry, your username or password is incorrect.": "对不起,您的用户名或密码不正确",
"Home": "主页",
"Settings": "设定",
"Tools": "工具箱",
"Sign Out": "退出登录",
"Checking for update...": "正在检查是否有新版本...",
"You're on the latest version": "已经是最新版本",
"WireGuard Configurations": "WireGuard 配置",
"You don't have any WireGuard configurations yet. Please check the configuration folder or change it in Settings. By default the folder is /etc/wireguard.": "您还没有任何WireGuard配置。请检查您的配置文件夹或前往设置更改路径。默认文件夹是 /etc/wireguard",
"Configuration": "配置",
"Configurations": "配置",
"Peers Default Settings": "端点默认设置",
"Dashboard Theme": "面板主题",
"Light": "简约白",
"Dark": "简约黑",
"This will be changed globally, and will be apply to all peer's QR code and configuration file.": "更改这个设定会应用到所有端点的配置文件和配置二维码",
"WireGuard Configurations Settings": "WireGuard 配置设定",
"Configurations Directory": "配置文件路径",
"Remember to remove / at the end of your path. e.g /etc/wireguard": "请把路径最后的 /(左斜杠)移除,例如:/etc/wireguard",
"WGDashboard Account Settings": "WGDashboard 账户设定",
"Current Password": "当前密码",
"New Password": "新密码",
"Repeat New Password": "重复新密码",
"Update Password": "更新密码",
"Multi-Factor Authentication \\(MFA\\)": "多重身份验证MFA)",
"Reset": "重置",
"Setup": "设置",
"API Keys": "API 秘钥",
"API Key": "API 秘钥",
"Key": "秘钥",
"Enabled": "已启用",
"Disabled": "已停用",
"No WGDashboard API Key": "没有 WGDashboard API 秘钥",
"Expire At": "过期于",
"Are you sure to delete this API key\\?": "确定删除此 API 秘钥?"
}