mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
implementing snapshots
This commit is contained in:
@@ -80,6 +80,9 @@ const { lineChartProps, lineChartRef } = useLineChart({ chartData: chartData, op
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
console.log('MOUNTED')
|
||||
|
||||
const c = document.createElement('canvas');
|
||||
const ctx = c.getContext("2d");
|
||||
let gradient: any = `${props.color}22`;
|
||||
@@ -106,5 +109,5 @@ onMounted(async () => {
|
||||
|
||||
|
||||
<template>
|
||||
<LineChart ref="lineChartRef" v-bind="lineChartProps"> </LineChart>
|
||||
<LineChart ref="lineChartRef" v-bind="lineChartProps"> </LineChart>
|
||||
</template>
|
||||
|
||||
@@ -1,46 +1,43 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
import DateService, { type Slice } from '@services/DateService';
|
||||
|
||||
const data = ref<number[]>([]);
|
||||
const labels = ref<string[]>([]);
|
||||
const ready = ref<boolean>(false);
|
||||
|
||||
const props = defineProps<{ slice: Slice }>();
|
||||
|
||||
const { snapshot } = useSnapshot();
|
||||
const slice = computed(() => props.slice);
|
||||
|
||||
const snapshotFrom = computed(() => {
|
||||
return new Date(snapshot.value?.from || '0').toISOString();
|
||||
});
|
||||
|
||||
const snapshotTo = computed(() => {
|
||||
return new Date(snapshot.value?.to || Date.now()).toISOString();
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
ready.value = false;
|
||||
const response = await useTimeline('sessions', props.slice,
|
||||
snapshotFrom.value.toString(),
|
||||
snapshotTo.value.toString()
|
||||
);
|
||||
if (!response) return;
|
||||
data.value = response.map(e => e.count);
|
||||
labels.value = response.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, props.slice));
|
||||
ready.value = true;
|
||||
}
|
||||
const res = useTimeline('sessions', slice);
|
||||
|
||||
onMounted(async () => {
|
||||
await loadData();
|
||||
watch(props, async () => { await loadData(); });
|
||||
watch(snapshot, async () => { await loadData(); });
|
||||
|
||||
res.onResponse(resData => {
|
||||
if (!resData.value) return;
|
||||
data.value = resData.value.map(e => e.count);
|
||||
labels.value = resData.value.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, props.slice));
|
||||
});
|
||||
|
||||
await res.refresh();
|
||||
|
||||
watch(props, () => res.refresh());
|
||||
})
|
||||
|
||||
|
||||
const chartVisible = computed(() => {
|
||||
if (res.pending.value) return false;
|
||||
if (!res.data.value) return false;
|
||||
return true;
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<AdvancedLineChart v-if="ready" :data="data" :labels="labels" color="#f56523"></AdvancedLineChart>
|
||||
<div v-if="!chartVisible" class="flex justify-center py-40">
|
||||
<i class="fas fa-spinner text-[2rem] text-accent animate-[spin_1s_linear_infinite] duration-500"></i>
|
||||
</div>
|
||||
<AdvancedLineChart v-if="chartVisible" :data="data" :labels="labels" color="#f56523"></AdvancedLineChart>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
import DateService from '@services/DateService';
|
||||
import type { Slice } from '@services/DateService';
|
||||
|
||||
const { data: metricsInfo } = useMetricsData();
|
||||
|
||||
@@ -75,31 +76,41 @@ const avgSessionDuration = computed(() => {
|
||||
return `${hours > 0 ? hours + 'h ' : ''}${minutes}m ${seconds.toFixed()}s`
|
||||
});
|
||||
|
||||
|
||||
const chartSlice = computed(() => {
|
||||
const snapshotSizeMs = new Date(snapshot.value.to).getTime() - new Date(snapshot.value.from).getTime();
|
||||
if (snapshotSizeMs < 1000 * 60 * 60 * 24 * 6) return 'hour' as Slice;
|
||||
if (snapshotSizeMs < 1000 * 60 * 60 * 24 * 30) return 'day' as Slice;
|
||||
if (snapshotSizeMs < 1000 * 60 * 60 * 24 * 90) return 'day' as Slice;
|
||||
return 'month' as Slice;
|
||||
});
|
||||
|
||||
async function loadData(timelineEndpointName: string, target: Data) {
|
||||
|
||||
target.ready = false;
|
||||
|
||||
const response = await useTimeline(timelineEndpointName as any, 'day',
|
||||
snapshot.value?.from.toString() || "0",
|
||||
snapshot.value?.to.toString() || Date.now().toString()
|
||||
);
|
||||
const response = useTimeline(timelineEndpointName as any, chartSlice);
|
||||
|
||||
console.log(timelineEndpointName,response);
|
||||
response.onResponse(data => {
|
||||
|
||||
if (!response) return;
|
||||
if (!data.value) return;
|
||||
|
||||
target.data = response.map(e => e.count);
|
||||
target.labels = response.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, 'day'));
|
||||
target.data = data.value.map(e => e.count);
|
||||
target.labels = data.value.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, chartSlice.value));
|
||||
|
||||
const pool = [...response.map(e => e.count)];
|
||||
pool.pop();
|
||||
const avg = pool.reduce((a, e) => a + e, 0) / pool.length;
|
||||
const pool = [...data.value.map(e => e.count)];
|
||||
pool.pop();
|
||||
const avg = pool.reduce((a, e) => a + e, 0) / pool.length;
|
||||
|
||||
const diffPercent: number = (100 / avg * (response.at(-1)?.count || 0)) - 100;
|
||||
const diffPercent: number = (100 / avg * (data.value.at(-1)?.count || 0)) - 100;
|
||||
|
||||
target.trend = Math.max(Math.min(diffPercent, 99), -99);
|
||||
target.trend = Math.max(Math.min(diffPercent, 99), -99);
|
||||
|
||||
target.ready = true;
|
||||
});
|
||||
|
||||
response.execute();
|
||||
|
||||
target.ready = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +124,7 @@ async function loadAllData() {
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
await loadAllData();
|
||||
@@ -137,13 +149,15 @@ onMounted(async () => {
|
||||
</DashboardCountCard>
|
||||
|
||||
<DashboardCountCard :ready="eventsData.ready" icon="far fa-flag" text="Total custom events"
|
||||
:value="formatNumberK(eventsData.data.reduce((a, e) => a + e, 0))" :avg="formatNumberK(avgEventsDay) + '/day'"
|
||||
:trend="eventsData.trend" :data="eventsData.data" :labels="eventsData.labels" color="#1e9b86">
|
||||
:value="formatNumberK(eventsData.data.reduce((a, e) => a + e, 0))"
|
||||
:avg="formatNumberK(avgEventsDay) + '/day'" :trend="eventsData.trend" :data="eventsData.data"
|
||||
:labels="eventsData.labels" color="#1e9b86">
|
||||
</DashboardCountCard>
|
||||
|
||||
<DashboardCountCard :ready="sessionsData.ready" icon="far fa-user" text="Unique visits sessions"
|
||||
:value="formatNumberK(sessionsData.data.reduce((a, e) => a + e, 0))" :avg="formatNumberK(avgSessionsDay) + '/day'"
|
||||
:trend="sessionsData.trend" :data="sessionsData.data" :labels="sessionsData.labels" color="#4abde8">
|
||||
:value="formatNumberK(sessionsData.data.reduce((a, e) => a + e, 0))"
|
||||
:avg="formatNumberK(avgSessionsDay) + '/day'" :trend="sessionsData.trend" :data="sessionsData.data"
|
||||
:labels="sessionsData.labels" color="#4abde8">
|
||||
</DashboardCountCard>
|
||||
|
||||
<DashboardCountCard :ready="sessionsDurationData.ready" icon="far fa-timer" text="Avg session time"
|
||||
|
||||
@@ -4,43 +4,41 @@ import DateService, { type Slice } from '@services/DateService';
|
||||
|
||||
const data = ref<number[]>([]);
|
||||
const labels = ref<string[]>([]);
|
||||
const ready = ref<boolean>(false);
|
||||
|
||||
const props = defineProps<{ slice: Slice }>();
|
||||
|
||||
const { snapshot } = useSnapshot();
|
||||
const slice = computed(() => props.slice);
|
||||
|
||||
const snapshotFrom = computed(() => {
|
||||
return new Date(snapshot.value?.from || '0').toISOString();
|
||||
});
|
||||
const res = useTimeline('visits', slice);
|
||||
|
||||
const snapshotTo = computed(() => {
|
||||
return new Date(snapshot.value?.to || Date.now()).toISOString();
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
ready.value = false;
|
||||
const response = await useTimeline('visits', props.slice,
|
||||
snapshotFrom.value.toString(),
|
||||
snapshotTo.value.toString()
|
||||
);
|
||||
|
||||
if (!response) return;
|
||||
data.value = response.map(e => e.count);
|
||||
labels.value = response.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, props.slice));
|
||||
ready.value = true;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadData();
|
||||
watch(props, async () => { await loadData(); });
|
||||
watch(snapshot, async () => { await loadData(); });
|
||||
|
||||
res.onResponse(resData => {
|
||||
if (!resData.value) return;
|
||||
data.value = resData.value.map(e => e.count);
|
||||
labels.value = resData.value.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, props.slice));
|
||||
});
|
||||
|
||||
await res.refresh();
|
||||
|
||||
watch(props, () => res.refresh());
|
||||
})
|
||||
|
||||
|
||||
const chartVisible = computed(() => {
|
||||
if (res.pending.value) return false;
|
||||
if (!res.data.value) return false;
|
||||
return true;
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<AdvancedLineChart v-if="ready" :data="data" :labels="labels" color="#5655d7"></AdvancedLineChart>
|
||||
<div v-if="!chartVisible" class="flex justify-center py-40">
|
||||
<i class="fas fa-spinner text-[2rem] text-accent animate-[spin_1s_linear_infinite] duration-500"></i>
|
||||
</div>
|
||||
<AdvancedLineChart v-if="chartVisible" :data="data" :labels="labels" color="#5655d7">
|
||||
</AdvancedLineChart>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user