1import { computed } from "vue" 2import { QIcon } from "quasar" 3import Jdenticon, { useJdenticon } from "appDeviceLogs/composables/jdenticon" 4import dateFormat from "dateformat" 5import _ from "lodash" 6 7import ubntDevices from "appDeviceLogs/utils/ubntDevices" 8 9export default { 10 components: { 11 QIcon, 12 Jdenticon, 13 }, 14 props: { 15 selectedLog: Object, 16 deviceId: String, 17 deviceName: String, 18 }, 19 setup(props) { 20 useJdenticon() 21 const devices = computed(() => { 22 if (!props.selectedLog.ubntDevices) return [] 23 const deviceMap = new Map() 24 props.selectedLog.ubntDevices.forEach((device) => { 25 device.name = device.deviceName || device.deviceModel 26 deviceMap.set(device.mac, device) 27 }) 28 deviceMap.forEach((device) => { 29 const extras = ubntDevices[device.deviceModel] || { 30 img: "", 31 label: device.deviceModel, 32 sizeClass: "s-6", 33 } 34 Object.assign(device, extras) 35 }) 36 return Array.from(deviceMap.values()).sort((deviceA, deviceB) => { 37 const priorityMap = { 38 "Edge Router": 1, 39 "Edge Switch": 2, 40 "UK-Pro": 3, 41 "NanoBeam 5AC": 4, 42 "UAP-AC-Mesh": 5, 43 "NanoStation M5": 6, 44 "NanoStation loco M5": 7, 45 } 46 const priorityA = priorityMap[deviceA.deviceModel] || Object.keys(priorityMap).length 47 const priorityB = priorityMap[deviceB.deviceModel] || Object.keys(priorityMap).length 48 if (priorityA === priorityB) { 49 return deviceA.name < deviceB.name ? -1 : 1 50 } 51 return priorityB - priorityA 52 }) 53 }) 54 55 const device = computed(() => { 56 return devices.value.find((device) => device.mac == props.deviceId) 57 }) 58 59 function textClass(value) { 60 return value ? "" : "text-gray-400" 61 } 62 63 return { 64 device, 65 textClass, 66 dateFormat, 67 } 68 }, 69 template: /*html*/ ` 70 71 <div class="card border-t-8 border-orange-500"> 72 <div v-if="device == undefined" class="row gap-2"> 73 <Jdenticon :jdid="deviceId"/> 74 <span>{{deviceName}}</span> 75 </div> 76 <div v-else class="column items-stretch gap-4"> 77 <!-- Model --> 78 <div class="row items-center gap-2"> 79 <div class="s-10 rounded-full border-2 border-white shadow relative"> 80 <img v-if="device.img" :src="device.img" class="abs-c" :class="device.sizeClass" /> 81 <q-icon v-else name="mdi-help-circle-outline" class="abs-c text-gray-400 bg-gray-100 rounded-full" size="2.25rem"/> 82 </div> 83 <div class="column items-start leading-snug"> 84 <span class="text-[1.25em] font-medium">{{device.name}}</span> 85 <span :class="textClass(device.model)">{{device.label || "Unknown Model"}}</span> 86 </div> 87 </div> 88 <!-- Firmware --> 89 <div class="pl-12"> 90 <div class="-ml-6 font-medium mb-2 row items-center gap-2"> 91 <q-icon name="mdi-history" size="1rem"/> 92 <span>Firmware</span> 93 </div> 94 <div class="w-full relative"> 95 96 <span class="abs-fill whitespace-normal break-all leading-none" :class="textClass(device.firmware)"> 97 {{device.firmware || "N/A"}} 98 </span> 99 </div> 100 </div> 101 <!-- Channel Frequency --> 102 <div class="pl-12"> 103 <div class="-ml-6 font-medium mb-2 row items-center gap-2"> 104 <q-icon name="mdi-sine-wave" size="1rem"/> 105 <span>Channel</span> 106 </div> 107 <span :class="textClass(device.channel)"> 108 {{device.channel || "N/A"}} 109 </span> 110 </div> 111 <!-- Channel Width --> 112 <div class="pl-12"> 113 <div class="-ml-6 font-medium mb-2 row items-center gap-2"> 114 <q-icon name="mdi-arrow-collapse-horizontal" size="1rem"/> 115 <span>Channel Width</span> 116 </div> 117 <span :class="textClass(device.channelWidth)"> 118 {{device.channelWidth || "N/A"}} 119 </span> 120 </div> 121 <!-- Frequency --> 122 <div class="pl-12"> 123 <div class="-ml-6 font-medium mb-2 row items-center gap-2"> 124 <q-icon name="mdi-barcode" size="1rem"/>
125 <span>Frequency</span> 126 </div> 127 <span :class="textClass(device.frequency)"> 128 {{device.frequency || "N/A"}} 129 </span> 130 </div> 131 <!-- LAN Speed --> 132 <div class="pl-6"> 133 <div class="font-medium mb-2 row items-center gap-2"> 134 <q-icon name="mdi-ethernet" size="1rem"/> 135 <span>LAN Speed</span> 136 </div> 137 <div class="-ml-6 column items-start text-left text-2xs gap-y-1"> 138 <!-- Port names --> 139 <div class="row items-baseline gap-x-4"> 140 <q-icon name="mdi-circle-medium" class="invisible"/> 141 <span class="w-8"></span> 142 <span v-for="portName of ['eth0', 'eth1']" class="w-20 row justify-between gap-2 font-semibold"> 143 {{portName}} 144 </span> 145 </div> 146 <!-- Port speeds --> 147 <div class="row items-baseline gap-x-4"> 148 <q-icon name="mdi-speedometer"/> 149 <span class="w-8 text-3xs uppercase font-medium text-gray-500">Speed</span> 150 <span v-for="[port, eth] of [['eth0', device.eth0], ['eth1', device.eth1]]" class="w-20 row justify-between gap-2"> 151 <span v-if="eth !== undefined" :title="eth.speed+'/'+'eth.duplex'" class="w-full"> 152 {{eth.speed}} / {{eth.duplex}} 153 </span> 154 </span> 155 </div> 156 <!-- Port status --> 157 <div class="row items-baseline gap-x-4"> 158 <q-icon name="mdi-list-status"/> 159 <span class="w-8 text-3xs uppercase font-medium text-gray-500">Status</span> 160 <span v-for="[port, eth] of [['eth0', device.eth0], ['eth1', device.eth1]]" class="w-20 row justify-between gap-2"> 161 <span v-if="eth?.enabled !== undefined" class="w-full whitespace-normal break-words"> 162 {{eth.enabled ? "Enabled" : "Disabled"}} / {{eth.plugged ? "Plugged" : "Unplugged"}} 163 </span> 164 </span> 165 </div> 166 </div> 167 </div> 168 </div> 169 </div> 170 `, 171};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.