mirror of
https://github.com/plausible/analytics.git
synced 2024-12-23 01:22:15 +03:00
87a63fe28a
This commit implements the custom comparison mode using a date range.
123 lines
5.1 KiB
JavaScript
123 lines
5.1 KiB
JavaScript
import { METRIC_FORMATTER, METRIC_LABELS } from './graph-util.js'
|
|
import dateFormatter from './date-formatter.js'
|
|
|
|
const renderBucketLabel = function(query, graphData, label, comparison = false) {
|
|
let isPeriodFull = graphData.full_intervals?.[label]
|
|
if (comparison) isPeriodFull = true
|
|
|
|
const formattedLabel = dateFormatter({
|
|
interval: graphData.interval, longForm: true, period: query.period, isPeriodFull,
|
|
})(label)
|
|
|
|
if (query.period === 'realtime') {
|
|
return dateFormatter({
|
|
interval: graphData.interval, longForm: true, period: query.period,
|
|
})(label)
|
|
}
|
|
|
|
if (graphData.interval === 'hour' || graphData.interval == 'minute') {
|
|
const date = dateFormatter({ interval: "date", longForm: true, period: query.period })(label)
|
|
return `${date}, ${formattedLabel}`
|
|
}
|
|
|
|
return formattedLabel
|
|
}
|
|
|
|
const calculatePercentageDifference = function(oldValue, newValue) {
|
|
if (oldValue == 0 && newValue > 0) {
|
|
return 100
|
|
} else if (oldValue == 0 && newValue == 0) {
|
|
return 0
|
|
} else {
|
|
return Math.round((newValue - oldValue) / oldValue * 100)
|
|
}
|
|
}
|
|
|
|
const buildTooltipData = function(query, graphData, metric, tooltipModel) {
|
|
const data = tooltipModel.dataPoints.find((dataPoint) => dataPoint.dataset.yAxisID == "y")
|
|
const comparisonData = tooltipModel.dataPoints.find((dataPoint) => dataPoint.dataset.yAxisID == "yComparison")
|
|
|
|
const label = data && renderBucketLabel(query, graphData, graphData.labels[data.dataIndex])
|
|
const comparisonLabel = comparisonData && renderBucketLabel(query, graphData, graphData.comparison_labels[comparisonData.dataIndex], true)
|
|
|
|
const value = data?.raw || 0
|
|
const comparisonValue = comparisonData?.raw || 0
|
|
const comparisonDifference = label && comparisonLabel && calculatePercentageDifference(comparisonValue, value)
|
|
|
|
const metricFormatter = METRIC_FORMATTER[metric]
|
|
const formattedValue = metricFormatter(value)
|
|
const formattedComparisonValue = comparisonData && metricFormatter(comparisonValue)
|
|
|
|
return { label, formattedValue, comparisonLabel, formattedComparisonValue, comparisonDifference }
|
|
}
|
|
|
|
export default function GraphTooltip(graphData, metric, query) {
|
|
return (context) => {
|
|
const tooltipModel = context.tooltip
|
|
const offset = document.getElementById("main-graph-canvas").getBoundingClientRect()
|
|
let tooltipEl = document.getElementById('chartjs-tooltip')
|
|
|
|
if (!tooltipEl) {
|
|
tooltipEl = document.createElement('div')
|
|
tooltipEl.id = 'chartjs-tooltip'
|
|
tooltipEl.style.display = 'none'
|
|
tooltipEl.style.opacity = 0
|
|
document.body.appendChild(tooltipEl)
|
|
}
|
|
|
|
if (tooltipEl && offset && window.innerWidth < 768) {
|
|
tooltipEl.style.top = offset.y + offset.height + window.scrollY + 15 + 'px'
|
|
tooltipEl.style.left = offset.x + 'px'
|
|
tooltipEl.style.right = null
|
|
tooltipEl.style.opacity = 1
|
|
}
|
|
|
|
if (tooltipModel.opacity === 0) {
|
|
tooltipEl.style.display = 'none'
|
|
return
|
|
}
|
|
|
|
if (tooltipModel.body) {
|
|
const tooltipData = buildTooltipData(query, graphData, metric, tooltipModel)
|
|
|
|
tooltipEl.innerHTML = `
|
|
<aside class="text-gray-100 flex flex-col">
|
|
<div class="flex justify-between items-center">
|
|
<span class="font-semibold mr-4 text-lg">${METRIC_LABELS[metric]}</span>
|
|
${tooltipData.comparisonDifference ?
|
|
`<div class="inline-flex items-center space-x-1">
|
|
${tooltipData.comparisonDifference > 0 ? `<span class="font-semibold text-sm text-green-500">↑</span><span>${tooltipData.comparisonDifference}%</span>` : ""}
|
|
${tooltipData.comparisonDifference < 0 ? `<span class="font-semibold text-sm text-red-400">↓</span><span>${tooltipData.comparisonDifference * -1}%</span>` : ""}
|
|
${tooltipData.comparisonDifference == 0 ? `<span class="font-semibold text-sm">〰 0%</span>` : ""}
|
|
</div>` : ''}
|
|
</div>
|
|
|
|
${tooltipData.label ?
|
|
`<div class="flex flex-col">
|
|
<div class="flex flex-row justify-between items-center">
|
|
<span class="flex items-center mr-4">
|
|
<div class="w-3 h-3 mr-1 rounded-full" style="background-color: rgba(101,116,205)"></div>
|
|
<span>${tooltipData.label}</span>
|
|
</span>
|
|
<span class="text-base font-bold">${tooltipData.formattedValue}</span>
|
|
</div>` : ''}
|
|
|
|
${tooltipData.comparisonLabel ?
|
|
`<div class="flex flex-row justify-between items-center">
|
|
<span class="flex items-center mr-4">
|
|
<div class="w-3 h-3 mr-1 rounded-full bg-gray-500"></div>
|
|
<span>${tooltipData.comparisonLabel}</span>
|
|
</span>
|
|
<span class="text-base font-bold">${tooltipData.formattedComparisonValue}</span>
|
|
</div>` : ""}
|
|
</div>
|
|
|
|
${graphData.interval === "month" ? `<span class="font-semibold italic">Click to view month</span>` : ""}
|
|
${graphData.interval === "date" ? `<span class="font-semibold italic">Click to view day</span>` : ""}
|
|
</aside>
|
|
`
|
|
}
|
|
tooltipEl.style.display = null
|
|
}
|
|
}
|