Added sorting and search to configuration list

This commit is contained in:
Donald Zou 2024-12-07 21:41:05 +08:00
parent d92e62e40b
commit 3e01079caf
6 changed files with 88 additions and 44 deletions

View File

@ -3108,7 +3108,6 @@ def ProtocolsEnabled() -> list[str]:
protocols.append("wg") protocols.append("wg")
return protocols return protocols
def InitWireguardConfigurationsList(startup: bool = False): def InitWireguardConfigurationsList(startup: bool = False):
confs = os.listdir(DashboardConfig.GetConfig("Server", "wg_conf_path")[1]) confs = os.listdir(DashboardConfig.GetConfig("Server", "wg_conf_path")[1])
confs.sort() confs.sort()
@ -3164,7 +3163,6 @@ def startThreads():
scheduleJobThread.daemon = True scheduleJobThread.daemon = True
scheduleJobThread.start() scheduleJobThread.start()
if __name__ == "__main__": if __name__ == "__main__":
startThreads() startThreads()
app.run(host=app_ip, debug=False, port=app_port) app.run(host=app_ip, debug=False, port=app_port)

View File

@ -204,6 +204,9 @@ export default {
this.dashboardConfigurationStore.newMessage("Server", this.dashboardConfigurationStore.newMessage("Server",
res.message, 'danger') res.message, 'danger')
} }
this.wireguardConfigurationStore.Configurations.find(x => x.Name === this.configurationInfo.Name).Status = res.data
console.log(this.wireguardConfigurationStore.Configurations.find(x => x.Name === this.configurationInfo.Name).Status)
this.configurationInfo.Status = res.data this.configurationInfo.Status = res.data
this.configurationToggling = false; this.configurationToggling = false;
}) })

View File

