Statistics styling
This commit is contained in:
parent
6c47c5b178
commit
3ce2ba5013
6 changed files with 198 additions and 19 deletions
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import {RouterLink, RouterView} from "vue-router";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
import PageFooter from "@/components/PageFooter.vue";
|
||||
import PageHeader from "@/components/page/PageHeader.vue";
|
||||
import PageFooter from "@/components/page/PageFooter.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
113
frontend/src/components/admin/StatisticsCard.vue
Normal file
113
frontend/src/components/admin/StatisticsCard.vue
Normal file
|
@ -0,0 +1,113 @@
|
|||
<script setup lang="ts">
|
||||
import {computed, defineProps} from "vue";
|
||||
|
||||
const {
|
||||
title,
|
||||
icon,
|
||||
variant,
|
||||
value,
|
||||
link,
|
||||
filter,
|
||||
} = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
link: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
filter: {
|
||||
type: Object,
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
|
||||
const linkTarget = computed(() => {
|
||||
if (filter) {
|
||||
const json = JSON.stringify(filter);
|
||||
return `${link}?search=${encodeURIComponent(json)}`;
|
||||
} else {
|
||||
return link;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterLink :to="linkTarget" :class="['statistics-card', 'statistics-card-' + variant]">
|
||||
<i :class="['fa', 'fa-' + icon]" aria-hidden="true" />
|
||||
<dl>
|
||||
<dt>{{ title }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
</dl>
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../scss/variables";
|
||||
|
||||
.statistics-card {
|
||||
display: flex;
|
||||
|
||||
min-height: $statistics-card-height;
|
||||
|
||||
margin: $statistics-card-margin;
|
||||
padding: $statistics-card-padding;
|
||||
|
||||
border-radius: $statistics-card-border-radius;
|
||||
|
||||
@each $variant, $color in $variant-colors {
|
||||
&.statistics-card-#{$variant} {
|
||||
background-color: $color;
|
||||
color: map-get($variant-text-colors, $variant);
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
margin-right: $statistics-card-icon-gap;
|
||||
font-size: $statistics-card-icon-size;
|
||||
width: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
dl {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
text-align: right;
|
||||
|
||||
dt {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
dd {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
font-weight: bold;
|
||||
font-size: $statistics-card-value-font-size;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -35,7 +35,7 @@ refresh();
|
|||
|
||||
<style lang="scss" scoped>
|
||||
@use "sass:math";
|
||||
@import "../scss/variables";
|
||||
@import "../../scss/variables";
|
||||
|
||||
footer {
|
||||
position: absolute;
|
|
@ -36,7 +36,7 @@ refresh();
|
|||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../scss/variables";
|
||||
@import "../../scss/variables";
|
||||
|
||||
header {
|
||||
background-color: $nav-bar-background-color;
|
|
@ -1,17 +1,34 @@
|
|||
// Grays
|
||||
$black: #000000;
|
||||
$gray-darkest: #222222;
|
||||
$gray-darker: #333333;
|
||||
$gray-dark: #444444;
|
||||
$gray: #666666;
|
||||
$gray-light: #d6d6d6;
|
||||
$gray-lighter: #ededed;
|
||||
$white: #ffffff;
|
||||
|
||||
// Colors
|
||||
$color-primary: #e5287a;
|
||||
$color-success: #449d44;
|
||||
$color-warning: #fdbc41;
|
||||
$color-danger: #c9302c;
|
||||
$color-info: #009ee0;
|
||||
$variant-colors: (
|
||||
primary: #e5287a,
|
||||
success: #4ba74b,
|
||||
warning: #fdbc41,
|
||||
danger: #ef5652,
|
||||
info: #009ee0,
|
||||
);
|
||||
$variant-text-colors: (
|
||||
// primary: do not use, contrast too low
|
||||
success: $gray-darkest,
|
||||
warning: $gray-darkest,
|
||||
danger: $gray-darkest,
|
||||
info: $gray-darkest,
|
||||
);
|
||||
|
||||
$variant-color-primary: map-get($variant-colors, primary);
|
||||
$variant-color-success: map-get($variant-colors, success);
|
||||
$variant-color-warning: map-get($variant-colors, warning);
|
||||
$variant-color-danger: map-get($variant-colors, danger);
|
||||
$variant-color-info: map-get($variant-colors, info);
|
||||
|
||||
// Page
|
||||
$page-background-color: $gray-darkest;
|
||||
|
@ -19,7 +36,7 @@ $page-text-color: $gray-lighter;
|
|||
$page-padding: 0.5em;
|
||||
|
||||
// Links
|
||||
$link-color: $color-warning;
|
||||
$link-color: $variant-color-warning;
|
||||
|
||||
// Navigation
|
||||
$nav-bar-background-color: $gray-darker;
|
||||
|
@ -31,3 +48,12 @@ $nav-header-logo-size: 2em;
|
|||
$nav-header-logo-margin: 0 0.5em 0 0;
|
||||
|
||||
$nav-footer-padding: 0.75em;
|
||||
|
||||
// Statistics
|
||||
$statistics-card-height: 4.5em;
|
||||
$statistics-card-margin: 0.5em;
|
||||
$statistics-card-padding: 0.3em 0.5em;
|
||||
$statistics-card-border-radius: 0.5em;
|
||||
$statistics-card-icon-size: 4em;
|
||||
$statistics-card-icon-gap: 0.15em;
|
||||
$statistics-card-value-font-size: 2.5em;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import StatisticsCard from "@/components/admin/StatisticsCard.vue";
|
||||
import { useStatisticsStore } from "@/stores/statistics";
|
||||
|
||||
const statistics = useStatisticsStore();
|
||||
|
@ -13,18 +14,57 @@ refresh();
|
|||
<template>
|
||||
<main>
|
||||
<div v-if="statistics.getStatistics">
|
||||
<h1>Nodes</h1>
|
||||
<h2>Knotenstatistik</h2>
|
||||
|
||||
<div>
|
||||
Registered: {{ statistics.getStatistics.nodes.registered }}<br />
|
||||
With VPN-key: {{ statistics.getStatistics.nodes.withVPN }}<br />
|
||||
With coordinates: {{ statistics.getStatistics.nodes.withCoords }}<br />
|
||||
Monitoring active: {{ statistics.getStatistics.nodes.monitoring.active }}<br />
|
||||
Monitoring pending: {{ statistics.getStatistics.nodes.monitoring.pending }}
|
||||
<div class="statistics">
|
||||
<StatisticsCard
|
||||
title="Registrierte Knoten"
|
||||
icon="circle-o"
|
||||
variant="info"
|
||||
:value="statistics.getStatistics.nodes.registered"
|
||||
link="/admin/nodes"
|
||||
/>
|
||||
<StatisticsCard
|
||||
title="Mit hinterlegtem fastd-Key"
|
||||
icon="lock"
|
||||
variant="warning"
|
||||
:value="statistics.getStatistics.nodes.withVPN"
|
||||
link="/admin/nodes"
|
||||
:filter="{hasKey: true}"
|
||||
/>
|
||||
<StatisticsCard
|
||||
title="Mit Koordinaten"
|
||||
icon="map-marker"
|
||||
variant="success"
|
||||
:value="statistics.getStatistics.nodes.withCoords"
|
||||
link="/admin/nodes"
|
||||
:filter="{hasCoords: true}"
|
||||
/>
|
||||
<StatisticsCard
|
||||
title="Monitoring aktiv"
|
||||
icon="heartbeat"
|
||||
variant="success"
|
||||
:value="statistics.getStatistics.nodes.monitoring.active"
|
||||
link="/admin/nodes"
|
||||
:filter="{monitoringState: 'active'}"
|
||||
/>
|
||||
<StatisticsCard
|
||||
title="Monitoring noch nicht bestätigt"
|
||||
icon="envelope"
|
||||
variant="danger"
|
||||
:value="statistics.getStatistics.nodes.monitoring.pending"
|
||||
link="/admin/nodes"
|
||||
:filter="{monitoringState: 'pending'}"
|
||||
/>
|
||||
</div>
|
||||
<button @click="refresh()">Refresh</button>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.statistics {
|
||||
display: grid;
|
||||
// TODO: Responsive sizes
|
||||
grid-template-columns: repeat(auto-fill, minmax(25%, 100%));
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue