Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@diamondlightsource/cs-web-lib",
"version": "0.10.14",
"version": "0.10.15",
"description": "Control system web library",
"main": "./dist/index.cjs",
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions src/ui/widgets/EmbeddedDisplay/bobParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ export const BOB_SIMPLE_PARSERS: ParserDict = {
majorTickStepHint: ["major_tick_step_hint", bobParseNumber],
maximum: ["maximum", bobParseNumber],
minimum: ["minimum", bobParseNumber],
autoscale: ["autoscale", opiParseBoolean],
format: ["format", bobParseNumber],
emptyColor: ["empty_color", opiParseColor],
knobColor: ["knob_color", opiParseColor],
Expand Down
20 changes: 14 additions & 6 deletions src/ui/widgets/XYPlot/xyPlot.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ import { useStyle } from "../../hooks/useStyle";
const linePlotMock = vi.fn();

vi.mock("@mui/x-charts", () => ({
ChartsContainer: ({ children }: any) => (
<div data-testid="charts-container">{children}</div>
ChartsDataProvider: ({ children }: any) => (
<div data-testid="charts-provider">{children}</div>
),
ChartsSurface: ({ children }: any) => (
<div data-testid="charts-surface">{children}</div>
),
ChartsTooltip: () => <div data-testid="tooltip" />,
ChartsAxisHighlight: () => <div data-testid="axis-highlight" />,

BarPlot: () => <div data-testid="bar-plot" />,
LinePlot: (props: any) => {
linePlotMock(props);
Expand Down Expand Up @@ -76,7 +82,8 @@ describe("XYPlotComponent", () => {
it("renders chart when dataset exists", () => {
render(<XYPlotComponent {...baseProps} />);

expect(screen.getByTestId("charts-container")).toBeInTheDocument();
expect(screen.getByTestId("charts-provider")).toBeInTheDocument();
expect(screen.getByTestId("charts-surface")).toBeInTheDocument();
expect(screen.getByTestId("bar-plot")).toBeInTheDocument();
expect(screen.getByTestId("line-plot")).toBeInTheDocument();
expect(screen.getByTestId("mark-plot")).toBeInTheDocument();
Expand All @@ -97,7 +104,7 @@ describe("XYPlotComponent", () => {
expect(utils.buildXAxes).toHaveBeenCalledWith(
baseProps.traces,
mockStyle,
baseProps.pvData
baseProps.xAxis
);
expect(utils.buildSeries).toHaveBeenCalledWith(
baseProps.traces,
Expand Down Expand Up @@ -154,8 +161,8 @@ describe("XYPlotComponent", () => {
expect(typeof props.slotProps.line).toBe("function");
});

it("hides line when traceType is 0", () => {
const traces = [{ traceType: 0 }, { traceType: 1 }];
it("hides line when traceType is 0 or 3", () => {
const traces = [{ traceType: 0 }, { traceType: 1 }, { traceType: 3 }];

render(<XYPlotComponent {...baseProps} traces={traces} />);

Expand All @@ -164,5 +171,6 @@ describe("XYPlotComponent", () => {

expect(lineFn({ seriesId: "0" })).toEqual({ stroke: "transparent" });
expect(lineFn({ seriesId: "1" })).toEqual({});
expect(lineFn({ seriesId: "2" })).toEqual({ stroke: "transparent" });
});
});
181 changes: 113 additions & 68 deletions src/ui/widgets/XYPlot/xyPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@ import {
AxesProp,
ArchivedDataPropOpt,
IntPropOpt,
TracesPropOpt
TracesPropOpt,
AxisProp
} from "../propTypes";
import { registerWidget } from "../register";
import { Box, Typography } from "@mui/material";
import {
ChartsContainer,
BarPlot,
ChartsLegend,
ChartsXAxis,
ChartsYAxis,
LinePlot,
MarkPlot
MarkPlot,
ChartsTooltip,
ChartsAxisHighlight,
ChartsSurface,
ChartsDataProvider
} from "@mui/x-charts";
import { Axes } from "../../../types/axis";
import { Axes, Axis } from "../../../types/axis";
import { fontToCss, newFont } from "../../../types/font";
import { useStyle } from "../../hooks/useStyle";
import { DatasetElementType } from "@mui/x-charts/internals";
Expand All @@ -37,9 +41,12 @@ import {

const widgetName = "xyplot";

const traceTypesWithoutLines = [0, 3];

const XYPlotProps = {
traces: TracesPropOpt,
axes: AxesProp,
xAxis: AxisProp,
start: StringPropOpt,
end: StringPropOpt,
foregroundColor: ColorPropOpt,
Expand Down Expand Up @@ -73,20 +80,22 @@ export const XYPlotComponent = (props: XYPlotComponentProps): JSX.Element => {
const {
traces,
axes,
xAxis,
pvData,
title,
titleFont = newFont(),
scaleFont = newFont(),
labelFont = newFont(),
showLegend = false,
showLegend = true,
visible = true
} = props;

const { yAxes, yAxesStyle } = useMemo(() => buildYAxes(axes as Axes), [axes]);
const { xAxis, hasXAxisData } = useMemo(
() => buildXAxes(traces, style, pvData),
[traces, style, pvData]
const { xAxis: xAxisMui, hasXAxisData } = useMemo(
() => buildXAxes(traces, style, xAxis as Axis),
[traces, style, xAxis]
);

const series = useMemo(
() => buildSeries(traces, pvData, visible),
[traces, pvData, visible]
Expand All @@ -96,13 +105,25 @@ export const XYPlotComponent = (props: XYPlotComponentProps): JSX.Element => {
() => buildPlotDataSet(pvData),
[pvData]
);

if (!hasXAxisData) {
plotDataSet = plotDataSet.map((point, i) => ({ ...point, x: i }));
}

if (!visible) {
return <Box></Box>;
}

// Use end value - this doesn't seem to do anything in Phoebus?
return (
<Box sx={{ width: "100%", height: "100%" }}>
<Box
sx={{
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column"
}}
>
<Typography
sx={{
...fontToCss(titleFont),
Expand All @@ -114,66 +135,90 @@ export const XYPlotComponent = (props: XYPlotComponentProps): JSX.Element => {
>
{title}
</Typography>

{plotDataSet?.length > 0 && (
<ChartsContainer
skipAnimation
dataset={plotDataSet}
series={series}
xAxis={xAxis}
yAxis={yAxes}
sx={{
width: "100%",
height: "95%",
".MuiChartsAxis-id-xaxis": {
".MuiChartsAxis-line": {
stroke: style?.colors?.color
},
".MuiChartsAxis-label": {
...(fontToCss(labelFont) ?? {})
},
".MuiChartsAxis-tickLabel": {
fill: style?.colors?.color,
...(fontToCss(scaleFont) ?? {})
},
".MuiChartsAxis-tick": {
stroke: style?.colors?.color
}
},

...yAxesStyle
}}
>
<BarPlot />
<LinePlot
slotProps={{
line: ({ seriesId }) => {
const trace = traces?.[Number(seriesId)];
// this hides the line if no line should be visible
if (trace?.traceType === 0) {
return {
stroke: "transparent"
};
}
return {};
}
}}
/>
<MarkPlot />
<ChartsXAxis />
<ChartsYAxis />

{showLegend && (
<ChartsLegend
slotProps={{
legend: {
sx: { color: style?.colors?.color }
}
<Box
sx={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }}
>
{plotDataSet?.length > 0 && (
<ChartsDataProvider
skipAnimation
dataset={plotDataSet}
series={series}
xAxis={xAxisMui}
yAxis={yAxes}
>
<Box
sx={{
flex: 1,
minHeight: 0,
display: "flex",
flexDirection: "column"
}}
/>
)}
</ChartsContainer>
)}
>
<ChartsSurface
sx={{
flex: 1,
minHeight: 0,
...style?.colors,
"& .MuiChartsAxis-root .MuiChartsAxis-line": {
stroke: style?.colors?.color
},
"& .MuiChartsAxis-root .MuiChartsAxis-label": {
...(fontToCss(labelFont) ?? {})
},
"& .MuiChartsAxis-root .MuiChartsAxis-tickLabel": {
fill: style?.colors?.color,
...(fontToCss(scaleFont) ?? {})
},
"& .MuiChartsAxis-root .MuiChartsAxis-tick": {
stroke: style?.colors?.color
},
...yAxesStyle
}}
>
<ChartsTooltip trigger="axis" />
<ChartsAxisHighlight x="line" />
<BarPlot />
<LinePlot
slotProps={{
line: ({ seriesId }) => {
const trace = traces?.[Number(seriesId)];
// this hides the line if no line should be visible
if (
trace?.traceType != null &&
traceTypesWithoutLines.includes(trace.traceType)
) {
return {
stroke: "transparent"
};
}
return {};
}
}}
/>
<MarkPlot />
{xAxis?.visible !== false && <ChartsXAxis />}
{yAxes.map(axis =>
axis.visible !== false ? (
<ChartsYAxis key={axis.id} axisId={axis.id} />
) : null
)}
</ChartsSurface>

{showLegend && (
<ChartsLegend
slotProps={{
legend: {
direction: "horizontal",
position: { vertical: "bottom", horizontal: "start" },
sx: { color: style?.colors?.color }
}
}}
/>
)}
</Box>
</ChartsDataProvider>
)}
</Box>
</Box>
);
};
Expand Down
Loading
Loading