Skip to content

Commit f5c536a

Browse files
authored
Merge pull request #53 from DiamondLightSource/8-23_tidy-up-buttons-and-fields
Add beamline stats fields and start tidying up
2 parents d0ea31f + 81947c0 commit f5c536a

15 files changed

+987
-1054
lines changed

package-lock.json

Lines changed: 615 additions & 853 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { DetectorMotionTabPanel } from "./screens/DetectorMotion";
44
import { BeamlineStatsTabPanel } from "./screens/BeamlineStats";
55
import { OavMover } from "./screens/OavMover";
66
import "./App.css";
7-
import { BlueApiInfo } from "./screens/BlueApiInfo";
87
import { ParamsPanel } from "./screens/CollectionPanel";
98
import {
109
ColourSchemeButton,
@@ -64,15 +63,14 @@ function FixedTargetPanels() {
6463
textColor="secondary"
6564
centered
6665
>
67-
<Tab label="BlueAPI info" {...a11yProps(0)} />
66+
<Tab label="Beamline info" {...a11yProps(0)} />
6867
<Tab label="Detector position" {...a11yProps(1)} />
6968
<Tab label="OAV view" {...a11yProps(2)} />
70-
<Tab label="Beamline stats" {...a11yProps(3)} />
71-
<Tab label="Fixed Target Collection" {...a11yProps(4)} />
69+
<Tab label="Fixed Target Collection" {...a11yProps(3)} />
7270
</Tabs>
7371
</Box>
7472
<CustomTabPanel value={value} index={0}>
75-
<BlueApiInfo />
73+
<BeamlineStatsTabPanel />
7674
</CustomTabPanel>
7775
<CustomTabPanel value={value} index={1}>
7876
<DetectorMotionTabPanel />
@@ -81,9 +79,6 @@ function FixedTargetPanels() {
8179
<OavMover />
8280
</CustomTabPanel>
8381
<CustomTabPanel value={value} index={3}>
84-
<BeamlineStatsTabPanel />
85-
</CustomTabPanel>
86-
<CustomTabPanel value={value} index={4}>
8782
<ParamsPanel />
8883
</CustomTabPanel>
8984
</div>

src/CustomTheme.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ declare module "@mui/material/styles" {
1414
}
1515
}
1616

17-
// Update the Button's color options to include a violet option
17+
// Update the Button's color options to include a new option
1818
declare module "@mui/material/Button" {
1919
interface ButtonPropsColorOverrides {
2020
custom: true;
@@ -49,6 +49,10 @@ export const I24DiamondTheme: Theme = createTheme({
4949
dark: "#10569b",
5050
contrastText: "#ffffff", // white
5151
},
52+
background: {
53+
default: "#050505",
54+
paper: "#121212",
55+
},
5256
},
5357
},
5458
},

src/components/OavVideoStream.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Box } from "@mui/material";
2+
import { PvComponent } from "../pv/PvComponent";
3+
import { PvItem, PvDescription } from "../pv/types";
24
import {
3-
PvComponent,
4-
PvItem,
5-
PvDescription,
5+
parseNumericPv,
6+
pvIntArrayToString,
67
useParsedPvConnection,
7-
} from "../pv/PvComponent";
8-
import { parseNumericPv, pvIntArrayToString } from "../pv/util";
8+
} from "../pv/util";
99
import React from "react";
1010

