Draw custom graphs tooltips so we are not limited to the canvas size when many apps are selected
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
import moment from 'moment-timezone';
|
||||
import { onMounted, onUnmounted, useTemplateRef, watch } from 'vue';
|
||||
import Chart from 'chart.js/auto';
|
||||
import { prettyDecimalSize } from '@cloudron/pankow/utils';
|
||||
import { prettyDecimalSize, prettyLongDate, prettyShortDate } from '@cloudron/pankow/utils';
|
||||
import annotationPlugin from 'chartjs-plugin-annotation';
|
||||
|
||||
Chart.register(annotationPlugin);
|
||||
@@ -12,6 +12,7 @@ Chart.register(annotationPlugin);
|
||||
const LIVE_REFRESH_INTERVAL_MSECS = 1000; // for realtime graphs, the time (x axis) advances at this pace
|
||||
|
||||
const graphNode = useTemplateRef('graphNode');
|
||||
const tooltipElem = useTemplateRef('tooltipElem');
|
||||
|
||||
let graph = null;
|
||||
let liveRefreshIntervalId = null;
|
||||
@@ -50,11 +51,40 @@ function createGraphOptions({ yscale, period, highMark }) {
|
||||
position: 'bottom' // not used, hidden since color code is shown in tooltip
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
external: function(context) {
|
||||
const tooltipModel = context.tooltip;
|
||||
if (tooltipModel.opacity === 0) {
|
||||
tooltipElem.value.style.opacity = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set Text
|
||||
if (tooltipModel.body) {
|
||||
const titleLines = tooltipModel.title || [];
|
||||
const bodyLines = tooltipModel.body.map(item => item.lines);
|
||||
|
||||
let innerHtml = `<div class="graphs-tooltip-title">${titleLines[0]}</div>`;
|
||||
|
||||
bodyLines.forEach(function(body, i) {
|
||||
const colors = tooltipModel.labelColors[i];
|
||||
innerHtml += `<div style="color: ${colors.borderColor}" class="graphs-tooltip-item">${body}</div>`;
|
||||
});
|
||||
|
||||
tooltipElem.value.innerHTML = innerHtml;
|
||||
}
|
||||
|
||||
tooltipElem.value.style.opacity = 1;
|
||||
tooltipElem.value.style.position = 'absolute';
|
||||
tooltipElem.value.style.left = tooltipModel.caretX + 'px';
|
||||
tooltipElem.value.style.top = 0 + 'px';
|
||||
tooltipElem.value.style.height = '100%';
|
||||
},
|
||||
callbacks: {
|
||||
title: (tooltipItem) => moment(tooltipItem[0].raw.x).format(period.tooltipFormat),
|
||||
title: (tooltipItem) => period.tooltipFormat === 'long' ? prettyLongDate(tooltipItem[0].raw.x) : prettyShortDate(tooltipItem[0].raw.x),
|
||||
label: (tooltipItem) => {
|
||||
const datasetLabel = tooltipItem.chart.data.datasets[tooltipItem.datasetIndex].label;
|
||||
return `${datasetLabel}: ${yscale.ticks.callback(tooltipItem.raw.y)}`;
|
||||
return `<span style="font-family: fixed">${yscale.ticks.callback(tooltipItem.raw.y)}</span>: ${datasetLabel}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -260,6 +290,7 @@ defineExpose({
|
||||
<label>{{ title }} <span class="pull-right text-small">{{ subtext }}</span></label>
|
||||
<div class="graph">
|
||||
<canvas ref="graphNode"></canvas>
|
||||
<div ref="tooltipElem" class="graphs-tooltip"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -277,3 +308,23 @@ defineExpose({
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
||||
.graphs-tooltip {
|
||||
white-space: nowrap;
|
||||
border-left: 1px var(--pankow-color-primary) solid;
|
||||
padding-left: 10px;
|
||||
pointer-events: none;
|
||||
backdrop-filter: blur(1px);
|
||||
}
|
||||
|
||||
.graphs-tooltip-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.graphs-tooltip-item {
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user