mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
implementing snapshots + change ui
This commit is contained in:
@@ -60,10 +60,30 @@ async function deleteSnapshot(close: () => any) {
|
|||||||
});
|
});
|
||||||
await updateSnapshots();
|
await updateSnapshots();
|
||||||
snapshot.value = snapshots.value[1];
|
snapshot.value = snapshots.value[1];
|
||||||
createAlert('Snapshot deleted','Snapshot deleted successfully', 'far fa-circle-check', 5000);
|
createAlert('Snapshot deleted', 'Snapshot deleted successfully', 'far fa-circle-check', 5000);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function generatePDF() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await $fetch<Blob>('/api/project/generate_pdf', {
|
||||||
|
...signHeaders(),
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = URL.createObjectURL(res);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `Report.pdf`;
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
} catch (ex: any) {
|
||||||
|
alert(ex.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -119,15 +139,22 @@ async function deleteSnapshot(close: () => any) {
|
|||||||
<div v-if="snapshot" class="flex flex-col text-[.8rem] mt-2 px-2">
|
<div v-if="snapshot" class="flex flex-col text-[.8rem] mt-2 px-2">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="grow poppins"> From:</div>
|
<div class="grow poppins"> From:</div>
|
||||||
<div class="poppins"> {{ new Date(snapshot.from).toLocaleString('it-IT').split(',')[0].trim() }} </div>
|
<div class="poppins"> {{ new Date(snapshot.from).toLocaleString('it-IT').split(',')[0].trim() }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="grow poppins"> To:</div>
|
<div class="grow poppins"> To:</div>
|
||||||
<div class="poppins"> {{ new Date(snapshot.to).toLocaleString('it-IT').split(',')[0].trim() }}</div>
|
<div class="poppins"> {{ new Date(snapshot.to).toLocaleString('it-IT').split(',')[0].trim() }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4" v-if="snapshot._id.toString().startsWith('default') === false">
|
</div>
|
||||||
|
|
||||||
|
<LyxUiButton @click="generatePDF()" type="primary" class="w-full text-center mt-4">
|
||||||
|
Download report
|
||||||
|
</LyxUiButton>
|
||||||
|
|
||||||
|
<div class="mt-2" v-if="snapshot._id.toString().startsWith('default') === false">
|
||||||
<UPopover placement="bottom">
|
<UPopover placement="bottom">
|
||||||
<LyxUiButton type="danger" class="w-full">
|
<LyxUiButton type="danger" class="w-full text-center">
|
||||||
Delete current snapshot
|
Delete current snapshot
|
||||||
</LyxUiButton>
|
</LyxUiButton>
|
||||||
|
|
||||||
|
|||||||
@@ -50,12 +50,7 @@ function openExternalLink(link: string) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="flex h-full">
|
<LyxUiCard class="w-full h-full p-4 flex flex-col gap-8 relative">
|
||||||
|
|
||||||
<div class="text-text flex flex-col items-start gap-4 w-full relative">
|
|
||||||
|
|
||||||
<div class="w-full h-full p-4 flex flex-col bg-card rounded-xl gap-8 card-shadow">
|
|
||||||
|
|
||||||
<div class="flex justify-between mb-3">
|
<div class="flex justify-between mb-3">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex gap-4 items-center">
|
<div class="flex gap-4 items-center">
|
||||||
@@ -121,8 +116,7 @@ function openExternalLink(link: string) {
|
|||||||
|
|
||||||
<i v-else :class="iconProvider(element._id)?.[1]"></i>
|
<i v-else :class="iconProvider(element._id)?.[1]"></i>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span class="text-ellipsis line-clamp-1 ui-font z-[20] text-[.95rem] text-text/70">
|
||||||
class="text-ellipsis line-clamp-1 ui-font z-[20] text-[.95rem] text-text/70">
|
|
||||||
{{ elementTextTransformer?.(element._id) || element._id }}
|
{{ elementTextTransformer?.(element._id) || element._id }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -132,8 +126,7 @@ function openExternalLink(link: string) {
|
|||||||
<div class="text-text font-semibold text-[.9rem] md:text-[1rem] manrope"> {{
|
<div class="text-text font-semibold text-[.9rem] md:text-[1rem] manrope"> {{
|
||||||
formatNumberK(element.count) }} </div>
|
formatNumberK(element.count) }} </div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="props.data.length == 0"
|
<div v-if="props.data.length == 0" class="flex justify-center text-text-sub font-bold text-[1.1rem]">
|
||||||
class="flex justify-center text-text-sub font-bold text-[1.1rem]">
|
|
||||||
No visits yet
|
No visits yet
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -147,15 +140,9 @@ function openExternalLink(link: string) {
|
|||||||
|
|
||||||
<div v-if="loading"
|
<div v-if="loading"
|
||||||
class="backdrop-blur-[1px] z-[20] left-0 top-0 w-full h-full flex items-center justify-center font-bold rockmann absolute">
|
class="backdrop-blur-[1px] z-[20] left-0 top-0 w-full h-full flex items-center justify-center font-bold rockmann absolute">
|
||||||
<i
|
<i class="fas fa-spinner text-[2rem] text-accent animate-[spin_1s_linear_infinite] duration-500"></i>
|
||||||
class="fas fa-spinner text-[2rem] text-accent animate-[spin_1s_linear_infinite] duration-500"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</LyxUiCard>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function showMore() {
|
|||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2 h-full">
|
||||||
<DashboardBarsCard @showMore="showMore()" @dataReload="refresh" :data="oss || []"
|
<DashboardBarsCard @showMore="showMore()" @dataReload="refresh" :data="oss || []"
|
||||||
desc="The operating systems most commonly used by your website's visitors." :dataIcons="false"
|
desc="The operating systems most commonly used by your website's visitors." :dataIcons="false"
|
||||||
:loading="pending" label="Top OS" sub-label="OSs"></DashboardBarsCard>
|
:loading="pending" label="Top OS" sub-label="OSs"></DashboardBarsCard>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { VisitsWebsiteAggregated } from '~/server/api/metrics/[project_id]/
|
|||||||
|
|
||||||
const { data: websites, pending, refresh } = useWebsitesData();
|
const { data: websites, pending, refresh } = useWebsitesData();
|
||||||
|
|
||||||
const currentViewData = ref<(VisitsWebsiteAggregated[] | null)>(websites.value);
|
const currentViewData = ref<(VisitsWebsiteAggregated[] | undefined)>(websites.value);
|
||||||
|
|
||||||
|
|
||||||
const isPagesView = ref<boolean>(false);
|
const isPagesView = ref<boolean>(false);
|
||||||
@@ -33,7 +33,7 @@ async function showDetails(website: string) {
|
|||||||
|
|
||||||
watch(pending, () => {
|
watch(pending, () => {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
currentViewData.value = pagesData.value;
|
currentViewData.value = pagesData.value as any;
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export function usePagesData(website: string, limit: number = 10) {
|
|||||||
|
|
||||||
|
|
||||||
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<VisitsWebsiteAggregated[]>(`/api/metrics/${activeProject.value?._id}/data/websites`,
|
||||||
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
() => signHeaders(createFromToHeaders({ 'x-query-limit': limit.toString() })).headers,
|
||||||
{ lazy: false, watchProps: [snapshot] }
|
{ lazy: false, watchProps: [snapshot] }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ const remoteSnapshots = useFetch<TProjectSnapshot[]>('/api/project/snapshots', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const activeProject = useActiveProject();
|
const activeProject = useActiveProject();
|
||||||
watch(activeProject, () => {
|
watch(activeProject, async () => {
|
||||||
remoteSnapshots.refresh();
|
await remoteSnapshots.refresh();
|
||||||
|
snapshot.value = snapshots.value[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
const snapshots = computed(() => {
|
const snapshots = computed(() => {
|
||||||
@@ -57,19 +58,14 @@ const snapshots = computed(() => {
|
|||||||
|
|
||||||
const snapshot = ref<TProjectSnapshot>(snapshots.value[1]);
|
const snapshot = ref<TProjectSnapshot>(snapshots.value[1]);
|
||||||
|
|
||||||
// watch(remoteSnapshots.data, () => {
|
|
||||||
// if (!remoteSnapshots.data.value) return;
|
|
||||||
// snapshot.value = remoteSnapshots.data.value[0];
|
|
||||||
// });
|
|
||||||
|
|
||||||
const safeSnapshotDates = computed(() => {
|
const safeSnapshotDates = computed(() => {
|
||||||
const from = new Date(snapshot.value?.from || 0).toISOString();
|
const from = new Date(snapshot.value?.from || 0).toISOString();
|
||||||
const to = new Date(snapshot.value?.to || Date.now()).toISOString();
|
const to = new Date(snapshot.value?.to || Date.now()).toISOString();
|
||||||
return { from, to }
|
return { from, to }
|
||||||
})
|
})
|
||||||
|
|
||||||
function updateSnapshots() {
|
async function updateSnapshots() {
|
||||||
remoteSnapshots.refresh();
|
await remoteSnapshots.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSnapshot() {
|
export function useSnapshot() {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const sections: Section[] = [
|
|||||||
{ label: 'Dashboard', to: '/', icon: 'far fa-home' },
|
{ label: 'Dashboard', to: '/', icon: 'far fa-home' },
|
||||||
{ label: 'Events', to: '/events', icon: 'far fa-bolt' },
|
{ label: 'Events', to: '/events', icon: 'far fa-bolt' },
|
||||||
{ label: 'Analyst', to: '/analyst', icon: 'far fa-microchip-ai' },
|
{ label: 'Analyst', to: '/analyst', icon: 'far fa-microchip-ai' },
|
||||||
{ label: 'Report', to: '/report', icon: 'far fa-notes' },
|
// { label: 'Report', to: '/report', icon: 'far fa-notes' },
|
||||||
// { label: 'AI', to: '/dashboard/settings', icon: 'far fa-robot brightness-[.4]' },
|
// { label: 'AI', to: '/dashboard/settings', icon: 'far fa-robot brightness-[.4]' },
|
||||||
// { label: 'Visits', to: '/dashboard/visits', icon: 'far fa-eye' },
|
// { label: 'Visits', to: '/dashboard/visits', icon: 'far fa-eye' },
|
||||||
// { label: 'Events', to: '/dashboard/events', icon: 'far fa-line-chart' },
|
// { label: 'Events', to: '/dashboard/events', icon: 'far fa-line-chart' },
|
||||||
|
|||||||
@@ -136,7 +136,6 @@ function testAlert() {
|
|||||||
</div>
|
</div>
|
||||||
</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