Commit 7e5496e8 authored by Janis Streib's avatar Janis Streib 🦉
Browse files

ADD: APliste

parent 274c6f12
Pipeline #157715 passed with stages
in 7 minutes and 17 seconds
import Axios from 'axios'
export default {
fetchList() {
return Axios.get('/api/apliste/json')
}
}
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
<font-awesome-icon fixed-width icon="question"/> <font-awesome-icon fixed-width icon="question"/>
MAC-Vendor-Suche MAC-Vendor-Suche
</b-dropdown-item> </b-dropdown-item>
<b-dropdown-item to="/tools/ap_list" v-if="$sysinfo_js_mods['ap_list'] && $store.state.token" :active="$route.path === '/tools/ap_list'">
<font-awesome-icon fixed-width icon="broadcast-tower"/>
AP-Liste
</b-dropdown-item>
</b-nav-item-dropdown> </b-nav-item-dropdown>
<b-nav-item-dropdown v-if="$store.state.token" right <b-nav-item-dropdown v-if="$store.state.token" right
:toggle-class="$route.path.startsWith('/cntl/')?'active':''"> :toggle-class="$route.path.startsWith('/cntl/')?'active':''">
......
...@@ -56,7 +56,10 @@ import { ...@@ -56,7 +56,10 @@ import {
faPlay, faPlay,
faThumbsUp, faThumbsUp,
faThumbsDown, faThumbsDown,
faCog faCog,
faBroadcastTower,
faCheck,
faBolt
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { import {
...@@ -133,5 +136,8 @@ library.add( ...@@ -133,5 +136,8 @@ library.add(
faPlay, faPlay,
faThumbsUp, faThumbsUp,
faThumbsDown, faThumbsDown,
faCog faCog,
faBroadcastTower,
faCheck,
faBolt
) )
...@@ -155,6 +155,16 @@ export default new Router({ ...@@ -155,6 +155,16 @@ export default new Router({
} }
} }
}, },
{
path: '/tools/ap_list',
name: 'ap_list',
component: () => import('./views/tools/APList'),
meta: {
resolveName: function () {
return 'AP-Liste'
}
}
},
{ {
path: '/dnsvs', path: '/dnsvs',
component: () => import('./views/dnsvs/Main.vue'), component: () => import('./views/dnsvs/Main.vue'),
......
import transactionutil from '@/util/transactionutil' import transactionutil from '@/util/transactionutil'
export default { export default {
dict_by_value_of_array (arr, val) { dict_by_value_of_array(arr, val) {
const res = {} const res = {}
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
res[arr[i][val]] = arr[i] res[arr[i][val]] = arr[i]
} }
return res return res
}, },
dict_of_lists_by_value_of_array (arr, val) { dict_of_lists_by_value_of_array(arr, val) {
const res = {} const res = {}
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
if (!(arr[i][val] in res)) { if (!(arr[i][val] in res)) {
...@@ -18,7 +18,20 @@ export default { ...@@ -18,7 +18,20 @@ export default {
} }
return res return res
}, },
denullify_dict (dict) { dict_of_lists_by_value_of_array_l2_l2_array(arr, val, val2) {
const res = {}
for (let i = 0; i < arr.length; i++) {
const valval = arr[i][val]
for (const j of valval) {
if (!(j[val2] in res)) {
res[j[val2]] = []
}
res[j[val2]].push(arr[i])
}
}
return res
},
denullify_dict(dict) {
const res = {} const res = {}
for (const key in dict) { for (const key in dict) {
if (dict[key] !== null) { if (dict[key] !== null) {
...@@ -27,7 +40,7 @@ export default { ...@@ -27,7 +40,7 @@ export default {
} }
return res return res
}, },
buildAPITaFromTaObjectArray (obj) { buildAPITaFromTaObjectArray(obj) {
const res = [] const res = []
for (let i = 0; i < obj.length; i++) { for (let i = 0; i < obj.length; i++) {
const app = { name: `${obj[i].object_fq_name}.${obj[i].object_function}` } const app = { name: `${obj[i].object_fq_name}.${obj[i].object_function}` }
...@@ -41,7 +54,7 @@ export default { ...@@ -41,7 +54,7 @@ export default {
} }
return res return res
}, },
getAPIErrorIndexFromDBException (e) { getAPIErrorIndexFromDBException(e) {
for (const t of e.traceback) { for (const t of e.traceback) {
if ('param' in t && 'wapi.transaction_stmt.index' in t.param) { if ('param' in t && 'wapi.transaction_stmt.index' in t.param) {
return t.param['wapi.transaction_stmt.index'] return t.param['wapi.transaction_stmt.index']
......
<template>
<div class="macfinder">
<h1>Accesspoint-Liste</h1>
<Loading :data="[baseList, apList]">
Stand: {{ lastGen }}<br/>
<span v-if="apList">Bestand: {{ apList.length }} Geräte</span>
<b-form-group label="Filter:" v-slot="{ ariaDescribedby }">
<b-form-checkbox-group
id="checkbox-group-1"
v-model="selectedFilter"
:aria-describedby="ariaDescribedby"
name="catFilter"
switches
@change="advFilter"
>
<b-form-checkbox v-bind:key="i.type" :title="i.description" v-for="i in Object.values(errorTypes)"
:value="i.type">{{ i.label }}
<b-badge :variant="i.weight > 10?'danger':'warning'">
{{ itemsByErrorType[i.type] ? itemsByErrorType[i.type].length : 0 }}
</b-badge>
</b-form-checkbox>
<b-form-checkbox value="down">Down
<b-badge variant="danger">{{ down.length }}</b-badge>
</b-form-checkbox>
</b-form-checkbox-group>
</b-form-group>
<FilterInput v-model="filter"></FilterInput>
<b-card class="shadow">
<b-pagination v-if="baseList && baseList.length > per_page && filter === ''" :total-rows="baseList.length"
:per-page="per_page" v-model="current_page" align="center"></b-pagination>
<b-table responsive striped :fields="res_fields" :filter="filter" :items="baseList"
:per-page="filter===''?per_page:null"
:current-page="filter === ''?current_page:null">
<template v-slot:head(power_consumption)="data">
<span class="text-nowrap">
{{ data.label }}
<font-awesome-icon icon="bolt"></font-awesome-icon>
</span>
</template>
<template v-slot:cell(mac)="item">
<code>{{ item.item.mac }}</code>
</template>
<template v-slot:cell(status)="item">
<ul>
<li v-if="!item.item.up">Down</li>
<template v-if="Object.keys(item.item.errors).length !== 0">
<li v-bind:key="i.description" v-for="i in item.item.errors">{{ errorTypes[i.type].label }}:
{{ i.description }}
</li>
</template>
</ul>
</template>
<template v-slot:cell(nd_module_type)="item">
<span class="text-nowrap">{{ item.item.nd_module_type }}</span>
</template>
<template v-slot:cell(nd_device_fqdn)="item">
<b-link :to="'/dnsvs/fqdns/'+item.item.nd_device_fqdn+'/records'">{{ item.item.nd_device_fqdn }}</b-link>
</template>
<template v-slot:cell(power_consumption)="item">
<template v-if="!isNaN(parseFloat(item.item.power_consumption))">{{ item.item.power_consumption }} Watt
</template>
<template v-else>{{ item.item.power_consumption }}</template>
</template>
<template v-slot:cell(nd_connection_speed)="item">
<template v-if="!isNaN(parseFloat(item.item.nd_connection_speed))">{{ item.item.nd_connection_speed }} /
<span v-if="item.item.snmp_connection_speed">{{ item.item.snmp_connection_speed }}</span><span
v-else>?</span> MBit/s
</template>
<template v-else>{{ item.item.nd_connection_speed }}</template>
</template>
<template v-slot:cell(nd_connection_switch)="item">
<template v-if="item.item.nd_connection_switch">{{ item.item.nd_connection_switch }}, Port
{{ item.item.nd_connection_port }}
</template>
</template>
<template v-slot:cell(up)="item">
<template v-if="item.item.up && Object.keys(item.item.errors).length === 0">
<font-awesome-icon class="text-success" icon="check"></font-awesome-icon>
</template>
<template v-else>
<font-awesome-icon class="text-danger" :icon="['fas', 'times']"></font-awesome-icon>
</template>
</template>
</b-table>
<b-pagination v-if="baseList && baseList.length > per_page && filter === ''" :total-rows="baseList.length"
:per-page="per_page" v-model="current_page" align="center"></b-pagination>
</b-card>
</Loading>
</div>
</template>
<script>
import APListService from '@/api-services/aplist.service'
import Loading from '@/components/Loading'
import FilterInput from '@/components/FilterInput'
import apiutil from '@/util/apiutil'
export default {
name: 'APList',
components: {FilterInput, Loading},
data() {
return {
apList: null,
per_page: 100,
filter: '',
current_page: 1,
lastGen: null,
speedErrors: {},
errorTypes: {},
itemsByErrorType: {},
selectedFilter: [],
down: [],
baseList: null,
res_fields: [
{
key: 'name',
label: 'Name',
sortable: true
},
{
key: 'nd_device_fqdn',
label: 'Device-FQDN',
sortable: true
},
{
key: 'nd_module_type',
label: 'Modultyp',
sortable: true
},
{
key: 'nd_connection_switch',
label: 'Switch',
sortable: true
},
{
key: 'nd_connection_type',
label: 'Anschlusstyp',
sortable: true
},
{
key: 'nd_wall_port',
label: 'Dose',
sortable: true
},
{
key: 'nd_connection_speed',
label: 'Anschlussgeschwindigkeit (möglich/ist)',
sortable: true
},
{
key: 'power_consumption',
label: 'Leistungsaufnahme',
sortable: true
},
{
key: 'mac',
label: 'MAC-Adresse',
sortable: true
},
{
key: 'serial',
label: 'Seriennummer',
sortable: true
},
{
key: 'up',
label: 'Status',
sortable: false
},
{
key: 'status',
label: 'Fehler',
sortable: false
}
]
}
},
methods: {
async fetch() {
const res = await APListService.fetchList()
this.errorTypes = apiutil.dict_by_value_of_array(res.data.errors, 'type')
this.lastGen = new Date(res.data.timestamp)
this.apList = res.data.data
this.itemsByErrorType = apiutil.dict_of_lists_by_value_of_array_l2_l2_array(res.data.data, 'errors', 'type')
window.console.debug(this.itemsByErrorType)
for (const item of this.apList) {
item._cellVariants = {}
if (Object.keys(item.errors).length !== 0) {
let errorCum = 0
for (const i of item.errors) {
errorCum += this.errorTypes[i.type].weight
}
if (errorCum > 0) {
item._rowVariant = 'warning'
}
if (errorCum > 10) {
item._rowVariant = 'danger'
}
}
if (!item.up) {
item._rowVariant = 'danger'
this.down.push(item)
}
}
this.baseList = this.apList
},
advFilter() {
this.baseList = null
const res = []
let baseList = this.apList
if (this.selectedFilter.includes('down')) {
baseList = this.down
}
if (this.selectedFilter.length === 0 || (this.selectedFilter.length === 1 && this.selectedFilter[0] === 'down')) {
this.baseList = baseList
return
}
for (const i of baseList) {
let affections = 0
for (const j of this.selectedFilter) {
if (j === 'down') {
if (!i.up) {
affections++
}
continue
}
for (const k of i.errors) {
if (k.type === j) {
affections++
}
}
}
if (affections === this.selectedFilter.length) {
res.push(i)
}
}
this.baseList = res
}
},
async mounted() {
await this.fetch()
}
}
</script>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment