Assign peers from client settings is done

This commit is contained in:
Donald Zou 2025-07-21 17:00:33 +08:00
parent 65287ba800
commit 90c35b67bd
7 changed files with 162 additions and 50 deletions

View File

@ -1277,7 +1277,7 @@ def API_Clients_AssignedPeers():
if not clientId:
return ResponseObject(False, "Please provide ClientID")
d = DashboardClients.GetClientAssignedPeers(clientId)
d = DashboardClients.GetClientAssignedPeersGrouped(clientId)
if d is None:
return ResponseObject(False, "Client does not exist")
return ResponseObject(data=d)

View File

@ -330,10 +330,15 @@ class DashboardClients:
a.Client = self.GetClient(a.ClientID)
return c
def GetClientAssignedPeers(self, ClientID):
def GetClientAssignedPeersGrouped(self, ClientID):
client = self.GetClient(ClientID)
if client is not None:
return self.DashboardClientsPeerAssignment.GetAssignedPeers(ClientID)
p = self.DashboardClientsPeerAssignment.GetAssignedPeers(ClientID)
configs = set(map(lambda x : x['configuration_name'], p))
d = {}
for i in configs:
d[i] = list(filter(lambda x : x['configuration_name'] == i, p))
return d
return None
def AssignClient(self, ConfigurationName, PeerID, ClientID) -> tuple[bool, dict[str, str]] | tuple[bool, None]:

View File

