User presence improvements
This commit is contained in:
parent
bfa7ec4573
commit
ba56fee068
|
@ -0,0 +1,68 @@
|
||||||
|
# Migration `20201119134248-add-controller-to-wifi-device`
|
||||||
|
|
||||||
|
This migration has been generated by Douglas Barone at 11/19/2020, 9:42:48 AM.
|
||||||
|
You can check out the [state of the schema](./schema.prisma) after the migration.
|
||||||
|
|
||||||
|
## Database Steps
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE "WifiDevice" ADD COLUMN "controller" TEXT NOT NULL DEFAULT E'unknown'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git schema.prisma schema.prisma
|
||||||
|
migration 20201110194349-init..20201119134248-add-controller-to-wifi-device
|
||||||
|
--- datamodel.dml
|
||||||
|
+++ datamodel.dml
|
||||||
|
@@ -3,9 +3,9 @@
|
||||||
|
}
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
- url = "***"
|
||||||
|
+ url = "***"
|
||||||
|
}
|
||||||
|
model ResetToken {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
@@ -71,23 +71,24 @@
|
||||||
|
WifiDevice WifiDevice[] @relation("wifidevice_to_user")
|
||||||
|
}
|
||||||
|
model WifiDevice {
|
||||||
|
- id Int @id @default(autoincrement())
|
||||||
|
- oui String?
|
||||||
|
- mac String @unique
|
||||||
|
- hostname String?
|
||||||
|
- firstSeen DateTime?
|
||||||
|
- lastSeen DateTime?
|
||||||
|
- essid String?
|
||||||
|
- ip String?
|
||||||
|
- uptime String?
|
||||||
|
- apName String?
|
||||||
|
- status Status?
|
||||||
|
- createdAt DateTime @default(now())
|
||||||
|
- updatedAt DateTime @updatedAt
|
||||||
|
- userId Int?
|
||||||
|
- user User? @relation(fields: [userId], references: [id], name: "wifidevice_to_user")
|
||||||
|
+ id Int @id @default(autoincrement())
|
||||||
|
+ mac String @unique
|
||||||
|
+ controller String @default("unknown")
|
||||||
|
+ createdAt DateTime @default(now())
|
||||||
|
+ updatedAt DateTime @updatedAt
|
||||||
|
+ oui String?
|
||||||
|
+ hostname String?
|
||||||
|
+ firstSeen DateTime?
|
||||||
|
+ lastSeen DateTime?
|
||||||
|
+ essid String?
|
||||||
|
+ ip String?
|
||||||
|
+ uptime String?
|
||||||
|
+ apName String?
|
||||||
|
+ status Status?
|
||||||
|
+ userId Int?
|
||||||
|
+ user User? @relation(fields: [userId], references: [id], name: "wifidevice_to_user")
|
||||||
|
}
|
||||||
|
enum Status {
|
||||||
|
ONLINE
|
||||||
|
```
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
url = "***"
|
||||||
|
}
|
||||||
|
|
||||||
|
model ResetToken {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
token String @unique
|
||||||
|
expiration DateTime
|
||||||
|
usedAt DateTime?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
user User @relation(fields: [userId], references: [id], name: "resettoken_to_user")
|
||||||
|
userId Int
|
||||||
|
creator User @relation(fields: [creatorId], references: [id], name: "resettoken_to_creator")
|
||||||
|
creatorId Int
|
||||||
|
}
|
||||||
|
|
||||||
|
model User {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
lastLogin DateTime?
|
||||||
|
lastLoginPrior DateTime?
|
||||||
|
roles Json?
|
||||||
|
groups Json?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
accountExpires String?
|
||||||
|
badPasswordTime String?
|
||||||
|
badPwdCount String?
|
||||||
|
cn String?
|
||||||
|
department String?
|
||||||
|
description String?
|
||||||
|
displayName String?
|
||||||
|
distinguishedName String?
|
||||||
|
dn String?
|
||||||
|
extensionAttribute1 String?
|
||||||
|
extensionAttribute10 String?
|
||||||
|
extensionAttribute2 String?
|
||||||
|
extensionAttribute6 String?
|
||||||
|
extensionAttribute7 String?
|
||||||
|
givenName String?
|
||||||
|
homeDirectory String?
|
||||||
|
homeDrive String?
|
||||||
|
lastLogoff String?
|
||||||
|
lastLogon String?
|
||||||
|
lastLogonTimestamp String?
|
||||||
|
lockoutTime String?
|
||||||
|
logonCount String?
|
||||||
|
mail String?
|
||||||
|
name String?
|
||||||
|
objectCategory String?
|
||||||
|
objectGUID String?
|
||||||
|
objectSid String?
|
||||||
|
primaryGroupID String?
|
||||||
|
pwdLastSet DateTime?
|
||||||
|
sAMAccountName String @unique
|
||||||
|
sAMAccountType String?
|
||||||
|
sn String?
|
||||||
|
thumbnailPhoto String?
|
||||||
|
title String?
|
||||||
|
userAccountControl String?
|
||||||
|
userPrincipalName String?
|
||||||
|
whenChanged String?
|
||||||
|
whenCreated String?
|
||||||
|
createdTokens ResetToken[] @relation("resettoken_to_user")
|
||||||
|
tokens ResetToken[] @relation("resettoken_to_creator")
|
||||||
|
WifiDevice WifiDevice[] @relation("wifidevice_to_user")
|
||||||
|
}
|
||||||
|
|
||||||
|
model WifiDevice {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
mac String @unique
|
||||||
|
controller String @default("unknown")
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
oui String?
|
||||||
|
hostname String?
|
||||||
|
firstSeen DateTime?
|
||||||
|
lastSeen DateTime?
|
||||||
|
essid String?
|
||||||
|
ip String?
|
||||||
|
uptime String?
|
||||||
|
apName String?
|
||||||
|
status Status?
|
||||||
|
userId Int?
|
||||||
|
user User? @relation(fields: [userId], references: [id], name: "wifidevice_to_user")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
ONLINE
|
||||||
|
OFFLINE
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"version": "0.3.14-fixed",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"tag": "CreateField",
|
||||||
|
"model": "WifiDevice",
|
||||||
|
"field": "controller",
|
||||||
|
"type": "String",
|
||||||
|
"arity": "Required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "CreateDirective",
|
||||||
|
"location": {
|
||||||
|
"path": {
|
||||||
|
"tag": "Field",
|
||||||
|
"model": "WifiDevice",
|
||||||
|
"field": "controller"
|
||||||
|
},
|
||||||
|
"directive": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "CreateArgument",
|
||||||
|
"location": {
|
||||||
|
"tag": "Directive",
|
||||||
|
"path": {
|
||||||
|
"tag": "Field",
|
||||||
|
"model": "WifiDevice",
|
||||||
|
"field": "controller"
|
||||||
|
},
|
||||||
|
"directive": "default"
|
||||||
|
},
|
||||||
|
"argument": "",
|
||||||
|
"value": "\"unknown\""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
# Prisma Migrate lockfile v1
|
# Prisma Migrate lockfile v1
|
||||||
|
|
||||||
20201110194349-init
|
20201110194349-init
|
||||||
|
20201119134248-add-controller-to-wifi-device
|
|
@ -72,21 +72,22 @@ model User {
|
||||||
}
|
}
|
||||||
|
|
||||||
model WifiDevice {
|
model WifiDevice {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
oui String?
|
mac String @unique
|
||||||
mac String @unique
|
controller String @default("unknown")
|
||||||
hostname String?
|
createdAt DateTime @default(now())
|
||||||
firstSeen DateTime?
|
updatedAt DateTime @updatedAt
|
||||||
lastSeen DateTime?
|
oui String?
|
||||||
essid String?
|
hostname String?
|
||||||
ip String?
|
firstSeen DateTime?
|
||||||
uptime String?
|
lastSeen DateTime?
|
||||||
apName String?
|
essid String?
|
||||||
status Status?
|
ip String?
|
||||||
createdAt DateTime @default(now())
|
uptime String?
|
||||||
updatedAt DateTime @updatedAt
|
apName String?
|
||||||
userId Int?
|
status Status?
|
||||||
user User? @relation(fields: [userId], references: [id], name: "wifidevice_to_user")
|
userId Int?
|
||||||
|
user User? @relation(fields: [userId], references: [id], name: "wifidevice_to_user")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
|
|
|
@ -106,11 +106,9 @@ const Query = {
|
||||||
},
|
},
|
||||||
|
|
||||||
userPresence: async (_, { search }) => {
|
userPresence: async (_, { search }) => {
|
||||||
if (!search) {
|
if (!search) search = ''
|
||||||
//await updateDBWithOnlineDevices()
|
|
||||||
updateDBWithOnlineDevices()
|
updateDBWithOnlineDevices()
|
||||||
search = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
const usersWithWifiDevices = await prisma.user.findMany({
|
const usersWithWifiDevices = await prisma.user.findMany({
|
||||||
where: {
|
where: {
|
||||||
|
@ -123,7 +121,9 @@ const Query = {
|
||||||
.filter(
|
.filter(
|
||||||
user =>
|
user =>
|
||||||
user.displayName.toLowerCase().includes(search.toLowerCase()) ||
|
user.displayName.toLowerCase().includes(search.toLowerCase()) ||
|
||||||
user.WifiDevice[0].apName.toLowerCase().includes(search.toLowerCase())
|
user.WifiDevice.some(device =>
|
||||||
|
device.apName.toLowerCase().includes(search.toLowerCase())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.map(user => ({
|
.map(user => ({
|
||||||
user: {
|
user: {
|
||||||
|
|
|
@ -28,7 +28,7 @@ const typeDefs = gql`
|
||||||
identifiedOnly: Boolean = true
|
identifiedOnly: Boolean = true
|
||||||
): [WifiDevice]!
|
): [WifiDevice]!
|
||||||
|
|
||||||
userPresence(search: String): [UserPresence!] @auth(roles: ["watcher"])
|
userPresence(search: String = ""): [UserPresence!] @auth(roles: ["watcher"])
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
@ -140,9 +140,10 @@ const typeDefs = gql`
|
||||||
|
|
||||||
type WifiDevice {
|
type WifiDevice {
|
||||||
user: User
|
user: User
|
||||||
id: String
|
id: ID!
|
||||||
oui: String
|
oui: String
|
||||||
mac: String
|
mac: String!
|
||||||
|
controller: String!
|
||||||
hostname: String
|
hostname: String
|
||||||
firstSeen: String
|
firstSeen: String
|
||||||
lastSeen: String
|
lastSeen: String
|
||||||
|
|
|
@ -61,7 +61,8 @@ export async function getOnlineWifiDevices() {
|
||||||
ip: client.IP,
|
ip: client.IP,
|
||||||
uptime: client.UT.toString(),
|
uptime: client.UT.toString(),
|
||||||
apName: client.AP,
|
apName: client.AP,
|
||||||
status: client.ST == 'Online' ? 'ONLINE' : 'OFFLINE'
|
status: client.ST == 'Online' ? 'ONLINE' : 'OFFLINE',
|
||||||
|
controller: "Cisco"
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return hydratedOnlineDevices
|
return hydratedOnlineDevices
|
||||||
|
|
|
@ -188,15 +188,14 @@ export async function getOnlineWifiDevices() {
|
||||||
ip: client.ip,
|
ip: client.ip,
|
||||||
uptime: client.uptime.toString(),
|
uptime: client.uptime.toString(),
|
||||||
apName: accessPoints[0].find(ap => ap.mac === client.ap_mac).name,
|
apName: accessPoints[0].find(ap => ap.mac === client.ap_mac).name,
|
||||||
status: 'ONLINE'
|
status: 'ONLINE',
|
||||||
|
controller: "UniFi"
|
||||||
}))
|
}))
|
||||||
|
|
||||||
unifiController.logout()
|
await unifiController.logout()
|
||||||
|
|
||||||
return hydratedOnlineDevices
|
return hydratedOnlineDevices
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('Error getting devices. ' + e)
|
throw new Error('Error getting devices. ' + e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,41 +13,49 @@ async function updateDBWithOnlineDevices() {
|
||||||
const onlineUnifiDevicesPromise = getOnlineUnifiDevices()
|
const onlineUnifiDevicesPromise = getOnlineUnifiDevices()
|
||||||
const onlineCiscoDevicesPromise = getOnlineCiscoDevices()
|
const onlineCiscoDevicesPromise = getOnlineCiscoDevices()
|
||||||
|
|
||||||
const [onlineUnifiDevices, onlineCiscoDevices] = await Promise.all([
|
try {
|
||||||
onlineUnifiDevicesPromise,
|
const [onlineUnifiDevices, onlineCiscoDevices] = await Promise.all([
|
||||||
onlineCiscoDevicesPromise
|
onlineUnifiDevicesPromise,
|
||||||
])
|
onlineCiscoDevicesPromise
|
||||||
|
])
|
||||||
|
|
||||||
await prisma.wifiDevice.updateMany({
|
await prisma.wifiDevice.updateMany({
|
||||||
data: {
|
data: {
|
||||||
status: 'OFFLINE'
|
status: 'OFFLINE'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const onlineDevices = [...onlineUnifiDevices, ...onlineCiscoDevices]
|
const onlineDevices = [...onlineUnifiDevices, ...onlineCiscoDevices]
|
||||||
|
|
||||||
for (const onlineDevice of onlineDevices) {
|
for (const onlineDevice of onlineDevices) {
|
||||||
const device = {
|
const device = {
|
||||||
...onlineDevice,
|
...onlineDevice,
|
||||||
user: onlineDevice.user
|
user: onlineDevice.user
|
||||||
? { connect: { sAMAccountName: onlineDevice.user } }
|
? { connect: { sAMAccountName: onlineDevice.user } }
|
||||||
: undefined
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await prisma.wifiDevice.upsert({
|
||||||
|
where: { mac: onlineDevice.mac },
|
||||||
|
create: device,
|
||||||
|
update: device
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code != 'P2016') console.log('[wifiDevice upsert error]', e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
setTimeout(() => {
|
||||||
await prisma.wifiDevice.upsert({
|
updating = false
|
||||||
where: { mac: onlineDevice.mac },
|
}, 10000)
|
||||||
create: device,
|
|
||||||
update: device
|
// TODO: pubsub
|
||||||
})
|
return onlineDevices.length
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code != 'P2016') console.log('[wifiDevice upsert error]', e)
|
console.log('Error updating DB: ', e)
|
||||||
}
|
return -2
|
||||||
}
|
}
|
||||||
|
|
||||||
updating = false
|
|
||||||
// TODO: pubsub
|
|
||||||
return onlineDevices.length
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { updateDBWithOnlineDevices }
|
export { updateDBWithOnlineDevices }
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 MiB |
Binary file not shown.
Before Width: | Height: | Size: 59 KiB |
31
web/src/assets/cisco_logo.svg
Normal file
31
web/src/assets/cisco_logo.svg
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1"
|
||||||
|
id="logo_1_" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 400 300"
|
||||||
|
style="enable-background:new 0 0 400 300;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#049FD9;}
|
||||||
|
</style>
|
||||||
|
<path id="logo" transform="translate(-446.85715,-442.59426)" class="st0" d="M836.9,554.6c0-4.6-3.7-8.2-8.2-8.2
|
||||||
|
c-4.6,0-8.3,3.7-8.3,8.2v17.3c0,4.6,3.7,8.3,8.3,8.3c4.5,0,8.2-3.7,8.2-8.3V554.6z M791.5,531.8c0-4.5-3.7-8.2-8.3-8.2
|
||||||
|
c-4.6,0-8.2,3.7-8.2,8.2v40.1c0,4.6,3.7,8.3,8.2,8.3c4.7,0,8.3-3.7,8.3-8.3C791.5,571.9,791.5,531.8,791.5,531.8z M746,500.7
|
||||||
|
c0-4.6-3.7-8.2-8.2-8.2c-4.6,0-8.2,3.7-8.2,8.2v87.7c0,4.6,3.7,8.3,8.2,8.3c4.6,0,8.2-3.7,8.2-8.3C746,588.4,746,500.7,746,500.7z
|
||||||
|
M700.6,531.8c0-4.5-3.7-8.2-8.2-8.2c-4.5,0-8.2,3.7-8.2,8.2v40.1c0,4.6,3.7,8.3,8.2,8.3c4.6,0,8.2-3.7,8.2-8.3
|
||||||
|
C700.6,571.9,700.6,531.8,700.6,531.8z M655.1,554.6c0-4.6-3.7-8.2-8.2-8.2c-4.6,0-8.3,3.7-8.3,8.2v17.3c0,4.6,3.7,8.3,8.3,8.3
|
||||||
|
c4.5,0,8.2-3.7,8.2-8.3C655.1,571.9,655.1,554.6,655.1,554.6z M609.7,531.8c0-4.5-3.7-8.2-8.3-8.2c-4.6,0-8.3,3.7-8.3,8.2v40.1
|
||||||
|
c0,4.6,3.7,8.3,8.3,8.3c4.6,0,8.3-3.7,8.3-8.3C609.7,571.9,609.7,531.8,609.7,531.8z M564.3,500.7c0-4.6-3.7-8.2-8.3-8.2
|
||||||
|
c-4.6,0-8.3,3.7-8.3,8.2v87.7c0,4.6,3.7,8.3,8.3,8.3c4.6,0,8.3-3.7,8.3-8.3C564.3,588.4,564.3,500.7,564.3,500.7z M518.8,531.8
|
||||||
|
c0-4.5-3.7-8.2-8.3-8.2s-8.3,3.7-8.3,8.2v40.1c0,4.6,3.7,8.3,8.3,8.3s8.3-3.7,8.3-8.3V531.8z M473.4,554.6c0-4.6-3.7-8.2-8.3-8.2
|
||||||
|
c-4.6,0-8.3,3.7-8.3,8.2v17.3c0,4.6,3.7,8.3,8.3,8.3c4.6,0,8.3-3.7,8.3-8.3L473.4,554.6L473.4,554.6z M644.2,626.4
|
||||||
|
c-0.5-0.1-8.1-2.1-16.2-2.1c-15.4,0-24.6,8.3-24.6,20.6c0,10.9,7.7,16.4,17,19.3c1,0.3,2.5,0.8,3.6,1.1c4.1,1.3,7.4,3.2,7.4,6.6
|
||||||
|
c0,3.7-3.8,6.2-12.1,6.2c-7.3,0-14.3-2.1-15.7-2.5v15.2c0.8,0.2,9.1,1.8,18,1.8c12.8,0,27.3-5.6,27.3-22.2c0-8-4.9-15.5-15.7-18.9
|
||||||
|
l-4.6-1.5c-2.7-0.9-7.6-2.3-7.6-6.3c0-3.2,3.6-5.4,10.3-5.4c5.8,0,12.8,1.9,13,2V626.4L644.2,626.4z M785,658.5
|
||||||
|
c0,9.6-7.4,17.4-17.2,17.4c-9.9,0-17.2-7.8-17.2-17.4c0-9.6,7.3-17.4,17.2-17.4C777.6,641.2,785,649,785,658.5 M767.8,624.4
|
||||||
|
c-20.3,0-34.9,15.3-34.9,34.2c0,18.9,14.6,34.2,34.9,34.2c20.3,0,34.9-15.3,34.9-34.2C802.7,639.7,788.1,624.4,767.8,624.4
|
||||||
|
M541.4,626.7c-1.6-0.5-7.4-2.4-15.2-2.4c-20.3,0-35.2,14.5-35.2,34.2c0,21.3,16.4,34.2,35.2,34.2c7.4,0,13.1-1.8,15.2-2.4v-17.7
|
||||||
|
c-0.7,0.4-6.2,3.5-14,3.5c-11.1,0-18.3-7.8-18.3-17.6c0-10.1,7.5-17.6,18.3-17.6c8,0,13.3,3.2,14,3.5V626.7z M715.3,626.7
|
||||||
|
c-1.6-0.5-7.4-2.4-15.2-2.4c-20.3,0-35.2,14.5-35.2,34.2c0,21.3,16.5,34.2,35.2,34.2c7.4,0,13.1-1.8,15.2-2.4v-17.7
|
||||||
|
c-0.7,0.4-6.2,3.5-14,3.5c-11.1,0-18.2-7.8-18.2-17.6c0-10.1,7.5-17.6,18.2-17.6c8,0,13.3,3.2,14,3.5V626.7z M581,691.6h-16.7v-66
|
||||||
|
H581V691.6z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
10
web/src/assets/unifi_logo.svg
Normal file
10
web/src/assets/unifi_logo.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generated by IcoMoon.io -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="720" height="1024" viewBox="0 0 720 1024">
|
||||||
|
<g id="icomoon-ignore">
|
||||||
|
</g>
|
||||||
|
<path fill="#4A4A4A" d="M288.4 419c3.2-19.6 10.4-45.6 26.6-68 21.8-29.8 58.2-55.6 129.4-55.4l7.2-33.4c-83.8-2.6-135.8 29.8-163.6 69.2-21.8 30.6-30 64-33.2 87.4l33.6 0.2zM349 419c2.8-9.8 7.2-20.4 14-29.8 12.4-16.8 31.6-31.6 69-34.6l7.2-34c-51.4 1.4-85 22.8-103.2 49-12 16.8-18 34.4-21.2 49.2zM314.4 419h34.6z"></path>
|
||||||
|
<path fill="#4A4A4A" d="M417.8 418.8l7.4-34c-20.8 1.6-33 11-41.2 23-3 4.2-4.8 7-6.6 11h40.4zM642.2 418.8h-36l7.6-34c0 0.2 27.8 6.4 28.4 34zM81.4 385l-38.4 181c-6.8 31.8 2.8 46 27.2 46 24 0 40-14.2 46.8-46l38.6-181h40.2l-37.8 177.8c-12.4 58.4-46 79.4-94 79.4-48.4 0-73-21.2-60.6-79.4l37.8-177.8h40.2zM211.6 447.4h36.2l-4.6 22.2h1c13.2-17 33.4-27.2 54.6-27.2 29 0 44.6 13.2 36.4 51.6l-30.4 143.6h-38.2l27.6-130.4c5.2-24.8 0-34.4-19.2-34.4-15.6 0-33 12.4-38.2 37.2l-27.2 127.6h-38l40-190.2zM373.8 447.4h38.2l-40.4 190.2h-38.2l40.4-190.2zM455.4 385h128.8l-7.4 34h-88.4l-14.8 70h88.6l-7 34h-88.6l-24.4 114.6h-40.4l53.6-252.6zM600.4 447.4h38.2l-40.4 190.2h-38.2l40.4-190.2z"></path>
|
||||||
|
<path fill="#4A4A4A" d="M694.2 438c-15.2 0-26-11.4-26-26.4 0-16 12-26.4 26-26.4 13.8 0 25.8 10.6 25.8 26.4 0.2 15.8-11.8 26.4-25.8 26.4zM694.2 389.6c-11.4 0-20.4 9-20.4 21.8 0 12 7.8 21.8 20.4 21.8 11.4 0 20.2-9 20.2-21.8 0.2-12.8-8.8-21.8-20.2-21.8zM689 426.6h-4.8v-29.2h11c7 0 10.6 2.4 10.6 8.4 0 5.4-3.2 7.4-7.6 8l8.2 12.8h-5.4l-7.6-12.6h-4.6l0.2 12.6zM694.4 410c3.6 0 6.8-0.4 6.8-4.6 0-3.6-3.4-4-6.4-4h-5.8v8.6h5.4z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
26
web/src/components/ApIcon.vue
Normal file
26
web/src/components/ApIcon.vue
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<v-avatar size="28px" class="ml-2">
|
||||||
|
<v-img contain :src="logo" />
|
||||||
|
</v-avatar>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import ciscoLogo from '../assets/cisco_logo.svg'
|
||||||
|
import unifiLogo from '../assets/unifi_logo.svg'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
controller: {
|
||||||
|
type: String,
|
||||||
|
default: 'unknown'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
logo() {
|
||||||
|
return {
|
||||||
|
Cisco: ciscoLogo,
|
||||||
|
UniFi: unifiLogo
|
||||||
|
}[this.controller]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -43,6 +43,7 @@
|
||||||
<span class="font-weight-medium"
|
<span class="font-weight-medium"
|
||||||
>{{ userPresence.wifiDevices[0].apName }}
|
>{{ userPresence.wifiDevices[0].apName }}
|
||||||
</span>
|
</span>
|
||||||
|
<ApIcon :controller="userPresence.wifiDevices[0].controller" />
|
||||||
</v-list-item-subtitle>
|
</v-list-item-subtitle>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
<v-list-item-icon>
|
<v-list-item-icon>
|
||||||
|
@ -96,9 +97,11 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Avatar from './Avatar'
|
import Avatar from './Avatar'
|
||||||
|
import ApIcon from './ApIcon'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UserPresenceStatusList',
|
name: 'UserPresenceStatusList',
|
||||||
components: { Avatar },
|
components: { Avatar, ApIcon },
|
||||||
props: {
|
props: {
|
||||||
userPresences: {
|
userPresences: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
|
|
@ -5,19 +5,20 @@
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="search"
|
v-model="search"
|
||||||
label="Pesquisar"
|
label="Pesquisar"
|
||||||
|
hint="Usuário ou Access Point (Ex.: jose, pp, sala 102)"
|
||||||
prepend-inner-icon="mdi-account-search"
|
prepend-inner-icon="mdi-account-search"
|
||||||
outlined
|
outlined
|
||||||
rounded
|
rounded
|
||||||
|
autofocus
|
||||||
clearable
|
clearable
|
||||||
hide-details
|
|
||||||
style="max-width: 480px"
|
style="max-width: 480px"
|
||||||
/>
|
/>
|
||||||
<v-btn
|
<v-btn
|
||||||
:loading="$apollo.queries.userPresence.loading"
|
:loading="$apollo.queries.userPresence.loading"
|
||||||
color="primary"
|
color="primary"
|
||||||
class="ml-4"
|
class="ml-4 mb-8"
|
||||||
icon
|
icon
|
||||||
large
|
x-large
|
||||||
@click="$apollo.queries.userPresence.refresh()"
|
@click="$apollo.queries.userPresence.refresh()"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-refresh</v-icon>
|
<v-icon>mdi-refresh</v-icon>
|
||||||
|
@ -71,7 +72,7 @@ export default {
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
pollInterval: 300000, // 5min
|
pollInterval: 300000, // 5min
|
||||||
query: gql`
|
query: gql`
|
||||||
query($search: String) {
|
query($search: String = "") {
|
||||||
userPresence(search: $search) {
|
userPresence(search: $search) {
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
|
@ -83,6 +84,7 @@ export default {
|
||||||
id
|
id
|
||||||
lastSeen
|
lastSeen
|
||||||
status
|
status
|
||||||
|
controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user