Extract component
This commit is contained in:
parent
0683a5e265
commit
d8a713045a
146
web/src/components/DevicesDataTable.vue
Normal file
146
web/src/components/DevicesDataTable.vue
Normal file
|
@ -0,0 +1,146 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-data-table
|
||||
sort-by="signalStrength"
|
||||
:items="wifiDevices"
|
||||
:headers="pickedHeaders"
|
||||
:search="filter"
|
||||
:hide-default-footer="!paginate"
|
||||
:disable-pagination="!paginate"
|
||||
no-data-text="Nenhum cliente conectado à este AP"
|
||||
>
|
||||
<template #[`item.user`]="{ item: { user } }">
|
||||
<span v-if="user">
|
||||
<Avatar left :src="user.thumbnailPhoto" size="24" />
|
||||
{{ user.displayName }} ({{ user.sAMAccountName }})
|
||||
</span>
|
||||
<span v-else><Avatar left size="24" /> Não logado</span>
|
||||
</template>
|
||||
|
||||
<template #[`item.uptime`]="{ item: { uptime } }">
|
||||
<small> {{ uptime | durationFromSeconds }}</small>
|
||||
</template>
|
||||
|
||||
<template #[`item.signalStrength`]="{ item: { signalStrength } }">
|
||||
<template v-if="signalStrength < 0">
|
||||
<v-chip
|
||||
small
|
||||
:color="signalStrengthColor(signalStrength) + ' lighten-5'"
|
||||
>
|
||||
<v-icon
|
||||
small
|
||||
left
|
||||
:color="signalStrengthColor(signalStrength) + ' darken-2'"
|
||||
>
|
||||
{{ signalStrengthIcon(signalStrength) }}
|
||||
</v-icon>
|
||||
<span class="font-weight-medium">{{ signalStrength }}</span>
|
||||
<small class="ml-1"> dBm </small>
|
||||
</v-chip>
|
||||
</template>
|
||||
<template v-else>
|
||||
<v-chip small color="grey lighten-4">
|
||||
<v-icon small left color="grey">mdi-signal-off</v-icon>
|
||||
<small>Aguarde...</small>
|
||||
</v-chip>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #[`item.speed`]="{ item: { speed } }">
|
||||
{{ speed }} <small>Mbps</small>
|
||||
</template>
|
||||
|
||||
<template #[`item.usage`]="{ item: { usage } }">
|
||||
{{ usage | bytes }}
|
||||
</template>
|
||||
|
||||
<template #[`item.protocol`]="{ item: { protocol } }">
|
||||
<code v-if="protocol">{{ protocol }}</code>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #[`item.frequency`]="{ item: { frequency } }">
|
||||
{{ frequency || '-' }}
|
||||
</template>
|
||||
</v-data-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Avatar from './Avatar.vue'
|
||||
|
||||
export default {
|
||||
components: { Avatar },
|
||||
props: {
|
||||
wifiDevices: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
filter: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
paginate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
headers: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
'hostname',
|
||||
'mac',
|
||||
'ip',
|
||||
'essid',
|
||||
'uptime',
|
||||
'user',
|
||||
'signalStrength',
|
||||
'frequency',
|
||||
'protocol',
|
||||
'speed',
|
||||
'usage'
|
||||
]
|
||||
}
|
||||
},
|
||||
data: () => ({
|
||||
availableHeaders: [
|
||||
{ text: 'Hostname', value: 'hostname' },
|
||||
{ text: 'MAC', value: 'mac' },
|
||||
{ text: 'IP', value: 'ip' },
|
||||
{ text: 'ESSID', value: 'essid' },
|
||||
{ text: 'Uptime', value: 'uptime' },
|
||||
{ text: 'Usuário', value: 'user' },
|
||||
{ text: 'Sinal', value: 'signalStrength' },
|
||||
{ text: 'Frequência', value: 'frequency', align: 'end' },
|
||||
{ text: 'Protocolo', value: 'protocol' },
|
||||
{ text: 'Velocidade', value: 'speed', align: 'end' },
|
||||
{ text: 'Uso', value: 'usage', align: 'end' }
|
||||
]
|
||||
}),
|
||||
computed: {
|
||||
pickedHeaders() {
|
||||
return this.availableHeaders.filter(({ value }) =>
|
||||
this.headers.includes(value)
|
||||
)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
signalStrengthIcon(signalStrength) {
|
||||
if (signalStrength > -50) return 'mdi-signal-cellular-3'
|
||||
if (signalStrength > -67) return 'mdi-signal-cellular-2'
|
||||
if (signalStrength > -80) return 'mdi-signal-cellular-1'
|
||||
return 'mdi-signal-cellular-outline'
|
||||
},
|
||||
signalStrengthColor(signalStrength) {
|
||||
if (signalStrength > -50) return 'green'
|
||||
else if (signalStrength > -60) return 'light-green'
|
||||
else if (signalStrength > -67) return 'lime'
|
||||
else if (signalStrength > -70) return 'amber'
|
||||
else if (signalStrength > -80) return 'orange'
|
||||
else if (signalStrength > -90) return 'deep-orange'
|
||||
else return 'red'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
|
@ -16,11 +16,14 @@ function bytes(bytes, kib, maxUnit) {
|
|||
const sizes = kib
|
||||
? ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB', 'BiB']
|
||||
: ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB', 'BB']
|
||||
var i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
|
||||
let i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
|
||||
if (maxUnit != undefined) {
|
||||
const index = sizes.indexOf(maxUnit)
|
||||
if (index != -1) i = index
|
||||
}
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
|
|
|
@ -41,70 +41,10 @@
|
|||
</v-card-title>
|
||||
<v-divider />
|
||||
<v-card-text>
|
||||
<v-data-table
|
||||
sort-by="signalStrength"
|
||||
:items="accessPoint.wifiDevices"
|
||||
:headers="headers"
|
||||
:search="filter"
|
||||
dense
|
||||
hide-default-footer
|
||||
disable-pagination
|
||||
no-data-text="Nenhum cliente conectado à este AP"
|
||||
>
|
||||
<template #[`item.user`]="{ item: { user } }">
|
||||
<span v-if="user">
|
||||
<Avatar left :src="user.thumbnailPhoto" size="24" />
|
||||
{{ user.displayName }} ({{ user.sAMAccountName }})
|
||||
</span>
|
||||
<span v-else><Avatar left size="24" /> Não logado</span>
|
||||
</template>
|
||||
|
||||
<template #[`item.uptime`]="{ item: { uptime } }">
|
||||
{{ uptime | durationFromSeconds }}
|
||||
</template>
|
||||
|
||||
<template #[`item.signalStrength`]="{ item: { signalStrength } }">
|
||||
<template v-if="signalStrength < 0">
|
||||
<v-chip
|
||||
small
|
||||
:color="signalStrengthColor(signalStrength) + ' lighten-5'"
|
||||
>
|
||||
<v-icon
|
||||
small
|
||||
left
|
||||
:color="signalStrengthColor(signalStrength) + ' darken-2'"
|
||||
>
|
||||
{{ signalStrengthIcon(signalStrength) }}
|
||||
</v-icon>
|
||||
<span class="font-weight-medium">{{ signalStrength }}</span>
|
||||
<small class="ml-1"> dBm </small>
|
||||
</v-chip>
|
||||
</template>
|
||||
<template v-else>
|
||||
<v-chip small color="grey lighten-4">
|
||||
<v-icon small left color="grey">mdi-signal-off</v-icon>
|
||||
<small>Aguarde...</small>
|
||||
</v-chip>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #[`item.speed`]="{ item: { speed } }">
|
||||
{{ speed }} <small>Mbps</small>
|
||||
</template>
|
||||
|
||||
<template #[`item.usage`]="{ item: { usage } }">
|
||||
{{ usage | bytes }}
|
||||
</template>
|
||||
|
||||
<template #[`item.protocol`]="{ item: { protocol } }">
|
||||
<code v-if="protocol">{{ protocol }}</code>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #[`item.frequency`]="{ item: { frequency } }">
|
||||
{{ frequency || '-' }}
|
||||
</template>
|
||||
</v-data-table>
|
||||
<DevicesDataTable
|
||||
:wifi-devices="accessPoint.wifiDevices"
|
||||
:filter="filter"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-divider />
|
||||
<v-card-actions>
|
||||
|
@ -122,28 +62,16 @@
|
|||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import Avatar from '../../components/Avatar.vue'
|
||||
|
||||
import ApIcon from '../../components/ApIcon.vue'
|
||||
import DevicesDataTable from '../../components/DevicesDataTable.vue'
|
||||
|
||||
export default {
|
||||
name: 'SingleAccessPoint',
|
||||
components: { Avatar, ApIcon },
|
||||
components: { ApIcon, DevicesDataTable },
|
||||
data: () => ({
|
||||
showDialog: true,
|
||||
filter: '',
|
||||
headers: [
|
||||
{ text: 'Hostname', value: 'hostname' },
|
||||
{ text: 'MAC', value: 'mac' },
|
||||
{ text: 'IP', value: 'ip' },
|
||||
{ text: 'ESSID', value: 'essid' },
|
||||
{ text: 'Uptime', value: 'uptime' },
|
||||
{ text: 'Usuário', value: 'user' },
|
||||
{ text: 'Sinal', value: 'signalStrength' },
|
||||
{ text: 'Frequência', value: 'frequency', align: 'end' },
|
||||
{ text: 'Protocolo', value: 'protocol' },
|
||||
{ text: 'Velocidade', value: 'speed', align: 'end' },
|
||||
{ text: 'Uso', value: 'usage', align: 'end' }
|
||||
]
|
||||
filter: ''
|
||||
}),
|
||||
watch: {
|
||||
showDialog() {
|
||||
|
@ -152,24 +80,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
signalStrengthIcon(signalStrength) {
|
||||
if (signalStrength > -50) return 'mdi-signal-cellular-3'
|
||||
if (signalStrength > -67) return 'mdi-signal-cellular-2'
|
||||
if (signalStrength > -80) return 'mdi-signal-cellular-1'
|
||||
return 'mdi-signal-cellular-outline'
|
||||
},
|
||||
signalStrengthColor(signalStrength) {
|
||||
if (signalStrength > -50) return 'green'
|
||||
else if (signalStrength > -60) return 'light-green'
|
||||
else if (signalStrength > -67) return 'lime'
|
||||
else if (signalStrength > -70) return 'amber'
|
||||
else if (signalStrength > -80) return 'orange'
|
||||
else if (signalStrength > -90) return 'deep-orange'
|
||||
else return 'red'
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
accessPoint: {
|
||||
pollInterval: 10000,
|
||||
|
|
|
@ -47,182 +47,8 @@
|
|||
no total.
|
||||
</div>
|
||||
|
||||
<v-data-iterator
|
||||
:items="computedWifiDevices"
|
||||
:items-per-page.sync="itemsPerPage"
|
||||
:page="page"
|
||||
:loading="$apollo.queries.wifiDevices.loading"
|
||||
>
|
||||
<template #loading>
|
||||
<v-expansion-panels disabled>
|
||||
<v-expansion-panel v-for="i in 10" :key="i">
|
||||
<v-expansion-panel-header class="pa-1">
|
||||
<v-skeleton-loader class="ma-0 pa-0" type="list-item-avatar" />
|
||||
</v-expansion-panel-header>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
</template>
|
||||
<template #default="{ items }">
|
||||
<v-expansion-panels multiple>
|
||||
<v-expansion-panel v-for="device in items" :key="device.mac">
|
||||
<v-expansion-panel-header>
|
||||
<v-row dense align-content="center" no-gutters>
|
||||
<v-col class="shrink" align-self="center">
|
||||
<v-badge
|
||||
:color="device.status == 'ONLINE' ? 'green' : 'grey'"
|
||||
left
|
||||
offset-y="16"
|
||||
dot
|
||||
>
|
||||
<ap-icon class="mr-4" :controller="device.controller" />
|
||||
</v-badge>
|
||||
</v-col>
|
||||
<v-col align-self="center" cols="3">
|
||||
{{ device.hostname }}
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="$vuetify.breakpoint.mdAndUp"
|
||||
cols="2"
|
||||
class="grow"
|
||||
>{{ device.ip }}</v-col
|
||||
>
|
||||
<v-col v-if="$vuetify.breakpoint.mdAndUp" class="grow">
|
||||
<div>
|
||||
<avatar left size="24px" :src="device.thumbnailPhoto" />{{
|
||||
device.displayName
|
||||
}}
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-expansion-panel-header>
|
||||
<v-expansion-panel-content>
|
||||
<v-list dense>
|
||||
<v-list-item v-if="device.status == 'ONLINE'">
|
||||
<v-list-item-action>
|
||||
<v-icon color="green darken-1">mdi-wifi</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.essid }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle> SSID </v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<DevicesDataTable :wifi-devices="computedWifiDevices" paginate />
|
||||
|
||||
<v-list-item v-else>
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-wifi-off</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.essid }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
Dispositivo off-line
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-access-point</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{
|
||||
device.accessPoint.name || device.accessPoint.hostname
|
||||
}}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
Access Point ({{ device.controller }})
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="device.accessPoint.local">
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-map-marker-radius</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.accessPoint.local }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
Localização do AP
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-ip-network</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.ip }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
Último endereço IP conhecido
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-expansion-card-variant</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.mac }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
{{ device.oui }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-eye</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.lastSeen | dateAndTime }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
Visto pela última vez
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-action>
|
||||
<v-icon>mdi-check-decagram</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.firstSeen | dateAndTime }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
Visto pela primeira vez
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-action>
|
||||
<Avatar :src="device.thumbnailPhoto" size="24px" />
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ device.displayName }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
{{ device.sAMAccountName }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-expansion-panel-content>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
</template>
|
||||
</v-data-iterator>
|
||||
<v-alert type="info" outlined dismissible>
|
||||
São exibidos apenas os 100 primeiros resultados da pesquisa
|
||||
</v-alert>
|
||||
|
@ -231,12 +57,11 @@
|
|||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import Avatar from '../components/Avatar.vue'
|
||||
import ApIcon from '../components/ApIcon.vue'
|
||||
import DevicesDataTable from '../components/DevicesDataTable.vue'
|
||||
|
||||
export default {
|
||||
name: 'WifiDevices',
|
||||
components: { Avatar, ApIcon },
|
||||
components: { DevicesDataTable },
|
||||
data: () => ({
|
||||
search: '',
|
||||
itemsPerPage: 10,
|
||||
|
@ -273,27 +98,28 @@ export default {
|
|||
query: gql`
|
||||
query wifiDevices($search: String) {
|
||||
wifiDevices(search: $search) {
|
||||
user {
|
||||
displayName
|
||||
sAMAccountName
|
||||
thumbnailPhoto
|
||||
}
|
||||
accessPoint {
|
||||
name
|
||||
hostname
|
||||
local
|
||||
}
|
||||
oui
|
||||
mac
|
||||
controller
|
||||
id
|
||||
hostname
|
||||
firstSeen
|
||||
lastSeen
|
||||
essid
|
||||
ip
|
||||
mac
|
||||
uptime
|
||||
apName
|
||||
status
|
||||
lastSeen
|
||||
ip
|
||||
signalStrength
|
||||
frequency
|
||||
protocol
|
||||
speed
|
||||
usage
|
||||
user {
|
||||
displayName
|
||||
sAMAccountName
|
||||
thumbnailPhoto
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
|
Loading…
Reference in New Issue
Block a user