change in progress

This commit is contained in:
Emily
2024-10-02 17:05:34 +02:00
parent f516c53b7b
commit 314660d8a3
22 changed files with 503 additions and 438 deletions

View File

@@ -3,15 +3,45 @@
import DateService from '@services/DateService';
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());
const snapshotDays = computed(() => {
return (snapshotTo.value - snapshotFrom.value) / 1000 / 60 / 60 / 24;
const to = new Date(safeSnapshotDates.value.to).getTime();
const from = new Date(safeSnapshotDates.value.from).getTime();
return (to - from) / 1000 / 60 / 60 / 24;
});
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;
});
function transformResponse(input: { _id: string, count: number }[]) {
const data = input.map(e => e.count || 0);
const labels = input.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, chartSlice.value));
const pool = [...input.map(e => e.count || 0)];
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 visitsData = useFetch('/api/timeline/visits', {
headers: useComputedHeaders({ slice: chartSlice.value }), lazy: true, transform: transformResponse
});
const sessionsData = useFetch('/api/timeline/sessions', {
headers: useComputedHeaders({ slice: chartSlice.value }), lazy: true, transform: transformResponse
});
const sessionsDurationData = useFetch('/api/timeline/sessions_duration', {
headers: useComputedHeaders({ slice: chartSlice.value }), lazy: true, transform: transformResponse
});
const bouncingRateData = useFetch('/api/timeline/bouncing_rate', {
headers: useComputedHeaders({ slice: chartSlice.value }), lazy: true, transform: transformResponse
});
const avgVisitDay = computed(() => {
@@ -21,13 +51,6 @@ const avgVisitDay = computed(() => {
return avg.toFixed(2);
});
// const avgEventsDay = computed(() => {
// 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(() => {
if (!sessionsData.data.value) return '0.00';
const counts = sessionsData.data.value.data.reduce((a, e) => e + a, 0);
@@ -47,8 +70,14 @@ const avgBouncingRate = computed(() => {
})
const avgSessionDuration = computed(() => {
if (!metricsInfo.value) return '0.00';
const avg = metricsInfo.value.avgSessionDuration;
if (!sessionsDurationData.data.value) return '0.00 %'
const counts = sessionsDurationData.data.value.data
.filter(e => e > 0)
.reduce((a, e) => e + a, 0);
const avg = counts / Math.max(sessionsDurationData.data.value.data.filter(e => e > 0).length, 1);
let hours = 0;
let minutes = 0;
let seconds = 0;
@@ -59,91 +88,6 @@ const avgSessionDuration = computed(() => {
});
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;
});
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 activeProject = useActiveProject();
function getBody() {
return JSON.stringify({
from: safeSnapshotDates.value.from,
to: safeSnapshotDates.value.to,
slice: chartSlice.value
});
}
const computedHeaders = computed(() => {
return {
...signHeaders().headers,
'x-pid': activeProject.value?._id.toString() || '',
'x-from': safeSnapshotDates.value.from,
'x-to': safeSnapshotDates.value.to,
'x-slice': chartSlice.value
}
})
const visitsData = useFetch(`/api/metrics/${activeProject.value?._id}/timeline/visits`, {
method: 'POST', ...signHeaders({ v2: 'true' }), body: getBody(), transform: transformResponse,
lazy: true, immediate: false
});
// 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
});
const bouncingRateData = useFetch(`/api/data/bouncing_rate`, {
headers: computedHeaders, lazy: true, immediate: false,
transform: (input: { data: string, value: number | null }[]) => {
const data = input.map(e => e.value || 0);
const labels = input.map(e => DateService.getChartLabelFromISO(e.data, navigator.language, chartSlice.value));
const pool = [...input.map(e => e.value || 0)];
pool.pop();
const avg = pool.reduce((a, e) => a + e, 0) / pool.length;
const diffPercent: number = (100 / avg * (input.at(-1)?.value || 0)) - 100;
const trend = Math.max(Math.min(diffPercent, 99), -99);
return { data, labels, trend }
}
})
onMounted(async () => {
visitsData.execute();
bouncingRateData.execute();
sessionsData.execute();
sessionsDurationData.execute()
});
</script>
@@ -157,8 +101,7 @@ onMounted(async () => {
</DashboardCountCard>
<DashboardCountCard :ready="!bouncingRateData.pending.value" icon="far fa-chart-user" text="Bouncing rate"
:value="avgBouncingRate" :trend="bouncingRateData.data.value?.trend"
:slow="true"
:value="avgBouncingRate" :trend="bouncingRateData.data.value?.trend" :slow="true"
:data="bouncingRateData.data.value?.data" :labels="bouncingRateData.data.value?.labels" color="#1e9b86">
</DashboardCountCard>
@@ -170,12 +113,12 @@ onMounted(async () => {
</DashboardCountCard>
<DashboardCountCard :ready="!sessionsDurationData.pending.value" icon="far fa-timer" text="Total avg session time"
:value="avgSessionDuration" :trend="sessionsDurationData.data.value?.trend"
<DashboardCountCard :ready="!sessionsDurationData.pending.value" icon="far fa-timer"
text="Total avg session time" :value="avgSessionDuration" :trend="sessionsDurationData.data.value?.trend"
:data="sessionsDurationData.data.value?.data" :labels="sessionsDurationData.data.value?.labels"
color="#f56523">
</DashboardCountCard>
</div>
</template>
</template>

View File

@@ -1,6 +1,8 @@
<script lang="ts" setup>
const activeProject = useActiveProject();
const { project } = useProject();
const { onlineUsers, stopWatching, startWatching } = useOnlineUsers();
onMounted(() => startWatching());
onUnmounted(() => stopWatching());
@@ -9,8 +11,9 @@ onUnmounted(() => stopWatching());
const { createAlert } = useAlert();
function copyProjectId() {
if (!navigator.clipboard) alert('You can\'t copy in HTTP');
navigator.clipboard.writeText((activeProject.value?._id || 0).toString());
if (!navigator.clipboard) return alert('You can\'t copy in HTTP');
if (!project.value) return alert('Project not loaded');
navigator.clipboard.writeText((project.value._id).toString());
createAlert('Success', 'Project id copied successfully.', 'far fa-circle-check', 5000);
}
@@ -42,7 +45,7 @@ function showAnomalyInfoAlert() {
<div class="flex md:gap-2 items-center md:justify-start flex-col md:flex-row">
<div class="poppins font-medium text-lyx-text-darker text-[1.2rem]">Project:</div>
<div class="text-lyx-text poppins font-medium text-[1.2rem]"> {{ activeProject?.name || 'Loading...' }}
<div class="text-lyx-text poppins font-medium text-[1.2rem]"> {{ project?.name || 'Loading...' }}
</div>
</div>
@@ -50,7 +53,7 @@ function showAnomalyInfoAlert() {
<div class="poppins font-medium text-lyx-text-darker text-[1.2rem]">Project id:</div>
<div class="flex gap-2">
<div class="text-lyx-text poppins font-medium text-[1.2rem]">
{{ activeProject?._id || 'Loading...' }}
{{ project?._id || 'Loading...' }}
</div>
<div class="flex items-center ml-3">
<i @click="copyProjectId()"