mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-09 23:48:36 +01:00
implementing snapshots
This commit is contained in:
@@ -80,6 +80,9 @@ const { lineChartProps, lineChartRef } = useLineChart({ chartData: chartData, op
|
|||||||
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
||||||
|
console.log('MOUNTED')
|
||||||
|
|
||||||
const c = document.createElement('canvas');
|
const c = document.createElement('canvas');
|
||||||
const ctx = c.getContext("2d");
|
const ctx = c.getContext("2d");
|
||||||
let gradient: any = `${props.color}22`;
|
let gradient: any = `${props.color}22`;
|
||||||
@@ -106,5 +109,5 @@ onMounted(async () => {
|
|||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LineChart ref="lineChartRef" v-bind="lineChartProps"> </LineChart>
|
<LineChart ref="lineChartRef" v-bind="lineChartProps"> </LineChart>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,46 +1,43 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
import DateService, { type Slice } from '@services/DateService';
|
import DateService, { type Slice } from '@services/DateService';
|
||||||
|
|
||||||
const data = ref<number[]>([]);
|
const data = ref<number[]>([]);
|
||||||
const labels = ref<string[]>([]);
|
const labels = ref<string[]>([]);
|
||||||
const ready = ref<boolean>(false);
|
|
||||||
|
|
||||||
const props = defineProps<{ slice: Slice }>();
|
const props = defineProps<{ slice: Slice }>();
|
||||||
|
|
||||||
const { snapshot } = useSnapshot();
|
const slice = computed(() => props.slice);
|
||||||
|
|
||||||
const snapshotFrom = computed(() => {
|
const res = useTimeline('sessions', slice);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadData();
|
|
||||||
watch(props, async () => { await loadData(); });
|
res.onResponse(resData => {
|
||||||
watch(snapshot, async () => { await loadData(); });
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
import DateService from '@services/DateService';
|
import DateService from '@services/DateService';
|
||||||
|
import type { Slice } from '@services/DateService';
|
||||||
|
|
||||||
const { data: metricsInfo } = useMetricsData();
|
const { data: metricsInfo } = useMetricsData();
|
||||||
|
|
||||||
@@ -75,31 +76,41 @@ const avgSessionDuration = computed(() => {
|
|||||||
return `${hours > 0 ? hours + 'h ' : ''}${minutes}m ${seconds.toFixed()}s`
|
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) {
|
async function loadData(timelineEndpointName: string, target: Data) {
|
||||||
|
|
||||||
target.ready = false;
|
target.ready = false;
|
||||||
|
|
||||||
const response = await useTimeline(timelineEndpointName as any, 'day',
|
const response = useTimeline(timelineEndpointName as any, chartSlice);
|
||||||
snapshot.value?.from.toString() || "0",
|
|
||||||
snapshot.value?.to.toString() || Date.now().toString()
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(timelineEndpointName,response);
|
response.onResponse(data => {
|
||||||
|
|
||||||
if (!response) return;
|
if (!data.value) return;
|
||||||
|
|
||||||
target.data = response.map(e => e.count);
|
target.data = data.value.map(e => e.count);
|
||||||
target.labels = response.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, 'day'));
|
target.labels = data.value.map(e => DateService.getChartLabelFromISO(e._id, navigator.language, chartSlice.value));
|
||||||
|
|
||||||
const pool = [...response.map(e => e.count)];
|
const pool = [...data.value.map(e => e.count)];
|
||||||
pool.pop();
|
pool.pop();
|
||||||
const avg = pool.reduce((a, e) => a + e, 0) / pool.length;
|
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 () => {
|
onMounted(async () => {
|
||||||
|
|
||||||
await loadAllData();
|
await loadAllData();
|
||||||
@@ -137,13 +149,15 @@ onMounted(async () => {
|
|||||||
</DashboardCountCard>
|
</DashboardCountCard>
|
||||||
|
|
||||||
<DashboardCountCard :ready="eventsData.ready" icon="far fa-flag" text="Total custom events"
|
<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'"
|
:value="formatNumberK(eventsData.data.reduce((a, e) => a + e, 0))"
|
||||||
:trend="eventsData.trend" :data="eventsData.data" :labels="eventsData.labels" color="#1e9b86">
|
:avg="formatNumberK(avgEventsDay) + '/day'" :trend="eventsData.trend" :data="eventsData.data"
|
||||||
|
:labels="eventsData.labels" color="#1e9b86">
|
||||||
</DashboardCountCard>
|
</DashboardCountCard>
|
||||||
|
|
||||||
<DashboardCountCard :ready="sessionsData.ready" icon="far fa-user" text="Unique visits sessions"
|
<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'"
|
:value="formatNumberK(sessionsData.data.reduce((a, e) => a + e, 0))"
|
||||||
:trend="sessionsData.trend" :data="sessionsData.data" :labels="sessionsData.labels" color="#4abde8">
|
:avg="formatNumberK(avgSessionsDay) + '/day'" :trend="sessionsData.trend" :data="sessionsData.data"
|
||||||
|
:labels="sessionsData.labels" color="#4abde8">
|
||||||
</DashboardCountCard>
|
</DashboardCountCard>
|
||||||
|
|
||||||
<DashboardCountCard :ready="sessionsDurationData.ready" icon="far fa-timer" text="Avg session time"
|
<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 data = ref<number[]>([]);
|
||||||
const labels = ref<string[]>([]);
|
const labels = ref<string[]>([]);
|
||||||
const ready = ref<boolean>(false);
|
|
||||||
|
|
||||||
const props = defineProps<{ slice: Slice }>();
|
const props = defineProps<{ slice: Slice }>();
|
||||||
|
|
||||||
const { snapshot } = useSnapshot();
|
const slice = computed(() => props.slice);
|
||||||
|
|
||||||
const snapshotFrom = computed(() => {
|
const res = useTimeline('visits', slice);
|
||||||
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('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 () => {
|
onMounted(async () => {
|
||||||
await loadData();
|
|
||||||
watch(props, async () => { await loadData(); });
|
res.onResponse(resData => {
|
||||||
watch(snapshot, async () => { await loadData(); });
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -6,7 +6,9 @@ type NitroFetchRequest = Exclude<keyof InternalApi, `/_${string}` | `/api/_${str
|
|||||||
|
|
||||||
export type CustomFetchOptions = {
|
export type CustomFetchOptions = {
|
||||||
watchProps?: WatchSource[],
|
watchProps?: WatchSource[],
|
||||||
lazy?: boolean
|
lazy?: boolean,
|
||||||
|
method?: string,
|
||||||
|
getBody?: () => Record<string, any>
|
||||||
}
|
}
|
||||||
|
|
||||||
type OnResponseCallback<TData> = (data: Ref<TData | undefined>) => any
|
type OnResponseCallback<TData> = (data: Ref<TData | undefined>) => any
|
||||||
@@ -27,7 +29,13 @@ export function useCustomFetch<T>(url: NitroFetchRequest, getHeaders: () => Reco
|
|||||||
pending.value = true;
|
pending.value = true;
|
||||||
error.value = undefined;
|
error.value = undefined;
|
||||||
try {
|
try {
|
||||||
data.value = await $fetch<T>(url, { headers: getHeaders() });
|
|
||||||
|
data.value = await $fetch<T>(url, {
|
||||||
|
headers: getHeaders(),
|
||||||
|
method: (options?.method || 'GET') as any,
|
||||||
|
body: options?.getBody ? JSON.stringify(options.getBody()) : undefined
|
||||||
|
});
|
||||||
|
|
||||||
onResponseCallback(data);
|
onResponseCallback(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error.value = err as Error;
|
error.value = err as Error;
|
||||||
|
|||||||
@@ -19,6 +19,26 @@ export function useMetricsData() {
|
|||||||
return metricsInfo;
|
return metricsInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const { safeSnapshotDates, snapshot } = useSnapshot()
|
||||||
|
const activeProject = useActiveProject();
|
||||||
|
|
||||||
|
const createFromToHeaders = (headers: Record<string, string> = {}) => ({
|
||||||
|
'x-from': safeSnapshotDates.value.from,
|
||||||
|
'x-to': safeSnapshotDates.value.to,
|
||||||
|
...headers
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFromToBody = (body: Record<string, any> = {}) => ({
|
||||||
|
from: safeSnapshotDates.value.from,
|
||||||
|
to: safeSnapshotDates.value.to,
|
||||||
|
...body
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function useFirstInteractionData() {
|
export function useFirstInteractionData() {
|
||||||
const activeProject = useActiveProject();
|
const activeProject = useActiveProject();
|
||||||
const metricsInfo = useFetch<boolean>(`/api/metrics/${activeProject.value?._id}/first_interaction`, signHeaders());
|
const metricsInfo = useFetch<boolean>(`/api/metrics/${activeProject.value?._id}/first_interaction`, signHeaders());
|
||||||
@@ -26,33 +46,25 @@ export function useFirstInteractionData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function useTimelineAdvanced(endpoint: string, slice: Slice, fromDate?: string, toDate?: string, customBody: Object = {}) {
|
export function useTimelineAdvanced(endpoint: string, slice: Ref<Slice>, customBody: Object = {}) {
|
||||||
|
const response = useCustomFetch<{ _id: string, count: number }[]>(
|
||||||
const { from, to } = DateService.prepareDateRange(
|
`/api/metrics/${activeProject.value?._id}/timeline/${endpoint}`,
|
||||||
fromDate || DateService.getDefaultRange(slice).from,
|
() => signHeaders({ 'Content-Type': 'application/json' }).headers, {
|
||||||
toDate || DateService.getDefaultRange(slice).to,
|
|
||||||
slice
|
|
||||||
);
|
|
||||||
|
|
||||||
const activeProject = useActiveProject();
|
|
||||||
const response = await $fetch(
|
|
||||||
`/api/metrics/${activeProject.value?._id}/timeline/${endpoint}`, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
...signHeaders({ 'Content-Type': 'application/json' }),
|
getBody: () => createFromToBody({ slice: slice.value, ...customBody }),
|
||||||
body: JSON.stringify({ slice, from, to, ...customBody })
|
lazy: true,
|
||||||
|
watchProps: [snapshot, slice]
|
||||||
});
|
});
|
||||||
|
return response;
|
||||||
return response as { _id: string, count: number }[];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function useTimeline(endpoint: 'visits' | 'sessions' | 'referrers', slice: Slice, fromDate?: string, toDate?: string) {
|
export function useTimeline(endpoint: 'visits' | 'sessions' | 'referrers', slice: Ref<Slice>) {
|
||||||
return await useTimelineAdvanced(endpoint, slice, fromDate, toDate, {});
|
return useTimelineAdvanced(endpoint, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function useReferrersTimeline(referrer: string, slice: Slice, fromDate?: string, toDate?: string) {
|
export async function useReferrersTimeline(referrer: string, slice: Ref<Slice>) {
|
||||||
return await useTimelineAdvanced('referrers', slice, fromDate, toDate, { referrer });
|
return await useTimelineAdvanced('referrers', slice, { referrer });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -93,21 +105,12 @@ export function usePagesData(website: string, limit: number = 10) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { safeSnapshotDates, snapshot } = useSnapshot()
|
|
||||||
const activeProject = useActiveProject();
|
|
||||||
|
|
||||||
const getFromToHeaders = (headers: Record<string, string> = {}) => ({
|
|
||||||
'x-from': safeSnapshotDates.value.from,
|
|
||||||
'x-to': safeSnapshotDates.value.to,
|
|
||||||
...headers
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function useWebsitesData(limit: number = 10) {
|
export function useWebsitesData(limit: number = 10) {
|
||||||
const res = useCustomFetch<ReferrersAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/websites`,
|
const res = useCustomFetch<ReferrersAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/websites`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
@@ -115,7 +118,7 @@ export function useWebsitesData(limit: number = 10) {
|
|||||||
|
|
||||||
export function useEventsData(limit: number = 10) {
|
export function useEventsData(limit: number = 10) {
|
||||||
const res = useCustomFetch<CustomEventsAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/events`,
|
const res = useCustomFetch<CustomEventsAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/events`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
@@ -123,7 +126,7 @@ export function useEventsData(limit: number = 10) {
|
|||||||
|
|
||||||
export function useReferrersData(limit: number = 10) {
|
export function useReferrersData(limit: number = 10) {
|
||||||
const res = useCustomFetch<ReferrersAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/referrers`,
|
const res = useCustomFetch<ReferrersAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/referrers`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
@@ -131,7 +134,7 @@ export function useReferrersData(limit: number = 10) {
|
|||||||
|
|
||||||
export function useBrowsersData(limit: number = 10) {
|
export function useBrowsersData(limit: number = 10) {
|
||||||
const res = useCustomFetch<BrowsersAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/browsers`,
|
const res = useCustomFetch<BrowsersAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/browsers`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
@@ -139,7 +142,7 @@ export function useBrowsersData(limit: number = 10) {
|
|||||||
|
|
||||||
export function useOssData(limit: number = 10) {
|
export function useOssData(limit: number = 10) {
|
||||||
const res = useCustomFetch<OssAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/oss`,
|
const res = useCustomFetch<OssAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/oss`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
@@ -147,7 +150,7 @@ export function useOssData(limit: number = 10) {
|
|||||||
|
|
||||||
export function useGeolocationData(limit: number = 10) {
|
export function useGeolocationData(limit: number = 10) {
|
||||||
const res = useCustomFetch<CountriesAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/countries`,
|
const res = useCustomFetch<CountriesAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/countries`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
@@ -155,7 +158,7 @@ export function useGeolocationData(limit: number = 10) {
|
|||||||
|
|
||||||
export function useDevicesData(limit: number = 10) {
|
export function useDevicesData(limit: number = 10) {
|
||||||
const res = useCustomFetch<DevicesAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/devices`,
|
const res = useCustomFetch<DevicesAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/devices`,
|
||||||
() => signHeaders(getFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ const selectLabels = [
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex w-full justify-center mt-6 px-6">
|
<div class="flex w-full justify-center mt-6 px-6">
|
||||||
<div class="flex w-full gap-6 flex-col xl:flex-row">
|
<div class="flex w-full gap-6 flex-col xl:flex-row">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
|
|||||||
Reference in New Issue
Block a user