Skip to content

Commit d2df494

Browse files
committed
fix bug in wall display - states sometimes not updating because setState not called - https://react.dev/learn/updating-arrays-in-state#replacing-items-in-an-array
1 parent 1e0e121 commit d2df494

File tree

3 files changed

+138
-123
lines changed

3 files changed

+138
-123
lines changed

app/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,8 @@ export interface ConfigOutputIocMacro {
141141
name: string;
142142
value: string;
143143
}
144+
145+
export interface targetStation {
146+
targetStation: string;
147+
instruments: Array<IfcInstrumentStatus>;
148+
}

app/wall/components/ShowHideBeamInfo.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ export default function ShowHideBeamInfo() {
2323
<Image
2424
src={`https://www.isis.stfc.ac.uk/Gallery/beam-status/ISIS_Status.jpg?t=${date}`}
2525
alt="beam info"
26-
height={600}
27-
width={600}
26+
height={400}
27+
width={0}
28+
className={"w-auto"}
2829
/>
2930
</span>
3031
</label>

app/wall/page.tsx

Lines changed: 130 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,102 @@
11
"use client";
2-
import { Inter } from "next/font/google";
3-
import { useState, useEffect } from "react";
2+
import { useEffect, useState } from "react";
43
import useWebSocket from "react-use-websocket";
54
import { dehex_and_decompress } from "../components/dehex_and_decompress";
65
import InstrumentGroup from "./components/InstrumentGroup";
76
import ShowHideBeamInfo from "./components/ShowHideBeamInfo";
87
import JenkinsJobIframe from "./components/JenkinsJobsIframe";
9-
import {
10-
IfcInstrumentStatus,
11-
IfcPVWSMessage,
12-
IfcPVWSRequest,
13-
} from "@/app/types";
14-
15-
const inter = Inter({ subsets: ["latin"] });
8+
import { IfcPVWSMessage, IfcPVWSRequest, targetStation } from "@/app/types";
169

1710
export default function WallDisplay() {
1811
const runstatePV = "DAE:RUNSTATE_STR";
1912
const instListPV = "CS:INSTLIST";
2013

21-
const [TS1Data] = useState<Array<IfcInstrumentStatus>>(
22-
[
23-
{ name: "ALF" },
24-
{ name: "CRISP" },
25-
{ name: "EMMA-A" },
26-
{ name: "EMU" },
27-
{ name: "ENGINX" },
28-
{ name: "GEM" },
29-
{
30-
name: "HIFI-CRYOMAG",
31-
},
32-
{ name: "HRPD" },
33-
{ name: "INES" },
34-
{ name: "IRIS" },
35-
{ name: "LOQ" },
36-
{ name: "MAPS" },
37-
{ name: "MARI" },
38-
{ name: "MERLIN" },
39-
{ name: "MUONFE" },
40-
{ name: "MUSR" },
41-
{ name: "OSIRIS" },
42-
{ name: "PEARL" },
43-
{ name: "POLARIS" },
44-
{ name: "RIKENFE" },
45-
{ name: "SANDALS" },
46-
{ name: "SCIDEMO" },
47-
{ name: "SURF" },
48-
{ name: "SXD" },
49-
{ name: "TOSCA" },
50-
{ name: "VESUVIO" },
51-
].sort((a, b) => a.name.localeCompare(b.name)),
52-
);
53-
const [TS2Data] = useState<Array<IfcInstrumentStatus>>(
54-
[
55-
{ name: "CHIPIR" },
56-
{ name: "IMAT" },
57-
{ name: "INTER" },
58-
{ name: "LARMOR" },
59-
{ name: "LET" },
60-
{ name: "NIMROD" },
61-
{ name: "OFFSPEC" },
62-
{ name: "POLREF" },
63-
{ name: "SANS2D" },
64-
{ name: "WISH" },
65-
{ name: "ZOOM" },
66-
].sort((a, b) => a.name.localeCompare(b.name)),
67-
);
68-
const [miscData] = useState<Array<IfcInstrumentStatus>>(
69-
[
70-
{ name: "ARGUS" },
71-
{ name: "CHRONUS" },
72-
{
73-
name: "CRYOLAB_R80",
74-
},
75-
{ name: "DCLAB" },
76-
{ name: "DEMO" },
77-
{ name: "DETMON" },
78-
{
79-
name: "ENGINX_SETUP",
80-
},
81-
{ name: "HIFI" },
82-
{
83-
name: "HRPD_SETUP",
84-
},
85-
{
86-
name: "IBEXGUITEST",
87-
},
88-
{
89-
name: "IRIS_SETUP",
90-
},
91-
{ name: "MOTION" },
92-
{
93-
name: "PEARL_SETUP",
94-
},
95-
{ name: "SELAB" },
96-
{ name: "SOFTMAT" },
97-
{
98-
name: "WISH_SETUP",
99-
},
100-
].sort((a, b) => a.name.localeCompare(b.name)),
101-
);
14+
const [data, setData] = useState<Array<targetStation>>([
15+
{
16+
targetStation: "Target Station 1",
17+
instruments: [
18+
{ name: "ALF" },
19+
{ name: "CRISP" },
20+
{ name: "EMMA-A" },
21+
{ name: "EMU" },
22+
{ name: "ENGINX" },
23+
{ name: "GEM" },
24+
{
25+
name: "HIFI-CRYOMAG",
26+
},
27+
{ name: "HRPD" },
28+
{ name: "INES" },
29+
{ name: "IRIS" },
30+
{ name: "LOQ" },
31+
{ name: "MAPS" },
32+
{ name: "MARI" },
33+
{ name: "MERLIN" },
34+
{ name: "MUONFE" },
35+
{ name: "MUSR" },
36+
{ name: "OSIRIS" },
37+
{ name: "PEARL" },
38+
{ name: "POLARIS" },
39+
{ name: "RIKENFE" },
40+
{ name: "SANDALS" },
41+
{ name: "SCIDEMO" },
42+
{ name: "SURF" },
43+
{ name: "SXD" },
44+
{ name: "TOSCA" },
45+
{ name: "VESUVIO" },
46+
].sort((a, b) => a.name.localeCompare(b.name)),
47+
},
48+
{
49+
targetStation: "Target Station 2",
50+
instruments: [
51+
{ name: "CHIPIR" },
52+
{ name: "IMAT" },
53+
{ name: "INTER" },
54+
{ name: "LARMOR" },
55+
{ name: "LET" },
56+
{ name: "NIMROD" },
57+
{ name: "OFFSPEC" },
58+
{ name: "POLREF" },
59+
{ name: "SANS2D" },
60+
{ name: "WISH" },
61+
{ name: "ZOOM" },
62+
].sort((a, b) => a.name.localeCompare(b.name)),
63+
},
64+
{
65+
targetStation: "Miscellaneous",
66+
instruments: [
67+
{ name: "ARGUS" },
68+
{ name: "CHRONUS" },
69+
{
70+
name: "CRYOLAB_R80",
71+
},
72+
{ name: "DCLAB" },
73+
{ name: "DEMO" },
74+
{ name: "DETMON" },
75+
{
76+
name: "ENGINX_SETUP",
77+
},
78+
{ name: "HIFI" },
79+
{
80+
name: "HRPD_SETUP",
81+
},
82+
{
83+
name: "IBEXGUITEST",
84+
},
85+
{
86+
name: "IRIS_SETUP",
87+
},
88+
{ name: "MOTION" },
89+
{
90+
name: "PEARL_SETUP",
91+
},
92+
{ name: "SELAB" },
93+
{ name: "SOFTMAT" },
94+
{
95+
name: "WISH_SETUP",
96+
},
97+
].sort((a, b) => a.name.localeCompare(b.name)),
98+
},
99+
]);
102100

103101
const socketURL = process.env.NEXT_PUBLIC_WS_URL!;
104102

@@ -140,32 +138,45 @@ export default function WallDisplay() {
140138
// Iterate through the instlist, find their associated object in the ts1data, ts2data or miscData arrays, get the runstate PV and subscribe
141139
const instName = item["name"];
142140
const instPrefix = item["pvPrefix"];
143-
const foundInstrument = [...TS1Data, ...TS2Data, ...miscData].find(
144-
(instrument) => instrument.name === instName,
145-
);
146-
if (foundInstrument) {
147-
// Subscribe to the instrument's runstate PV
148-
foundInstrument.pv = instPrefix + runstatePV;
149-
sendJsonMessage({ type: "subscribe", pvs: [foundInstrument.pv] });
150-
}
141+
setData((prev) => {
142+
const newData: Array<targetStation> = [...prev];
143+
newData.map((targetStation) => {
144+
const foundInstrument = targetStation.instruments.find(
145+
(instrument) => instrument.name === instName,
146+
);
147+
if (foundInstrument) {
148+
// Subscribe to the instrument's runstate PV
149+
foundInstrument.pv = instPrefix + runstatePV;
150+
sendJsonMessage({
151+
type: "subscribe",
152+
pvs: [foundInstrument.pv],
153+
});
154+
}
155+
});
156+
return newData;
157+
});
151158
}
152159
}
153-
} else {
154-
// An instrument's runstate has changed. Find the instrument and update its status (if there is one!).
155-
const foundInstrument = [...TS1Data, ...TS2Data, ...miscData].find(
156-
(instrument) => instrument.pv === updatedPVName,
157-
);
158-
if (updatedPVvalue && foundInstrument) {
159-
foundInstrument.status = updatedPVvalue;
160-
}
160+
} else if (updatedPVvalue) {
161+
setData((prev) => {
162+
const newData: Array<targetStation> = [...prev];
163+
newData.map((targetStation) => {
164+
const foundInstrument = targetStation.instruments.findIndex(
165+
(instrument) => instrument.pv === updatedPVName,
166+
);
167+
if (foundInstrument >= 0)
168+
targetStation.instruments[foundInstrument].status = updatedPVvalue;
169+
});
170+
return newData;
171+
});
161172
}
162-
}, [lastJsonMessage, TS1Data, TS2Data, miscData, sendJsonMessage]);
173+
}, [lastJsonMessage, sendJsonMessage]);
163174

