mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-11 00:08:37 +01:00
fix
This commit is contained in:
@@ -56,14 +56,35 @@ const chartData = ref<ChartData<'funnel'>>({
|
||||
datasets: [
|
||||
{
|
||||
data: [],
|
||||
backgroundColor: ['#5680F8' + '77'],
|
||||
backgroundColor: [
|
||||
'#5680F877',
|
||||
"#6bbbe377",
|
||||
"#a6d5cb77",
|
||||
"#fae0b977",
|
||||
"#f28e8e77",
|
||||
"#e3a7e477",
|
||||
"#c4a8e177",
|
||||
"#8cc1d877",
|
||||
"#f9c2cd77",
|
||||
"#b4e3b277",
|
||||
"#ffdfba77",
|
||||
"#e9c3b577",
|
||||
"#d5b8d677",
|
||||
"#add7f677",
|
||||
"#ffd1dc77",
|
||||
"#ffe7a177",
|
||||
"#a8e6cf77",
|
||||
"#d4a5a577",
|
||||
"#f3d6e477",
|
||||
"#c3aed677"
|
||||
],
|
||||
// borderColor: '#0000CC',
|
||||
// borderWidth: 4,
|
||||
fill: true,
|
||||
tension: 0.45,
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 10,
|
||||
hoverBackgroundColor: '#5680F8',
|
||||
hoverBackgroundColor: '#26262677',
|
||||
// hoverBorderColor: 'white',
|
||||
// hoverBorderWidth: 2,
|
||||
},
|
||||
@@ -89,16 +110,10 @@ onMounted(async () => {
|
||||
|
||||
});
|
||||
|
||||
const eventsCount = await useFetch<{ _id: string, count: number }[]>(`/api/data/query`, {
|
||||
lazy: true, headers: useComputedHeaders({
|
||||
limit: 1000,
|
||||
custom: {
|
||||
'schema': 'events'
|
||||
}
|
||||
})
|
||||
const eventsData = useFetch(`/api/data/events`, {
|
||||
headers: useComputedHeaders(), lazy: true, immediate: false
|
||||
});
|
||||
|
||||
|
||||
const enabledEvents = ref<string[]>([]);
|
||||
|
||||
async function onEventCheck(eventName: string) {
|
||||
@@ -114,7 +129,7 @@ async function onEventCheck(eventName: string) {
|
||||
chartData.value.datasets[0].data = [];
|
||||
|
||||
for (const enabledEvent of enabledEvents.value) {
|
||||
const target = (eventsCount.data.value ?? []).find(e => e._id == enabledEvent);
|
||||
const target = (eventsData.data.value ?? []).find(e => e._id == enabledEvent);
|
||||
chartData.value.datasets[0].data.push(target?.count || 0);
|
||||
}
|
||||
}
|
||||
@@ -123,16 +138,19 @@ async function onEventCheck(eventName: string) {
|
||||
|
||||
|
||||
<template>
|
||||
<CardTitled title="Funnel" sub="Funnel events">
|
||||
<CardTitled title="Funnel"
|
||||
sub="Monitor and analyze the actions your users are performing on your platform to gain insights into their behavior and optimize the user experience">
|
||||
<div class="flex gap-2 justify-between">
|
||||
<div>
|
||||
<div class="min-w-[20rem]">
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="min-w-[20rem] text-lyx-text-darker">
|
||||
Select two or more events
|
||||
</div>
|
||||
<div v-for="event of eventsCount.data.value">
|
||||
<UCheckbox @change="onEventCheck(event._id)" :value="enabledEvents.includes(event._id)"
|
||||
:label="event._id">
|
||||
</UCheckbox>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div v-for="event of eventsData.data.value">
|
||||
<UCheckbox color="secondary" @change="onEventCheck(event._id)"
|
||||
:value="enabledEvents.includes(event._id)" :label="event._id">
|
||||
</UCheckbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grow">
|
||||
|
||||
@@ -20,7 +20,7 @@ watch(selectedMetadataField, () => {
|
||||
});
|
||||
|
||||
async function getMetadataFields() {
|
||||
metadataFields.value = await $fetch<string[]>(`/api/metrics/events_data/metadata_fields?name=${selectedEventName.value}`, {
|
||||
metadataFields.value = await $fetch<string[]>(`/api/data/events_data/metadata_fields?name=${selectedEventName.value}`, {
|
||||
headers: useComputedHeaders().value
|
||||
});
|
||||
selectedMetadataField.value = undefined;
|
||||
@@ -42,7 +42,7 @@ async function getMetadataFieldGrouped() {
|
||||
|
||||
const queryParamsString = Object.keys(queryParams).map((key) => `${key}=${queryParams[key]}`).join('&');
|
||||
|
||||
metadataFieldGrouped.value = await $fetch<string[]>(`/api/metrics/events_data/metadata_field_group?${queryParamsString}`, {
|
||||
metadataFieldGrouped.value = await $fetch<string[]>(`/api/data/events_data/metadata_field_group?${queryParamsString}`, {
|
||||
headers: useComputedHeaders().value
|
||||
});
|
||||
}
|
||||
@@ -74,7 +74,76 @@ const canSearch = computed(() => {
|
||||
|
||||
<CardTitled title="Event metadata analyzer" sub="Filter events metadata fields to analyze them" class="w-full p-4">
|
||||
|
||||
<div class="p-2 flex flex-col">
|
||||
<div class="">
|
||||
|
||||
<LyxUiCard class="h-full w-full flex gap-2">
|
||||
|
||||
<div class="flex-[2]">
|
||||
<div class="flex flex-col gap-2">
|
||||
<USelectMenu :uiMenu="{
|
||||
select: '!bg-lyx-widget-light !shadow-none focus:!ring-lyx-widget-lighter !ring-lyx-widget-lighter',
|
||||
base: '!bg-lyx-widget',
|
||||
option: {
|
||||
base: 'hover:!bg-lyx-widget-lighter cursor-pointer',
|
||||
active: '!bg-lyx-widget-lighter'
|
||||
}
|
||||
}" searchable searchable-placeholder="Search an event..." class="w-full"
|
||||
placeholder="Select an event" :options="eventNames.data.value || []"
|
||||
v-model="selectedEventName">
|
||||
</USelectMenu>
|
||||
|
||||
<USelectMenu :uiMenu="{
|
||||
select: '!bg-lyx-widget-light !shadow-none focus:!ring-lyx-widget-lighter !ring-lyx-widget-lighter',
|
||||
base: '!bg-lyx-widget',
|
||||
option: {
|
||||
base: 'hover:!bg-lyx-widget-lighter cursor-pointer',
|
||||
active: '!bg-lyx-widget-lighter'
|
||||
}
|
||||
}" searchable searchable-placeholder="Search a field..." class="w-full"
|
||||
placeholder="Select a field" :options="metadataFields" v-model="selectedMetadataField">
|
||||
</USelectMenu>
|
||||
</div>
|
||||
|
||||
<div class="text-lyx-text-darker poppins mt-4 flex items-center gap-4">
|
||||
<div class="w-[10rem]">
|
||||
Search results: {{ metadataFieldGroupedFiltered.length }}
|
||||
</div>
|
||||
<div v-if="canSearch" class="h-full flex items-center text-[1.2rem]">
|
||||
|
||||
<div class="bg-lyx-widget-light flex items-center rounded-md pl-4">
|
||||
<div><i class="far fa-search"></i></div>
|
||||
<input class="bg-transparent px-4 py-2 text-[1rem] outline-none" type="text"
|
||||
placeholder="Filter by metadata name" v-model="currentSearchText">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-2 mt-4">
|
||||
|
||||
<div class="bg-lyx-widget-light text-lyx-text-dark px-3 py-2 rounded-md w-fit"
|
||||
v-for="item of metadataFieldGroupedFiltered">
|
||||
<div class="flex gap-2">
|
||||
<div> {{ item._id || 'OLD_EVENTS' }} </div>
|
||||
<div> {{ item.count }} </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- <div class="border-solid border-[#212121] border-l-[1px]"></div> -->
|
||||
|
||||
<!-- <div class="flex-[1]">
|
||||
<div class="poppins font-semibold"> </div>
|
||||
</div> -->
|
||||
|
||||
</LyxUiCard>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- <div class="p-2 flex flex-col">
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<USelectMenu searchable searchable-placeholder="Search an event..." class="w-full"
|
||||
@@ -103,17 +172,11 @@ const canSearch = computed(() => {
|
||||
Search results: {{ metadataFieldGroupedFiltered.length }}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<div v-for="item of metadataFieldGroupedFiltered">
|
||||
<div class="flex gap-2">
|
||||
<div> {{ item._id || 'OLD_EVENTS' }} </div>
|
||||
<div> {{ item.count }} </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</CardTitled>
|
||||
|
||||
|
||||
|
||||
@@ -42,23 +42,30 @@ async function analyzeEvent() {
|
||||
sub="Track your user's journey from external links to in-app events, maintaining a complete view of their path from entry to engagement."
|
||||
class="w-full p-4">
|
||||
|
||||
<div class="p-2 flex flex-col gap-3">
|
||||
<USelectMenu searchable searchable-placeholder="Search an event..." class="w-full"
|
||||
placeholder="Select an event" :options="eventNames.data.value || []" v-model="selectedEventName">
|
||||
</USelectMenu>
|
||||
<div v-if="selectedEventName && !analyzing" class="flex justify-center">
|
||||
<div @click="analyzeEvent()"
|
||||
class="bg-bg w-fit px-8 py-2 poppins rounded-lg hover:bg-bg/80 cursor-pointer">
|
||||
Analyze
|
||||
<div class="flex flex-col gap-4">
|
||||
|
||||
<div class="py-2 flex items-center gap-3">
|
||||
<USelectMenu :uiMenu="{
|
||||
select: '!bg-lyx-widget-light !shadow-none focus:!ring-lyx-widget-lighter !ring-lyx-widget-lighter',
|
||||
base: '!bg-lyx-widget',
|
||||
option: {
|
||||
base: 'hover:!bg-lyx-widget-lighter cursor-pointer',
|
||||
active: '!bg-lyx-widget-lighter'
|
||||
}
|
||||
}" searchable searchable-placeholder="Search an event..." class="w-full" placeholder="Select an event"
|
||||
:options="eventNames.data.value || []" v-model="selectedEventName">
|
||||
</USelectMenu>
|
||||
<div v-if="selectedEventName && !analyzing" class="flex justify-center">
|
||||
<LyxUiButton @click="analyzeEvent()" type="primary" class="w-fit px-8 py-1">
|
||||
Analyze
|
||||
</LyxUiButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="analyzing">
|
||||
Analyzing...
|
||||
</div>
|
||||
<div v-if="analyzing"> Analyzing... </div>
|
||||
|
||||
<div class="flex flex-col gap-2" v-if="userFlowData">
|
||||
<div class="flex gap-4 items-center bg-bg py-1 px-2 rounded-lg"
|
||||
<div class="flex gap-4 items-center bg-bg py-2 px-2 bg-lyx-widget-light rounded-lg"
|
||||
v-for="(count, referrer) in userFlowData">
|
||||
<div class="w-5 h-5 flex items-center justify-center">
|
||||
<img :src="`https://s2.googleusercontent.com/s2/favicons?domain=${referrer}&sz=64`"
|
||||
@@ -69,8 +76,8 @@ async function analyzeEvent() {
|
||||
<div> {{ count.toFixed(2).replace('.', ',') }} % </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</CardTitled>
|
||||
</template>
|
||||
Reference in New Issue
Block a user