mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-10-03 07:46:18 +00:00
Commit for #355
This commit is contained in:
@@ -76,7 +76,6 @@ const configurationModals = ref({
|
||||
}
|
||||
})
|
||||
const peerSearchBar = ref(false)
|
||||
|
||||
// Fetch Peer =====================================
|
||||
const fetchPeerList = async () => {
|
||||
await fetchGet("/api/getWireguardConfigurationInfo", {
|
||||
@@ -110,6 +109,7 @@ setFetchPeerListInterval()
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(fetchPeerListInterval.value);
|
||||
fetchPeerListInterval.value = undefined;
|
||||
wireguardConfigurationStore.Filter.HiddenTags = []
|
||||
})
|
||||
|
||||
watch(() => {
|
||||
@@ -155,13 +155,28 @@ const configurationSummary = computed(() => {
|
||||
|
||||
const showPeersCount = ref(10)
|
||||
const showPeersThreshold = 20;
|
||||
const hiddenPeers = computed(() => {
|
||||
return wireguardConfigurationStore.Filter.HiddenTags.map(tag => {
|
||||
return configurationInfo.value.Info.PeerGroups[tag].Peers
|
||||
}).flat()
|
||||
})
|
||||
const taggedPeers = computed(() => {
|
||||
return Object.values(configurationInfo.value.Info.PeerGroups).map(x => x.Peers).flat()
|
||||
})
|
||||
|
||||
const searchPeers = computed(() => {
|
||||
const result = wireguardConfigurationStore.searchString ?
|
||||
configurationPeers.value.filter(x => {
|
||||
return x.name.includes(wireguardConfigurationStore.searchString) ||
|
||||
return (x.name.includes(wireguardConfigurationStore.searchString) ||
|
||||
x.id.includes(wireguardConfigurationStore.searchString) ||
|
||||
x.allowed_ip.includes(wireguardConfigurationStore.searchString)
|
||||
}) : configurationPeers.value;
|
||||
x.allowed_ip.includes(wireguardConfigurationStore.searchString))
|
||||
&& !hiddenPeers.value.includes(x.id)
|
||||
&& (
|
||||
wireguardConfigurationStore.Filter.ShowAllPeersWhenHiddenTags || (!wireguardConfigurationStore.Filter.ShowAllPeersWhenHiddenTags && taggedPeers.value.includes(x.id))
|
||||
)
|
||||
}) : configurationPeers.value.filter(x => !hiddenPeers.value.includes(x.id) && (
|
||||
wireguardConfigurationStore.Filter.ShowAllPeersWhenHiddenTags || (!wireguardConfigurationStore.Filter.ShowAllPeersWhenHiddenTags && taggedPeers.value.includes(x.id))
|
||||
));
|
||||
|
||||
if (dashboardStore.Configuration.Server.dashboard_sort === "restricted"){
|
||||
return result.sort((a, b) => {
|
||||
@@ -201,6 +216,7 @@ watch(() => route.query.id, (newValue) => {
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -352,10 +368,10 @@ watch(() => route.query.id, (newValue) => {
|
||||
:configurationInfo="configurationInfo"
|
||||
></PeerDataUsageCharts>
|
||||
<hr>
|
||||
<div style="margin-bottom: 80px">
|
||||
<div style="margin-bottom: 10rem">
|
||||
<PeerSearch
|
||||
v-if="configurationPeers.length > 0"
|
||||
@search="peerSearchBar = true"
|
||||
@search="peerSearchBar = !peerSearchBar"
|
||||
@jobsAll="configurationModals.peerScheduleJobsAll.modalOpen = true"
|
||||
@jobLogs="configurationModals.peerScheduleJobsLogs.modalOpen = true"
|
||||
@editConfiguration="configurationModals.editConfiguration.modalOpen = true"
|
||||
@@ -383,8 +399,11 @@ watch(() => route.query.id, (newValue) => {
|
||||
</TransitionGroup>
|
||||
|
||||
</div>
|
||||
<Transition name="slideUp">
|
||||
<PeerSearchBar @close="peerSearchBar = false" v-if="peerSearchBar"></PeerSearchBar>
|
||||
<Transition name="slide-fade">
|
||||
<PeerSearchBar
|
||||
v-if="peerSearchBar"
|
||||
:ConfigurationInfo="configurationInfo"
|
||||
@close="peerSearchBar = false"></PeerSearchBar>
|
||||
</Transition>
|
||||
<PeerListModals
|
||||
:configurationModals="configurationModals"
|
||||
|
@@ -16,7 +16,7 @@ export default {
|
||||
return {store, wireguardConfigurationStore}
|
||||
},
|
||||
props: {
|
||||
configuration: Object
|
||||
configuration: Object, displayTags: Array
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
@@ -163,7 +163,7 @@ export default {
|
||||
@click="tagManager = !tagManager"
|
||||
class="btn btn-sm w-100 text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle position-relative">
|
||||
|
||||
<i class="bi me-2 bi-hash"></i>
|
||||
<i class="bi me-2 bi-tag"></i>
|
||||
<LocaleText t="Tags"></LocaleText>
|
||||
|
||||
</button>
|
||||
|
@@ -2,8 +2,7 @@
|
||||
import {GetLocale} from "@/utilities/locale.js";
|
||||
import {computed, onMounted, ref, useTemplateRef} from "vue";
|
||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||
import LocaleText from "@/components/text/localeText.vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {onBeforeRouteUpdate, useRoute, useRouter} from "vue-router";
|
||||
|
||||
const searchBarPlaceholder = computed(() => {
|
||||
return GetLocale("Search Peers...")
|
||||
@@ -27,7 +26,7 @@ const debounce = () => {
|
||||
|
||||
const emits = defineEmits(['close'])
|
||||
const input = useTemplateRef('searchBar')
|
||||
|
||||
const props = defineProps(["ConfigurationInfo"])
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
if (route.query.peer){
|
||||
@@ -35,53 +34,42 @@ if (route.query.peer){
|
||||
router.replace({ query: null })
|
||||
}
|
||||
|
||||
const show = ref(true)
|
||||
onMounted(() => {
|
||||
input.value.focus();
|
||||
document.querySelector("#searchPeers").focus()
|
||||
})
|
||||
|
||||
onBeforeRouteUpdate(() => {
|
||||
show.value = false
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition name="slideUp" appear type="animation" style="animation-delay: 1s">
|
||||
<div class="fixed-bottom w-100 bottom-0 z-2" style="z-index: 1;">
|
||||
<div class="container-fluid">
|
||||
<div class="row g-0">
|
||||
<div class="col-md-3 col-lg-2"></div>
|
||||
<div class="col-md-9 col-lg-10 d-flex justify-content-center py-2">
|
||||
<div class="rounded-3 p-2 border shadow searchPeersContainer bg-body-tertiary">
|
||||
<div class="d-flex gap-1 align-items-center px-2">
|
||||
<h6 class="mb-0 me-2">
|
||||
<label for="searchPeers">
|
||||
<i class="bi bi-search"></i>
|
||||
</label>
|
||||
</h6>
|
||||
<input
|
||||
ref="searchBar"
|
||||
class="flex-grow-1 form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle "
|
||||
:placeholder="searchBarPlaceholder"
|
||||
id="searchPeers"
|
||||
@keyup="debounce()"
|
||||
v-model="searchString">
|
||||
<button
|
||||
@click="emits('close')"
|
||||
style="white-space: nowrap"
|
||||
class="btn bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 d-flex align-items-center">
|
||||
<span>
|
||||
<i class="bi bi-x-circle-fill me-2"></i><LocaleText t="Done"></LocaleText>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-bottom w-100 bottom-0 z-2 p-3" style="z-index: 1;" v-if="show">
|
||||
<div class="d-flex flex-column searchPeersContainer ms-auto p-2 rounded-5"
|
||||
style="width: 300px;">
|
||||
<div class="rounded-5 border border-white p-2 d-flex align-items-center gap-1 w-100">
|
||||
<input
|
||||
ref="searchBar"
|
||||
|
||||
class="flex-grow-1 form-control form-control-sm rounded-5 bg-transparent border-0 border-secondary-subtle "
|
||||
:placeholder="searchBarPlaceholder"
|
||||
id="searchPeers"
|
||||
@keyup="debounce()"
|
||||
v-model="searchString">
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.searchPeersContainer{
|
||||
backdrop-filter: blur(8px);
|
||||
width: 100%;
|
||||
background: linear-gradient(var(--degree), rgba(45, 173, 255, 0.4), rgba(255, 108, 109, 0.4), var(--brandColor2) 100%);
|
||||
}
|
||||
#searchPeers::placeholder{
|
||||
color: white;
|
||||
}
|
||||
</style>
|
@@ -162,7 +162,7 @@ export default {
|
||||
data-bs-toggle="dropdown"
|
||||
|
||||
>
|
||||
<i class="me-auto bi bi-diagram-2"></i> <LocaleText t="Tag Peer"></LocaleText>
|
||||
<i class="me-auto bi bi-tag"></i> <LocaleText t="Tag Peer"></LocaleText>
|
||||
</a>
|
||||
<PeerTagSelectDropdown
|
||||
@update="this.$emit('refresh')"
|
||||
|
@@ -106,7 +106,8 @@ const predefinedColors = {
|
||||
"white": "#fff",
|
||||
"black": "#000",
|
||||
}
|
||||
|
||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js"
|
||||
const store = WireguardConfigurationsStore()
|
||||
const props = defineProps(['configuration'])
|
||||
const groups = reactive({...props.configuration.Info.PeerGroups})
|
||||
import { v4 } from "uuid"
|
||||
@@ -154,10 +155,22 @@ watch(() => groups, (newVal) => {
|
||||
}, {
|
||||
deep: true
|
||||
})
|
||||
|
||||
const edit = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card shadow" id="peerTag">
|
||||
<div class="card shadow rounded-3" id="peerTag">
|
||||
<div class="card-header">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="showAllPeers" v-model="store.Filter.ShowAllPeersWhenHiddenTags">
|
||||
<label class="form-check-label" for="showAllPeers">
|
||||
<small>
|
||||
<LocaleText t="Show All Peers"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-2" >
|
||||
<Transition name="zoom" mode="out-in">
|
||||
<div v-if="!iconPickerOpen && !colorPickerOpen">
|
||||
@@ -165,12 +178,16 @@ watch(() => groups, (newVal) => {
|
||||
<small><LocaleText t="No tag"></LocaleText></small>
|
||||
</div>
|
||||
<div class="d-flex flex-column gap-2" v-else>
|
||||
<PeerTagSetting v-for="(group, key) in groups"
|
||||
@delete="delete groups[key]"
|
||||
@colorPickerOpen="colorPickerOpen = true; selectedKey = key"
|
||||
@iconPickerOpen="iconPickerOpen = true; selectedKey = key"
|
||||
:key="key"
|
||||
:group="group"></PeerTagSetting>
|
||||
<TransitionGroup name="slide-fade">
|
||||
<PeerTagSetting v-for="(group, key) in groups"
|
||||
:groupId="key"
|
||||
@delete="delete groups[key]; store.Filter.HiddenTags = store.Filter.HiddenTags.filter(x => x !== key)"
|
||||
@colorPickerOpen="colorPickerOpen = true; selectedKey = key"
|
||||
@iconPickerOpen="iconPickerOpen = true; selectedKey = key"
|
||||
:key="key"
|
||||
:edit="edit"
|
||||
:group="group"></PeerTagSetting>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</div>
|
||||
<PeerTagIconPicker
|
||||
@@ -184,16 +201,31 @@ watch(() => groups, (newVal) => {
|
||||
</Transition>
|
||||
</div>
|
||||
<div class="card-footer p-2 d-flex gap-2" >
|
||||
<button
|
||||
@click="emits('close')"
|
||||
class="btn btn-sm bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3">
|
||||
<small><LocaleText t="Close"></LocaleText></small>
|
||||
</button>
|
||||
<button
|
||||
@click="addGroup"
|
||||
class="btn btn-sm bg-primary-subtle text-primary-emphasis border-primary-subtle rounded-3 ms-auto">
|
||||
<small><i class="bi bi-plus-lg me-2"></i><LocaleText t="Tag"></LocaleText></small>
|
||||
</button>
|
||||
<template v-if="!edit">
|
||||
<button
|
||||
@click="emits('close')"
|
||||
class="btn btn-sm bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3">
|
||||
<small><LocaleText t="Close"></LocaleText></small>
|
||||
</button>
|
||||
<button
|
||||
@click="edit = true"
|
||||
class="btn btn-sm bg-primary-subtle text-primary-emphasis border-primary-subtle rounded-3 ms-auto">
|
||||
<small><i class="bi bi-pen me-2"></i><LocaleText t="Edit"></LocaleText></small>
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
<button
|
||||
@click="addGroup"
|
||||
class="btn btn-sm bg-primary-subtle text-primary-emphasis border-primary-subtle rounded-3 ">
|
||||
<small><i class="bi bi-plus-lg me-2"></i><LocaleText t="Tag"></LocaleText></small>
|
||||
</button>
|
||||
<button
|
||||
@click="edit = false"
|
||||
class="btn btn-sm bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 ms-auto">
|
||||
<small><LocaleText t="Done"></LocaleText></small>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -16,14 +16,6 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div class="w-100 bg-body top-0 border rounded-2">
|
||||
<div class="p-2 d-flex align-items-center gap-2 border-bottom">
|
||||
<label>
|
||||
<i class="bi bi-search"></i>
|
||||
</label>
|
||||
<input v-model="searchString"
|
||||
placeholder="Search Icon"
|
||||
class="form-control form-control-sm rounded-2">
|
||||
</div>
|
||||
<div class="p-2 d-grid icon-grid"
|
||||
style="grid-template-columns: repeat(auto-fit, minmax(30px, 30px)); gap: 3px; max-height: 300px; overflow-y: scroll">
|
||||
<div class="rounded-1 border icon d-flex"
|
||||
|
@@ -3,41 +3,65 @@ import LocaleText from "@/components/text/localeText.vue";
|
||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js"
|
||||
import {ref} from "vue";
|
||||
const store = WireguardConfigurationsStore();
|
||||
const props = defineProps(['group'])
|
||||
const emits = defineEmits(['delete', 'iconPickerOpen', 'colorPickerOpen'])
|
||||
|
||||
const props = defineProps(['group', 'edit', 'groupId'])
|
||||
const emits = defineEmits(['delete', 'iconPickerOpen', 'colorPickerOpen', 'toggle'])
|
||||
const groupName = ref(props.group.GroupName)
|
||||
const toggleTag = () => {
|
||||
if (store.Filter.HiddenTags.includes(props.groupId)){
|
||||
store.Filter.HiddenTags = store.Filter.HiddenTags.filter(x => x !== props.groupId)
|
||||
}else{
|
||||
store.Filter.HiddenTags.push(props.groupId)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border rounded-3 p-2">
|
||||
<div
|
||||
class="rounded-3 align-items-center overflow-scroll d-flex gap-2 position-relative">
|
||||
<div
|
||||
class=" align-items-center overflow-scroll d-flex gap-2 position-relative">
|
||||
<button
|
||||
@click="emits('iconPickerOpen')"
|
||||
aria-label="Pick icon button"
|
||||
:class="{disabled: !edit}"
|
||||
class="d-flex align-items-center p-2 btn btn-sm border rounded-2">
|
||||
<i class="bi" :class="'bi-' + group.Icon" :aria-label="group.Icon" v-if="group.Icon"></i>
|
||||
<span style="white-space: nowrap" v-else>
|
||||
<LocaleText t="No Icon"></LocaleText>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
:class="{disabled: !edit}"
|
||||
aria-label="Pick color button"
|
||||
@click="emits('colorPickerOpen')"
|
||||
:style="{'background-color': group.BackgroundColor, 'color': store.colorText(group.BackgroundColor)}"
|
||||
class="d-flex align-items-center p-2 btn btn-sm border rounded-2">
|
||||
<i class="bi bi-eyedropper" ></i>
|
||||
</div>
|
||||
<i class="bi bi-eyedropper" ></i>
|
||||
</button>
|
||||
<input
|
||||
:disabled="!edit"
|
||||
v-model="groupName"
|
||||
@change="group.GroupName = groupName"
|
||||
placeholder="Tag Name"
|
||||
class="form-control form-control-sm p-2 rounded-2 w-100">
|
||||
<div
|
||||
aria-label="Pick color button" @click="emits('delete')"
|
||||
<button
|
||||
v-if="edit"
|
||||
aria-label="Delete Tag Button" @click="emits('delete')"
|
||||
class="rounded-2 border p-2 btn btn-sm btn-outline-danger">
|
||||
<i class="bi bi-trash-fill" ></i>
|
||||
</div>
|
||||
<i class="bi bi-trash-fill"></i>
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
aria-label="Show / Hide Button"
|
||||
style="white-space: nowrap"
|
||||
:class="{active: !store.Filter.HiddenTags.includes(groupId)}"
|
||||
@click="toggleTag()"
|
||||
class="rounded-2 p-2 btn btn-sm btn-outline-primary">
|
||||
<i class="bi"
|
||||
:class="[!store.Filter.HiddenTags.includes(groupId) ? 'bi-eye-fill':'bi-eye-slash-fill']"
|
||||
></i>
|
||||
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -10,6 +10,10 @@ export const WireguardConfigurationsStore = defineStore('WireguardConfigurations
|
||||
ConfigurationLoaded: false,
|
||||
searchString: "",
|
||||
ConfigurationListInterval: undefined,
|
||||
Filter: {
|
||||
HiddenTags: [],
|
||||
ShowAllPeersWhenHiddenTags: true
|
||||
},
|
||||
SortOptions: {
|
||||
Name: GetLocale("Name"),
|
||||
Status: GetLocale("Status"),
|
||||
@@ -131,7 +135,7 @@ export const WireguardConfigurationsStore = defineStore('WireguardConfigurations
|
||||
},
|
||||
persist: {
|
||||
pick: [
|
||||
"CurrentSort", "CurrentDisplay"
|
||||
"CurrentSort", "CurrentDisplay", "Filter.ShowAllPeersWhenHiddenTags"
|
||||
]
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user