mirror of https://github.com/Lissy93/dashy.git
✨ Adds a network interface widget
This commit is contained in:
parent
6b8a5ee086
commit
6d9e34c90f
|
@ -52,6 +52,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||||
- [Disk IO](#disk-io)
|
- [Disk IO](#disk-io)
|
||||||
- [System Load](#system-load)
|
- [System Load](#system-load)
|
||||||
- [System Load History](#system-load-history)
|
- [System Load History](#system-load-history)
|
||||||
|
- [Network Interfaces](#network-interfaces)
|
||||||
- [Resource Usage Alerts](#resource-usage-alerts)
|
- [Resource Usage Alerts](#resource-usage-alerts)
|
||||||
- **[Dynamic Widgets](#dynamic-widgets)**
|
- **[Dynamic Widgets](#dynamic-widgets)**
|
||||||
- [Iframe Widget](#iframe-widget)
|
- [Iframe Widget](#iframe-widget)
|
||||||
|
@ -1355,11 +1356,27 @@ Shows recent historical system load, calculated from the number of processes wai
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Network Interfaces
|
||||||
|
|
||||||
|
Lists visible network interfaces, including real-time upload/ download stats
|
||||||
|
|
||||||
|
<p align="center"><img width="400" src="https://i.ibb.co/FnhgHfG/gl-network-interfaces.png" /></p>
|
||||||
|
|
||||||
|
##### Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- type: gl-network-interfaces
|
||||||
|
options:
|
||||||
|
hostname: http://192.168.130.2:61208
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Resource Usage Alerts
|
### Resource Usage Alerts
|
||||||
|
|
||||||
Lists recent high resource usage alerts (e.g. CPU, mem, IO, load, temp)
|
Lists recent high resource usage alerts (e.g. CPU, mem, IO, load, temp)
|
||||||
|
|
||||||
<p align="center"><img width="500" src="https://i.ibb.co/w01NX5R/gl-alerts.png" /></p>
|
<p align="center"><img width="400" src="https://i.ibb.co/w01NX5R/gl-alerts.png" /></p>
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
<template>
|
||||||
|
<div class="glances-network-interfaces-wrapper" v-if="networks">
|
||||||
|
<div class="interface-row" v-for="network in networks" :key="network.name">
|
||||||
|
<div class="network-info">
|
||||||
|
<p class="network-name">{{ network.name }}</p>
|
||||||
|
<p class="network-speed">{{ network.speed | formatSpeed }}</p>
|
||||||
|
<p :class="`network-online ${network.online}`">
|
||||||
|
{{ network.online }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="current" v-if="network.online === 'up'">
|
||||||
|
<span class="upload">
|
||||||
|
↑ <span class="val">{{ network.currentUpload | formatDataSize }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="separator">|</span>
|
||||||
|
<span class="download">
|
||||||
|
↓ <span class="val">{{ network.currentDownload | formatDataSize }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="total">
|
||||||
|
<b class="lbl">Total</b> Up
|
||||||
|
<span class="val">{{ network.totalUpload | formatDataSize }}</span>
|
||||||
|
<span class="separator">|</span>
|
||||||
|
Down
|
||||||
|
<span class="val">{{ network.totalDownload | formatDataSize }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||||
|
import { convertBytes } from '@/utils/MiscHelpers';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [WidgetMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
networks: null,
|
||||||
|
previous: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hostname() {
|
||||||
|
if (!this.options.hostname) this.error('You must specify a \'hostname\' for Glaces');
|
||||||
|
return this.options.hostname;
|
||||||
|
},
|
||||||
|
endpoint() {
|
||||||
|
return `${this.hostname}/api/3/network`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
formatDataSize(data) {
|
||||||
|
return convertBytes(data);
|
||||||
|
},
|
||||||
|
formatSpeed(byteValue) {
|
||||||
|
if (!byteValue) return '';
|
||||||
|
return `${convertBytes(byteValue)}/s`;
|
||||||
|
},
|
||||||
|
getArrow(direction) {
|
||||||
|
if (direction === 'up') return '↑';
|
||||||
|
if (direction === 'down') return '↓';
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchData() {
|
||||||
|
this.makeRequest(this.endpoint).then(this.processData);
|
||||||
|
},
|
||||||
|
processData(networkData) {
|
||||||
|
this.previous = this.disks;
|
||||||
|
const networks = [];
|
||||||
|
networkData.forEach((network, index) => {
|
||||||
|
networks.push({
|
||||||
|
name: network.interface_name,
|
||||||
|
speed: network.speed,
|
||||||
|
online: network.is_up ? 'up' : 'down',
|
||||||
|
currentDownload: network.rx,
|
||||||
|
currentUpload: network.tx,
|
||||||
|
totalDownload: network.cumulative_rx,
|
||||||
|
totalUpload: network.cumulative_tx,
|
||||||
|
changeDownload: this.previous && network.rx > this.previous[index].rx,
|
||||||
|
changeUpload: this.previous && network.tx > this.previous[index].tx,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.networks = networks;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.overrideUpdateInterval = 5;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.glances-network-interfaces-wrapper {
|
||||||
|
color: var(--widget-text-color);
|
||||||
|
.interface-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
.network-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.network-name {
|
||||||
|
width: 50%;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
overflow: hidden;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.network-speed {
|
||||||
|
font-family: var(--font-monospace);
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
.network-online {
|
||||||
|
min-width: 15%;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: right;
|
||||||
|
text-transform: capitalize;
|
||||||
|
&.up { color: var(--success); }
|
||||||
|
&.down { color: var(--danger); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.total, .current {
|
||||||
|
display: inline;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
b.lbl {
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
span.val {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
font-family: var(--font-monospace);
|
||||||
|
}
|
||||||
|
span.separator {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
}
|
||||||
|
&.total {
|
||||||
|
opacity: var(--dimming-factor);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
&.current {
|
||||||
|
text-align: center;
|
||||||
|
background: var(--widget-accent-color);
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: 1px dashed var(--widget-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -172,6 +172,13 @@
|
||||||
@error="handleError"
|
@error="handleError"
|
||||||
:ref="widgetRef"
|
:ref="widgetRef"
|
||||||
/>
|
/>
|
||||||
|
<GlNetworkInterfaces
|
||||||
|
v-else-if="widgetType === 'gl-network-interfaces'"
|
||||||
|
:options="widgetOptions"
|
||||||
|
@loading="setLoaderState"
|
||||||
|
@error="handleError"
|
||||||
|
:ref="widgetRef"
|
||||||
|
/>
|
||||||
<GlSystemLoad
|
<GlSystemLoad
|
||||||
v-else-if="widgetType === 'gl-system-load'"
|
v-else-if="widgetType === 'gl-system-load'"
|
||||||
:options="widgetOptions"
|
:options="widgetOptions"
|
||||||
|
@ -378,6 +385,7 @@ export default {
|
||||||
GlLoadHistory: () => import('@/components/Widgets/GlLoadHistory.vue'),
|
GlLoadHistory: () => import('@/components/Widgets/GlLoadHistory.vue'),
|
||||||
GlMemGauge: () => import('@/components/Widgets/GlMemGauge.vue'),
|
GlMemGauge: () => import('@/components/Widgets/GlMemGauge.vue'),
|
||||||
GlMemHistory: () => import('@/components/Widgets/GlMemHistory.vue'),
|
GlMemHistory: () => import('@/components/Widgets/GlMemHistory.vue'),
|
||||||
|
GlNetworkInterfaces: () => import('@/components/Widgets/GlNetworkInterfaces.vue'),
|
||||||
GlSystemLoad: () => import('@/components/Widgets/GlSystemLoad.vue'),
|
GlSystemLoad: () => import('@/components/Widgets/GlSystemLoad.vue'),
|
||||||
HealthChecks: () => import('@/components/Widgets/HealthChecks.vue'),
|
HealthChecks: () => import('@/components/Widgets/HealthChecks.vue'),
|
||||||
IframeWidget: () => import('@/components/Widgets/IframeWidget.vue'),
|
IframeWidget: () => import('@/components/Widgets/IframeWidget.vue'),
|
||||||
|
|
Loading…
Reference in New Issue