cleanup Lens repo with tighter linting

Signed-off-by: Sebastian Malton <smalton@mirantis.com>
This commit is contained in:
Sebastian Malton committed 2020-07-09 17:00:23 -04:00
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();
}
}
};
+47 -28
View File
@@ -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)}`;
}
}
}
}
};
+61 -57
View File
@@ -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>
</>
)
);
}
}
+3 -3
View File
@@ -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";
+20 -16
View File
@@ -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";
}
}
}
};