1111
export const useContainerDimensions = (

src/components/SelectionControl.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from "react";
2-
import { PvDescription, useParsedPvConnection } from "../pv/PvComponent";
2+
import { PvDescription } from "../pv/types";
33
import { submitAndRunPlanImmediately } from "../blueapi/blueapi";
44
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
5-
import { forceString } from "../pv/util";
5+
import { forceString, useParsedPvConnection } from "../pv/util";
66

77
type SelectionProps = PvDescription & {
88
id: string;

src/components/SleepButton.tsx

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

src/components/WorkerStatus.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, Stack } from "@mui/material";
1+
import { Box, Grid2, Stack } from "@mui/material";
22

33
import { processUseBlueApiCall, useBlueApiCall } from "../blueapi/blueapi";
44
import { useState } from "react";
@@ -7,16 +7,18 @@ export function WorkerStatus() {
77
const [currentState, setCurrentState] = useState<string>("UNKNOWN");
88
const workerStateInfo = useBlueApiCall("/worker/state");
99
return (
10-
<Stack padding={1} direction={"row"} spacing={1}>
11-
<b>BlueAPI worker status: </b>
12-
<Box>
13-
{processUseBlueApiCall(workerStateInfo, (res) => {
14-
if (!res.bodyUsed) {
15-
res.json().then((text) => setCurrentState(text));
16-
}
17-
return currentState;
18-
})}
19-
</Box>
20-
</Stack>
10+
<Grid2 size={12}>
11+
<Stack direction={"row"} spacing={1} justifyContent={"center"}>
12+
<b>BlueAPI worker status: </b>
13+
<Box>
14+
{processUseBlueApiCall(workerStateInfo, (res) => {
15+
if (!res.bodyUsed) {
16+
res.json().then((text) => setCurrentState(text));
17+
}
18+
return currentState;
19+
})}
20+
</Box>
21+
</Stack>
22+
</Grid2>
2123
);
2224
}

src/pv/PvComponent.tsx

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,55 @@
1-
import { useConnection } from "@diamondlightsource/cs-web-lib";
2-
import { Box } from "@mui/material";
1+
import { Box, useTheme } from "@mui/material";
32
import { ErrorBoundary } from "react-error-boundary";
4-
import { RawValue } from "./util";
3+
import { PvComponentProps, PvDescription, PvItem } from "./types";
4+
import { useParsedPvConnection, forceString } from "./util";
55

6-
type Transformer = (value: RawValue) => string | number;
7-
export type PvDisplayTypes = string | number;
8-
export type PvItem = { label: string; value: RawValue | PvDisplayTypes };
9-
export type PvItemComponent = ({ label, value }: PvItem) => JSX.Element;
10-
export type PvItemHandler = ({ label, value }: PvItem) => void;
11-
export type PvDescription = {
12-
label: string;
13-
pv: string;
14-
};
15-
export type PvComponentProps = PvDescription & {
16-
render: PvItemComponent;
17-
transformValue?: Transformer;
18-
};
19-
20-
export function useParsedPvConnection(
21-
props: PvDescription & { transformValue?: Transformer }
22-
) {
23-
const [_effectivePvName, connected, _readonly, latestValue] = useConnection(
24-
props.label,
25-
props.pv
26-
);
27-
const rawValue: RawValue = connected ? latestValue : "not connected";
28-
const returnValue = props.transformValue
29-
? props.transformValue(rawValue)
30-
: rawValue;
31-
console.log(
32-
`fetched parsed value ${returnValue} for PV: ${props.pv} labeled ${props.label}`
6+
function defaultPvBox(label: string, value: number | string): JSX.Element {
7+
return (
8+
<Box>
9+
<p>
10+
<b>{label}:</b> {value}
11+
</p>
12+
</Box>
3313
);
34-
return returnValue;
3514
}
3615

37-
function WsPvComponent(props: PvComponentProps) {
16+
function WsPvComponent(props: PvComponentProps): JSX.Element {
3817
const latestValue = useParsedPvConnection(props);
39-
return <Box>{props.render({ label: props.label, value: latestValue })}</Box>;
18+
const renderedPvBox = props.render ? (
19+
<Box>{props.render({ label: props.label, value: latestValue })}</Box>
20+
) : (
21+
defaultPvBox(props.label, latestValue)
22+
);
23+
return renderedPvBox;
4024
}
4125

4226
export function PvComponent(props: PvComponentProps) {
27+
const theme = useTheme();
4328
return (
44-
<ErrorBoundary fallback={<p>Error Connecting!</p>}>
29+
<ErrorBoundary
30+
fallback={
31+
<Box color={theme.palette.error.main}>
32+
<p>Error Connecting!</p>
33+
</Box>
34+
}
35+
>
4536
{WsPvComponent(props)}
4637
</ErrorBoundary>
4738
);
4839
}
40+
41+
export function RoPvBox(props: PvDescription) {
42+
return PvComponent({
43+
...props,
44+
transformValue: forceString,
45+
render: (props: PvItem) => {
46+
return (
47+
<Box>
48+
<p>
49+
{props.label} : {props.value}
50+
</p>
51+
</Box>
52+
);
53+
},
54+
});
55+
}

src/pv/types.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { DType } from "@diamondlightsource/cs-web-lib";
2+
3+
type NotConnected = "not connected";
4+
export type RawValue = DType | undefined | NotConnected;
5+
6+
type TransformString = (value: RawValue) => string | number;
7+
type TransformNumeric = (
8+
value: RawValue,
9+
decimals?: number,
10+
scaleFactor?: number
11+
) => string | number;
12+
export type PvTransformer = TransformString | TransformNumeric;
13+
14+
export type PvDescription = {
15+
label: string;
16+
pv: string;
17+
};
18+
19+
export type PvItem = { label: string; value: number | string | NotConnected };
20+
type PvItemComponent = ({ label, value }: PvItem) => JSX.Element;
21+
22+
export type RenderedPvValue = RawValue | string | number;
23+
24+
export type ParsePvProps = PvDescription & {
25+
transformValue: PvTransformer;
26+
decimals?: number;
27+
scaleFactor?: number;
28+
};
29+
30+
export type PvComponentProps = ParsePvProps & { render?: PvItemComponent };

src/pv/util.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { DType } from "@diamondlightsource/cs-web-lib";
2-
export type RawValue = DType | "not connected" | undefined;
2+
import { useConnection } from "@diamondlightsource/cs-web-lib";
3+
import { ParsePvProps, PvDescription, RawValue } from "./types";
34

45
export function forceString(value: RawValue | string | number): string {
56
let displayValue: string;
@@ -21,7 +22,7 @@ export function parseNumericPv(
2122
value: string | number | DType | undefined,
2223
decimals?: number,
2324
scaleFactor?: number
24-
) {
25+
): string {
2526
const decimalsToUse = decimals ? decimals : 2;
2627
const scaleFactorToUse = scaleFactor ? scaleFactor : 1;
2728
if (value === undefined) {
@@ -57,3 +58,37 @@ export function pvIntArrayToString(value: RawValue): string {
5758
}
5859
}
5960
}
61+
62+
function ReadPvRawValue(props: PvDescription): RawValue {
63+
const [_effectivePvName, connected, _readonly, latestValue] = useConnection(
64+
props.label,
65+
props.pv
66+
);
67+
const rawValue: RawValue = connected ? latestValue : "not connected";
68+
return rawValue;
69+
}
70+
71+
export function useParsedPvConnection(props: ParsePvProps): number | string {
72+
const rawValue = ReadPvRawValue({ label: props.label, pv: props.pv });
73+
let returnValue;
74+
if (rawValue === "not connected") {
75+
returnValue = "not connected";
76+
} else if (!rawValue) {
77+
console.error("Parsed value was undefined");
78+
returnValue = "undefined";
79+
} else {
80+
returnValue = props.transformValue
81+
? props.transformValue(rawValue, props.decimals, props.scaleFactor)
82+
: rawValue;
83+
}
84+
85+
// If it's a Dtype cast to string
86+
if (typeof returnValue !== "string" || typeof returnValue !== "number") {
87+
returnValue = returnValue.toString();
88+
}
89+
90+
console.log(
91+
`fetched parsed value ${returnValue} for PV: ${props.pv} labeled ${props.label}`
92+
);
93+
return returnValue;
94+
}

0 commit comments

Comments
 (0)