From 5a26c8c788f66c2a9d97ced6f5b2ed758135c0d5 Mon Sep 17 00:00:00 2001 From: Emily Date: Sat, 3 Aug 2024 19:39:12 +0200 Subject: [PATCH] fix topcards reactivity --- dashboard/components/dashboard/TopCards.vue | 176 ++++++++------------ dashboard/pages/index.vue | 15 +- 2 files changed, 82 insertions(+), 109 deletions(-) diff --git a/dashboard/components/dashboard/TopCards.vue b/dashboard/components/dashboard/TopCards.vue index ad906f1..715bef9 100644 --- a/dashboard/components/dashboard/TopCards.vue +++ b/dashboard/components/dashboard/TopCards.vue @@ -5,50 +5,33 @@ import type { Slice } from '@services/DateService'; const { data: metricsInfo } = useMetricsData(); +const { snapshot, safeSnapshotDates } = useSnapshot() +const snapshotFrom = computed(() => new Date(snapshot.value?.from || '0').getTime()); +const snapshotTo = computed(() => new Date(snapshot.value?.to || Date.now()).getTime()); - -type Data = { - data: number[], - labels: string[], - trend: number, - ready: boolean -} - - -const { snapshot } = useSnapshot() - -const visitsData = reactive({ data: [], labels: [], trend: 0, ready: false }); -const eventsData = reactive({ data: [], labels: [], trend: 0, ready: false }); -const sessionsData = reactive({ data: [], labels: [], trend: 0, ready: false }); -const sessionsDurationData = reactive({ data: [], labels: [], trend: 0, ready: false }); - -const snapshotFrom = computed(() => { - return new Date(snapshot.value?.from || '0').getTime(); -}); - -const snapshotTo = computed(() => { - return new Date(snapshot.value?.to || Date.now()).getTime(); +const snapshotDays = computed(() => { + return (snapshotTo.value - snapshotFrom.value) / 1000 / 60 / 60 / 24; }); const avgVisitDay = computed(() => { - const days = (snapshotTo.value - snapshotFrom.value) / 1000 / 60 / 60 / 24; - const counts = visitsData.data.reduce((a, e) => e + a, 0); - const avg = counts / Math.max(days, 1); + if (!visitsData.data.value) return '0.00'; + const counts = visitsData.data.value.data.reduce((a, e) => e + a, 0); + const avg = counts / Math.max(snapshotDays.value, 1); return avg.toFixed(2); }); const avgEventsDay = computed(() => { - const days = (snapshotTo.value - snapshotFrom.value) / 1000 / 60 / 60 / 24; - const counts = eventsData.data.reduce((a, e) => e + a, 0); - const avg = counts / Math.max(days, 1); + if (!eventsData.data.value) return '0.00'; + const counts = eventsData.data.value.data.reduce((a, e) => e + a, 0); + const avg = counts / Math.max(snapshotDays.value, 1); return avg.toFixed(2); }); const avgSessionsDay = computed(() => { - const days = (snapshotTo.value - snapshotFrom.value) / 1000 / 60 / 60 / 24; - const counts = sessionsData.data.reduce((a, e) => e + a, 0); - const avg = counts / Math.max(days, 1); + if (!sessionsData.data.value) return '0.00'; + const counts = sessionsData.data.value.data.reduce((a, e) => e + a, 0); + const avg = counts / Math.max(snapshotDays.value, 1); return avg.toFixed(2); }); @@ -56,23 +39,12 @@ const avgSessionsDay = computed(() => { const avgSessionDuration = computed(() => { if (!metricsInfo.value) return '0.00'; const avg = metricsInfo.value.avgSessionDuration; - let hours = 0; let minutes = 0; let seconds = 0; seconds += avg * 60; - - while (seconds > 60) { - seconds -= 60; - minutes += 1; - } - - while (minutes > 60) { - minutes -= 60; - hours += 1; - } - - + while (seconds > 60) { seconds -= 60; minutes += 1; } + while (minutes > 60) { minutes -= 60; hours += 1; } return `${hours > 0 ? hours + 'h ' : ''}${minutes}m ${seconds.toFixed()}s` }); @@ -85,90 +57,88 @@ const chartSlice = computed(() => { return 'month' as Slice; }); -async function loadData(timelineEndpointName: string, target: Data) { - target.ready = false; +function transformResponse(input: { _id: string, count: number }[]) { + const data = input.map(e => e.count); + const labels = input.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, chartSlice.value)); + const pool = [...input.map(e => e.count)]; + pool.pop(); + const avg = pool.reduce((a, e) => a + e, 0) / pool.length; + const diffPercent: number = (100 / avg * (input.at(-1)?.count || 0)) - 100; + const trend = Math.max(Math.min(diffPercent, 99), -99); + return { data, labels, trend } +} - const response = useTimeline(timelineEndpointName as any, chartSlice); +const activeProject = useActiveProject(); - response.onRequest(() => { - target.ready = false; - target.data = []; - target.labels = []; - }) - - response.onResponse(data => { - - if (!data.value) return; - - target.data = data.value.map(e => e.count); - target.labels = data.value.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, chartSlice.value)); - - 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 * (data.value.at(-1)?.count || 0)) - 100; - - target.trend = Math.max(Math.min(diffPercent, 99), -99); - - target.ready = true; +function getBody() { + return JSON.stringify({ + from: safeSnapshotDates.value.from, + to: safeSnapshotDates.value.to, + slice: chartSlice.value }); - - response.execute(); - } +const visitsData = useFetch(`/api/metrics/${activeProject.value?._id}/timeline/visits`, { + method: 'POST', ...signHeaders({ v2: 'true' }), body: getBody(), transform: transformResponse, + lazy: true, immediate: false +}); -async function loadAllData() { - console.log('LOAD ALL DATA') - await Promise.all([ - loadData('visits', visitsData), - loadData('events', eventsData), - loadData('sessions', sessionsData), - loadData('sessions_duration', sessionsDurationData), - ]) -} +const eventsData = useFetch(`/api/metrics/${activeProject.value?._id}/timeline/events`, { + method: 'POST', ...signHeaders({ v2: 'true' }), body: getBody(), transform: transformResponse, + lazy: true, immediate: false +}); + +const sessionsData = useFetch(`/api/metrics/${activeProject.value?._id}/timeline/sessions`, { + method: 'POST', ...signHeaders({ v2: 'true' }), body: getBody(), transform: transformResponse, + lazy: true, immediate: false +}); + +const sessionsDurationData = useFetch(`/api/metrics/${activeProject.value?._id}/timeline/sessions_duration`, { + method: 'POST', ...signHeaders({ v2: 'true' }), body: getBody(), transform: transformResponse, + lazy: true, immediate: false +}); onMounted(async () => { - - await loadAllData(); - watch(snapshot, async () => { - await loadAllData(); - }) - + console.log('MOUNTED') + visitsData.execute(); + eventsData.execute(); + sessionsData.execute(); + sessionsDurationData.execute(); }); -