mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-11 23:17:19 -04:00
113 lines
4.3 KiB
Vue
113 lines
4.3 KiB
Vue
<script setup lang="ts">
|
|
const { data: stats } = useFetch('/api/admin/stats-public', { lazy: true });
|
|
|
|
const runtimeConfig = useRuntimeConfig();
|
|
const plausibleHost = runtimeConfig.public.plausible.apiHost;
|
|
const heartbeatHost = runtimeConfig.public.heartbeatLink;
|
|
|
|
const overall = ref(true);
|
|
|
|
const activeStats = computed(() => {
|
|
if (stats.value === null) {
|
|
return undefined;
|
|
}
|
|
|
|
return overall.value
|
|
? stats.value.overall
|
|
: stats.value.current || {};
|
|
});
|
|
|
|
const formatNumber = (number: number): string => {
|
|
if (number > 1000000) {
|
|
return `${Math.round(10 * number / 1000000) / 10}M`;
|
|
}
|
|
if (number > 1000) {
|
|
return `${Math.round(10 * number / 1000) / 10}k`;
|
|
}
|
|
return number.toString();
|
|
};
|
|
|
|
const formatDuration = (secondsCount: number): string => {
|
|
const minutes = Math.floor(secondsCount / 60);
|
|
const seconds = secondsCount % 60;
|
|
const res = [];
|
|
if (minutes > 0) {
|
|
res.push(`${minutes}m`);
|
|
}
|
|
if (seconds > 0) {
|
|
res.push(`${seconds}s`);
|
|
}
|
|
return res.join(' ');
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="stats !== null">
|
|
<p class="h6 mb-2">
|
|
<T>footer.stats.header</T><T>quotation.colon</T>
|
|
</p>
|
|
<p v-if="overall" :key="`a${overall}`" class="small mb-2">
|
|
<strong><T>footer.stats.overall</T></strong>
|
|
|
|
|
<a href="#" @click.prevent="overall = false"><T>footer.stats.current</T></a>
|
|
</p>
|
|
<p v-else :key="`b${overall}`" class="small mb-2">
|
|
<a href="#" @click.prevent="overall = true"><T>footer.stats.overall</T></a>
|
|
|
|
|
<strong><T>footer.stats.current</T></strong>
|
|
</p>
|
|
<ul v-if="activeStats" :key="`${overall}`" class="list-unstyled">
|
|
<li v-if="activeStats.cards" class="mb-2">
|
|
<Icon v="id-card" />
|
|
<T>footer.stats.keys.cards</T><T>quotation.colon</T>
|
|
<strong>{{ formatNumber(activeStats.cards) }}</strong>
|
|
</li>
|
|
<li v-if="activeStats.visitors" class="mb-2">
|
|
<Icon v="fingerprint" />
|
|
<T>footer.stats.keys.visitors</T><T>quotation.colon</T>
|
|
<strong>{{ formatNumber(activeStats.visitors) }}</strong> / <T>footer.stats.month</T>
|
|
</li>
|
|
<li v-if="activeStats.pageViews" class="mb-2">
|
|
<Icon v="mouse" />
|
|
<T>footer.stats.keys.pageviews</T><T>quotation.colon</T>
|
|
<strong>{{ formatNumber(activeStats.pageViews) }}</strong> / <T>footer.stats.month</T>
|
|
</li>
|
|
<li v-if="activeStats.online" class="mb-2">
|
|
<Icon v="user-clock" />
|
|
<T>footer.stats.keys.realTimeVisitors</T><T>quotation.colon</T>
|
|
<strong>{{ formatNumber(activeStats.online) }}</strong>
|
|
</li>
|
|
<li v-if="activeStats.users" class="mb-2">
|
|
<Icon v="user-friends" />
|
|
<T>footer.stats.keys.users</T><T>quotation.colon</T>
|
|
<strong>{{ formatNumber(activeStats.users) }}</strong>
|
|
</li>
|
|
<li v-if="activeStats.visitDuration" class="mb-2">
|
|
<Icon v="clock" />
|
|
<T>footer.stats.keys.visitDuration</T><T>quotation.colon</T>
|
|
<strong>{{ formatDuration(activeStats.visitDuration) }}</strong>
|
|
</li>
|
|
<li v-if="activeStats.uptime" class="mb-2">
|
|
<Icon v="monitor-heart-rate" />
|
|
<T>footer.stats.keys.uptime</T><T>quotation.colon</T>
|
|
<strong>{{ activeStats.uptime }}%</strong>
|
|
</li>
|
|
<li v-if="activeStats.responseTime" class="mb-2">
|
|
<Icon v="stopwatch" />
|
|
<T>footer.stats.keys.responseTime</T><T>quotation.colon</T>
|
|
<strong>{{ activeStats.responseTime }} ms</strong>
|
|
</li>
|
|
<li class="mb-2 small">
|
|
<a v-if="$isGranted()" :href="`${plausibleHost}/${$t('domain')}?period=30d`" target="_blank" rel="noopener">
|
|
<Icon v="external-link" />
|
|
Plausible
|
|
</a>
|
|
<a :href="`${heartbeatHost}`" target="_blank" rel="noopener">
|
|
<Icon v="external-link" />
|
|
heartbeat
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|