@ -127,6 +127,7 @@ class DashboardClientsPeerAssignment:
self.wireguardConfigurations[a.ConfigurationName].Peers)
for p in peer:
peers.append({
'assignment_id': a.AssignmentID,
'protocol': self.wireguardConfigurations[a.ConfigurationName].Protocol,
'id': p.id,
'private_key': p.private_key,

View File

@ -0,0 +1,78 @@
<script setup lang="ts">
import {computed, ref} from "vue";
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
import LocaleText from "@/components/text/localeText.vue";
const props = defineProps(['configuration', 'peers', 'clientAssignedPeers'])
const emits = defineEmits(['assign', 'unassign'])
const assignmentStore = DashboardClientAssignmentStore()
const available = computed(() => {
if (props.clientAssignedPeers){
if (Object.keys(props.clientAssignedPeers).includes(props.configuration)){
return props.peers.filter(
x => !props.clientAssignedPeers[props.configuration].map(
x => x.id
).includes(x.id)
)
}
}
return props.peers
})
const confirmDelete = ref(false)
</script>
<template>
<div class="card rounded-0 border-0">
<div class="card-header rounded-top-3 sticky-top z-5 bg-body-secondary border-0 shadow border-bottom btn-brand text-white">
<samp>{{ configuration }}</samp>
</div>
<div class="card-body p-0">
<div class="list-group list-group-flush" >
<div
class="list-group-item d-flex border-bottom list-group-item-action d-flex align-items-center gap-3"
:key="peer.id"
v-for="peer in available" >
<div v-if="!confirmDelete">
<small class="text-body">
<samp>{{ peer.id }}</samp>
</small><br>
<small class="text-muted">
{{ peer.name ? peer.name : 'Untitled Peer'}}
</small>
</div>
<div v-else>
<small class="text-body">
<LocaleText t="Are you sure to remove this peer?"></LocaleText>
</small><br>
<small class="text-muted">
<samp>{{ peer.id }}</samp>
</small>
</div>
<template v-if="clientAssignedPeers">
<button
@click="emits('assign', peer.id)"
:class="{disabled: assignmentStore.assigning}"
class="btn bg-success-subtle text-success-emphasis ms-auto">
<i class="bi bi-plus-circle-fill" ></i>
</button>
</template>
<button
v-else
@click="emits('unassign', peer.assignment_id)"
:class="{disabled: assignmentStore.unassigning}"
aria-label="Delete Assignment"
class="btn bg-danger-subtle text-danger-emphasis ms-auto">
<i class="bi bi-trash-fill"></i>
</button>
</div>
</div>
</div>
</div>
</template>
<style scoped>
</style>

View File

@ -1,62 +1,92 @@
<script setup lang="ts">
import {onMounted, watch, watchEffect} from "vue";
import {onMounted, ref, watch, watchEffect} from "vue";
import { fetchGet } from "@/utilities/fetch.js"
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
import AvailablePeersGroup from "@/components/clientComponents/availablePeersGroup.vue";
import LocaleText from "@/components/text/localeText.vue";
import configuration from "@/views/configuration.vue";
const props = defineProps(['client'])
watchEffect(async () => {
const clientId = props.client.ClientID;
const clientAssignedPeers = ref({})
const loading = ref(false)
const assignmentStore = DashboardClientAssignmentStore()
const manage = ref(false)
const selectedAssign = ref(undefined)
const selectedUnassign = ref(undefined)
const getAssignedPeers = async () => {
await fetchGet('/api/clients/assignedPeers', {
ClientID: clientId
ClientID: props.client.ClientID
}, (res) => {
console.log(res)
clientAssignedPeers.value = res.data;
loading.value = false;
})
}
watchEffect(async () => {
loading.value = true
await getAssignedPeers()
})
const assignmentStore = DashboardClientAssignmentStore()
const assign = async (ConfigurationName, Peer, ClientID) => {
await assignmentStore.assignClient(ConfigurationName, Peer, ClientID, false)
await getAssignedPeers()
}
const unassign = async (AssignmentID) => {
await assignmentStore.unassignClient(undefined, undefined, AssignmentID)
await getAssignedPeers()
}
</script>
<template>
<div class="border w-100 d-flex " style="height: 400px">
<div style="flex: 1 0 0; overflow: scroll">
<div class="card rounded-0 border-0" v-for="(peers, configuration) in assignmentStore.allConfigurationsPeers">
<div class="card-header sticky-top z-5 bg-body-secondary border-0 rounded-0 shadow border-bottom btn-brand text-white">
<samp>{{ configuration }}</samp>
</div>
<div class="card-body p-0">
<div class="list-group list-group-flush" >
<button
class="list-group-item d-flex flex-column border-bottom list-group-item-action"
v-for="peer in peers" >
<small class="text-body">
{{ peer.id }}
</small>
<small class="text-muted">
{{ client.name ? client.name : 'Untitled Peer'}}
</small>
</button>
</div>
</div>
<div class="d-flex rounded-3 flex-column gap-3">
<div style="height: 300px" class="d-flex flex-column">
<div class="d-flex align-items-center mb-2">
<h6 class="mb-0">
<LocaleText t="Assigned Peers"></LocaleText>
</h6>
<button class="btn btn-sm bg-primary-subtle text-primary-emphasis rounded-3 ms-auto"
@click="manage = !manage">
<template v-if="!manage">
<i class="bi bi-list-check me-2"></i>Manage
</template>
<template v-else>
<i class="bi bi-check me-2"></i>Done
</template>
</button>
</div>
<div class="rounded-3 availablePeers border h-100 overflow-scroll flex-grow-1">
<AvailablePeersGroup
:configuration="configuration"
:peers="peers"
@unassign="async (id) => await unassign(id)"
v-for="(peers, configuration) in clientAssignedPeers">
</AvailablePeersGroup>
</div>
</div>
<div class="px-3 border-start border-end d-flex flex-column justify-content-center gap-3">
<button class="btn">
<i class="bi bi-chevron-left"></i>
</button>
<button class="btn">
<i class="bi bi-chevron-right"></i>
</button>
</div>
<div style="flex: 1 0 0">
hi
<div style="height: 300px" class="d-flex flex-column" v-if="manage">
<h6>
<LocaleText t="Available Peers"></LocaleText>
</h6>
<div class="rounded-3 availablePeers border h-100 overflow-scroll flex-grow-1">
<AvailablePeersGroup
:configuration="configuration"
:clientAssignedPeers="clientAssignedPeers"
:peers="peers"
@assign="async (id) => await assign(configuration, id, props.client.ClientID)"
v-for="(peers, configuration) in assignmentStore.allConfigurationsPeers">
</AvailablePeersGroup>
</div>
</div>
</div>
</template>
<style scoped>
div .list-group-item:last-child{
border-bottom: none !important;
}
</style>

View File

@ -34,9 +34,7 @@ const client = computed(() => {
</div>
</div>
<div class="px-4">
<h5 class="mb-3">
<LocaleText t="Assign Peers"></LocaleText>
</h5>
<ClientAssignedPeers :client="client"></ClientAssignedPeers>
</div>
</div>

View File

@ -37,7 +37,7 @@ export const DashboardClientAssignmentStore =
})
}
const assignClient = async (ConfigurationName, Peer, ClientID) => {
const assignClient = async (ConfigurationName, Peer, ClientID, get=true) => {
assigning.value = ClientID;
await fetchPost('/api/clients/assignClient', {
ConfigurationName: ConfigurationName,
@ -45,7 +45,7 @@ export const DashboardClientAssignmentStore =
ClientID: ClientID
}, async (res) => {
if (res.status){
await getAssignedClients(ConfigurationName, Peer)
if (get) await getAssignedClients(ConfigurationName, Peer)
assigning.value = "";
}else{
assigning.value = "";
@ -59,7 +59,7 @@ export const DashboardClientAssignmentStore =
AssignmentID: AssignmentID
}, async (res) => {
if (res.status){
await getAssignedClients(ConfigurationName, Peer)
if (ConfigurationName && Peer) await getAssignedClients(ConfigurationName, Peer)
}
unassigning.value = false;
})