All checks were successful
continuous-integration/drone/push Build is passing
124 lines
3.1 KiB
Vue
124 lines
3.1 KiB
Vue
<template>
|
|
<div class="chart-container">
|
|
<Loader v-if="loading"></Loader>
|
|
<div class="chart" id="chart" ref="chart" v-else></div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import { ref, computed, watch } from 'vue'
|
|
import * as Highcharts from 'highcharts'
|
|
import 'highcharts/css/highcharts.scss'
|
|
import Loader from '@/components/Loader.vue'
|
|
import { capitalizeFirstLetter } from '@/utils/helpers'
|
|
import type { Window, NavType } from '@/utils/types'
|
|
import { typeApi } from '@/utils/types'
|
|
import { useFetch } from '@vueuse/core'
|
|
|
|
Highcharts.setOptions({
|
|
time: {
|
|
timezoneOffset: new Date().getTimezoneOffset()
|
|
}
|
|
})
|
|
|
|
const props = defineProps<{
|
|
activeWindow: Window
|
|
activeType: NavType | undefined
|
|
}>()
|
|
|
|
const chart = ref<HTMLElement | null>(null)
|
|
|
|
const fetchUrl = computed(() => {
|
|
const [start, end] = [props.activeWindow.getStart(), props.activeWindow.getEnd()]
|
|
const sample = Math.round((end - start) / 60 / 288) || 1
|
|
const host = import.meta.env.MODE === 'development' ? 'http://localhost:3000' : ''
|
|
const fetchUrl = `${host}/type/${
|
|
typeApi[props.activeType || 'temperatuur']
|
|
}/startDate/${start}/endDate/${end}/sample/${sample}`
|
|
return fetchUrl
|
|
})
|
|
|
|
interface ChartDataPoint {
|
|
date: Number
|
|
value: Number
|
|
}
|
|
const { data: chartData, isFetching: loading } = useFetch(fetchUrl, { refetch: true }).json<ChartDataPoint[]>()
|
|
|
|
watch([chart, chartData], () => {
|
|
if (chart.value && chartData.value) renderChart()
|
|
})
|
|
|
|
const renderChart = () => {
|
|
const data = (chartData.value || []).map(({ date, value }) => ({ x: date, y: value })) as any[]
|
|
Highcharts.chart({
|
|
chart: { renderTo: chart.value || '', styledMode: true, marginBottom: 25 },
|
|
title: { text: '' },
|
|
legend: { enabled: false },
|
|
plotOptions: { series: { animation: false, marker: { enabled: false } } },
|
|
xAxis: {
|
|
type: 'datetime',
|
|
dateTimeLabelFormats: {
|
|
millisecond: '%H:%M:%S.%L',
|
|
second: '%H:%M:%S',
|
|
minute: '%H:%M',
|
|
hour: '%H:%M',
|
|
day: '%a %e %b',
|
|
week: '%e %b',
|
|
month: "%b '%y",
|
|
year: '%Y'
|
|
}
|
|
},
|
|
yAxis: {
|
|
labels: {
|
|
formatter() {
|
|
const suffix = props.activeType === 'temperatuur' ? '°C' : '%'
|
|
return this.value + suffix
|
|
}
|
|
},
|
|
title: { text: null },
|
|
minTickInterval: 0.1
|
|
},
|
|
series: [{ name: capitalizeFirstLetter(props.activeType || ''), data: data, type: 'line' }],
|
|
credits: { enabled: false }
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import '@/style/_variables.scss';
|
|
.chart-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-grow: 1;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 24px;
|
|
position: relative;
|
|
}
|
|
.chart {
|
|
top: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
position: absolute;
|
|
}
|
|
.highcharts-graph {
|
|
stroke-width: 3px;
|
|
}
|
|
.highcharts-color-0 {
|
|
fill: $primary;
|
|
stroke: $primary;
|
|
}
|
|
.highcharts-axis-line {
|
|
// stroke-width: 1px !important;
|
|
stroke: $border !important;
|
|
}
|
|
.highcharts-grid-line {
|
|
stroke-width: 1px !important;
|
|
stroke-dasharray: 5, 5 !important;
|
|
stroke: $border !important;
|
|
}
|
|
text {
|
|
font-size: 0.8rem;
|
|
}
|
|
</style>
|