diff --git a/app/assets/css/tailwind.css b/app/assets/css/tailwind.css index 280d20f..64d822f 100644 --- a/app/assets/css/tailwind.css +++ b/app/assets/css/tailwind.css @@ -42,8 +42,8 @@ --vis-tooltip-backdrop-filter: none !important; --vis-tooltip-padding: none !important; - --vis-primary-color: 198 93% 60%; - --vis-secondary-color: 158 64% 52%; + --vis-primary-color: 158 64% 52%; + --vis-secondary-color: 198 93% 60%; /* --vis-secondary-color: 160 81% 40%; */ /* --vis-secondary-color: var(--primary); */ --vis-text-color: var(--muted-foreground); diff --git a/app/components/dashboard/TimePicker.vue b/app/components/dashboard/TimePicker.vue new file mode 100644 index 0000000..d67b9f5 --- /dev/null +++ b/app/components/dashboard/TimePicker.vue @@ -0,0 +1,94 @@ + + + diff --git a/app/components/dashboard/analysis/Views.vue b/app/components/dashboard/analysis/Views.vue index 9ed866a..01555f9 100644 --- a/app/components/dashboard/analysis/Views.vue +++ b/app/components/dashboard/analysis/Views.vue @@ -2,15 +2,30 @@ import { AreaChart } from '@/components/ui/chart-area' import { BarChart } from '@/components/ui/chart-bar' +const props = defineProps({ + mode: { + type: String, + default: 'full', + }, + chartType: { + type: String, + default: 'area', + }, +}) + const views = ref([]) -const chart = computed(() => views.value.length > 1 ? AreaChart : BarChart) +const chart = computed(() => (props.chartType === 'area' && views.value.length > 1) ? AreaChart : BarChart) const id = inject('id') const time = inject('time') const filters = inject('filters') +const OneHour = 60 * 60 // 1 hour in seconds const OneDay = 24 * 60 * 60 // 1 day in seconds function getUnit(startAt, endAt) { + if (startAt && endAt && endAt - startAt <= OneHour) + return 'minute' + if (startAt && endAt && endAt - startAt <= OneDay) return 'hour' @@ -61,16 +76,20 @@ function formatTime(tick) { diff --git a/app/components/dashboard/realtime/Chart.vue b/app/components/dashboard/realtime/Chart.vue new file mode 100644 index 0000000..7e248bf --- /dev/null +++ b/app/components/dashboard/realtime/Chart.vue @@ -0,0 +1,56 @@ + + + diff --git a/app/components/dashboard/realtime/Globe.vue b/app/components/dashboard/realtime/Globe.vue index b07f527..08985e8 100644 --- a/app/components/dashboard/realtime/Globe.vue +++ b/app/components/dashboard/realtime/Globe.vue @@ -13,6 +13,9 @@ const props = defineProps({ }, }) +const time = inject('time') +const filters = inject('filters') + const countries = ref({}) const locations = ref([]) @@ -39,7 +42,9 @@ async function getGlobeJSON() { async function getLiveLocations() { const { data } = await useAPI('/api/logs/locations', { query: { - startAt: Math.floor(Date.now() / 1000) - 60 * props.minutes, + startAt: time.value.startAt, + endAt: time.value.endAt, + ...filters.value, }, }) locations.value = data?.map(e => ({ @@ -59,7 +64,7 @@ function initGlobe() { // .globeOffset([width.value > 768 ? -100 : 0, width.value > 768 ? 0 : 100]) .atmosphereColor('rgba(170, 170, 200, 1)') .globeMaterial(new MeshPhongMaterial({ - color: 'hsl(220.9, 30.3%, 16%)', + color: 'rgb(228, 228, 231)', transparent: false, opacity: 1, })) @@ -99,6 +104,10 @@ function stopRotation() { } } +const stopWatchQueryChange = watch([time, filters], getLiveLocations, { + deep: true, +}) + watch(width, () => { if (globe) { globe.width(size.value.width) @@ -106,10 +115,20 @@ watch(width, () => { } }) +watch(locations, () => { + if (globe) { + globe.hexBinPointsData(locations.value) + } +}) + onMounted(async () => { await Promise.all([getGlobeJSON(), getLiveLocations()]) initGlobe() }) + +onBeforeUnmount(() => { + stopWatchQueryChange() +})