@ -1,9 +1,9 @@
<script> <script>
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"; import LocaleText from "@/components/text/localeText.vue";
import SystemStatus from "@/components/systemStatusComponents/systemStatusWidget.vue"; import SystemStatus from "@/components/systemStatusComponents/systemStatusWidget.vue";
import {GetLocale} from "@/utilities/locale.js";
export default { export default {
name: "configurationList", name: "configurationList",
@ -14,10 +14,26 @@ export default {
}, },
data(){ data(){
return { return {
configurationLoaded: false configurationLoaded: false,
sort: {
Name: GetLocale("Name"),
Status: GetLocale("Status"),
'DataUsage.Total': GetLocale("Total Usage")
},
currentSort: {
key: "Name",
order: "asc"
},
searchKey: ""
} }
}, },
async mounted() { async mounted() {
if (!window.localStorage.getItem('ConfigurationListSort')){
window.localStorage.setItem('ConfigurationListSort', JSON.stringify(this.currentSort))
}else{
this.currentSort = JSON.parse(window.localStorage.getItem('ConfigurationListSort'))
}
await this.wireguardConfigurationsStore.getConfigurations(); await this.wireguardConfigurationsStore.getConfigurations();
this.configurationLoaded = true; this.configurationLoaded = true;
@ -27,6 +43,37 @@ export default {
}, },
beforeUnmount() { beforeUnmount() {
clearInterval(this.wireguardConfigurationsStore.ConfigurationListInterval) clearInterval(this.wireguardConfigurationsStore.ConfigurationListInterval)
},
computed: {
configurations(){
return [...this.wireguardConfigurationsStore.Configurations]
.filter(x => x.Name.includes(this.searchKey) || x.PublicKey.includes(this.searchKey) || !this.searchKey)
.sort((a, b) => {
if (this.currentSort.order === 'desc') {
return this.dotNotation(a, this.currentSort.key) < this.dotNotation(b, this.currentSort.key) ?
1 : this.dotNotation(a, this.currentSort.key) > this.dotNotation(b, this.currentSort.key) ? -1 : 0;
} else {
return this.dotNotation(a, this.currentSort.key) > this.dotNotation(b, this.currentSort.key) ?
1 : this.dotNotation(a, this.currentSort.key) < this.dotNotation(b, this.currentSort.key) ? -1 : 0;
}
})
}
},
methods: {
dotNotation(object, dotNotation){
return dotNotation.split('.').reduce((o, key) => o && o[key], object)
},
updateSort(key){
if (this.currentSort.key === key){
if (this.currentSort.order === 'asc') this.currentSort.order = 'desc'
else this.currentSort.order = 'asc'
}else{
this.currentSort.key = key
}
window.localStorage.setItem('ConfigurationListSort', JSON.stringify(this.currentSort))
}
} }
} }
</script> </script>
@ -35,33 +82,53 @@ export default {
<div class="mt-md-5 mt-3"> <div class="mt-md-5 mt-3">
<div class="container-md"> <div class="container-md">
<SystemStatus></SystemStatus> <SystemStatus></SystemStatus>
<div class="d-flex mb-4 configurationListTitle align-items-center gap-3"> <div class="d-flex mb-4 configurationListTitle align-items-md-center gap-3 flex-column flex-md-row">
<h2 class="text-body d-flex"> <h2 class="text-body d-flex mb-0">
<span>
<LocaleText t="WireGuard Configurations"></LocaleText> <LocaleText t="WireGuard Configurations"></LocaleText>
</span>
</h2> </h2>
<RouterLink to="/new_configuration" <RouterLink to="/new_configuration"
class="btn btn-dark btn-brand rounded-3 p-2 shadow ms-auto rounded-3"> class="ms-md-auto py-2 text-decoration-none btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle">
<h2 class="mb-0" style="line-height: 0"> <i class="bi bi-plus-circle me-2"></i><LocaleText t="Configuration"></LocaleText>
<i class="bi bi-plus-circle"></i>
</h2>
</RouterLink> </RouterLink>
<RouterLink to="/restore_configuration" <RouterLink to="/restore_configuration"
class="btn btn-dark btn-brand p-2 shadow ms-2" style="border-radius: 100%"> class="py-2 text-decoration-none btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle">
<h2 class="mb-0" style="line-height: 0"> <i class="bi bi-clock-history me-2"></i><LocaleText t="Restore"></LocaleText>
<i class="bi bi-clock-history "></i>
</h2>
</RouterLink> </RouterLink>
</div> </div>
<div class="text-body filter mb-3 d-flex gap-2 flex-column flex-md-row" v-if="this.configurationLoaded">
<div class="d-flex align-items-center gap-3 align-items-center ">
<small class="text-muted">
<LocaleText t="Sort By"></LocaleText>
</small>
<a role="button"
@click="updateSort(sv)"
:class="{'bg-primary-subtle text-primary-emphasis': this.currentSort.key === sv}"
class="px-2 py-1 rounded-3" v-for="(s, sv) in this.sort">
<small>
<i class="bi me-2"
:class="[this.currentSort.order === 'asc' ? 'bi-sort-up' : 'bi-sort-down']"
v-if="this.currentSort.key === sv"></i>{{s}}
</small>
</a>
</div>
<div class="d-flex align-items-center ms-md-auto">
<label for="configurationSearch" class="text-muted">
<i class="bi bi-search me-2"></i>
</label>
<input class="form-control form-control-sm rounded-3"
v-model="this.searchKey"
id="configurationSearch">
</div>
</div>
<TransitionGroup name="fade" tag="div" class="d-flex flex-column gap-3 mb-4"> <TransitionGroup name="fade" tag="div" class="d-flex flex-column gap-3 mb-4">
<p class="text-muted" <p class="text-muted"
key="noConfiguration" key="noConfiguration"
v-if="this.configurationLoaded && this.wireguardConfigurationsStore.Configurations.length === 0"> v-if="this.configurationLoaded && this.wireguardConfigurationsStore.Configurations.length === 0">
<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> <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>
<ConfigurationCard v-for="(c, index) in this.wireguardConfigurationsStore.Configurations" <ConfigurationCard v-for="(c, index) in configurations"
:delay="index*0.05 + 's'" :delay="index*0.05 + 's'"
v-else-if="this.configurationLoaded" v-else-if="this.configurationLoaded"
:key="c.Name" :c="c"></ConfigurationCard> :key="c.Name" :c="c"></ConfigurationCard>
@ -73,9 +140,7 @@ export default {
</template> </template>
<style scoped> <style scoped>
.configurationListTitle{ .filter a{
.btn{ text-decoration: none;
border-radius: 50% !important;
}
} }
</style> </style>

View File

@ -1,5 +1,4 @@
<script> <script>
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";

View File

@ -156,7 +156,6 @@ router.beforeEach(async (to, from, next) => {
dashboardConfigurationStore.ShowNavBar = false; dashboardConfigurationStore.ShowNavBar = false;
document.querySelector(".loadingBar").classList.remove("loadingDone") document.querySelector(".loadingBar").classList.remove("loadingDone")
document.querySelector(".loadingBar").classList.add("loading") document.querySelector(".loadingBar").classList.add("loading")
console.log(to.path)
if (to.meta.requiresAuth){ if (to.meta.requiresAuth){
if (!dashboardConfigurationStore.getActiveCrossServer()){ if (!dashboardConfigurationStore.getActiveCrossServer()){
if (await checkAuth()){ if (await checkAuth()){

View File

@ -1,20 +0,0 @@
import {defineStore} from "pinia";
import {fetchGet} from "@/utilities/fetch.js";
export const wgdashboardStore = defineStore('WGDashboardStore', {
state: () => ({
WireguardConfigurations: undefined,
DashboardConfiguration: undefined
}),
actions: {
async getDashboardConfiguration(){
await fetchGet("/api/getDashboardConfiguration", {}, (res) => {
console.log(res.status)
if (res.status) this.DashboardConfiguration = res.data
})
}
}
});