mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
cleanup Lens repo with tighter linting
Signed-off-by: Sebastian Malton <smalton@mirantis.com>
This commit is contained in:
1 parent
e468105143
commit
b1ff34879a
470 files changed
+8447
-7443
No files matched your search
@@ -6,24 +6,26 @@ const defaultOptions = {
|
||||
coverBars: 3,
|
||||
borderColor: "#44474A",
|
||||
backgroundColor: "#00000033"
|
||||
}
|
||||
};
|
||||
|
||||
export const BackgroundBlock = {
|
||||
options: {},
|
||||
|
||||
getOptions(chart: ChartJS) {
|
||||
getOptions(chart: ChartJS): any {
|
||||
return get(chart, "options.plugins.BackgroundBlock");
|
||||
},
|
||||
|
||||
afterInit(chart: ChartJS) {
|
||||
afterInit(chart: ChartJS): void {
|
||||
this.options = {
|
||||
...defaultOptions,
|
||||
...this.getOptions(chart)
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
beforeDraw(chart: ChartJS) {
|
||||
if (!chart.chartArea) return;
|
||||
beforeDraw(chart: ChartJS): void {
|
||||
if (!chart.chartArea) {
|
||||
return;
|
||||
}
|
||||
const { interval, coverBars, borderColor, backgroundColor } = this.options;
|
||||
const { ctx, chartArea } = chart;
|
||||
const { left, right, top, bottom } = chartArea;
|
||||
@@ -39,4 +41,4 @@ export const BackgroundBlock = {
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -18,7 +18,7 @@ interface Props extends ChartProps {
|
||||
timeLabelStep?: number; // Minute labels appearance step
|
||||
}
|
||||
|
||||
interface IChartContext {
|
||||
interface ChartContext {
|
||||
chart: ChartJS;
|
||||
dataIndex?: number;
|
||||
dataset?: ChartDataSet;
|
||||
@@ -29,23 +29,28 @@ const defaultProps: Partial<Props> = {
|
||||
plugins: [ZebraStripes]
|
||||
};
|
||||
|
||||
BarChart.defaultProps = defaultProps;
|
||||
|
||||
export function BarChart(props: Props) {
|
||||
const { name, data, className, timeLabelStep, plugins, options: customOptions, ...settings } = props;
|
||||
export function BarChart({
|
||||
name: _name,
|
||||
data,
|
||||
className,
|
||||
timeLabelStep,
|
||||
plugins,
|
||||
options: customOptions,
|
||||
...settings
|
||||
}: Props): JSX.Element {
|
||||
const { textColorPrimary, borderFaintColor, chartStripesColor } = themeStore.activeTheme.colors;
|
||||
|
||||
const savedName = useRef<string>();
|
||||
|
||||
useEffect(() => {
|
||||
savedName.current = props.name;
|
||||
savedName.current = name;
|
||||
});
|
||||
|
||||
const getBarColor = (ctx: IChartContext) => {
|
||||
const getBarColor = (ctx: ChartContext): string => {
|
||||
const { dataset } = ctx;
|
||||
const color = dataset.borderColor;
|
||||
return Color(color).alpha(0.2).string();
|
||||
}
|
||||
};
|
||||
|
||||
// Remove empty sets and insert default data
|
||||
const chartData: ChartData = {
|
||||
@@ -59,15 +64,19 @@ export function BarChart(props: Props) {
|
||||
barPercentage: 1,
|
||||
categoryPercentage: 1,
|
||||
...item
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
const formatTimeLabels = (timestamp: string, index: number) => {
|
||||
const formatTimeLabels = (timestamp: string, index: number): string => {
|
||||
const label = moment(parseInt(timestamp)).format("HH:mm");
|
||||
const offset = " ";
|
||||
if (index == 0) return offset + label;
|
||||
if (index == 60) return label + offset;
|
||||
if (index == 0) {
|
||||
return offset + label;
|
||||
}
|
||||
if (index == 60) {
|
||||
return label + offset;
|
||||
}
|
||||
return index % timeLabelStep == 0 ? label : "";
|
||||
};
|
||||
|
||||
@@ -98,7 +107,7 @@ export function BarChart(props: Props) {
|
||||
displayFormats: {
|
||||
minute: "x"
|
||||
},
|
||||
parser: timestamp => moment.unix(parseInt(timestamp))
|
||||
parser: (timestamp): moment.Moment => moment.unix(parseInt(timestamp))
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
@@ -122,16 +131,18 @@ export function BarChart(props: Props) {
|
||||
mode: "index",
|
||||
position: "cursor",
|
||||
callbacks: {
|
||||
title: tooltipItems => {
|
||||
const now = new Date().getTime()
|
||||
if (new Date(tooltipItems[0].xLabel).getTime() > now) return "";
|
||||
return `${tooltipItems[0].xLabel}`
|
||||
title: (tooltipItems): string => {
|
||||
const now = new Date().getTime();
|
||||
if (new Date(tooltipItems[0].xLabel).getTime() > now) {
|
||||
return "";
|
||||
}
|
||||
return `${tooltipItems[0].xLabel}`;
|
||||
},
|
||||
labelColor: ({ datasetIndex }) => {
|
||||
labelColor: ({ datasetIndex }): ChartJS.ChartTooltipLabelColor => {
|
||||
return {
|
||||
borderColor: "darkgray",
|
||||
backgroundColor: chartData.datasets[datasetIndex].borderColor as string
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -151,7 +162,7 @@ export function BarChart(props: Props) {
|
||||
};
|
||||
const options = merge(barOptions, customOptions);
|
||||
if (chartData.datasets.length == 0) {
|
||||
return <NoMetrics/>
|
||||
return <NoMetrics/>;
|
||||
}
|
||||
return (
|
||||
<Chart
|
||||
@@ -162,9 +173,11 @@ export function BarChart(props: Props) {
|
||||
plugins={plugins}
|
||||
{...settings}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
BarChart.defaultProps = defaultProps;
|
||||
|
||||
// Default options for all charts containing memory units (network, disk, memory, etc)
|
||||
export const memoryOptions: ChartOptions = {
|
||||
scales: {
|
||||
@@ -188,14 +201,14 @@ export const memoryOptions: ChartOptions = {
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: ({ datasetIndex, index }, { datasets }) => {
|
||||
label: ({ datasetIndex, index }, { datasets }): string => {
|
||||
const { label, data } = datasets[datasetIndex];
|
||||
const value = data[index] as ChartPoint;
|
||||
return `${label}: ${bytesToUnits(parseInt(value.y.toString()), 3)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Default options for all charts with cpu units or other decimal numbers
|
||||
export const cpuOptions: ChartOptions = {
|
||||
@@ -204,9 +217,15 @@ export const cpuOptions: ChartOptions = {
|
||||
ticks: {
|
||||
callback: (value: number | string): string => {
|
||||
const float = parseFloat(`${value}`);
|
||||
if (float == 0) return "0";
|
||||
if (float < 10) return float.toFixed(3);
|
||||
if (float < 100) return float.toFixed(2);
|
||||
if (float == 0) {
|
||||
return "0";
|
||||
}
|
||||
if (float < 10) {
|
||||
return float.toFixed(3);
|
||||
}
|
||||
if (float < 100) {
|
||||
return float.toFixed(2);
|
||||
}
|
||||
return float.toFixed(1);
|
||||
}
|
||||
}
|
||||
@@ -214,11 +233,11 @@ export const cpuOptions: ChartOptions = {
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: ({ datasetIndex, index }, { datasets }) => {
|
||||
label: ({ datasetIndex, index }, { datasets }): string => {
|
||||
const { label, data } = datasets[datasetIndex];
|
||||
const value = data[index] as ChartPoint;
|
||||
return `${label}: ${parseFloat(value.y as string).toPrecision(2)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -60,88 +60,92 @@ export class Chart extends PureComponent<ChartProps> {
|
||||
// We clone new data prop into currentChartData to compare props and prevProps
|
||||
private currentChartData: ChartData
|
||||
|
||||
componentDidMount() {
|
||||
const { showChart } = this.props
|
||||
if (!showChart) return
|
||||
this.renderChart()
|
||||
componentDidMount(): void {
|
||||
const { showChart } = this.props;
|
||||
if (!showChart) {
|
||||
return;
|
||||
}
|
||||
this.renderChart();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: ChartProps) {
|
||||
const { data, showChart, redraw } = this.props
|
||||
componentDidUpdate(prevProps: ChartProps): void {
|
||||
const { data, showChart, redraw } = this.props;
|
||||
if (redraw) {
|
||||
this.chart.destroy()
|
||||
this.renderChart()
|
||||
return
|
||||
this.chart.destroy();
|
||||
this.renderChart();
|
||||
return;
|
||||
}
|
||||
if (!isEqual(prevProps.data, data) && showChart) {
|
||||
if (!this.chart) this.renderChart()
|
||||
else this.updateChart()
|
||||
if (!this.chart) {
|
||||
this.renderChart();
|
||||
} else {
|
||||
this.updateChart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memoizeDataProps() {
|
||||
const { data } = this.props
|
||||
memoizeDataProps(): void {
|
||||
const { data } = this.props;
|
||||
this.currentChartData = {
|
||||
...data,
|
||||
datasets: data.datasets && data.datasets.map(set => {
|
||||
return {
|
||||
...set
|
||||
}
|
||||
})
|
||||
}
|
||||
datasets: data.datasets && data.datasets.map(set => ({ ...set }))
|
||||
};
|
||||
}
|
||||
|
||||
updateChart() {
|
||||
const { options } = this.props
|
||||
updateChart(): void {
|
||||
const { options } = this.props;
|
||||
|
||||
if (!this.chart) return
|
||||
if (!this.chart) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.chart.options = ChartJS.helpers.configMerge(this.chart.options, options)
|
||||
this.chart.options = ChartJS.helpers.configMerge(this.chart.options, options);
|
||||
|
||||
this.memoizeDataProps()
|
||||
this.memoizeDataProps();
|
||||
|
||||
const datasets: ChartDataSet[] = this.chart.config.data.datasets
|
||||
const nextDatasets: ChartDataSet[] = this.currentChartData.datasets || []
|
||||
const datasets: ChartDataSet[] = this.chart.config.data.datasets;
|
||||
const nextDatasets: ChartDataSet[] = this.currentChartData.datasets || [];
|
||||
|
||||
// Remove stale datasets if they're not available in nextDatasets
|
||||
if (datasets.length > nextDatasets.length) {
|
||||
const sets = [...datasets];
|
||||
sets.forEach(set => {
|
||||
if (!nextDatasets.find(next => next.id === set.id)) {
|
||||
remove(datasets, (item => item.id === set.id))
|
||||
remove(datasets, (item => item.id === set.id));
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Mutating inner chart datasets to enable seamless transitions
|
||||
nextDatasets.forEach((next, datasetIndex) => {
|
||||
const index = datasets.findIndex(set => set.id === next.id)
|
||||
const index = datasets.findIndex(set => set.id === next.id);
|
||||
if (index !== -1) {
|
||||
datasets[index].data = datasets[index].data.slice() // "Clean" mobx observables data to use in ChartJS
|
||||
datasets[index].data.splice(next.data.length)
|
||||
datasets[index].data = datasets[index].data.slice(); // "Clean" mobx observables data to use in ChartJS
|
||||
datasets[index].data.splice(next.data.length);
|
||||
next.data.forEach((point: any, dataIndex: number) => {
|
||||
datasets[index].data[dataIndex] = next.data[dataIndex]
|
||||
})
|
||||
datasets[index].data[dataIndex] = next.data[dataIndex];
|
||||
});
|
||||
|
||||
// Merge other fields
|
||||
const { data, ...props } = next
|
||||
const { data: _data, ...props } = next;
|
||||
datasets[index] = {
|
||||
...datasets[index],
|
||||
...props
|
||||
}
|
||||
};
|
||||
} else {
|
||||
datasets[datasetIndex] = next;
|
||||
}
|
||||
else {
|
||||
datasets[datasetIndex] = next
|
||||
}
|
||||
})
|
||||
this.chart.update()
|
||||
});
|
||||
this.chart.update();
|
||||
}
|
||||
|
||||
renderLegend() {
|
||||
if (!this.props.showLegend) return null
|
||||
const { data, legendColors } = this.props
|
||||
const { labels, datasets } = data
|
||||
const labelElem = (title: string, color: string, tooltip?: string) => (
|
||||
renderLegend(): JSX.Element {
|
||||
if (!this.props.showLegend) {
|
||||
return null;
|
||||
}
|
||||
const { data, legendColors } = this.props;
|
||||
const { labels, datasets } = data;
|
||||
const labelElem = (title: string, color: string, tooltip?: string): JSX.Element => (
|
||||
<Badge
|
||||
key={title}
|
||||
className="flex gaps align-center"
|
||||
@@ -153,24 +157,24 @@ export class Chart extends PureComponent<ChartProps> {
|
||||
)}
|
||||
tooltip={tooltip}
|
||||
/>
|
||||
)
|
||||
);
|
||||
return (
|
||||
<div className="legend flex wrap gaps">
|
||||
{labels && labels.map((label: string, index) => {
|
||||
const { backgroundColor } = datasets[0] as any
|
||||
const color = legendColors ? legendColors[index] : backgroundColor[index]
|
||||
return labelElem(label, color)
|
||||
const { backgroundColor } = datasets[0] as any;
|
||||
const color = legendColors ? legendColors[index] : backgroundColor[index];
|
||||
return labelElem(label, color);
|
||||
})}
|
||||
{!labels && datasets.map(({ borderColor, label, tooltip }) =>
|
||||
labelElem(label, borderColor as any, tooltip)
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderChart() {
|
||||
const { type, options, plugins } = this.props
|
||||
this.memoizeDataProps()
|
||||
renderChart(): void {
|
||||
const { type, options, plugins } = this.props;
|
||||
this.memoizeDataProps();
|
||||
this.chart = new ChartJS(this.canvas.current, {
|
||||
type,
|
||||
plugins,
|
||||
@@ -181,11 +185,11 @@ export class Chart extends PureComponent<ChartProps> {
|
||||
},
|
||||
},
|
||||
data: this.currentChartData,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { width, height, showChart, title, className } = this.props
|
||||
render(): JSX.Element {
|
||||
const { width, height, showChart, title, className } = this.props;
|
||||
return (
|
||||
<>
|
||||
<div className={cssNames("Chart", className)}>
|
||||
@@ -203,6 +207,6 @@ export class Chart extends PureComponent<ChartProps> {
|
||||
{this.renderLegend()}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from "./chart"
|
||||
export * from "./pie-chart"
|
||||
export * from "./bar-chart"
|
||||
export * from "./chart";
|
||||
export * from "./pie-chart";
|
||||
export * from "./bar-chart";
|
||||
@@ -1,7 +1,7 @@
|
||||
import "./pie-chart.scss";
|
||||
import * as React from "react";
|
||||
import * as ChartJS from "chart.js";
|
||||
import { ChartData, ChartOptions } from "chart.js";
|
||||
import ChartJS from "chart.js";
|
||||
import { ChartOptions } from "chart.js";
|
||||
import { Chart, ChartProps } from "./chart";
|
||||
import { cssNames } from "../../utils";
|
||||
import { themeStore } from "../../theme.store";
|
||||
@@ -11,27 +11,31 @@ interface Props extends ChartProps {
|
||||
}
|
||||
|
||||
export class PieChart extends React.Component<Props> {
|
||||
render() {
|
||||
const { data, className, options, ...settings } = this.props
|
||||
render(): JSX.Element {
|
||||
const { data, className, options, ...settings } = this.props;
|
||||
const { contentColor } = themeStore.activeTheme.colors;
|
||||
const cutouts = [88, 76, 63]
|
||||
const cutouts = [88, 76, 63];
|
||||
const opts: ChartOptions = this.props.showChart === false ? {} : {
|
||||
maintainAspectRatio: false,
|
||||
tooltips: {
|
||||
mode: "index",
|
||||
callbacks: {
|
||||
title: () => "",
|
||||
label: (tooltipItem, data) => {
|
||||
const dataset: any = data["datasets"][tooltipItem.datasetIndex]
|
||||
const metaData = Object.values<{ total: number }>(dataset["_meta"])[0]
|
||||
const percent = Math.round((dataset["data"][tooltipItem["index"]] / metaData.total) * 100)
|
||||
if (isNaN(percent)) return "N/A";
|
||||
title: (): string => "",
|
||||
label: (tooltipItem, data): string => {
|
||||
const dataset: any = data["datasets"][tooltipItem.datasetIndex];
|
||||
const metaData = Object.values<{ total: number }>(dataset["_meta"])[0];
|
||||
const percent = Math.round((dataset["data"][tooltipItem["index"]] / metaData.total) * 100);
|
||||
if (isNaN(percent)) {
|
||||
return "N/A";
|
||||
}
|
||||
return percent + "%";
|
||||
},
|
||||
},
|
||||
filter: ({ datasetIndex, index }, { datasets }) => {
|
||||
filter: ({ datasetIndex, index }, { datasets }): boolean => {
|
||||
const { data } = datasets[datasetIndex];
|
||||
if (datasets.length === 1) return true;
|
||||
if (datasets.length === 1) {
|
||||
return true;
|
||||
}
|
||||
return index !== data.length - 1;
|
||||
},
|
||||
position: "cursor",
|
||||
@@ -45,7 +49,7 @@ export class PieChart extends React.Component<Props> {
|
||||
cutoutPercentage: cutouts[data.datasets.length - 1] || 50,
|
||||
responsive: true,
|
||||
...options
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Chart
|
||||
className={cssNames("PieChart flex column align-center", className)}
|
||||
@@ -53,10 +57,10 @@ export class PieChart extends React.Component<Props> {
|
||||
options={opts}
|
||||
{...settings}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChartJS.Tooltip.positioners.cursor = function (elements: any, position: { x: number; y: number }) {
|
||||
ChartJS.Tooltip.positioners.cursor = function (elements: any, position: { x: number; y: number }): {x: number; y: number } {
|
||||
return position;
|
||||
};
|
||||
@@ -2,15 +2,18 @@ import moment from "moment";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useInterval } from "../../hooks";
|
||||
|
||||
type IMetricValues = [number, string][];
|
||||
type IChartData = { x: number; y: string }[]
|
||||
type MetricValue = [number, string];
|
||||
interface ChartDatum {
|
||||
x: number;
|
||||
y: string;
|
||||
}
|
||||
|
||||
const defaultParams = {
|
||||
fetchInterval: 15,
|
||||
updateInterval: 5
|
||||
}
|
||||
};
|
||||
|
||||
export function useRealTimeMetrics(metrics: IMetricValues, chartData: IChartData, params = defaultParams) {
|
||||
export function useRealTimeMetrics(metrics: MetricValue[], chartData: ChartDatum[], params = defaultParams): ChartDatum[] {
|
||||
const [index, setIndex] = useState(0);
|
||||
const { fetchInterval, updateInterval } = params;
|
||||
const rangeMetrics = metrics.slice(-updateInterval);
|
||||
|
||||
@@ -9,33 +9,37 @@ const defaultOptions = {
|
||||
interval: 61,
|
||||
stripeMinutes: 10,
|
||||
stripeColor: "#ffffff08",
|
||||
}
|
||||
};
|
||||
|
||||
export const ZebraStripes = {
|
||||
updated: null as Moment, // timestamp which all stripe movements based on
|
||||
options: {},
|
||||
|
||||
getOptions(chart: ChartJS) {
|
||||
getOptions(chart: ChartJS): any {
|
||||
return get(chart, "options.plugins.ZebraStripes");
|
||||
},
|
||||
|
||||
getLastUpdate(chart: ChartJS) {
|
||||
getLastUpdate(chart: ChartJS): moment.Moment {
|
||||
const data = chart.data.datasets[0].data[0] as ChartPoint;
|
||||
return moment.unix(parseInt(data.x as string));
|
||||
},
|
||||
|
||||
getStripesElem(chart: ChartJS) {
|
||||
getStripesElem(chart: ChartJS): Element {
|
||||
return chart.canvas.parentElement.querySelector(".zebra-cover");
|
||||
},
|
||||
|
||||
removeStripesElem(chart: ChartJS) {
|
||||
removeStripesElem(chart: ChartJS): void {
|
||||
const elem = this.getStripesElem(chart);
|
||||
if (!elem) return;
|
||||
if (!elem) {
|
||||
return;
|
||||
}
|
||||
chart.canvas.parentElement.removeChild(elem);
|
||||
},
|
||||
|
||||
renderStripes(chart: ChartJS) {
|
||||
if (!chart.data.datasets.length) return;
|
||||
renderStripes(chart: ChartJS): void {
|
||||
if (!chart.data.datasets.length) {
|
||||
return;
|
||||
}
|
||||
const { interval, stripeMinutes, stripeColor } = this.options;
|
||||
const { top, left, bottom, right } = chart.chartArea;
|
||||
const step = (right - left) / interval;
|
||||
@@ -43,7 +47,9 @@ export const ZebraStripes = {
|
||||
const cover = document.createElement("div");
|
||||
const styles = cover.style;
|
||||
|
||||
if (this.getStripesElem(chart)) return;
|
||||
if (this.getStripesElem(chart)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cover.className = "zebra-cover";
|
||||
styles.width = right - left + "px";
|
||||
@@ -57,25 +63,29 @@ export const ZebraStripes = {
|
||||
chart.canvas.parentElement.appendChild(cover);
|
||||
},
|
||||
|
||||
afterInit(chart: ChartJS) {
|
||||
if (!chart.data.datasets.length) return;
|
||||
afterInit(chart: ChartJS): void {
|
||||
if (!chart.data.datasets.length) {
|
||||
return;
|
||||
}
|
||||
this.options = {
|
||||
...defaultOptions,
|
||||
...this.getOptions(chart)
|
||||
}
|
||||
};
|
||||
this.updated = this.getLastUpdate(chart);
|
||||
},
|
||||
|
||||
afterUpdate(chart: ChartJS) {
|
||||
afterUpdate(chart: ChartJS): void {
|
||||
this.renderStripes(chart);
|
||||
},
|
||||
|
||||
resize(chart: ChartJS) {
|
||||
resize(chart: ChartJS): void {
|
||||
this.removeStripesElem(chart);
|
||||
},
|
||||
|
||||
afterDatasetUpdate(chart: ChartJS): void {
|
||||
if (!this.updated) this.updated = this.getLastUpdate(chart);
|
||||
if (!this.updated) {
|
||||
this.updated = this.getLastUpdate(chart);
|
||||
}
|
||||
|
||||
const { interval } = this.options;
|
||||
const { left, right } = chart.chartArea;
|
||||
@@ -92,4 +102,4 @@ export const ZebraStripes = {
|
||||
cover.style.backgroundPositionX = -step * minutes + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user