1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/renderer/components/chart/zebra-stripes.plugin.ts
Sebastian Malton c6dce043a7
Lint: comma-spacing (error) & comma-dangle (error) (#4200)
Signed-off-by: Sebastian Malton <sebastian@malton.name>
2021-11-02 17:38:20 -04:00

127 lines
4.0 KiB
TypeScript

/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Plugin for drawing stripe bars on top of any timeseries barchart
// Based on cover DIV element with repeating-linear-gradient style
import type ChartJS from "chart.js";
import moment, { Moment } from "moment";
import get from "lodash/get";
const defaultOptions = {
stripeColor: "#ffffff08",
};
export const ZebraStripes = {
updated: null as Moment, // timestamp which all stripe movements based on
options: {},
getOptions(chart: ChartJS) {
return get(chart, "options.plugins.ZebraStripes");
},
getLastUpdate(chart: ChartJS) {
const data = chart.data.datasets[0].data[0] as ChartJS.ChartPoint;
return moment.unix(parseInt(data.x as string));
},
getStripesElem(chart: ChartJS) {
return chart.canvas.parentElement.querySelector(".zebra-cover");
},
removeStripesElem(chart: ChartJS) {
const elem = this.getStripesElem(chart);
if (!elem) return;
chart.canvas.parentElement.removeChild(elem);
},
updateOptions(chart: ChartJS) {
this.options = {
...defaultOptions,
...this.getOptions(chart),
};
},
getStripeMinutes() {
return this.options.interval < 10 ? 0 : 10;
},
renderStripes(chart: ChartJS) {
if (!chart.data.datasets.length) return;
const { interval, stripeColor } = this.options;
const { top, left, bottom, right } = chart.chartArea;
const step = (right - left) / interval;
const stripeWidth = step * this.getStripeMinutes();
const cover = document.createElement("div");
const styles = cover.style;
if (this.getStripesElem(chart)) return;
cover.className = "zebra-cover";
styles.width = `${right - left}px`;
styles.left = `${left}px`;
styles.top = `${top}px`;
styles.height = `${bottom - top}px`;
styles.backgroundImage = `
repeating-linear-gradient(to right, ${stripeColor} 0px, ${stripeColor} ${stripeWidth}px,
transparent ${stripeWidth}px, transparent ${stripeWidth * 2 + step}px)
`;
chart.canvas.parentElement.appendChild(cover);
},
afterInit(chart: ChartJS) {
if (!chart.data.datasets.length) return;
this.updateOptions(chart);
this.updated = this.getLastUpdate(chart);
},
afterUpdate(chart: ChartJS) {
this.updateOptions(chart);
this.renderStripes(chart);
},
resize(chart: ChartJS) {
this.removeStripesElem(chart);
},
afterDatasetUpdate(chart: ChartJS): void {
if (!this.updated) this.updated = this.getLastUpdate(chart);
const { interval } = this.options;
const { left, right } = chart.chartArea;
const step = (right - left) / interval;
const diff = moment(this.updated).diff(this.getLastUpdate(chart), "minutes");
const minutes = Math.abs(diff);
this.removeStripesElem(chart);
this.renderStripes(chart);
if (minutes > 0) {
// Move position regarding to difference in time
const cover = this.getStripesElem(chart);
cover.style.backgroundPositionX = `${-step * minutes}px`;
}
},
};