Skip to content

Commit e2308c5

Browse files
authored
Merge pull request #107 from HyperloopUPV-H8/ethernet-view/optimise-charts
[ethernet-view] Optimise charts
2 parents e7f6a00 + c4d5d75 commit e2308c5

5 files changed

Lines changed: 67 additions & 132 deletions

File tree

ethernet-view/src/components/ChartMenu/ChartElement/ChartCanvas/ChartCanvas.tsx

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
1-
import { MeasurementId, UpdateFunction, useGlobalTicker } from "common";
2-
import { ChartId, useChartStore } from "components/ChartMenu/ChartStore";
1+
import { MeasurementId, NumericMeasurementInfo, UpdateFunction, useGlobalTicker } from "common";
32
import { ColorType, IChartApi, ISeriesApi, UTCTimestamp, createChart } from "lightweight-charts";
43
import { useEffect, useRef } from "react";
54

65
type DataSerieAndUpdater = Map<MeasurementId, [ISeriesApi<"Line">, UpdateFunction]>;
76

87
interface Props {
9-
chartId: ChartId
10-
}
8+
measurementsInChart: NumericMeasurementInfo[];
9+
}
1110

1211
const CHART_HEIGHT = 300;
1312

14-
export const ChartCanvas = ({ chartId }: Props) => {
13+
export const ChartCanvas = ({ measurementsInChart }: Props) => {
1514

16-
const measurements = useChartStore((state) => {
17-
const chart = state.charts.find((chart) => chart.chartId === chartId);
18-
return chart ? chart.measurements : [];
19-
})
20-
21-
const chartContainerRef = useRef<HTMLDivElement>(null);
2215
const chart = useRef<IChartApi | null>(null);
16+
const chartContainerRef = useRef<HTMLDivElement>(null);
2317
const chartDataSeries = useRef<DataSerieAndUpdater>(new Map());
2418

2519
useEffect(() => {
@@ -61,11 +55,11 @@ export const ChartCanvas = ({ chartId }: Props) => {
6155

6256
useEffect(() => {
6357
chartDataSeries.current.clear();
64-
measurements.forEach((measurement) => {
58+
measurementsInChart.forEach((measurement) => {
6559
if(chart.current)
6660
chartDataSeries.current.set(measurement.id, [chart.current.addLineSeries({color: measurement.color}), measurement.getUpdate]);
6761
});
68-
}, [measurements.length])
62+
})
6963

7064
useGlobalTicker(() => {
7165
const now = Date.now() / 1000 as UTCTimestamp;
Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,40 @@
11
import styles from "./ChartElement.module.scss";
22
import { AiOutlineCloseCircle } from 'react-icons/ai'
3-
import { useMeasurementsStore } from 'common';
3+
import { MeasurementId, NumericMeasurementInfo, useMeasurementsStore } from 'common';
44
import { ChartCanvas } from './ChartCanvas/ChartCanvas';
55
import { ChartLegend } from './ChartLegend/ChartLegend';
6-
import { ChartId, useChartStore } from "../ChartStore";
6+
import { memo, useCallback, useState } from "react";
7+
import { ChartId } from "../ChartMenu";
78

89
type Props = {
910
chartId: ChartId;
11+
initialMeasurementId: MeasurementId;
12+
removeChart: (chartId: ChartId) => void;
1013
};
1114

1215
// React component that keeps the chart render and measurements represented on it.
13-
export const ChartElement = ({ chartId }: Props) => {
16+
export const ChartElement = memo(({ chartId, initialMeasurementId, removeChart }: Props) => {
1417

15-
const addMeasurementToChart = useChartStore(state => state.addMeasurementToChart);
16-
const removeChart = useChartStore(state => state.removeChart);
1718
const getNumericMeasurementInfo = useMeasurementsStore(state => state.getNumericMeasurementInfo);
19+
const initialMeasurement = getNumericMeasurementInfo(initialMeasurementId);
20+
21+
const [measurementsInChart, setMeasurementsInChart] = useState([initialMeasurement]);
22+
23+
const addMeasurementToChart = (measurement: NumericMeasurementInfo) => {
24+
if(!measurementsInChart.some(measurementInChart => measurementInChart.id === measurement.id)) {
25+
setMeasurementsInChart([...measurementsInChart, measurement]);
26+
}
27+
}
28+
29+
const removeMeasurementFromChart = useCallback((measurementId: MeasurementId) => {
30+
setMeasurementsInChart(prevMeasurements => prevMeasurements.filter(measurement => measurement.id !== measurementId));
31+
}, []);
1832

1933
const handleDrop = (ev: React.DragEvent<HTMLDivElement>) => {
2034
ev.stopPropagation();
2135
const id = ev.dataTransfer.getData("id");
2236
const measurementInfo = getNumericMeasurementInfo(id);
23-
addMeasurementToChart(chartId, measurementInfo);
37+
addMeasurementToChart(measurementInfo);
2438
};
2539

2640
return (
@@ -36,13 +50,16 @@ export const ChartElement = ({ chartId }: Props) => {
3650
cursor="pointer"
3751
onClick={() => removeChart(chartId)}
3852
/>
39-
<ChartCanvas
40-
chartId={chartId}
53+
<ChartCanvas
54+
measurementsInChart={measurementsInChart}
4155
/>
4256
<ChartLegend
4357
chartId={chartId}
58+
measurementsInChart={measurementsInChart}
59+
removeMeasurementFromChart={removeMeasurementFromChart}
60+
removeChart={removeChart}
4461
/>
4562
</div>
4663
</div>
4764
);
48-
};
65+
});

ethernet-view/src/components/ChartMenu/ChartElement/ChartLegend/ChartLegend.tsx

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,34 @@
11
import styles from "./ChartLegend.module.scss";
22
import { useEffect, useRef } from "react";
33
import { MeasurementId, NumericMeasurementInfo } from "common";
4-
import { ChartId, useChartStore } from "components/ChartMenu/ChartStore";
4+
import { ChartId } from "components/ChartMenu/ChartMenu";
55

66

77
interface Props {
88
chartId: ChartId;
9+
measurementsInChart: NumericMeasurementInfo[];
10+
removeMeasurementFromChart: (measurementId: MeasurementId) => void;
11+
removeChart: (chartId: ChartId) => void;
912
}
1013

11-
export const ChartLegend = ({ chartId }: Props) => {
14+
export const ChartLegend = ({ chartId, measurementsInChart, removeMeasurementFromChart, removeChart }: Props) => {
1215

1316
const legendRef = useRef<HTMLDivElement>(null);
14-
15-
const measurements = useChartStore((state) => {
16-
const chart = state.charts.find((chart) => chart.chartId === chartId);
17-
return chart ? chart.measurements : [];
18-
});
19-
const removeMeasurementFromChart = useChartStore((state) => state.removeMeasurementFromChart);
20-
const removeChart = useChartStore((state) => state.removeChart);
2117

2218
const onRemoveMeasurement = (measurementId: MeasurementId) => {
23-
removeMeasurementFromChart(chartId, measurementId);
19+
removeMeasurementFromChart(measurementId);
2420
};
2521

2622
useEffect(() => {
27-
if(measurements.length == 0) removeChart(chartId);
28-
}, [measurements.length])
23+
if(measurementsInChart.length == 0) removeChart(chartId);
24+
}, [measurementsInChart.length])
2925

3026
useEffect(() => {
3127
if (legendRef.current) {
3228
while (legendRef.current.firstChild) {
3329
legendRef.current.removeChild(legendRef.current.firstChild);
3430
}
35-
measurements.forEach((measurement) => {
31+
measurementsInChart.forEach((measurement) => {
3632
const newChartLegendItem = createChartLegendItem(measurement);
3733
newChartLegendItem.onclick = (_) => onRemoveMeasurement(measurement.id);
3834
legendRef.current?.appendChild(newChartLegendItem);

ethernet-view/src/components/ChartMenu/ChartMenu.tsx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,41 @@
11
import styles from "components/ChartMenu/ChartMenu.module.scss";
2-
import { DragEvent } from "react";
2+
import { DragEvent, memo, useCallback, useState } from "react";
33
import Sidebar from "components/ChartMenu/Sidebar/Sidebar";
44
import { Section } from "./Sidebar/Section/Section";
5-
import { useMeasurementsStore } from "common";
5+
import { MeasurementId, useMeasurementsStore } from "common";
66
import { nanoid } from "nanoid";
77
import { ChartElement } from "./ChartElement/ChartElement";
8-
import { useChartStore } from "./ChartStore";
8+
9+
export type ChartId = string;
10+
11+
type ChartInfo = {
12+
chartId: ChartId;
13+
initialMeasurementId: MeasurementId;
14+
};
915

1016
type Props = {
1117
sidebarSections: Section[];
1218
};
1319

14-
export const ChartMenu = ({ sidebarSections }: Props) => {
20+
export const ChartMenu = memo(({ sidebarSections }: Props) => {
1521

16-
const charts = useChartStore((state) => state.charts);
17-
const addChart = useChartStore((state) => state.addChart);
1822
const getNumericMeasurementInfo = useMeasurementsStore((state) => state.getNumericMeasurementInfo);
1923

24+
const [charts, setCharts] = useState<ChartInfo[]>([]);
25+
26+
const addChart = ((chartId: ChartId, initialMeasurementId: MeasurementId) => {
27+
setCharts([...charts, { chartId, initialMeasurementId }]);
28+
});
29+
30+
const removeChart = useCallback((chartId: ChartId) => {
31+
setCharts(prevCharts => prevCharts.filter(chart => chart.chartId !== chartId));
32+
}, []);
33+
2034
const handleDrop = (ev: DragEvent<HTMLDivElement>) => {
2135
ev.preventDefault();
2236
const id = ev.dataTransfer.getData("id");
23-
const initialMeasurementInfo = getNumericMeasurementInfo(id);
24-
addChart(nanoid(), initialMeasurementInfo);
37+
const initialMeasurementId = getNumericMeasurementInfo(id).id;
38+
addChart(nanoid(), initialMeasurementId);
2539
};
2640

2741
if (sidebarSections.length == 0) {
@@ -46,10 +60,12 @@ export const ChartMenu = ({ sidebarSections }: Props) => {
4660
<ChartElement
4761
key={chart.chartId}
4862
chartId={chart.chartId}
63+
initialMeasurementId={chart.initialMeasurementId}
64+
removeChart={removeChart}
4965
/>
5066
))}
5167
</div>
5268
</div>
5369
);
5470
}
55-
};
71+
});

ethernet-view/src/components/ChartMenu/ChartStore.ts

Lines changed: 0 additions & 88 deletions
This file was deleted.

0 commit comments

Comments
 (0)