mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-07-28 01:12:22 +00:00
Commit
This commit is contained in:
parent
b0bb320fb6
commit
2cf337a606
@ -3,23 +3,27 @@ import {computed, ref} from "vue";
|
|||||||
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
|
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
|
||||||
const props = defineProps(['configuration', 'peers', 'clientAssignedPeers'])
|
const props = defineProps(['configuration', 'peers', 'clientAssignedPeers', 'availablePeerSearchString'])
|
||||||
const emits = defineEmits(['assign', 'unassign'])
|
const emits = defineEmits(['assign', 'unassign'])
|
||||||
const assignmentStore = DashboardClientAssignmentStore()
|
const assignmentStore = DashboardClientAssignmentStore()
|
||||||
const available = computed(() => {
|
const available = computed(() => {
|
||||||
if (props.clientAssignedPeers){
|
if (props.clientAssignedPeers){
|
||||||
if (Object.keys(props.clientAssignedPeers).includes(props.configuration)){
|
if (Object.keys(props.clientAssignedPeers).includes(props.configuration)){
|
||||||
return props.peers.filter(
|
return props.peers.filter(
|
||||||
x => !props.clientAssignedPeers[props.configuration].map(
|
x => {
|
||||||
x => x.id
|
return !props.clientAssignedPeers[props.configuration].map(
|
||||||
).includes(x.id)
|
x => x.id
|
||||||
|
).includes(x.id) &&
|
||||||
|
(!props.availablePeerSearchString ||
|
||||||
|
(props.availablePeerSearchString &&
|
||||||
|
(x.id.includes(props.availablePeerSearchString) || x.name.includes(props.availablePeerSearchString))))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return props.peers
|
return props.peers
|
||||||
})
|
})
|
||||||
const confirmDelete = ref(false)
|
const confirmDelete = ref(false)
|
||||||
|
|
||||||
const collapse = ref(false)
|
const collapse = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -28,8 +32,8 @@ const collapse = ref(false)
|
|||||||
<div
|
<div
|
||||||
@click="collapse = !collapse"
|
@click="collapse = !collapse"
|
||||||
role="button"
|
role="button"
|
||||||
class="card-header rounded-0 sticky-top z-5 bg-body-secondary border-0 shadow border-bottom btn-brand text-white d-flex">
|
class="card-header rounded-0 sticky-top z-5 bg-body-secondary border-0 border-bottom text-white d-flex">
|
||||||
<samp>{{ configuration }}</samp>
|
<small><samp>{{ configuration }}</samp></small>
|
||||||
<a role="button" class="ms-auto text-white" >
|
<a role="button" class="ms-auto text-white" >
|
||||||
<i class="bi bi-chevron-compact-down" v-if="collapse"></i>
|
<i class="bi bi-chevron-compact-down" v-if="collapse"></i>
|
||||||
<i class="bi bi-chevron-compact-up" v-else></i>
|
<i class="bi bi-chevron-compact-up" v-else></i>
|
||||||
|
@ -1,115 +1,103 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts" async>
|
||||||
import {onMounted, ref, watch, watchEffect} from "vue";
|
import {onMounted, ref, watch, watchEffect} from "vue";
|
||||||
import { fetchGet } from "@/utilities/fetch.js"
|
import { fetchGet } from "@/utilities/fetch.js"
|
||||||
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
|
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
|
||||||
import AvailablePeersGroup from "@/components/clientComponents/availablePeersGroup.vue";
|
import AvailablePeersGroup from "@/components/clientComponents/availablePeersGroup.vue";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
import configuration from "@/views/configuration.vue";
|
const props = defineProps(['client', 'clientAssignedPeers'])
|
||||||
const props = defineProps(['client'])
|
|
||||||
const clientAssignedPeers = ref({})
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const assignmentStore = DashboardClientAssignmentStore()
|
const assignmentStore = DashboardClientAssignmentStore()
|
||||||
const manage = ref(false)
|
const manage = ref(false)
|
||||||
|
const emits = defineEmits(['refresh'])
|
||||||
const selectedAssign = ref(undefined)
|
|
||||||
const selectedUnassign = ref(undefined)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const getAssignedPeers = async () => {
|
|
||||||
await fetchGet('/api/clients/assignedPeers', {
|
|
||||||
ClientID: props.client.ClientID
|
|
||||||
}, (res) => {
|
|
||||||
clientAssignedPeers.value = res.data;
|
|
||||||
loading.value = false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
watchEffect(async () => {
|
|
||||||
loading.value = true
|
|
||||||
await getAssignedPeers()
|
|
||||||
})
|
|
||||||
|
|
||||||
const assign = async (ConfigurationName, Peer, ClientID) => {
|
const assign = async (ConfigurationName, Peer, ClientID) => {
|
||||||
await assignmentStore.assignClient(ConfigurationName, Peer, ClientID, false)
|
await assignmentStore.assignClient(ConfigurationName, Peer, ClientID, false)
|
||||||
await getAssignedPeers()
|
emits('refresh')
|
||||||
}
|
}
|
||||||
|
|
||||||
const unassign = async (AssignmentID) => {
|
const unassign = async (AssignmentID) => {
|
||||||
await assignmentStore.unassignClient(undefined, undefined, AssignmentID)
|
await assignmentStore.unassignClient(undefined, undefined, AssignmentID)
|
||||||
await getAssignedPeers()
|
emits('refresh')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const availablePeerSearchString = ref("")
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="d-flex rounded-3 flex-column gap-3">
|
<div>
|
||||||
<div style="height: 400px" class="d-flex flex-column">
|
<div class="d-flex rounded-0 border-0 flex-column d-flex flex-column border-bottom pb-1" v-if="!loading">
|
||||||
<div class="d-flex align-items-center mb-2">
|
<div class="d-flex flex-column p-3 gap-3">
|
||||||
<h6 class="mb-0">
|
<div class="d-flex align-items-center">
|
||||||
<LocaleText t="Assigned Peers"></LocaleText>
|
<h6 class="mb-0">
|
||||||
<span class="text-bg-primary badge ms-2">
|
<LocaleText t="Assigned Peers"></LocaleText>
|
||||||
{{ Object.keys(clientAssignedPeers).length }} <LocaleText :t="Object.keys(clientAssignedPeers).length > 1 ? 'Configurations' : 'Configuration'"></LocaleText>
|
<span class="text-bg-primary badge ms-2">
|
||||||
</span>
|
{{ Object.keys(clientAssignedPeers).length }} <LocaleText :t="Object.keys(clientAssignedPeers).length > 1 ? 'Configurations' : 'Configuration'"></LocaleText>
|
||||||
<span class="text-bg-info badge ms-2">
|
</span>
|
||||||
{{ Object.values(clientAssignedPeers).flat().length }} <LocaleText :t="Object.values(clientAssignedPeers).flat().length > 1 ? 'Peers' : 'Peer'"></LocaleText>
|
<span class="text-bg-info badge ms-2">
|
||||||
</span>
|
{{ Object.values(clientAssignedPeers).flat().length }} <LocaleText :t="Object.values(clientAssignedPeers).flat().length > 1 ? 'Peers' : 'Peer'"></LocaleText>
|
||||||
</h6>
|
</span>
|
||||||
<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 d-flex flex-column">
|
|
||||||
<AvailablePeersGroup
|
|
||||||
:configuration="configuration"
|
|
||||||
:peers="peers"
|
|
||||||
@unassign="async (id) => await unassign(id)"
|
|
||||||
v-for="(peers, configuration) in clientAssignedPeers">
|
|
||||||
</AvailablePeersGroup>
|
|
||||||
<h6 class="text-muted m-auto" v-if="Object.keys(clientAssignedPeers).length === 0">
|
|
||||||
<LocaleText t="No peer assigned to this client"></LocaleText>
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="height: 500px" class="d-flex flex-column" v-if="manage">
|
|
||||||
|
|
||||||
<div class="mt-3 availablePeers border h-100 card rounded-3">
|
|
||||||
<div class="card-header sticky-top p-3">
|
|
||||||
<h6 class="mb-0 d-flex align-items-center">
|
|
||||||
<LocaleText t="Available Peers"></LocaleText>
|
|
||||||
</h6>
|
</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>
|
||||||
<div class="card-body p-0 overflow-scroll">
|
<div class="rounded-3 availablePeers border h-100 overflow-scroll flex-grow-1 d-flex flex-column">
|
||||||
<AvailablePeersGroup
|
<AvailablePeersGroup
|
||||||
:configuration="configuration"
|
:configuration="configuration"
|
||||||
:clientAssignedPeers="clientAssignedPeers"
|
|
||||||
:peers="peers"
|
:peers="peers"
|
||||||
@assign="async (id) => await assign(configuration, id, props.client.ClientID)"
|
@unassign="async (id) => await unassign(id)"
|
||||||
v-for="(peers, configuration) in assignmentStore.allConfigurationsPeers">
|
v-for="(peers, configuration) in clientAssignedPeers">
|
||||||
</AvailablePeersGroup>
|
</AvailablePeersGroup>
|
||||||
<h6 class="text-muted m-auto" v-if="Object.keys(assignmentStore.allConfigurationsPeers).length === 0">
|
<h6 class="text-muted m-auto p-3" v-if="Object.keys(clientAssignedPeers).length === 0">
|
||||||
<LocaleText t="No peer is available to assign"></LocaleText>
|
<LocaleText t="No peer assigned to this client"></LocaleText>
|
||||||
</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer d-flex gap-2 p-3 align-items-center justify-content-end">
|
</div>
|
||||||
<label for="availablePeerSearchString">
|
<div style="height: 500px" class="d-flex flex-column p-3" v-if="manage">
|
||||||
<i class="bi bi-search me-2"></i>
|
<div class="availablePeers border h-100 card rounded-3">
|
||||||
</label>
|
<div class="card-header sticky-top p-3">
|
||||||
<input
|
<h6 class="mb-0 d-flex align-items-center">
|
||||||
id="availablePeerSearchString"
|
<LocaleText t="Available Peers"></LocaleText>
|
||||||
class="form-control form-control-sm rounded-3 w-auto" type="text">
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-0 overflow-scroll">
|
||||||
|
<AvailablePeersGroup
|
||||||
|
:availablePeerSearchString="availablePeerSearchString"
|
||||||
|
:configuration="configuration"
|
||||||
|
:clientAssignedPeers="clientAssignedPeers"
|
||||||
|
:peers="peers"
|
||||||
|
@assign="async (id) => await assign(configuration, id, props.client.ClientID)"
|
||||||
|
v-for="(peers, configuration) in assignmentStore.allConfigurationsPeers">
|
||||||
|
</AvailablePeersGroup>
|
||||||
|
<h6 class="text-muted m-auto" v-if="Object.keys(assignmentStore.allConfigurationsPeers).length === 0">
|
||||||
|
<LocaleText t="No peer is available to assign"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer d-flex gap-2 p-3 align-items-center justify-content-end">
|
||||||
|
<label for="availablePeerSearchString">
|
||||||
|
<i class="bi bi-search me-2"></i>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="availablePeerSearchString"
|
||||||
|
v-model="availablePeerSearchString"
|
||||||
|
class="form-control form-control-sm rounded-3 w-auto" type="text">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="p-3 placeholder-glow border-bottom">
|
||||||
|
<h6 class="placeholder w-100 rounded-3"></h6>
|
||||||
|
<div class="placeholder w-100 rounded-3" style="height: 400px"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -27,14 +27,12 @@ const getClients = computed(() => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
|
|
||||||
<div class="list-group list-group-flush" >
|
<div class="list-group list-group-flush" >
|
||||||
<RouterLink
|
<RouterLink
|
||||||
:to="{ name: 'Client Viewer', params: { id: client.ClientID } }"
|
:to="{ name: 'Client Viewer', params: { id: client.ClientID } }"
|
||||||
class="list-group-item d-flex flex-column border-bottom list-group-item-action"
|
class="list-group-item d-flex flex-column border-bottom list-group-item-action"
|
||||||
v-for="client in getClients" >
|
v-for="client in getClients" >
|
||||||
<small class="text-body">
|
<small class="text-body">
|
||||||
|
|
||||||
{{ client.Email }}
|
{{ client.Email }}
|
||||||
</small>
|
</small>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-3">
|
||||||
|
<h6>
|
||||||
|
<LocaleText t="Reset Password"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
<div class="row g-2">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<label class="mb-1">
|
||||||
|
<small class="fw-bold text-muted">
|
||||||
|
<LocaleText t="Current Password"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="password" class="form-control form-control-sm rounded-3">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<label class="mb-1">
|
||||||
|
<small class="fw-bold text-muted">
|
||||||
|
<LocaleText t="New Password"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="password" class="form-control form-control-sm rounded-3">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<label class="mb-1">
|
||||||
|
<small class="fw-bold text-muted">
|
||||||
|
<LocaleText t="Confirm New Password"></LocaleText>
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
<input type="password" class="form-control form-control-sm rounded-3">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -4,19 +4,36 @@ import { fetchGet } from "@/utilities/fetch.js"
|
|||||||
|
|
||||||
|
|
||||||
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
|
import {DashboardClientAssignmentStore} from "@/stores/DashboardClientAssignmentStore.js";
|
||||||
import {computed} from "vue";
|
import {computed, ref, watch} from "vue";
|
||||||
import LocaleText from "@/components/text/localeText.vue";
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
import ClientAssignedPeers from "@/components/clientComponents/clientAssignedPeers.vue";
|
import ClientAssignedPeers from "@/components/clientComponents/clientAssignedPeers.vue";
|
||||||
|
import ClientResetPassword from "@/components/clientComponents/clientResetPassword.vue";
|
||||||
const assignmentStore = DashboardClientAssignmentStore()
|
const assignmentStore = DashboardClientAssignmentStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const client = computed(() => {
|
const client = computed(() => {
|
||||||
return assignmentStore.getClientById(route.params.id)
|
return assignmentStore.getClientById(route.params.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const clientAssignedPeers = ref({})
|
||||||
|
const getAssignedPeers = async () => {
|
||||||
|
await fetchGet('/api/clients/assignedPeers', {
|
||||||
|
ClientID: client.value.ClientID
|
||||||
|
}, (res) => {
|
||||||
|
clientAssignedPeers.value = res.data;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.value){
|
||||||
|
watch(() => client.value.ClientID, async () => {
|
||||||
|
await getAssignedPeers()
|
||||||
|
})
|
||||||
|
await getAssignedPeers()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="text-body d-flex flex-column gap-3" v-if="client">
|
<div class="text-body d-flex flex-column" v-if="client">
|
||||||
<div class="p-4 border-bottom bg-body-tertiary">
|
<div class="p-4 border-bottom bg-body-tertiary">
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
<LocaleText t="Email"></LocaleText>
|
<LocaleText t="Email"></LocaleText>
|
||||||
@ -33,10 +50,11 @@ const client = computed(() => {
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="px-4">
|
<ClientAssignedPeers
|
||||||
|
@refresh="getAssignedPeers()"
|
||||||
<ClientAssignedPeers :client="client"></ClientAssignedPeers>
|
:clientAssignedPeers="clientAssignedPeers"
|
||||||
</div>
|
:client="client"></ClientAssignedPeers>
|
||||||
|
<ClientResetPassword :client="client" v-if="client.ClientGroup === 'Local'"></ClientResetPassword>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="d-flex w-100 h-100 text-muted">
|
<div v-else class="d-flex w-100 h-100 text-muted">
|
||||||
<div class="m-auto text-center">
|
<div class="m-auto text-center">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user