Merge branch 'preview'
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -18,6 +18,9 @@ const route = useRoute()
|
|||
<TabsTrigger value="/dashboard/analysis">
|
||||
{{ $t('nav.analysis') }}
|
||||
</TabsTrigger>
|
||||
<!-- <TabsTrigger value="/dashboard/realtime">
|
||||
{{ $t('nav.realtime') }}
|
||||
</TabsTrigger> -->
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
<slot name="left" />
|
||||
|
|
@ -74,8 +74,8 @@ onBeforeMount(() => {
|
|||
</DashboardNav>
|
||||
<DashboardFilters v-if="!link" @change="changeFilter" />
|
||||
</div>
|
||||
<DashboardCounters />
|
||||
<DashboardViews />
|
||||
<DashboardMetrics />
|
||||
<DashboardAnalysisCounters />
|
||||
<DashboardAnalysisViews />
|
||||
<DashboardAnalysisMetrics />
|
||||
</main>
|
||||
</template>
|
||||
|
|
@ -31,7 +31,7 @@ defineProps({
|
|||
:value="rawTabs[index]"
|
||||
class="flex-1"
|
||||
>
|
||||
<DashboardMetricsMetric
|
||||
<DashboardAnalysisMetricsMetric
|
||||
:type="rawTabs[index]"
|
||||
:name="tab"
|
||||
class="h-full"
|
||||
|
|
@ -20,28 +20,28 @@ const translatedTabs = computed(() => ({
|
|||
|
||||
<template>
|
||||
<main class="grid gap-8 lg:grid-cols-12">
|
||||
<LazyDashboardMetricsLocations class="col-span-1 lg:col-span-8" />
|
||||
<DashboardMetricsGroup
|
||||
<LazyDashboardAnalysisMetricsLocations class="col-span-1 lg:col-span-8" />
|
||||
<DashboardAnalysisMetricsGroup
|
||||
class="lg:col-span-4"
|
||||
:tabs="translatedTabs.location"
|
||||
:raw-tabs="tabs.location"
|
||||
/>
|
||||
<DashboardMetricsGroup
|
||||
<DashboardAnalysisMetricsGroup
|
||||
class="lg:col-span-6"
|
||||
:tabs="translatedTabs.referer"
|
||||
:raw-tabs="tabs.referer"
|
||||
/>
|
||||
<DashboardMetricsGroup
|
||||
<DashboardAnalysisMetricsGroup
|
||||
class="lg:col-span-6"
|
||||
:tabs="translatedTabs.time"
|
||||
:raw-tabs="tabs.time"
|
||||
/>
|
||||
<DashboardMetricsGroup
|
||||
<DashboardAnalysisMetricsGroup
|
||||
class="lg:col-span-6"
|
||||
:tabs="translatedTabs.device"
|
||||
:raw-tabs="tabs.device"
|
||||
/>
|
||||
<DashboardMetricsGroup
|
||||
<DashboardAnalysisMetricsGroup
|
||||
class="lg:col-span-6"
|
||||
:tabs="translatedTabs.browser"
|
||||
:raw-tabs="tabs.browser"
|
||||
|
|
@ -39,7 +39,7 @@ defineProps({
|
|||
<div
|
||||
class="flex-1 leading-5 truncate font-mediums"
|
||||
>
|
||||
<DashboardMetricsName
|
||||
<DashboardAnalysisMetricsName
|
||||
:name="metric.name"
|
||||
:type="type"
|
||||
/>
|
||||
|
|
@ -61,7 +61,7 @@ onBeforeUnmount(() => {
|
|||
<template>
|
||||
<Card class="flex flex-col">
|
||||
<template v-if="metrics.length">
|
||||
<DashboardMetricsList
|
||||
<DashboardAnalysisMetricsList
|
||||
class="flex-1"
|
||||
:metrics="top6"
|
||||
:type="type"
|
||||
|
|
@ -83,7 +83,7 @@ onBeforeUnmount(() => {
|
|||
<DialogHeader>
|
||||
<DialogTitle>{{ name }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DashboardMetricsList
|
||||
<DashboardAnalysisMetricsList
|
||||
class="overflow-y-auto"
|
||||
:metrics="metrics"
|
||||
:type="type"
|
||||
|
|
@ -10,19 +10,28 @@ defineProps({
|
|||
},
|
||||
})
|
||||
|
||||
const locale = useI18n().locale
|
||||
|
||||
function formatName(name, type) {
|
||||
if (!name || typeof Intl === 'undefined')
|
||||
return name
|
||||
|
||||
try {
|
||||
if (type === 'country') {
|
||||
const regionNames = new Intl.DisplayNames(['en'], { type: 'region' })
|
||||
const regionNames = new Intl.DisplayNames([locale.value], { type: 'region' })
|
||||
return `${getFlag(name)} ${regionNames.of(name)}`
|
||||
}
|
||||
if (type === 'language') {
|
||||
const languageNames = new Intl.DisplayNames(['en'], { type: 'language' })
|
||||
const languageNames = new Intl.DisplayNames([locale.value], { type: 'language' })
|
||||
return languageNames.of(name)
|
||||
}
|
||||
|
||||
// TODO: Add support for timezone
|
||||
// if (type === 'timezone' && typeof Intl.TimeZone === 'function') {
|
||||
// const tz = new Intl.TimeZone(name)
|
||||
// return tz.getDisplayName(locale.value, { type: 'long' })
|
||||
// }
|
||||
|
||||
return name
|
||||
}
|
||||
catch (e) {
|
||||
|
|
@ -36,15 +45,15 @@ function formatName(name, type) {
|
|||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger class="w-full text-left">
|
||||
<DashboardMetricsNameReferer
|
||||
<DashboardAnalysisMetricsNameReferer
|
||||
v-if="name && type === 'referer'"
|
||||
:name="name"
|
||||
/>
|
||||
<DashboardMetricsNameSlug
|
||||
<DashboardAnalysisMetricsNameSlug
|
||||
v-else-if="name && type === 'slug'"
|
||||
:name="name"
|
||||
/>
|
||||
<DashboardMetricsNameIcon
|
||||
<DashboardAnalysisMetricsNameIcon
|
||||
v-else-if="name && ['os', 'browser', 'browserType', 'device', 'deviceType'].includes(type)"
|
||||
:name="name"
|
||||
:type="type"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import { DependencyType } from '@/components/ui/auto-form/interface'
|
||||
import { LinkSchema, nanoid } from '@/schemas/link'
|
||||
import { LinkSchema, nanoid } from '@@/schemas/link'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { Shuffle, Sparkles } from 'lucide-vue-next'
|
||||
import { useForm } from 'vee-validate'
|
||||
10
app/components/dashboard/realtime/Index.vue
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<template>
|
||||
<main class="space-y-6">
|
||||
<div class="flex flex-col gap-6 sm:gap-2 sm:flex-row sm:justify-between">
|
||||
<DashboardNav />
|
||||
</div>
|
||||
<div>
|
||||
Realtime
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||