Improve logs

This commit is contained in:
Piotr Rogowski 2021-12-15 20:28:55 +01:00
parent 5efa4a6c31
commit 2073b41031
No known key found for this signature in database
GPG Key ID: F40F61D5587F5673
4 changed files with 60 additions and 28 deletions

View File

@ -12,6 +12,7 @@
"scripts": { "scripts": {
"start": "craco start", "start": "craco start",
"build": "craco build", "build": "craco build",
"build:stats": "craco build --stats",
"test": "craco test", "test": "craco test",
"lint": "tsc && eslint --max-warnings=0 src", "lint": "tsc && eslint --max-warnings=0 src",
"lint:fix": "eslint --fix src" "lint:fix": "eslint --fix src"

View File

@ -104,5 +104,5 @@ html, body {
.log-canvas { .log-canvas {
color: @text; color: @text;
--background-overlay: transparent; --background-overlay: rgba(34, 38, 41, 0.9);
} }

View File

@ -215,9 +215,6 @@ const Log = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loadedLo
Files Files
</PerfectScrollbar> </PerfectScrollbar>
</TabPane> </TabPane>
<TabPane tab={<DashboardOutlined />} key="gauges">
Gauges
</TabPane>
</Tabs> </Tabs>
} }
</Sider> </Sider>
@ -229,7 +226,7 @@ const Log = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loadedLo
<LogCanvas <LogCanvas
data={loadedLogs || (logs!.records as Logs)} data={loadedLogs || (logs!.records as Logs)}
width={canvasWidth} width={canvasWidth}
height={800} height={canvasWidth * 0.45}
selectedFields={prepareSelectedFields} selectedFields={prepareSelectedFields}
/> />
: :

View File

@ -8,8 +8,16 @@ import {
Logs, Logs,
LogEntry, LogEntry,
} from '@speedy-tuner/types'; } from '@speedy-tuner/types';
import {
Popover,
Space,
Typography,
Grid,
} from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import TimeChart from 'timechart'; import TimeChart from 'timechart';
import { colorHsl } from '../../utils/number'; import { colorHsl } from '../../utils/number';
import LandscapeNotice from '../Dialog/LandscapeNotice';
// enum Colors { // enum Colors {
// RED = '#f32450', // RED = '#f32450',
@ -23,6 +31,9 @@ import { colorHsl } from '../../utils/number';
// BG = '#222629', // BG = '#222629',
// } // }
const { Text } = Typography;
const { useBreakpoint } = Grid;
export interface SelectedField { export interface SelectedField {
name: string; name: string;
label: string; label: string;
@ -49,8 +60,8 @@ export interface PlottableField {
}; };
const LogCanvas = ({ data, width, height, selectedFields }: Props) => { const LogCanvas = ({ data, width, height, selectedFields }: Props) => {
const { sm } = useBreakpoint();
const canvasRef = useRef<HTMLDivElement | null>(null); const canvasRef = useRef<HTMLDivElement | null>(null);
const hsl = useCallback((fieldIndex: number, allFields: number) => { const hsl = useCallback((fieldIndex: number, allFields: number) => {
const [hue] = colorHsl(0, allFields - 1, fieldIndex); const [hue] = colorHsl(0, allFields - 1, fieldIndex);
return `hsl(${hue}, 90%, 50%)`; return `hsl(${hue}, 90%, 50%)`;
@ -60,8 +71,6 @@ const LogCanvas = ({ data, width, height, selectedFields }: Props) => {
const filtered = useMemo(() => data.filter(fieldsOnly), [data]); const filtered = useMemo(() => data.filter(fieldsOnly), [data]);
// find max values for each selected field so we can calculate scale
// TODO: unused
const fieldsToPlot = useMemo(() => { const fieldsToPlot = useMemo(() => {
const temp: { [index: string]: PlottableField } = {}; const temp: { [index: string]: PlottableField } = {};
@ -94,35 +103,60 @@ const LogCanvas = ({ data, width, height, selectedFields }: Props) => {
}, [filtered, selectedFields]); }, [filtered, selectedFields]);
useEffect(() => { useEffect(() => {
const series = selectedFields.map((field) => ({ const series = Object.keys(fieldsToPlot).map((label, index) => ({
name: field.label, name: fieldsToPlot[label].units ? `${label} (${fieldsToPlot[label].units})` : label,
color: hsl(selectedFields.indexOf(field), selectedFields.length), color: hsl(index, selectedFields.length),
data: data.map((entry) => ({ data: data.map((entry) => ({
x: entry.Time as number, x: entry.Time as number,
y: entry[field.label] as number, y: entry[label] as number,
})).filter((entry) => entry.x !== undefined || entry.y !== undefined), })).filter((entry) => entry.x !== undefined || entry.y !== undefined),
})); }));
let chart: TimeChart;
const chart = new TimeChart(canvasRef.current!, { if (canvasRef.current) {
series, chart = new TimeChart(canvasRef.current, {
lineWidth: 2, series,
tooltip: true, lineWidth: 2,
legend: false, tooltip: true,
zoom: { legend: false,
x: { autoRange: true }, zoom: {
y: { autoRange: true }, x: { autoRange: true },
}, },
}); tooltipXLabel: 'Time (s)',
});
}
return () => chart.dispose(); return () => chart && chart.dispose();
}, [data, fieldsToPlot, filtered, hsl, selectedFields, width, height]); }, [data, fieldsToPlot, filtered, hsl, selectedFields, width, height]);
if (!sm) {
return <LandscapeNotice />;
}
return ( return (
<div <>
ref={canvasRef} <div style={{ marginTop: -20, marginBottom: 10, textAlign: 'left', marginLeft: 20 }}>
style={{ width, height }} <Popover
className="log-canvas" placement="bottom"
/> content={
<Space direction="vertical">
<Typography.Title level={5}>Navigation</Typography.Title>
<Text>Pinch to zoom</Text>
<Text>Drag to pan</Text>
<Text>Ctrl + wheel scroll to zoom X axis</Text>
<Text>Hold Shift to speed up zoom 5 times</Text>
</Space>
}
>
<QuestionCircleOutlined />
</Popover>
</div>
<div
ref={canvasRef}
style={{ width, height }}
className="log-canvas"
/>
</>
); );
}; };