From 5779ed06318333ee26e736f8e90f4c5863a3d84d Mon Sep 17 00:00:00 2001 From: Piotr Rogowski Date: Mon, 20 Dec 2021 23:23:04 +0100 Subject: [PATCH] Remove old LogCanvas component (#329) --- src/components/Log.tsx | 7 +- src/components/Log/LogCanvas.tsx | 152 ++++++++++++++---------- src/components/Log/LogCanvas2.tsx | 186 ------------------------------ 3 files changed, 97 insertions(+), 248 deletions(-) delete mode 100644 src/components/Log/LogCanvas2.tsx diff --git a/src/components/Log.tsx b/src/components/Log.tsx index b45c781..e7ba7f6 100644 --- a/src/components/Log.tsx +++ b/src/components/Log.tsx @@ -37,7 +37,7 @@ import { DatalogEntry, } from '@speedy-tuner/types'; import { loadLogs } from '../utils/api'; -import LogCanvas2 from './Log/LogCanvas2'; +import LogCanvas from './Log/LogCanvas'; import store from '../store'; import { formatBytes, @@ -88,7 +88,6 @@ const Log = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loadedLo collapsed: ui.sidebarCollapsed, onCollapse: (collapsed: boolean) => { store.dispatch({ type: 'ui/sidebarCollapsed', payload: collapsed }); - setTimeout(calculateCanvasSize, 1); }, }; const [logs, setLogs] = useState(); @@ -195,7 +194,7 @@ const Log = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loadedLo worker.terminate(); window.removeEventListener('resize', calculateCanvasSize); }; - }, [calculateCanvasSize, config.datalog, config.outputChannels, loadedLogs]); + }, [calculateCanvasSize, config.datalog, config.outputChannels, loadedLogs, ui.sidebarCollapsed]); return ( <> @@ -249,7 +248,7 @@ const Log = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loadedLo
{logs || !!loadedLogs.length ? - { +const LogCanvas = ({ data, width, height, selectedFields1, selectedFields2 }: Props) => { const { sm } = useBreakpoint(); - const canvasRef = useRef(null); const hsl = useCallback((fieldIndex: number, allFields: number) => { const [hue] = colorHsl(0, allFields - 1, fieldIndex); return `hsl(${hue}, 90%, 50%)`; }, []); + const [options1, setOptions1] = useState(); + const [plotData1, setPlotData1] = useState(); + const [options2, setOptions2] = useState(); + const [plotData2, setPlotData2] = useState(); - const fieldsToPlot = useMemo(() => { + const generateFieldsToPlot = useCallback((selectedFields: SelectedField[]) => { const temp: { [index: string]: PlottableField } = {}; data.forEach((entry) => { @@ -76,74 +86,100 @@ const LogCanvas = ({ data, width, height, selectedFields }: Props) => { }); return temp; - }, [data, selectedFields]); + }, [data]); - useEffect(() => { - const markers: { x: number, name: string }[] = []; - const series = Object.keys(fieldsToPlot).map((label, index) => { + const generatePlotConfig = useCallback((fieldsToPlot: { [index: string]: PlottableField }, selectedFieldsLength: number, plotSyncKey: string) => { + const dataSeries: uPlot.Series[] = []; + const xData: number[] = []; + const yData: (number | null)[][] = []; + + Object.keys(fieldsToPlot).forEach((label, index) => { const field = fieldsToPlot[label]; - return { - name: field.units ? `${label} (${field.units})` : label, - color: hsl(index, selectedFields.length), - data: data.map((entry, entryIndex) => { + dataSeries.push({ + label: field.units ? `${label} (${field.units})` : label, + points: { show: false }, + stroke: hsl(index, selectedFieldsLength), + scale: field.units, + width: 2, + value: (_self, val) => isNumber(val) ? val.toFixed(2) : 0, + }); + + data.forEach((entry) => { + if (entry.type === 'field') { + xData.push(entry.Time as number); + let value = entry[label]; if (value !== undefined) { value = (value as number * field.scale) + field.transform; } - if (entry.type === 'marker') { - const previousEntry = data[entryIndex - 1]; - if (previousEntry && previousEntry.Time !== undefined) { - markers.push({ - x: previousEntry.Time as number, - name: '', - }); - } + if (!yData[index]) { + yData[index] = []; } - return { - x: entry.Time, - y: value, - } as { x: number, y: number }; - }).filter((entry) => entry.x !== undefined && entry.y !== undefined), - }; - }); - let chart: TimeChart; - - if (canvasRef.current && sm) { - chart = new TimeChart(canvasRef.current, { - series, - lineWidth: 2, - tooltip: true, - legend: false, - zoom: { - x: { autoRange: true }, - }, - tooltipXLabel: 'Time (s)', - plugins: { - events: new EventsPlugin(markers), - }, + yData[index].push(value); + } }); - } + }); - return () => chart && chart.dispose(); - }, [data, fieldsToPlot, hsl, selectedFields, width, height, sm]); + return { + xData, + yData, + options: { + width, + height, + scales: { x: { time: false } }, + series: [ + { label: 'Time (s)' }, + ...dataSeries, + ], + axes: [ + { + stroke: Colors.TEXT, + grid: { stroke: Colors.MAIN_LIGHT }, + }, + ], + cursor: { + drag: { y: false }, + sync: { + key: plotSyncKey, + }, + }, + plugins: [touchZoomPlugin()], + }, + }; + }, [data, height, hsl, width]); + + useEffect(() => { + const plotSync = uPlot.sync('logs'); + + const result1 = generatePlotConfig(generateFieldsToPlot(selectedFields1), selectedFields1.length, plotSync.key); + setOptions1(result1.options); + setPlotData1([result1.xData, ...result1.yData]); + + const result2 = generatePlotConfig(generateFieldsToPlot(selectedFields2), selectedFields2.length, plotSync.key); + setOptions2(result2.options); + setPlotData2([result2.xData, ...result2.yData]); + + }, [data, hsl, width, height, sm, generatePlotConfig, generateFieldsToPlot, selectedFields1, selectedFields2]); if (!sm) { return ; } return ( - <> - -
+ - + + ); }; diff --git a/src/components/Log/LogCanvas2.tsx b/src/components/Log/LogCanvas2.tsx deleted file mode 100644 index 03f0abd..0000000 --- a/src/components/Log/LogCanvas2.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import { - useCallback, - useEffect, - useState, -} from 'react'; -import { Logs } from '@speedy-tuner/types'; -import { - Grid, - Space, -} from 'antd'; -import UplotReact from 'uplot-react'; -import uPlot from 'uplot'; -import { colorHsl } from '../../utils/number'; -import LandscapeNotice from '../Dialog/LandscapeNotice'; -import { Colors } from '../../utils/colors'; -import touchZoomPlugin from '../../utils/uPlot/touchZoomPlugin'; - -import 'uplot/dist/uPlot.min.css'; -import { isNumber } from '../../utils/tune/expression'; - -const { useBreakpoint } = Grid; - -export interface SelectedField { - name: string; - label: string; - units: string; - scale: string | number; - transform: string | number; - format: string; -}; - -interface Props { - data: Logs; - width: number; - height: number; - selectedFields1: SelectedField[]; - selectedFields2: SelectedField[]; -}; - -export interface PlottableField { - min: number; - max: number; - scale: number; - transform: number; - units: string; - format: string; -}; - -const LogCanvas2 = ({ data, width, height, selectedFields1, selectedFields2 }: Props) => { - const { sm } = useBreakpoint(); - const hsl = useCallback((fieldIndex: number, allFields: number) => { - const [hue] = colorHsl(0, allFields - 1, fieldIndex); - return `hsl(${hue}, 90%, 50%)`; - }, []); - const [options1, setOptions1] = useState(); - const [plotData1, setPlotData1] = useState(); - const [options2, setOptions2] = useState(); - const [plotData2, setPlotData2] = useState(); - - const generateFieldsToPlot = useCallback((selectedFields: SelectedField[]) => { - const temp: { [index: string]: PlottableField } = {}; - - data.forEach((entry) => { - selectedFields.forEach(({ label, scale, transform, units, format }) => { - const value = entry[label]; - - if (!temp[label]) { - temp[label] = { - min: 0, - max: 0, - scale: (scale || 1) as number, - transform: (transform || 0) as number, - units: units || '', - format: format || '', - }; - } - - if (value > temp[label].max) { - temp[label].max = entry[label] as number; - } - - if (value < temp[label].min) { - temp[label].min = entry[label] as number; - } - }); - }); - - return temp; - }, [data]); - - const generatePlotConfig = useCallback((fieldsToPlot: { [index: string]: PlottableField }, selectedFieldsLength: number, plotSyncKey: string) => { - const dataSeries: uPlot.Series[] = []; - const xData: number[] = []; - const yData: (number | null)[][] = []; - - Object.keys(fieldsToPlot).forEach((label, index) => { - const field = fieldsToPlot[label]; - - dataSeries.push({ - label: field.units ? `${label} (${field.units})` : label, - points: { show: false }, - stroke: hsl(index, selectedFieldsLength), - scale: field.units, - width: 2, - value: (_self, val) => isNumber(val) ? val.toFixed(2) : 0, - }); - - data.forEach((entry) => { - if (entry.type !== 'marker') { - xData.push(entry.Time as number); - - let value = entry[label]; - - if (value !== undefined) { - value = (value as number * field.scale) + field.transform; - } - - if (!yData[index]) { - yData[index] = []; - } - - yData[index].push(value); - } - }); - }); - - return { - xData, - yData, - options: { - width, - height, - scales: { x: { time: false } }, - series: [ - { label: 'Time (s)' }, - ...dataSeries, - ], - axes: [ - { - stroke: Colors.TEXT, - grid: { stroke: Colors.MAIN_LIGHT }, - }, - ], - cursor: { - drag: { y: false }, - sync: { - key: plotSyncKey, - }, - }, - plugins: [touchZoomPlugin()], - }, - }; - }, [data, height, hsl, width]); - - useEffect(() => { - const plotSync = uPlot.sync('logs'); - - const result1 = generatePlotConfig(generateFieldsToPlot(selectedFields1), selectedFields1.length, plotSync.key); - setOptions1(result1.options); - setPlotData1([result1.xData, ...result1.yData]); - - const result2 = generatePlotConfig(generateFieldsToPlot(selectedFields2), selectedFields2.length, plotSync.key); - setOptions2(result2.options); - setPlotData2([result2.xData, ...result2.yData]); - - }, [data, hsl, width, height, sm, generatePlotConfig, generateFieldsToPlot, selectedFields1, selectedFields2]); - - if (!sm) { - return ; - } - - return ( - - - - - ); -}; - -export default LogCanvas2;