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:
parent
d458a28337
commit
a3a312e3db
@ -399,7 +399,6 @@ class PeerShareLinks:
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
self.__getSharedLinks()
|
self.__getSharedLinks()
|
||||||
# print(self.Links)
|
|
||||||
def __getSharedLinks(self):
|
def __getSharedLinks(self):
|
||||||
self.Links.clear()
|
self.Links.clear()
|
||||||
allLinks = sqlSelect("SELECT * FROM PeerShareLinks WHERE ExpireDate IS NULL OR ExpireDate > datetime('now', 'localtime')").fetchall()
|
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],
|
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1],
|
||||||
f"{self.Name}.conf"), "w+") as configFile:
|
f"{self.Name}.conf"), "w+") as configFile:
|
||||||
# print(self.__parser.sections())
|
|
||||||
self.__parser.write(configFile)
|
self.__parser.write(configFile)
|
||||||
|
|
||||||
self.Peers: list[Peer] = []
|
self.Peers: list[Peer] = []
|
||||||
@ -613,7 +611,6 @@ class WireguardConfiguration:
|
|||||||
|
|
||||||
if regex_match("#Name# = (.*)", i):
|
if regex_match("#Name# = (.*)", i):
|
||||||
split = re.split(r'\s*=\s*', i, 1)
|
split = re.split(r'\s*=\s*', i, 1)
|
||||||
print(split)
|
|
||||||
if len(split) == 2:
|
if len(split) == 2:
|
||||||
p[pCounter]["name"] = split[1]
|
p[pCounter]["name"] = split[1]
|
||||||
|
|
||||||
@ -1283,8 +1280,6 @@ def _regexMatch(regex, text):
|
|||||||
|
|
||||||
|
|
||||||
def _getConfigurationList():
|
def _getConfigurationList():
|
||||||
# configurations = {}
|
|
||||||
print(DashboardConfig.GetConfig("Server", "wg_conf_path")[1])
|
|
||||||
for i in os.listdir(DashboardConfig.GetConfig("Server", "wg_conf_path")[1]):
|
for i in os.listdir(DashboardConfig.GetConfig("Server", "wg_conf_path")[1]):
|
||||||
if _regexMatch("^(.{1,}).(conf)$", i):
|
if _regexMatch("^(.{1,}).(conf)$", i):
|
||||||
i = i.replace('.conf', '')
|
i = i.replace('.conf', '')
|
||||||
@ -1478,6 +1473,7 @@ def auth_req():
|
|||||||
and "getDashboardVersion" not in request.path
|
and "getDashboardVersion" not in request.path
|
||||||
and "sharePeer/get" not in request.path
|
and "sharePeer/get" not in request.path
|
||||||
and "isTotpEnabled" not in request.path
|
and "isTotpEnabled" not in request.path
|
||||||
|
and "locale" not in request.path
|
||||||
):
|
):
|
||||||
response = Flask.make_response(app, {
|
response = Flask.make_response(app, {
|
||||||
"status": False,
|
"status": False,
|
||||||
@ -2132,6 +2128,24 @@ def API_Welcome_Finish():
|
|||||||
DashboardConfig.SetConfig("Other", "welcome_session", False)
|
DashboardConfig.SetConfig("Other", "welcome_session", False)
|
||||||
return ResponseObject()
|
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'])
|
@app.route(f'{APP_PREFIX}/', methods=['GET'])
|
||||||
def index():
|
def index():
|
||||||
@ -2148,8 +2162,6 @@ def backGroundThread():
|
|||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
while True:
|
while True:
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
print(DashboardConfig.GetConfig("Server", "wg_conf_path")[1])
|
|
||||||
print(id(WireguardConfigurations))
|
|
||||||
for c in WireguardConfigurations.values():
|
for c in WireguardConfigurations.values():
|
||||||
if c.getStatus():
|
if c.getStatus():
|
||||||
try:
|
try:
|
||||||
@ -2176,11 +2188,6 @@ def gunicornConfig():
|
|||||||
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
||||||
return app_ip, app_port
|
return app_ip, app_port
|
||||||
|
|
||||||
def clearWireguardConfigurations():
|
|
||||||
WireguardConfigurations = {}
|
|
||||||
WireguardConfigurations.clear()
|
|
||||||
print(WireguardConfigurations.keys())
|
|
||||||
|
|
||||||
|
|
||||||
AllPeerShareLinks: PeerShareLinks = PeerShareLinks()
|
AllPeerShareLinks: PeerShareLinks = PeerShareLinks()
|
||||||
AllPeerJobs: PeerJobs = PeerJobs()
|
AllPeerJobs: PeerJobs = PeerJobs()
|
||||||
|
BIN
src/static/app/dist/assets/bootstrap-icons.woff
vendored
BIN
src/static/app/dist/assets/bootstrap-icons.woff
vendored
Binary file not shown.
BIN
src/static/app/dist/assets/bootstrap-icons.woff2
vendored
BIN
src/static/app/dist/assets/bootstrap-icons.woff2
vendored
Binary file not shown.
10
src/static/app/dist/assets/index.css
vendored
10
src/static/app/dist/assets/index.css
vendored
File diff suppressed because one or more lines are too long
58
src/static/app/dist/assets/index.js
vendored
58
src/static/app/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
<script setup>
|
<script setup async>
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {computed, watch} from "vue";
|
import {computed, watch} from "vue";
|
||||||
@ -21,7 +21,6 @@ const getActiveCrossServer = computed(() => {
|
|||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
import {wgdashboardStore} from "@/stores/wgdashboardStore.js";
|
import {wgdashboardStore} from "@/stores/wgdashboardStore.js";
|
||||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
import ConfigurationCard from "@/components/configurationListComponents/configurationCard.vue";
|
import ConfigurationCard from "@/components/configurationListComponents/configurationCard.vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "configurationList",
|
name: "configurationList",
|
||||||
components: {ConfigurationCard},
|
components: {LocaleText, ConfigurationCard},
|
||||||
async setup(){
|
async setup(){
|
||||||
const wireguardConfigurationsStore = WireguardConfigurationsStore();
|
const wireguardConfigurationsStore = WireguardConfigurationsStore();
|
||||||
return {wireguardConfigurationsStore}
|
return {wireguardConfigurationsStore}
|
||||||
@ -36,16 +37,18 @@ export default {
|
|||||||
<div class="d-flex mb-4 configurationListTitle">
|
<div class="d-flex mb-4 configurationListTitle">
|
||||||
<h3 class="text-body d-flex">
|
<h3 class="text-body d-flex">
|
||||||
<i class="bi bi-body-text me-2"></i>
|
<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">
|
<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>
|
<i class="bi bi-plus-circle-fill me-2"></i>
|
||||||
Configuration
|
<LocaleText t="Configuration"></LocaleText>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
<Transition name="fade" mode="out-in">
|
<Transition name="fade" mode="out-in">
|
||||||
<div v-if="this.configurationLoaded">
|
<div v-if="this.configurationLoaded">
|
||||||
<p class="text-muted" v-if="this.wireguardConfigurationsStore.Configurations.length === 0">
|
<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>
|
</p>
|
||||||
<div class="d-flex gap-3 flex-column mb-3" v-else>
|
<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>
|
<ConfigurationCard v-for="c in this.wireguardConfigurationsStore.Configurations" :key="c.Name" :c="c"></ConfigurationCard>
|
||||||
|
@ -3,9 +3,11 @@ import {wgdashboardStore} from "@/stores/wgdashboardStore.js";
|
|||||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {fetchGet} from "@/utilities/fetch.js";
|
import {fetchGet} from "@/utilities/fetch.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "navbar",
|
name: "navbar",
|
||||||
|
components: {LocaleText},
|
||||||
setup(){
|
setup(){
|
||||||
const wireguardConfigurationsStore = WireguardConfigurationsStore();
|
const wireguardConfigurationsStore = WireguardConfigurationsStore();
|
||||||
const dashboardConfigurationStore = DashboardConfigurationStore();
|
const dashboardConfigurationStore = DashboardConfigurationStore();
|
||||||
@ -47,17 +49,19 @@ export default {
|
|||||||
<RouterLink class="nav-link rounded-3"
|
<RouterLink class="nav-link rounded-3"
|
||||||
to="/" exact-active-class="active">
|
to="/" exact-active-class="active">
|
||||||
<i class="bi bi-house me-2"></i>
|
<i class="bi bi-house me-2"></i>
|
||||||
Home</RouterLink></li>
|
<LocaleText t="Home"></LocaleText>
|
||||||
|
</RouterLink></li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<RouterLink class="nav-link rounded-3" to="/settings"
|
<RouterLink class="nav-link rounded-3" to="/settings"
|
||||||
exact-active-class="active">
|
exact-active-class="active">
|
||||||
<i class="bi bi-gear me-2"></i>
|
<i class="bi bi-gear me-2"></i>
|
||||||
Settings</RouterLink></li>
|
<LocaleText t="Settings"></LocaleText>
|
||||||
|
</RouterLink></li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr class="text-body">
|
<hr class="text-body">
|
||||||
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">
|
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">
|
||||||
<i class="bi bi-body-text me-2"></i>
|
<i class="bi bi-body-text me-2"></i>
|
||||||
Configurations
|
<LocaleText t="WireGuard Configurations"></LocaleText>
|
||||||
</h6>
|
</h6>
|
||||||
<ul class="nav flex-column px-2">
|
<ul class="nav flex-column px-2">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@ -72,7 +76,7 @@ export default {
|
|||||||
<hr class="text-body">
|
<hr class="text-body">
|
||||||
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">
|
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted text-center">
|
||||||
<i class="bi bi-tools me-2"></i>
|
<i class="bi bi-tools me-2"></i>
|
||||||
Tools
|
<LocaleText t="Tools"></LocaleText>
|
||||||
</h6>
|
</h6>
|
||||||
<ul class="nav flex-column px-2">
|
<ul class="nav flex-column px-2">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@ -87,16 +91,18 @@ export default {
|
|||||||
@click="this.dashboardConfigurationStore.signOut()"
|
@click="this.dashboardConfigurationStore.signOut()"
|
||||||
role="button" style="font-weight: bold">
|
role="button" style="font-weight: bold">
|
||||||
<i class="bi bi-box-arrow-left me-2"></i>
|
<i class="bi bi-box-arrow-left me-2"></i>
|
||||||
Sign Out</a>
|
<LocaleText t="Sign Out"></LocaleText>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" style="font-size: 0.8rem">
|
<li class="nav-item" style="font-size: 0.8rem">
|
||||||
<a :href="this.updateUrl" v-if="this.updateAvailable" class="text-decoration-none" target="_blank">
|
<a :href="this.updateUrl" v-if="this.updateAvailable" class="text-decoration-none" target="_blank">
|
||||||
<small class="nav-link text-muted rounded-3" >
|
<small class="nav-link text-muted rounded-3" >
|
||||||
{{ this.updateMessage }}
|
<LocaleText :t="this.updateMessage"></LocaleText>
|
||||||
</small>
|
</small>
|
||||||
</a>
|
</a>
|
||||||
<small class="nav-link text-muted" v-else>
|
<small class="nav-link text-muted" v-else>
|
||||||
{{ this.updateMessage }}
|
<LocaleText :t="this.updateMessage"></LocaleText>
|
||||||
|
({{ dashboardConfigurationStore.Configuration.Server.version}})
|
||||||
</small>
|
</small>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "accountSettingsInputPassword",
|
name: "accountSettingsInputPassword",
|
||||||
|
components: {LocaleText},
|
||||||
props:{
|
props:{
|
||||||
targetData: String,
|
targetData: String,
|
||||||
warning: false,
|
warning: false,
|
||||||
@ -81,7 +83,9 @@ export default {
|
|||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label :for="'currentPassword_' + this.uuid" class="text-muted mb-1">
|
<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>
|
</label>
|
||||||
<input type="password" class="form-control mb-2"
|
<input type="password" class="form-control mb-2"
|
||||||
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
||||||
@ -93,7 +97,9 @@ export default {
|
|||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label :for="'newPassword_' + this.uuid" class="text-muted mb-1">
|
<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>
|
</label>
|
||||||
<input type="password" class="form-control mb-2"
|
<input type="password" class="form-control mb-2"
|
||||||
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
||||||
@ -105,7 +111,9 @@ export default {
|
|||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label :for="'repeatNewPassword_' + this.uuid" class="text-muted mb-1">
|
<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>
|
</label>
|
||||||
<input type="password" class="form-control mb-2"
|
<input type="password" class="form-control mb-2"
|
||||||
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
||||||
@ -117,7 +125,8 @@ export default {
|
|||||||
<button
|
<button
|
||||||
:disabled="!this.passwordValid"
|
: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()">
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "accountSettingsInputUsername",
|
name: "accountSettingsInputUsername",
|
||||||
|
components: {LocaleText},
|
||||||
props:{
|
props:{
|
||||||
targetData: String,
|
targetData: String,
|
||||||
title: String,
|
title: String,
|
||||||
warning: false,
|
|
||||||
warningText: ""
|
|
||||||
},
|
},
|
||||||
setup(){
|
setup(){
|
||||||
const store = DashboardConfigurationStore();
|
const store = DashboardConfigurationStore();
|
||||||
@ -62,7 +62,9 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label :for="this.uuid" class="text-muted mb-1">
|
<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>
|
</label>
|
||||||
<input type="text" class="form-control"
|
<input type="text" class="form-control"
|
||||||
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
||||||
@ -73,11 +75,6 @@ export default {
|
|||||||
:disabled="this.updating"
|
:disabled="this.updating"
|
||||||
>
|
>
|
||||||
<div class="invalid-feedback">{{this.invalidFeedback}}</div>
|
<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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "accountSettingsMFA",
|
name: "accountSettingsMFA",
|
||||||
|
components: {LocaleText},
|
||||||
setup(){
|
setup(){
|
||||||
const store = DashboardConfigurationStore();
|
const store = DashboardConfigurationStore();
|
||||||
const uuid = `input_${v4()}`;
|
const uuid = `input_${v4()}`;
|
||||||
@ -43,7 +45,9 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="d-flex align-items-center">
|
<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">
|
<div class="form-check form-switch ms-3">
|
||||||
<input class="form-check-input" type="checkbox"
|
<input class="form-check-input" type="checkbox"
|
||||||
v-model="this.status"
|
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"
|
<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()">
|
v-if="this.status" @click="this.resetMFA()">
|
||||||
<i class="bi bi-shield-lock-fill me-2"></i>
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,10 +4,11 @@ import {v4} from "uuid";
|
|||||||
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
||||||
import NewDashboardAPIKey from "@/components/settingsComponent/dashboardAPIKeysComponents/newDashboardAPIKey.vue";
|
import NewDashboardAPIKey from "@/components/settingsComponent/dashboardAPIKeysComponents/newDashboardAPIKey.vue";
|
||||||
import DashboardAPIKey from "@/components/settingsComponent/dashboardAPIKeysComponents/dashboardAPIKey.vue";
|
import DashboardAPIKey from "@/components/settingsComponent/dashboardAPIKeysComponents/dashboardAPIKey.vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "dashboardAPIKeys",
|
name: "dashboardAPIKeys",
|
||||||
components: {DashboardAPIKey, NewDashboardAPIKey},
|
components: {LocaleText, DashboardAPIKey, NewDashboardAPIKey},
|
||||||
setup(){
|
setup(){
|
||||||
const store = DashboardConfigurationStore();
|
const store = DashboardConfigurationStore();
|
||||||
return {store};
|
return {store};
|
||||||
@ -64,14 +65,17 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div class="card mb-4 shadow rounded-3">
|
<div class="card mb-4 shadow rounded-3">
|
||||||
<div class="card-header d-flex">
|
<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()">
|
<div class="form-check form-switch ms-auto" v-if="!this.store.getActiveCrossServer()">
|
||||||
<input class="form-check-input" type="checkbox"
|
<input class="form-check-input" type="checkbox"
|
||||||
v-model="this.value"
|
v-model="this.value"
|
||||||
@change="this.toggleDashboardAPIKeys()"
|
@change="this.toggleDashboardAPIKeys()"
|
||||||
role="switch" id="allowAPIKeysSwitch">
|
role="switch" id="allowAPIKeysSwitch">
|
||||||
<label class="form-check-label" for="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>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -80,12 +84,13 @@ export default {
|
|||||||
@click="this.newDashboardAPIKey = true"
|
@click="this.newDashboardAPIKey = true"
|
||||||
v-if="!this.store.getActiveCrossServer()"
|
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>
|
</button>
|
||||||
<div class="card" style="height: 300px" v-if="this.apiKeys.length === 0">
|
<div class="card" style="height: 300px" v-if="this.apiKeys.length === 0">
|
||||||
<div class="card-body d-flex text-muted">
|
<div class="card-body d-flex text-muted">
|
||||||
<span class="m-auto">
|
<span class="m-auto">
|
||||||
No Dashboard API Key
|
<LocaleText t="No WGDashboard API Key"></LocaleText>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "dashboardAPIKey",
|
name: "dashboardAPIKey",
|
||||||
|
components: {LocaleText},
|
||||||
props: {
|
props: {
|
||||||
apiKey: Object
|
apiKey: Object
|
||||||
},
|
},
|
||||||
@ -37,11 +39,15 @@ export default {
|
|||||||
<div class="card rounded-3 shadow-sm">
|
<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="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">
|
<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>
|
<span style="word-break: break-all">{{this.apiKey.Key}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center gap-2 ms-auto">
|
<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'}}
|
{{this.apiKey.ExpiredAt ? this.apiKey.ExpiredAt : 'Never'}}
|
||||||
</div>
|
</div>
|
||||||
<a role="button" class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3"
|
<a role="button" class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3"
|
||||||
@ -52,7 +58,7 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
<div v-else class="card-body d-flex gap-3 align-items-center justify-content-end"
|
<div v-else class="card-body d-flex gap-3 align-items-center justify-content-end"
|
||||||
v-if="!this.store.getActiveCrossServer()">
|
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"
|
<a role="button" class="btn btn-sm bg-success-subtle text-success-emphasis rounded-3"
|
||||||
@click="this.deleteAPIKey()"
|
@click="this.deleteAPIKey()"
|
||||||
>
|
>
|
||||||
|
@ -3,9 +3,11 @@ import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.
|
|||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "dashboardSettingsInputWireguardConfigurationPath",
|
name: "dashboardSettingsInputWireguardConfigurationPath",
|
||||||
|
components: {LocaleText},
|
||||||
props:{
|
props:{
|
||||||
targetData: String,
|
targetData: String,
|
||||||
title: String,
|
title: String,
|
||||||
@ -66,7 +68,9 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label :for="this.uuid" class="text-muted mb-1">
|
<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>
|
</label>
|
||||||
<div class="d-flex gap-2 align-items-start mb-2">
|
<div class="d-flex gap-2 align-items-start mb-2">
|
||||||
<div class="flex-grow-1">
|
<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"
|
<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"
|
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>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "dashboardTheme",
|
name: "dashboardTheme",
|
||||||
|
components: {LocaleText},
|
||||||
setup(){
|
setup(){
|
||||||
const dashboardConfigurationStore = DashboardConfigurationStore();
|
const dashboardConfigurationStore = DashboardConfigurationStore();
|
||||||
return {dashboardConfigurationStore}
|
return {dashboardConfigurationStore}
|
||||||
@ -26,19 +28,21 @@ export default {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="card mb-4 shadow rounded-3">
|
<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">
|
<div class="card-body d-flex gap-2">
|
||||||
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
|
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
|
||||||
@click="this.switchTheme('light')"
|
@click="this.switchTheme('light')"
|
||||||
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'light'}">
|
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'light'}">
|
||||||
<i class="bi bi-sun-fill"></i>
|
<i class="bi bi-sun-fill me-2"></i>
|
||||||
Light
|
<LocaleText t="Light"></LocaleText>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
|
<button class="btn bg-primary-subtle text-primary-emphasis flex-grow-1"
|
||||||
@click="this.switchTheme('dark')"
|
@click="this.switchTheme('dark')"
|
||||||
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'dark'}">
|
:class="{active: this.dashboardConfigurationStore.Configuration.Server.dashboard_theme === 'dark'}">
|
||||||
<i class="bi bi-moon-fill"></i>
|
<i class="bi bi-moon-fill me-2"></i>
|
||||||
Dark
|
<LocaleText t="Dark"></LocaleText>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
import {fetchPost} from "@/utilities/fetch.js";
|
import {fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {LocaleText},
|
||||||
props:{
|
props:{
|
||||||
targetData: String,
|
targetData: String,
|
||||||
title: String,
|
title: String,
|
||||||
@ -61,7 +63,9 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label :for="this.uuid" class="text-muted mb-1">
|
<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>
|
</label>
|
||||||
<input type="text" class="form-control"
|
<input type="text" class="form-control"
|
||||||
:class="{'is-invalid': showInvalidFeedback, 'is-valid': isValid}"
|
: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"
|
<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"
|
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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
30
src/static/app/src/components/signIn/signInInput.vue
Normal file
30
src/static/app/src/components/signIn/signInInput.vue
Normal 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>
|
29
src/static/app/src/components/signIn/signInTOTP.vue
Normal file
29
src/static/app/src/components/signIn/signInTOTP.vue
Normal 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>
|
@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import {GetLocale} from "@/utilities/locale.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "RemoteServer",
|
name: "RemoteServer",
|
||||||
@ -73,7 +74,7 @@ export default {
|
|||||||
return `${dayjs().subtract(this.startTime).millisecond()}ms`
|
return `${dayjs().subtract(this.startTime).millisecond()}ms`
|
||||||
}else{
|
}else{
|
||||||
if (this.refreshing){
|
if (this.refreshing){
|
||||||
return `Pinging...`
|
return GetLocale(`Pinging...`)
|
||||||
}
|
}
|
||||||
return this.errorMsg ? this.errorMsg : "N/A"
|
return this.errorMsg ? this.errorMsg : "N/A"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import RemoteServer from "@/components/signInComponents/RemoteServer.vue";
|
import RemoteServer from "@/components/signInComponents/RemoteServer.vue";
|
||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "RemoteServerList",
|
name: "RemoteServerList",
|
||||||
@ -8,18 +9,21 @@ export default {
|
|||||||
const store = DashboardConfigurationStore();
|
const store = DashboardConfigurationStore();
|
||||||
return {store}
|
return {store}
|
||||||
},
|
},
|
||||||
components: {RemoteServer}
|
components: {LocaleText, RemoteServer}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-100 mt-3">
|
<div class="w-100 mt-3">
|
||||||
<div class="d-flex align-items-center mb-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
|
<button
|
||||||
@click="this.store.addCrossServerConfiguration()"
|
@click="this.store.addCrossServerConfiguration()"
|
||||||
class="btn bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle shadow-sm ms-auto">
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-100 d-flex gap-3 flex-column p-3 border border-1 border-secondary-subtle rounded-3"
|
<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"
|
:key="key"
|
||||||
:server="server"></RemoteServer>
|
:server="server"></RemoteServer>
|
||||||
<h6 class="text-muted m-auto" v-if="Object.keys(this.store.CrossServerConfiguration.ServerList).length === 0">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
23
src/static/app/src/components/text/localeText.vue
Normal file
23
src/static/app/src/components/text/localeText.vue
Normal 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>
|
@ -10,17 +10,24 @@ import { createPinia } from 'pinia'
|
|||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
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)
|
const app = createApp(App)
|
||||||
app.use(router)
|
|
||||||
const pinia = createPinia();
|
|
||||||
|
|
||||||
|
app.use(router)
|
||||||
|
|
||||||
|
const pinia = createPinia();
|
||||||
pinia.use(({ store }) => {
|
pinia.use(({ store }) => {
|
||||||
store.$router = markRaw(router)
|
store.$router = markRaw(router)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
|
|
||||||
|
const store = DashboardConfigurationStore()
|
||||||
app.mount('#app')
|
window.Locale = Locale;
|
||||||
|
app.mount('#app')
|
@ -1,6 +1,7 @@
|
|||||||
import {defineStore} from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
||||||
import {v4} from "uuid";
|
import {v4} from "uuid";
|
||||||
|
import {GetLocale} from "@/utilities/locale.js";
|
||||||
|
|
||||||
export const DashboardConfigurationStore = defineStore('DashboardConfigurationStore', {
|
export const DashboardConfigurationStore = defineStore('DashboardConfigurationStore', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@ -17,7 +18,8 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
|
|||||||
},
|
},
|
||||||
ActiveServerConfiguration: undefined,
|
ActiveServerConfiguration: undefined,
|
||||||
IsElectronApp: false,
|
IsElectronApp: false,
|
||||||
ShowNavBar: false
|
ShowNavBar: false,
|
||||||
|
Locale: undefined
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
initCrossServerConfiguration(){
|
initCrossServerConfiguration(){
|
||||||
@ -57,19 +59,11 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
|
|||||||
this.ActiveServerConfiguration = undefined;
|
this.ActiveServerConfiguration = undefined;
|
||||||
localStorage.removeItem('ActiveCrossServerConfiguration')
|
localStorage.removeItem('ActiveCrossServerConfiguration')
|
||||||
},
|
},
|
||||||
|
|
||||||
async getConfiguration(){
|
async getConfiguration(){
|
||||||
await fetchGet("/api/getDashboardConfiguration", {}, (res) => {
|
await fetchGet("/api/getDashboardConfiguration", {}, (res) => {
|
||||||
if (res.status) this.Configuration = res.data
|
if (res.status) this.Configuration = res.data
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// async updateConfiguration(){
|
|
||||||
// await fetchPost("/api/updateDashboardConfiguration", {
|
|
||||||
// DashboardConfiguration: this.Configuration
|
|
||||||
// }, (res) => {
|
|
||||||
// console.log(res)
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
async signOut(){
|
async signOut(){
|
||||||
await fetchGet("/api/signout", {}, (res) => {
|
await fetchGet("/api/signout", {}, (res) => {
|
||||||
this.removeActiveCrossServer();
|
this.removeActiveCrossServer();
|
||||||
@ -79,11 +73,25 @@ export const DashboardConfigurationStore = defineStore('DashboardConfigurationSt
|
|||||||
newMessage(from, content, type){
|
newMessage(from, content, type){
|
||||||
this.Messages.push({
|
this.Messages.push({
|
||||||
id: v4(),
|
id: v4(),
|
||||||
from: from,
|
from: GetLocale(from),
|
||||||
content: content,
|
content: GetLocale(content),
|
||||||
type: type,
|
type: type,
|
||||||
show: true
|
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]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
16
src/static/app/src/utilities/locale.js
Normal file
16
src/static/app/src/utilities/locale.js
Normal 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]]
|
||||||
|
}
|
@ -12,11 +12,13 @@ import DashboardSettingsInputIPAddressAndPort
|
|||||||
from "@/components/settingsComponent/dashboardSettingsInputIPAddressAndPort.vue";
|
from "@/components/settingsComponent/dashboardSettingsInputIPAddressAndPort.vue";
|
||||||
import DashboardAPIKeys from "@/components/settingsComponent/dashboardAPIKeys.vue";
|
import DashboardAPIKeys from "@/components/settingsComponent/dashboardAPIKeys.vue";
|
||||||
import AccountSettingsMFA from "@/components/settingsComponent/accountSettingsMFA.vue";
|
import AccountSettingsMFA from "@/components/settingsComponent/accountSettingsMFA.vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "settings",
|
name: "settings",
|
||||||
methods: {ipV46RegexCheck},
|
methods: {ipV46RegexCheck},
|
||||||
components: {
|
components: {
|
||||||
|
LocaleText,
|
||||||
AccountSettingsMFA,
|
AccountSettingsMFA,
|
||||||
DashboardAPIKeys,
|
DashboardAPIKeys,
|
||||||
DashboardSettingsInputIPAddressAndPort,
|
DashboardSettingsInputIPAddressAndPort,
|
||||||
@ -27,24 +29,20 @@ export default {
|
|||||||
const dashboardConfigurationStore = DashboardConfigurationStore()
|
const dashboardConfigurationStore = DashboardConfigurationStore()
|
||||||
return {dashboardConfigurationStore}
|
return {dashboardConfigurationStore}
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
// 'dashboardConfigurationStore.Configuration': {
|
|
||||||
// deep: true,
|
|
||||||
// handler(){
|
|
||||||
// this.dashboardConfigurationStore.updateConfiguration();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mt-md-5 mt-3">
|
<div class="mt-md-5 mt-3">
|
||||||
<div class="container-md">
|
<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>
|
<DashboardTheme></DashboardTheme>
|
||||||
<div class="card mb-4 shadow rounded-3">
|
<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">
|
<div class="card-body">
|
||||||
<PeersDefaultSettingsInput targetData="peer_global_dns" title="DNS"></PeersDefaultSettingsInput>
|
<PeersDefaultSettingsInput targetData="peer_global_dns" title="DNS"></PeersDefaultSettingsInput>
|
||||||
<PeersDefaultSettingsInput targetData="peer_endpoint_allowed_ip" title="Peer Endpoint Allowed IPs"></PeersDefaultSettingsInput>
|
<PeersDefaultSettingsInput targetData="peer_endpoint_allowed_ip" title="Peer Endpoint Allowed IPs"></PeersDefaultSettingsInput>
|
||||||
@ -56,19 +54,23 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-4 shadow rounded-3">
|
<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">
|
<div class="card-body">
|
||||||
<DashboardSettingsInputWireguardConfigurationPath
|
<DashboardSettingsInputWireguardConfigurationPath
|
||||||
targetData="wg_conf_path"
|
targetData="wg_conf_path"
|
||||||
title="Configurations Directory"
|
title="Configurations Directory"
|
||||||
:warning="true"
|
: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>
|
</DashboardSettingsInputWireguardConfigurationPath>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-4 shadow rounded-3">
|
<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">
|
<div class="card-body d-flex gap-4 flex-column">
|
||||||
<AccountSettingsInputUsername targetData="username"
|
<AccountSettingsInputUsername targetData="username"
|
||||||
title="Username"
|
title="Username"
|
||||||
|
@ -3,10 +3,14 @@ import {fetchGet, fetchPost} from "../utilities/fetch.js";
|
|||||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
import Message from "@/components/messageCentreComponent/message.vue";
|
import Message from "@/components/messageCentreComponent/message.vue";
|
||||||
import RemoteServerList from "@/components/signInComponents/RemoteServerList.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 {
|
export default {
|
||||||
name: "signin",
|
name: "signin",
|
||||||
components: {RemoteServerList, Message},
|
components: {SignInTOTP, SignInInput, LocaleText, RemoteServerList, Message},
|
||||||
async setup(){
|
async setup(){
|
||||||
const store = DashboardConfigurationStore()
|
const store = DashboardConfigurationStore()
|
||||||
let theme = "dark"
|
let theme = "dark"
|
||||||
@ -22,6 +26,7 @@ export default {
|
|||||||
}),
|
}),
|
||||||
fetchGet("/api/getDashboardVersion", {}, (res) => {
|
fetchGet("/api/getDashboardVersion", {}, (res) => {
|
||||||
version = res.data
|
version = res.data
|
||||||
|
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -30,9 +35,11 @@ export default {
|
|||||||
},
|
},
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
username: "",
|
data: {
|
||||||
password: "",
|
username: "",
|
||||||
totp: "",
|
password: "",
|
||||||
|
totp: "",
|
||||||
|
},
|
||||||
loginError: false,
|
loginError: false,
|
||||||
loginErrorMessage: "",
|
loginErrorMessage: "",
|
||||||
loading: false
|
loading: false
|
||||||
@ -41,17 +48,17 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
getMessages(){
|
getMessages(){
|
||||||
return this.store.Messages.filter(x => x.show)
|
return this.store.Messages.filter(x => x.show)
|
||||||
|
},
|
||||||
|
applyLocale(key){
|
||||||
|
return GetLocale(key)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
GetLocale,
|
||||||
async auth(){
|
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
|
this.loading = true
|
||||||
await fetchPost("/api/authenticate", {
|
await fetchPost("/api/authenticate", this.data, (response) => {
|
||||||
username: this.username,
|
|
||||||
password: this.password,
|
|
||||||
totp: this.totp
|
|
||||||
}, (response) => {
|
|
||||||
if (response.status){
|
if (response.status){
|
||||||
this.loginError = false;
|
this.loginError = false;
|
||||||
this.$refs["signInBtn"].classList.add("signedIn")
|
this.$refs["signInBtn"].classList.add("signedIn")
|
||||||
@ -97,45 +104,38 @@ export default {
|
|||||||
:data-bs-theme="this.theme">
|
:data-bs-theme="this.theme">
|
||||||
<div class="login-box m-auto" >
|
<div class="login-box m-auto" >
|
||||||
<div class="m-auto" style="width: 700px;">
|
<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>
|
<span class="dashboardLogo display-3"><strong>WGDashboard</strong></span>
|
||||||
<div class="alert alert-danger mt-2 mb-0" role="alert" v-if="loginError">
|
<div class="alert alert-danger mt-2 mb-0" role="alert" v-if="loginError">
|
||||||
{{this.loginErrorMessage}}
|
<LocaleText :t="this.loginErrorMessage"></LocaleText>
|
||||||
</div>
|
</div>
|
||||||
<form @submit="(e) => {e.preventDefault(); this.auth();}"
|
<form @submit="(e) => {e.preventDefault(); this.auth();}"
|
||||||
v-if="!this.store.CrossServerConfiguration.Enable">
|
v-if="!this.store.CrossServerConfiguration.Enable">
|
||||||
<div class="form-group text-body">
|
<div class="form-group text-body">
|
||||||
<label for="username" class="text-left" style="font-size: 1rem">
|
<label for="username" class="text-left" style="font-size: 1rem">
|
||||||
<i class="bi bi-person-circle"></i></label>
|
<i class="bi bi-person-circle"></i></label>
|
||||||
<input type="text" v-model="username" class="form-control" id="username" name="username"
|
<SignInInput id="username" :data="this.data"
|
||||||
autocomplete="on"
|
type="text" placeholder="Username"></SignInInput>
|
||||||
placeholder="Username" required>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group text-body">
|
<div class="form-group text-body">
|
||||||
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i></label>
|
<label for="password" class="text-left" style="font-size: 1rem"><i class="bi bi-key-fill"></i></label>
|
||||||
<input type="password"
|
<SignInInput id="password" :data="this.data"
|
||||||
v-model="password" class="form-control" id="password" name="password"
|
type="password" placeholder="Password"></SignInInput>
|
||||||
autocomplete="on"
|
|
||||||
placeholder="Password" required>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group text-body" v-if="totpEnabled">
|
<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>
|
<label for="totp" class="text-left" style="font-size: 1rem"><i class="bi bi-lock-fill"></i></label>
|
||||||
<input class="form-control totp"
|
<SignInTOTP :data="this.data"></SignInTOTP>
|
||||||
required
|
|
||||||
id="totp" maxlength="6" type="text" inputmode="numeric" autocomplete="one-time-code"
|
|
||||||
placeholder="OTP from your authenticator"
|
|
||||||
v-model="this.totp"
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-lg btn-dark ms-auto mt-4 w-100 d-flex btn-brand signInBtn" ref="signInBtn">
|
<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">
|
<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>
|
||||||
<span v-else class="d-flex w-100 align-items-center">
|
<span v-else class="d-flex w-100 align-items-center">
|
||||||
Signing In...
|
<LocaleText t="Signing In..."></LocaleText>
|
||||||
<span class="spinner-border ms-auto spinner-border-sm" role="status">
|
<span class="spinner-border ms-auto spinner-border-sm" role="status"></span>
|
||||||
<span class="visually-hidden">Loading...</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@ -146,7 +146,9 @@ export default {
|
|||||||
<input
|
<input
|
||||||
v-model="this.store.CrossServerConfiguration.Enable"
|
v-model="this.store.CrossServerConfiguration.Enable"
|
||||||
class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckChecked">
|
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,7 @@ export default defineConfig(({mode}) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
|
target: "es2022",
|
||||||
outDir: '../../../../WGDashboard-Desktop',
|
outDir: '../../../../WGDashboard-Desktop',
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
@ -50,6 +51,7 @@ export default defineConfig(({mode}) => {
|
|||||||
host: '0.0.0.0'
|
host: '0.0.0.0'
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
|
target: "es2022",
|
||||||
outDir: 'dist',
|
outDir: 'dist',
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Index": {
|
|
||||||
"configurationList": {
|
|
||||||
"mainTitle": "WireGuard Configurations",
|
|
||||||
"addConfigurationBtn": "Configuration"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Index": {
|
|
||||||
"configurationList": {
|
|
||||||
"mainTitle": "WireGuard 配置",
|
|
||||||
"addConfigurationBtn": "配置"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,11 @@
|
|||||||
"lang_name": "English"
|
"lang_name": "English"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"lang_id": "zh-cn",
|
"lang_id": "zh-CN",
|
||||||
"lang_name": "Chinese (Simplified)"
|
"lang_name": "Chinese (Simplified)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lang_id": "zh-HK",
|
||||||
|
"lang_name": "Chinese (Traditional)"
|
||||||
}
|
}
|
||||||
]
|
]
|
10
src/static/locale/languages.json
Normal file
10
src/static/locale/languages.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"WireGuard Configurations": {
|
||||||
|
"zh-CN": "WireGuard 配置",
|
||||||
|
"zh-HK": "WireGuard 配置"
|
||||||
|
},
|
||||||
|
"Configuration": {
|
||||||
|
"zh-CN": "配置",
|
||||||
|
"zh-HK": "配置"
|
||||||
|
}
|
||||||
|
}
|
49
src/static/locale/zh-CN.json
Normal file
49
src/static/locale/zh-CN.json
Normal 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 秘钥?"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user