164175
return (
165176
<main
166-
className={`flex min-h-screen bg-white dark:bg-zinc-800 flex-col items-center justify-between ${inter.className}`}
177+
className={`flex min-h-screen bg-white dark:bg-zinc-800 flex-col items-center justify-between`}
167178
>
168-
<section className=" rounded-xl w-full w-full md:px-0 md:w-11/12 my-4 ">
179+
<section className=" rounded-xl w-full md:px-0 md:w-11/12 my-4 ">
169180
<div className="mx-auto ">
170181
<ShowHideBeamInfo />
171182
<div className="w-full mx-auto text-left flex justify-center items-center p-8 dark:bg-zinc-900 rounded-xl">
@@ -176,18 +187,16 @@ export default function WallDisplay() {
176187
<h1 className="w-full text-left text-black dark:text-white font-semibold text-2xl ">
177188
Instrument Status:
178189
</h1>
179-
<InstrumentGroup
180-
groupName={"Target Station 1"}
181-
data={TS1Data}
182-
></InstrumentGroup>
183-
<InstrumentGroup
184-
groupName={"Target Station 2"}
185-
data={TS2Data}
186-
></InstrumentGroup>
187-
<InstrumentGroup
188-
groupName={"Miscellaneous"}
189-
data={miscData}
190-
></InstrumentGroup>
190+
191+
{data.map((targetStation) => {
192+
return (
193+
<InstrumentGroup
194+
key={targetStation.targetStation}
195+
groupName={targetStation.targetStation}
196+
data={targetStation.instruments}
197+
/>
198+
);
199+
})}
191200
</div>
192201
</div>
193202
<hr className="h-[2px] rounded my-4 bg-gray-200 border-0 dark:bg-gray-600" />

0 commit comments

Comments
 (0)