mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 15:58:38 +01:00
rewrite litlyx
This commit is contained in:
11
TODO
11
TODO
@@ -1,7 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
- Slice change on Actionable Chart
|
|
||||||
- Show more on Dashboard cards
|
|
||||||
- Fix devices Dashboard card, replace empty with "unkwnwn"
|
- Fix devices Dashboard card, replace empty with "unkwnwn"
|
||||||
- Component first interaction must make the request inside
|
- Component first interaction must make the request inside
|
||||||
- Reactivity on project delete (update dropdown)
|
- Reactivity on project delete (update dropdown)
|
||||||
|
- Fix CSV Endpoint
|
||||||
|
- Devices remove empty
|
||||||
|
- docs vertical navigation not wfull
|
||||||
|
- project creation
|
||||||
|
- Event funnel / metadata analyzer / user flow
|
||||||
|
- Test guest actions
|
||||||
|
- Refactor UI Data analyst
|
||||||
|
- Remove Top Events from web analytics and move to custom events (with raw data access)
|
||||||
|
- Fix email on plan upgrade and resub
|
||||||
@@ -1,19 +1,24 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const browsersData = useFetch('/api/data/browsers', {
|
const browsersData = useFetch('/api/data/browsers', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({ limit: 10, }), lazy: true
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
|
||||||
}), lazy: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
||||||
|
|
||||||
function showMore() {
|
async function showMore() {
|
||||||
isShowMore.value = true;
|
dialogBarData.value=[];
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
dialogBarData.value = browsersData.data.value || [];
|
isDataLoading.value = true;
|
||||||
|
|
||||||
|
const res = await $fetch('/api/data/browsers', {
|
||||||
|
headers: useComputedHeaders({ limit: 1000 }).value
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogBarData.value = res || [];
|
||||||
|
|
||||||
|
isDataLoading.value = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,9 +27,9 @@ function showMore() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<BarCardBase @showMore="showMore()" @dataReload="browsersData.refresh()"
|
<BarCardBase @showMore="showMore()" @dataReload="browsersData.refresh()" :data="browsersData.data.value || []"
|
||||||
:data="browsersData.data.value || []" desc="The browsers most used to search your website."
|
desc="The browsers most used to search your website." :dataIcons="false"
|
||||||
:dataIcons="false" :loading="browsersData.pending.value" label="Top Browsers" sub-label="Browsers">
|
:loading="browsersData.pending.value" label="Top Browsers" sub-label="Browsers">
|
||||||
</BarCardBase>
|
</BarCardBase>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const devicesData = useFetch('/api/data/devices', {
|
const devicesData = useFetch('/api/data/devices', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({ limit: 10, }), lazy: true
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
|
||||||
}), lazy: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
||||||
|
|
||||||
|
async function showMore() {
|
||||||
function showMore() {
|
dialogBarData.value=[];
|
||||||
isShowMore.value = true;
|
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
dialogBarData.value = devicesData.data.value || [];
|
isDataLoading.value = true;
|
||||||
|
|
||||||
|
const res = await $fetch('/api/data/devices', {
|
||||||
|
headers: useComputedHeaders({ limit: 1000 }).value
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogBarData.value = res || [];
|
||||||
|
|
||||||
|
isDataLoading.value = false;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,27 @@ function goToView() {
|
|||||||
router.push('/dashboard/events');
|
router.push('/dashboard/events');
|
||||||
}
|
}
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const eventsData = useFetch('/api/data/events', {
|
const eventsData = useFetch('/api/data/events', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
limit: 10,
|
||||||
}), lazy: true
|
}), lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
||||||
|
|
||||||
function showMore() {
|
async function showMore() {
|
||||||
isShowMore.value = true;
|
dialogBarData.value=[];
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
dialogBarData.value = eventsData.data.value || [];
|
isDataLoading.value = true;
|
||||||
|
|
||||||
|
const res = await $fetch('/api/data/events', {
|
||||||
|
headers: useComputedHeaders({ limit: 1000 }).value
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogBarData.value = res || [];
|
||||||
|
|
||||||
|
isDataLoading.value = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -12,25 +12,26 @@ function iconProvider(id: string): ReturnType<IconProvider> {
|
|||||||
|
|
||||||
const customIconStyle = `width: 2rem; padding: 1px;`
|
const customIconStyle = `width: 2rem; padding: 1px;`
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const geolocationData = useFetch('/api/data/countries', {
|
const geolocationData = useFetch('/api/data/countries', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({ limit: 10, }), lazy: true
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
|
||||||
}), lazy: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
||||||
|
|
||||||
function showMore() {
|
async function showMore() {
|
||||||
|
dialogBarData.value=[];
|
||||||
isShowMore.value = true;
|
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
|
isDataLoading.value = true;
|
||||||
|
|
||||||
dialogBarData.value = geolocationData.data.value?.map(e => {
|
const res = await $fetch('/api/data/countries', {
|
||||||
|
headers: useComputedHeaders({limit: 1000}).value
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogBarData.value = res?.map(e => {
|
||||||
return { ...e, icon: iconProvider(e._id) }
|
return { ...e, icon: iconProvider(e._id) }
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
isDataLoading.value = false;
|
isDataLoading.value = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -40,9 +41,10 @@ function showMore() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<BarCardBase @showMore="showMore()" @dataReload="geolocationData.refresh()" :data="geolocationData.data.value || []" :dataIcons="false"
|
<BarCardBase @showMore="showMore()" @dataReload="geolocationData.refresh()"
|
||||||
:loading="geolocationData.pending.value" label="Top Countries" sub-label="Countries" :iconProvider="iconProvider"
|
:data="geolocationData.data.value || []" :dataIcons="false" :loading="geolocationData.pending.value"
|
||||||
:customIconStyle="customIconStyle" desc=" Lists the countries where users access your website.">
|
label="Top Countries" sub-label="Countries" :iconProvider="iconProvider" :customIconStyle="customIconStyle"
|
||||||
|
desc=" Lists the countries where users access your website.">
|
||||||
</BarCardBase>
|
</BarCardBase>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const ossData = useFetch('/api/data/oss', {
|
const ossData = useFetch('/api/data/oss', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
limit: 10,
|
||||||
}), lazy: true
|
}), lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
||||||
|
|
||||||
|
|
||||||
function showMore() {
|
async function showMore() {
|
||||||
isShowMore.value = true;
|
dialogBarData.value=[];
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
dialogBarData.value = ossData.data.value || [];
|
isDataLoading.value = true;
|
||||||
|
|
||||||
|
const res = await $fetch('/api/data/oss', {
|
||||||
|
headers: useComputedHeaders({ limit: 1000 }).value
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogBarData.value = res || [];
|
||||||
|
|
||||||
|
isDataLoading.value = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,31 @@ function elementTextTransformer(element: string) {
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const referrersData = useFetch('/api/data/referrers', {
|
const referrersData = useFetch('/api/data/referrers', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
limit: 10,
|
||||||
}), lazy: true
|
}), lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
const { showDialog, dialogBarData, isDataLoading } = useBarCardDialog();
|
||||||
|
|
||||||
function showMore() {
|
async function showMore() {
|
||||||
isShowMore.value = true;
|
|
||||||
|
dialogBarData.value=[];
|
||||||
|
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
dialogBarData.value = referrersData.data.value?.map(e => {
|
isDataLoading.value = true;
|
||||||
|
|
||||||
|
const res = await $fetch('/api/data/referrers', {
|
||||||
|
headers: useComputedHeaders({limit: 1000}).value
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
dialogBarData.value = res?.map(e => {
|
||||||
return { ...e, icon: iconProvider(e._id) }
|
return { ...e, icon: iconProvider(e._id) }
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
|
isDataLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
const isShowMore = ref<boolean>(false);
|
|
||||||
|
|
||||||
const currentWebsite = ref<string>("");
|
const currentWebsite = ref<string>("");
|
||||||
|
|
||||||
const websitesData = useFetch('/api/data/websites', {
|
const websitesData = useFetch('/api/data/websites', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
limit: 10,
|
||||||
}), lazy: true
|
}), lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const pagesData = useFetch('/api/data/websites_pages', {
|
const pagesData = useFetch('/api/data/websites_pages', {
|
||||||
headers: useComputedHeaders({
|
headers: useComputedHeaders({
|
||||||
limit: computed(() => isShowMore.value ? '200' : '10'),
|
limit: 10,
|
||||||
custom: {
|
custom: {
|
||||||
'x-website-name': currentWebsite
|
'x-website-name': currentWebsite
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ const pricingDrawer = usePricingDrawer();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="CVerticalNavigation h-full w-[20rem] bg-lyx-background flex shadow-[1px_0_10px_#000000] rounded-r-lg"
|
<div class="CVerticalNavigation border-solid border-[#202020] border-r-[1px] h-full w-[20rem] bg-lyx-background flex shadow-[1px_0_10px_#000000] rounded-r-lg"
|
||||||
:class="{
|
:class="{
|
||||||
'absolute top-0 w-full md:w-[20rem] z-[45] open': isOpen,
|
'absolute top-0 w-full md:w-[20rem] z-[45] open': isOpen,
|
||||||
'hidden lg:flex': !isOpen
|
'hidden lg:flex': !isOpen
|
||||||
@@ -141,11 +141,13 @@ const pricingDrawer = usePricingDrawer();
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<NuxtLink to="/project_creation" v-if="projectList && (projectList.length < (maxProjects || 1))"
|
<LyxUiButton to="/project_creation" v-if="projectList && (projectList.length < (maxProjects || 1))"
|
||||||
class="flex items-center text-[.8rem] gap-1 justify-end pt-2 pr-2 text-lyx-text-dark hover:text-lyx-text cursor-pointer">
|
type="outlined" class="w-full py-1 mt-2 text-[.8rem]">
|
||||||
|
<div class="flex items-center gap-2 justify-center">
|
||||||
<div><i class="fas fa-plus"></i></div>
|
<div><i class="fas fa-plus"></i></div>
|
||||||
<div> Create new project </div>
|
<div> Create new project </div>
|
||||||
</NuxtLink>
|
</div>
|
||||||
|
</LyxUiButton>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -156,13 +158,23 @@ const pricingDrawer = usePricingDrawer();
|
|||||||
<div class="poppins text-[.8rem]">
|
<div class="poppins text-[.8rem]">
|
||||||
Snapshots
|
Snapshots
|
||||||
</div>
|
</div>
|
||||||
<div @click="openSnapshotDialog()"
|
|
||||||
class="poppins text-[.8rem] px-2 rounded-lg outline outline-[2px] outline-lyx-widget-lighter cursor-pointer hover:bg-lyx-widget-lighter">
|
<div class="flex gap-2">
|
||||||
<i class="far fa-plus"></i>
|
<UTooltip text="Download report">
|
||||||
Add
|
<LyxUiButton @click="generatePDF()" type="outlined" class="!px-3 !py-1">
|
||||||
</div>
|
<div><i class="far fa-download text-[.8rem]"></i></div>
|
||||||
|
</LyxUiButton>
|
||||||
|
</UTooltip>
|
||||||
|
<UTooltip text="Create new snapshot">
|
||||||
|
<LyxUiButton @click="openSnapshotDialog()" type="outlined" class="!px-3 !py-1">
|
||||||
|
<div><i class="fas fa-plus text-[.9rem]"></i></div>
|
||||||
|
</LyxUiButton>
|
||||||
|
</UTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
<USelectMenu :uiMenu="{
|
<USelectMenu :uiMenu="{
|
||||||
select: '!bg-lyx-widget-light !shadow-none focus:!ring-lyx-widget-lighter !ring-lyx-widget-lighter',
|
select: '!bg-lyx-widget-light !shadow-none focus:!ring-lyx-widget-lighter !ring-lyx-widget-lighter',
|
||||||
base: '!bg-lyx-widget',
|
base: '!bg-lyx-widget',
|
||||||
@@ -186,22 +198,19 @@ const pricingDrawer = usePricingDrawer();
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
|
|
||||||
<div v-if="snapshot" class="flex flex-col text-[.8rem] mt-2">
|
|
||||||
<div class="flex">
|
|
||||||
<div class="grow poppins"> From:</div>
|
|
||||||
<div class="poppins"> {{ new Date(snapshot.from).toLocaleString('it-IT').split(',')[0].trim() }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex">
|
|
||||||
<div class="grow poppins"> To:</div>
|
|
||||||
<div class="poppins"> {{ new Date(snapshot.to).toLocaleString('it-IT').split(',')[0].trim() }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LyxUiButton @click="generatePDF()" type="secondary" class="w-full text-center mt-4">
|
<div v-if="snapshot" class="flex flex-col text-[.7rem] mt-2">
|
||||||
Download report
|
<div class="flex gap-1 items-center justify-center text-lyx-text-dark">
|
||||||
</LyxUiButton>
|
<div class="poppins">
|
||||||
|
{{ new Date(snapshot.from).toLocaleString('it-IT').split(',')[0].trim().replace(/\//g, '-')
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div class="poppins"> to </div>
|
||||||
|
<div class="poppins">
|
||||||
|
{{ new Date(snapshot.to).toLocaleString('it-IT').split(',')[0].trim().replace(/\//g, '-') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-2" v-if="snapshot._id.toString().startsWith('default') === false">
|
<div class="mt-2" v-if="snapshot._id.toString().startsWith('default') === false">
|
||||||
<UPopover placement="bottom">
|
<UPopover placement="bottom">
|
||||||
@@ -226,7 +235,7 @@ const pricingDrawer = usePricingDrawer();
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-lyx-widget-lighter h-[2px] w-full"></div>
|
<div class="bg-[#202020] h-[1px] w-full"></div>
|
||||||
|
|
||||||
<div class="flex flex-col h-full">
|
<div class="flex flex-col h-full">
|
||||||
|
|
||||||
@@ -262,26 +271,28 @@ const pricingDrawer = usePricingDrawer();
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grow"></div>
|
<div class="grow"></div>
|
||||||
<div class="bg-lyx-widget-lighter h-[2px] px-4 w-full mb-3"></div>
|
|
||||||
|
<div class="bg-[#202020] h-[1px] w-full px-4 mb-3"></div>
|
||||||
|
|
||||||
<div class="flex justify-end px-2">
|
<div class="flex justify-end px-2">
|
||||||
|
|
||||||
<div class="grow flex gap-3">
|
<div class="grow flex gap-3">
|
||||||
<NuxtLink to="https://github.com/litlyx/litlyx" target="_blank"
|
<!-- <NuxtLink to="https://github.com/litlyx/litlyx" target="_blank"
|
||||||
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
||||||
<i class="fab fa-github"></i>
|
<i class="fab fa-github"></i>
|
||||||
</NuxtLink>
|
</NuxtLink> -->
|
||||||
<NuxtLink to="https://discord.gg/9cQykjsmWX" target="_blank"
|
<!-- <NuxtLink to="https://discord.gg/9cQykjsmWX" target="_blank"
|
||||||
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
||||||
<i class="fab fa-discord"></i>
|
<i class="fab fa-discord"></i>
|
||||||
</NuxtLink>
|
</NuxtLink> -->
|
||||||
<NuxtLink to="https://x.com/litlyx" target="_blank"
|
<NuxtLink to="https://x.com/litlyx" target="_blank"
|
||||||
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
||||||
<i class="fab fa-x-twitter"></i>
|
<i class="fab fa-x-twitter"></i>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink to="https://dev.to/litlyx-org" target="_blank"
|
<!-- <NuxtLink to="https://dev.to/litlyx-org" target="_blank"
|
||||||
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
||||||
<i class="fab fa-dev"></i>
|
<i class="fab fa-dev"></i>
|
||||||
</NuxtLink>
|
</NuxtLink> -->
|
||||||
<NuxtLink to="/admin" v-if="userRoles.isAdmin"
|
<NuxtLink to="/admin" v-if="userRoles.isAdmin"
|
||||||
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
class="cursor-pointer hover:text-lyx-text text-lyx-text-dark">
|
||||||
<i class="fas fa-cat"></i>
|
<i class="fas fa-cat"></i>
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ const selectLabels: { label: string, value: Slice }[] = [
|
|||||||
{ label: 'Month', value: 'month' },
|
{ label: 'Month', value: 'month' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const selectedSlice = computed(()=>selectLabels[selectedLabelIndex.value].value);
|
||||||
|
|
||||||
const selectedLabelIndex = ref<number>(1);
|
const selectedLabelIndex = ref<number>(1);
|
||||||
const allDatesFull = ref<string[]>([]);
|
const allDatesFull = ref<string[]>([]);
|
||||||
|
|
||||||
@@ -157,17 +159,17 @@ function onResponse(e: any) {
|
|||||||
|
|
||||||
|
|
||||||
const visitsData = useFetch('/api/timeline/visits', {
|
const visitsData = useFetch('/api/timeline/visits', {
|
||||||
headers: useComputedHeaders({ slice: selectLabels[selectedLabelIndex.value].value }), lazy: true,
|
headers: useComputedHeaders({ slice: selectedSlice }), lazy: true,
|
||||||
transform: transformResponse, onResponseError, onResponse
|
transform: transformResponse, onResponseError, onResponse
|
||||||
});
|
});
|
||||||
|
|
||||||
const sessionsData = useFetch('/api/timeline/sessions', {
|
const sessionsData = useFetch('/api/timeline/sessions', {
|
||||||
headers: useComputedHeaders({ slice: selectLabels[selectedLabelIndex.value].value }), lazy: true,
|
headers: useComputedHeaders({ slice: selectedSlice }), lazy: true,
|
||||||
transform: transformResponse, onResponseError, onResponse
|
transform: transformResponse, onResponseError, onResponse
|
||||||
});
|
});
|
||||||
|
|
||||||
const eventsData = useFetch('/api/timeline/events', {
|
const eventsData = useFetch('/api/timeline/events', {
|
||||||
headers: useComputedHeaders({ slice: selectLabels[selectedLabelIndex.value].value }), lazy: true,
|
headers: useComputedHeaders({ slice: selectedSlice }), lazy: true,
|
||||||
transform: transformResponse, onResponseError, onResponse
|
transform: transformResponse, onResponseError, onResponse
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -98,19 +98,8 @@ function transformResponse(input: CustomEventsAggregated[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = computed(() => {
|
const eventsData = useFetch(`/api/data/events`, {
|
||||||
return {
|
method: 'POST', headers: useComputedHeaders({ limit: 6 }), lazy: true, immediate: false, transform: transformResponse
|
||||||
'x-from': safeSnapshotDates.value.from,
|
|
||||||
'x-to': safeSnapshotDates.value.to,
|
|
||||||
'Authorization': authorizationHeaderComputed.value,
|
|
||||||
'x-schema': 'events',
|
|
||||||
'x-limit': "6",
|
|
||||||
'x-pid': projectId.value || ''
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const eventsData = useFetch(`/api/data/query`, {
|
|
||||||
method: 'POST', headers, lazy: true, immediate: false, transform: transformResponse
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -34,37 +34,37 @@ function showAnomalyInfoAlert() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="w-full px-6 py-2 lg:py-6 font-bold text-text-sub/40 flex flex-col xl:flex-row text-lg gap-2 xl:gap-12 lg:text-2xl">
|
class="w-full px-6 pb-2 lg:pb-6 font-bold text-text-sub/40 flex flex-col xl:flex-row text-lg gap-2 xl:gap-12 lg:text-2xl">
|
||||||
|
|
||||||
<div class="flex gap-2 items-center text-text/90 justify-center md:justify-start">
|
<div class="flex gap-2 items-center text-text/90 justify-center md:justify-start">
|
||||||
<div class="animate-pulse w-[1rem] h-[1rem] bg-green-400 rounded-full"> </div>
|
<div class="animate-pulse w-[1rem] h-[1rem] bg-green-400 rounded-full"> </div>
|
||||||
<div class="poppins font-medium text-[1.2rem]"> {{ onlineUsers.data }} Online users</div>
|
<div class="poppins font-medium text-[.9rem]"> {{ onlineUsers.data }} Online users</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grow"></div>
|
<div class="grow"></div>
|
||||||
|
|
||||||
<div class="flex md:gap-2 items-center md:justify-start flex-col md:flex-row">
|
<!-- <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="poppins font-medium text-lyx-text-darker text-[.9rem]">Project:</div>
|
||||||
<div class="text-lyx-text poppins font-medium text-[1.2rem]"> {{ project?.name || 'Loading...' }}
|
<div class="text-lyx-text poppins font-medium text-[.9rem]"> {{ project?.name || 'Loading...' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col md:flex-row md:gap-2 items-center md:justify-start">
|
<div class="flex flex-col md:flex-row md:gap-2 items-center md:justify-start">
|
||||||
<div class="poppins font-medium text-lyx-text-darker text-[1.2rem]">Project id:</div>
|
<div class="poppins font-medium text-lyx-text-darker text-[.9rem]">Project id:</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<div class="text-lyx-text poppins font-medium text-[1.2rem]">
|
<div class="text-lyx-text poppins font-medium text-[.9rem]">
|
||||||
{{ project?._id || 'Loading...' }}
|
{{ project?._id || 'Loading...' }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center ml-3">
|
<div class="flex items-center ml-3">
|
||||||
<i @click="copyProjectId()"
|
<i @click="copyProjectId()"
|
||||||
class="far fa-copy text-lyx-text hover:text-lyx-primary cursor-pointer text-[1.2rem]"></i>
|
class="far fa-copy text-lyx-text hover:text-lyx-primary cursor-pointer text-[.9rem]"></i>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<div class="flex gap-2 items-center text-text/90 justify-center md:justify-start">
|
<div class="flex gap-2 items-center text-text/90 justify-center md:justify-start">
|
||||||
<div class="animate-pulse w-[1rem] h-[1rem] bg-green-400 rounded-full"> </div>
|
<div class="animate-pulse w-[1rem] h-[1rem] bg-green-400 rounded-full"> </div>
|
||||||
<div class="poppins font-regular text-[1rem]"> AI Anomaly Detector </div>
|
<div class="poppins font-regular text-[.9rem]"> AI Anomaly Detector </div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<i class="far fa-info-circle text-[.9rem] hover:text-lyx-primary cursor-pointer"
|
<i class="far fa-info-circle text-[.9rem] hover:text-lyx-primary cursor-pointer"
|
||||||
@click="showAnomalyInfoAlert"></i>
|
@click="showAnomalyInfoAlert"></i>
|
||||||
|
|||||||
@@ -8,15 +8,6 @@ const slice = computed(() => props.slice);
|
|||||||
|
|
||||||
const { safeSnapshotDates } = useSnapshot()
|
const { safeSnapshotDates } = useSnapshot()
|
||||||
|
|
||||||
const body = computed(() => {
|
|
||||||
return {
|
|
||||||
from: safeSnapshotDates.value.from,
|
|
||||||
to: safeSnapshotDates.value.to,
|
|
||||||
slice: slice.value,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
function transformResponse(input: { _id: string, name: string, count: number }[]) {
|
function transformResponse(input: { _id: string, name: string, count: number }[]) {
|
||||||
|
|
||||||
const fixed = fixMetrics({
|
const fixed = fixMetrics({
|
||||||
@@ -90,9 +81,9 @@ function onResponse(e: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const eventsStackedData = useFetch(`/api/timeline/events_stacked`, {
|
const eventsStackedData = useFetch(`/api/timeline/events_stacked`, {
|
||||||
method: 'POST', body, lazy: true, immediate: false,
|
lazy: true, immediate: false,
|
||||||
transform: transformResponse,
|
transform: transformResponse,
|
||||||
headers: useComputedHeaders(),
|
headers: useComputedHeaders({slice}),
|
||||||
onResponseError,
|
onResponseError,
|
||||||
onResponse
|
onResponse
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import type { TApiSettings } from '@schema/ApiSettingsSchema';
|
import type { TApiSettings } from '@schema/ApiSettingsSchema';
|
||||||
import type { SettingsTemplateEntry } from './Template.vue';
|
import type { SettingsTemplateEntry } from './Template.vue';
|
||||||
|
|
||||||
const { project, actions, projectList } = useProject();
|
const { project, actions, projectList, isGuest, projectId } = useProject();
|
||||||
|
|
||||||
const entries: SettingsTemplateEntry[] = [
|
const entries: SettingsTemplateEntry[] = [
|
||||||
{ id: 'pname', title: 'Name', text: 'Project name' },
|
{ id: 'pname', title: 'Name', text: 'Project name' },
|
||||||
@@ -107,7 +107,7 @@ async function deleteProject() {
|
|||||||
|
|
||||||
const firstProjectId = projectList.value?.[0]?._id.toString();
|
const firstProjectId = projectList.value?.[0]?._id.toString();
|
||||||
if (firstProjectId) {
|
if (firstProjectId) {
|
||||||
await setActiveProject(firstProjectId);
|
await actions.setActiveProject(firstProjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -120,8 +120,6 @@ async function deleteProject() {
|
|||||||
|
|
||||||
const { createAlert } = useAlert()
|
const { createAlert } = useAlert()
|
||||||
|
|
||||||
const activeProjectId = useActiveProjectId()
|
|
||||||
|
|
||||||
function copyScript() {
|
function copyScript() {
|
||||||
if (!navigator.clipboard) alert('You can\'t copy in HTTP');
|
if (!navigator.clipboard) alert('You can\'t copy in HTTP');
|
||||||
|
|
||||||
@@ -129,7 +127,7 @@ function copyScript() {
|
|||||||
const createScriptText = () => {
|
const createScriptText = () => {
|
||||||
return [
|
return [
|
||||||
'<script defer ',
|
'<script defer ',
|
||||||
`data-project="${activeProjectId.data.value}" `,
|
`data-project="${projectId.value}" `,
|
||||||
'src="https://cdn.jsdelivr.net/gh/litlyx/litlyx-js/browser/litlyx.js"></',
|
'src="https://cdn.jsdelivr.net/gh/litlyx/litlyx-js/browser/litlyx.js"></',
|
||||||
'script>'
|
'script>'
|
||||||
].join('')
|
].join('')
|
||||||
@@ -142,7 +140,7 @@ function copyScript() {
|
|||||||
|
|
||||||
function copyProjectId() {
|
function copyProjectId() {
|
||||||
if (!navigator.clipboard) alert('You can\'t copy in HTTP');
|
if (!navigator.clipboard) alert('You can\'t copy in HTTP');
|
||||||
navigator.clipboard.writeText(activeProjectId.data.value || '');
|
navigator.clipboard.writeText(projectId.value || '');
|
||||||
createAlert('Success', 'Project id copied successfully.', 'far fa-circle-check', 5000);
|
createAlert('Success', 'Project id copied successfully.', 'far fa-circle-check', 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { SettingsTemplateEntry } from './Template.vue';
|
import type { SettingsTemplateEntry } from './Template.vue';
|
||||||
|
|
||||||
const { projectId } = useProject();
|
const { projectId, isGuest } = useProject();
|
||||||
|
|
||||||
definePageMeta({ layout: 'dashboard' });
|
definePageMeta({ layout: 'dashboard' });
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const project = computed(() => {
|
|||||||
|
|
||||||
|
|
||||||
const isGuest = computed(() => {
|
const isGuest = computed(() => {
|
||||||
return (projectList.value || []).find(e => e._id.toString() === activeProjectId.value);
|
return (projectList.value || []).find(e => e._id.toString() === activeProjectId.value) == undefined;
|
||||||
})
|
})
|
||||||
|
|
||||||
export function useProject() {
|
export function useProject() {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { TProjectSnapshot } from "@schema/ProjectSnapshot";
|
import type { TProjectSnapshot } from "@schema/ProjectSnapshot";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { projectId, project } = useProject();
|
const { projectId, project } = useProject();
|
||||||
|
|
||||||
const headers = computed(() => {
|
const headers = computed(() => {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ const sections: Section[] = [
|
|||||||
{
|
{
|
||||||
title: '',
|
title: '',
|
||||||
entries: [
|
entries: [
|
||||||
{ label: 'Dashboard', to: '/', icon: 'fal fa-table-layout' },
|
{ label: 'Web Analytics', to: '/', icon: 'fal fa-table-layout' },
|
||||||
{ label: 'Events', to: '/events', icon: 'fal fa-square-bolt' },
|
{ label: 'Custom Events', to: '/events', icon: 'fal fa-square-bolt' },
|
||||||
{ label: 'AI Analyst', to: '/analyst', icon: 'fal fa-sparkles' },
|
{ label: 'AI Analyst', to: '/analyst', icon: 'fal fa-sparkles' },
|
||||||
{ label: 'Security', to: '/security', icon: 'fal fa-shield' },
|
{ label: 'Security', to: '/security', icon: 'fal fa-shield' },
|
||||||
// { label: 'Insights (soon)', to: '#', icon: 'fal fa-lightbulb', disabled: true },
|
// { label: 'Insights (soon)', to: '#', icon: 'fal fa-lightbulb', disabled: true },
|
||||||
@@ -23,22 +23,27 @@ const sections: Section[] = [
|
|||||||
{ label: 'Settings', to: '/settings', icon: 'fal fa-gear' },
|
{ label: 'Settings', to: '/settings', icon: 'fal fa-gear' },
|
||||||
{
|
{
|
||||||
grow: true,
|
grow: true,
|
||||||
label: 'Documentation', to: 'https://docs.litlyx.com', icon: 'fal fa-book', external: true,
|
label: 'Docs', to: 'https://docs.litlyx.com', icon: 'fal fa-book', external: true,
|
||||||
action() { Lit.event('docs_clicked') },
|
action() { Lit.event('docs_clicked') },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Slack support', icon: 'fab fa-slack',
|
label: 'Discord support', icon: 'fab fa-discord',
|
||||||
to: '#',
|
to: 'https://discord.gg/9cQykjsmWX',
|
||||||
premiumOnly: true,
|
external: true,
|
||||||
action() {
|
|
||||||
if (isLogged.value === true) return;
|
|
||||||
if (userRoles.isPremium.value === true) {
|
|
||||||
window.open('https://join.slack.com/t/litlyx/shared_invite/zt-2q3oawn29-hZlu_fBUBlc4052Ooe3FZg', '_blank');
|
|
||||||
} else {
|
|
||||||
pricingDrawer.visible.value = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// label: 'Slack support', icon: 'fab fa-slack',
|
||||||
|
// to: '#',
|
||||||
|
// premiumOnly: true,
|
||||||
|
// action() {
|
||||||
|
// if (isLogged.value === true) return;
|
||||||
|
// if (userRoles.isPremium.value === true) {
|
||||||
|
// window.open('https://join.slack.com/t/litlyx/shared_invite/zt-2q3oawn29-hZlu_fBUBlc4052Ooe3FZg', '_blank');
|
||||||
|
// } else {
|
||||||
|
// pricingDrawer.visible.value = true;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -76,7 +81,7 @@ const { isOpen, close, open } = useMenu();
|
|||||||
</CVerticalNavigation>
|
</CVerticalNavigation>
|
||||||
|
|
||||||
|
|
||||||
<div class="overflow-hidden w-full bg-lyx-background-light relative h-full">
|
<div class="overflow-hidden w-full bg-lyx-background relative h-full">
|
||||||
|
|
||||||
<div v-if="showDialog" class="barrier w-full h-full z-[34] absolute bg-black/50 backdrop-blur-[2px]">
|
<div v-if="showDialog" class="barrier w-full h-full z-[34] absolute bg-black/50 backdrop-blur-[2px]">
|
||||||
<i
|
<i
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import type { MetricsCounts } from '~/server/api/metrics/[project_id]/counts';
|
|||||||
|
|
||||||
definePageMeta({ layout: 'dashboard' });
|
definePageMeta({ layout: 'dashboard' });
|
||||||
|
|
||||||
const activeProject = useActiveProject();
|
const {project} = useProject();
|
||||||
|
|
||||||
const isPremium = computed(() => (activeProject.value?.premium_type || 0) > 0);
|
const isPremium = computed(() => (project.value?.premium_type || 0) > 0);
|
||||||
|
|
||||||
const metricsInfo = ref<number>(0);
|
const metricsInfo = ref<number>(0);
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ const totalItems = computed(() => metricsInfo.value);
|
|||||||
|
|
||||||
|
|
||||||
const { data: tableData, pending: loadingData } = await useLazyFetch<any[]>(() =>
|
const { data: tableData, pending: loadingData } = await useLazyFetch<any[]>(() =>
|
||||||
`/api/metrics/${activeProject.value?._id}/query?type=1&orderBy=${sort.value.column}&order=${sort.value.direction}&page=${page.value}&limit=${itemsPerPage}`, {
|
`/api/metrics/${project.value?._id}/query?type=1&orderBy=${sort.value.column}&order=${sort.value.direction}&page=${page.value}&limit=${itemsPerPage}`, {
|
||||||
...signHeaders(),
|
...signHeaders(),
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const counts = await $fetch<MetricsCounts>(`/api/metrics/${activeProject.value?._id}/counts`, signHeaders());
|
const counts = await $fetch<MetricsCounts>(`/api/metrics/${project.value?._id}/counts`, signHeaders());
|
||||||
metricsInfo.value = counts.eventsCount;
|
metricsInfo.value = counts.eventsCount;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import type { MetricsCounts } from '~/server/api/metrics/[project_id]/counts';
|
|||||||
|
|
||||||
definePageMeta({ layout: 'dashboard' });
|
definePageMeta({ layout: 'dashboard' });
|
||||||
|
|
||||||
const activeProject = useActiveProject();
|
const {project} = useProject();
|
||||||
|
|
||||||
const isPremium = computed(() => (activeProject.value?.premium_type || 0) > 0);
|
const isPremium = computed(() => (project.value?.premium_type || 0) > 0);
|
||||||
|
|
||||||
const metricsInfo = ref<number>(0);
|
const metricsInfo = ref<number>(0);
|
||||||
|
|
||||||
@@ -35,12 +35,12 @@ const totalItems = computed(() => metricsInfo.value);
|
|||||||
|
|
||||||
|
|
||||||
const { data: tableData, pending: loadingData } = await useLazyFetch<any[]>(() =>
|
const { data: tableData, pending: loadingData } = await useLazyFetch<any[]>(() =>
|
||||||
`/api/metrics/${activeProject.value?._id}/query?type=0&orderBy=${sort.value.column}&order=${sort.value.direction}&page=${page.value}&limit=${itemsPerPage}`, {
|
`/api/metrics/${project.value?._id}/query?type=0&orderBy=${sort.value.column}&order=${sort.value.direction}&page=${page.value}&limit=${itemsPerPage}`, {
|
||||||
...signHeaders(),
|
...signHeaders(),
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const counts = await $fetch<MetricsCounts>(`/api/metrics/${activeProject.value?._id}/counts`, signHeaders());
|
const counts = await $fetch<MetricsCounts>(`/api/metrics/${project.value?._id}/counts`, signHeaders());
|
||||||
metricsInfo.value = counts.visitsCount;
|
metricsInfo.value = counts.visitsCount;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,21 +10,7 @@ const selectLabelsEvents = [
|
|||||||
];
|
];
|
||||||
const eventsStackedSelectIndex = ref<number>(0);
|
const eventsStackedSelectIndex = ref<number>(0);
|
||||||
|
|
||||||
const { projectId } = useProject();
|
const eventsData = await useFetch(`/api/data/count`, { headers: useComputedHeaders({ custom: { 'x-schema': 'events' } }), lazy: true });
|
||||||
const { snapshot, safeSnapshotDates } = useSnapshot();
|
|
||||||
|
|
||||||
|
|
||||||
const headers = computed(() => {
|
|
||||||
return {
|
|
||||||
'x-from': safeSnapshotDates.value.from,
|
|
||||||
'x-to': safeSnapshotDates.value.to,
|
|
||||||
'Authorization': authorizationHeaderComputed.value,
|
|
||||||
'x-schema': 'events',
|
|
||||||
'x-pid': projectId.value ?? ''
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const eventsData = await useFetch(`/api/data/count`, { method: 'POST', headers, lazy: true });
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -36,9 +22,9 @@ const eventsData = await useFetch(`/api/data/count`, { method: 'POST', headers,
|
|||||||
<LyxUiCard class="w-full flex justify-between items-center">
|
<LyxUiCard class="w-full flex justify-between items-center">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<div>
|
<div>
|
||||||
Total events: {{ eventsData.data.value?.[0]?.total || '0' }}
|
Total events: {{ eventsData.data.value?.[0]?.count || '0' }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(eventsData.data.value?.[0]?.total || 0) === 0">
|
<div v-if="(eventsData.data.value?.[0]?.count || 0) === 0">
|
||||||
Waiting for your first event...
|
Waiting for your first event...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,7 +57,7 @@ const eventsData = await useFetch(`/api/data/count`, { method: 'POST', headers,
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex">
|
<!-- <div class="flex">
|
||||||
<EventsFunnelChart :key="refreshKey" class="w-full"></EventsFunnelChart>
|
<EventsFunnelChart :key="refreshKey" class="w-full"></EventsFunnelChart>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -81,7 +67,7 @@ const eventsData = await useFetch(`/api/data/count`, { method: 'POST', headers,
|
|||||||
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<EventsMetadataAnalyzer :key="refreshKey"></EventsMetadataAnalyzer>
|
<EventsMetadataAnalyzer :key="refreshKey"></EventsMetadataAnalyzer>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
definePageMeta({ layout: 'dashboard' });
|
definePageMeta({ layout: 'dashboard' });
|
||||||
|
|
||||||
|
|
||||||
const activeProject = useActiveProject();
|
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{ label: 'General', slot: 'general' },
|
{ label: 'General', slot: 'general' },
|
||||||
{ label: 'Members', slot: 'members' },
|
{ label: 'Members', slot: 'members' },
|
||||||
@@ -20,16 +18,16 @@ const items = [
|
|||||||
|
|
||||||
<CustomTab :items="items" class="mt-8">
|
<CustomTab :items="items" class="mt-8">
|
||||||
<template #general>
|
<template #general>
|
||||||
<SettingsGeneral :key="activeProject?._id.toString()"></SettingsGeneral>
|
<SettingsGeneral :key="refreshKey"></SettingsGeneral>
|
||||||
</template>
|
</template>
|
||||||
<template #members>
|
<template #members>
|
||||||
<SettingsMembers :key="activeProject?._id.toString()"></SettingsMembers>
|
<SettingsMembers :key="refreshKey"></SettingsMembers>
|
||||||
</template>
|
</template>
|
||||||
<template #billing>
|
<template #billing>
|
||||||
<SettingsBilling :key="activeProject?._id.toString()"></SettingsBilling>
|
<SettingsBilling :key="refreshKey"></SettingsBilling>
|
||||||
</template>
|
</template>
|
||||||
<template #account>
|
<template #account>
|
||||||
<SettingsAccount :key="activeProject?._id.toString()"></SettingsAccount>
|
<SettingsAccount :key="refreshKey"></SettingsAccount>
|
||||||
</template>
|
</template>
|
||||||
</CustomTab>
|
</CustomTab>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `browsers:${pid}:${from}:${to}`;
|
const cacheKey = `browsers:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { getRequestData } from "~/server/utils/getRequestData";
|
|||||||
export default defineEventHandler(async event => {
|
export default defineEventHandler(async event => {
|
||||||
|
|
||||||
|
|
||||||
const data = await getRequestData(event);
|
const data = await getRequestData(event, { requireSchema: true });
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
const { schemaName, pid, from, to, model, project_id } = data;
|
const { schemaName, pid, from, to, model, project_id } = data;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `countries:${pid}:${from}:${to}`;
|
const cacheKey = `countries:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `devices:${pid}:${from}:${to}`;
|
const cacheKey = `devices:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `events:${pid}:${from}:${to}`;
|
const cacheKey = `events:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `oss:${pid}:${from}:${to}`;
|
const cacheKey = `oss:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `referrers:${pid}:${from}:${to}`;
|
const cacheKey = `referrers:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const { pid, from, to, project_id, limit } = data;
|
const { pid, from, to, project_id, limit } = data;
|
||||||
|
|
||||||
const cacheKey = `websites:${pid}:${from}:${to}`;
|
const cacheKey = `websites:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default defineEventHandler(async event => {
|
|||||||
|
|
||||||
const websiteName = getHeader(event, 'x-website-name');
|
const websiteName = getHeader(event, 'x-website-name');
|
||||||
|
|
||||||
const cacheKey = `websites_pages:${websiteName}:${pid}:${from}:${to}`;
|
const cacheKey = `websites_pages:${websiteName}:${pid}:${limit}:${from}:${to}`;
|
||||||
const cacheExp = 60;
|
const cacheExp = 60;
|
||||||
|
|
||||||
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
return await Redis.useCacheV2(cacheKey, cacheExp, async () => {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ module.exports = {
|
|||||||
darker: '#6A6A6A'
|
darker: '#6A6A6A'
|
||||||
},
|
},
|
||||||
"lyx-widget": {
|
"lyx-widget": {
|
||||||
DEFAULT: '#151515',
|
DEFAULT: '#0E0E0E',
|
||||||
light: '#1E1E1E',
|
light: '#1E1E1E',
|
||||||
lighter: '#262626'
|
lighter: '#262626'
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user