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
97 changes: 46 additions & 51 deletions app/components/Block.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render } from "@testing-library/react";
import { fireEvent, render } from "@testing-library/react";
import Block from "@/app/components/Block";
import { IfcBlock } from "@/app/types";

Expand All @@ -20,12 +20,7 @@ it("renders topbar unchanged", () => {
};
const instName = "Instrument";
const { container } = render(
<Block
pv={aBlock}
instName={instName}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={instName} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand All @@ -36,12 +31,7 @@ it("renders topbar unchanged", () => {
it("renders nothing if pv is hidden", () => {
const aBlock: IfcBlock = { pvaddress: "SOME:PV", visible: false };
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand All @@ -56,12 +46,7 @@ it("renders block with correct name", () => {
human_readable_name: "MyBlock",
};
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand All @@ -80,12 +65,7 @@ it("renders block with run control that is in range as a tick", () => {
runcontrol_enabled: true,
};
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand All @@ -105,12 +85,7 @@ it("renders block with run control that is not in range as a cross", () => {
runcontrol_enabled: true,
};
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand All @@ -130,12 +105,7 @@ it("renders block without run control without tick or cross", () => {
runcontrol_enabled: false,
};
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand All @@ -159,19 +129,49 @@ it("renders block with SP and shows SP value", () => {
value: expectedValue,
};
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={true}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
);
const valueSpan = container.querySelector(
`#${aBlock.human_readable_name}_VALUE`,
)!;

fireEvent.click(valueSpan);
expect(valueSpan.innerHTML).toContain(`${expectedValue}`);
expect(
container.querySelector(`#${aBlock.human_readable_name}_VALUE`)!.innerHTML,
).toContain(`${expectedValue} <br>(SP: ${expectedSpValue})`);
container.querySelector(`#${aBlock.human_readable_name}_SP`)!.innerHTML,
).toContain(expectedSpValue.toString());
});

it("renders block with timestamp and shows timestamp value", () => {
const expectedValue = 123;
const expectedTimeStamp = 1731342022;
const aBlock: IfcBlock = {
pvaddress: "SOME:PV",
visible: true,
human_readable_name: "MyBlock",
runcontrol_inrange: false,
runcontrol_enabled: false,
updateSeconds: expectedTimeStamp,
value: expectedValue,
};
const { container } = render(
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
);
const valueSpan = container.querySelector(
`#${aBlock.human_readable_name}_VALUE`,
)!;
fireEvent.click(valueSpan);
expect(valueSpan.innerHTML).toContain(`${expectedValue}`);
expect(
container.querySelector(`#${aBlock.human_readable_name}_TIMESTAMP`)!
.innerHTML,
).toContain(new Date(expectedTimeStamp * 1000).toLocaleString());
});

it("renders block without SP and hides SP value", () => {
Expand All @@ -187,12 +187,7 @@ it("renders block without SP and hides SP value", () => {
sp_value: expectedSpValue,
};
const { container } = render(
<Block
pv={aBlock}
instName={""}
showHiddenBlocks={false}
showSetpoints={false}
/>,
<Block pv={aBlock} instName={""} showHiddenBlocks={false} />,
{
container: tableBody,
},
Expand Down
96 changes: 65 additions & 31 deletions app/components/Block.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import { IfcBlock } from "@/app/types";
import { useState } from "react";
import React, { useState } from "react";

const grafana_stub =
"https://shadow.nd.rl.ac.uk/grafana/d/wMlwwaHMk/block-history?viewPanel=2&orgId=1&var-block=";
Expand All @@ -9,16 +9,15 @@ export default function Block({
pv,
instName,
showHiddenBlocks,
showSetpoints,
}: {
pv: IfcBlock;
instName: string;
showHiddenBlocks: boolean;
showSetpoints: boolean;
}) {
const [currentValue, setCurrentValue] = useState<
string | number | undefined
>();
const [showAdvanced, setShowAdvanced] = useState(false);
if (!pv.visible && !showHiddenBlocks && !instName) {
return null;
}
Expand All @@ -38,12 +37,16 @@ export default function Block({
}, 2000);
}

const minimum_date_to_be_shown = 631152000; // This is what PVWS thinks epoch time is for some reason. don't bother showing it as the instrument wasn't running EPICS on 01/01/1990
return (
<tr
key={pv.human_readable_name}
className="border-b border-blue-gray-200 transition duration-100 hover:bg-gray-100 hover:text-black"
onClick={() => {
setShowAdvanced(!showAdvanced);
}}
>
<td className="py-1 px-4">
<td className="py-1 px-2 w-1/3 flex-row">
<a
className="underline"
href={
Expand All @@ -58,39 +61,70 @@ export default function Block({
</a>
</td>

<td className="py-1 px-4 ">
<span id={pv.human_readable_name + "_VALUE"}>
{pv.value} {pv.units != null && pv.units}
{showSetpoints && pv.sp_value != null ? (
<>
<br />
{`(SP: ${pv.sp_value})`}
</>
) : null}
{pv.severity != "NONE" ? (
<a
href="https://github.com/ISISComputingGroup/ibex_user_manual/wiki/Blocks#alarms"
className="text-red-600"
<td className="py-1 px-2 w-7/12">
<span id={pv.human_readable_name + "_VALUE_ROW"}>
<div className="flex justify-between">
<span
id={pv.human_readable_name + "_VALUE"}
className={pv.severity != "NONE" ? "text-red-400" : ""}
>
<br />
{pv.severity}
</a>
) : null}
{showAdvanced && "Readback: "}
{pv.value} {pv.units != null && pv.units}
</span>
<svg
id={pv.human_readable_name + "_CIRCLE"}
className="min-w-2 min-h-2 max-w-2 max-h-2 transition-all text-transparent"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
>
<circle cx="12" cy="12" r="12" />
</svg>
</div>

{showAdvanced && (
<div>
<hr />
{pv.severity != "NONE" ? (
<a
href="https://github.com/ISISComputingGroup/ibex_user_manual/wiki/Blocks#alarms"
className="text-red-400"
>
Alarm: {pv.severity}
</a>
) : null}
<hr />
{pv.sp_value != null ? (
<span id={pv.human_readable_name + "_SP"}>
{`Setpoint: ${pv.sp_value}`}
<hr />
</span>
) : null}
{pv.updateSeconds != null &&
pv.updateSeconds > minimum_date_to_be_shown ? (
<span id={pv.human_readable_name + "_TIMESTAMP"}>
{/*Multiply by 1000 here as Date() expects milliseconds*/}
{`Last update: ${new Date(pv.updateSeconds * 1000).toLocaleString()}`}
</span>
) : null}
</div>
)}
</span>
</td>
<td className="py-1 px-4 flex justify-between items-center">
<span id={pv.human_readable_name + "_VALUE_RC"}>
<td className="py-1 px-2 flex justify-between items-center">
<span
id={pv.human_readable_name + "_VALUE_RC"}
title={"Run control in-range?"}
>
{pv.runcontrol_enabled && (pv.runcontrol_inrange ? "✅" : "❌")}
</span>
<svg
id={pv.human_readable_name + "_CIRCLE"}
className="min-w-2 min-h-2 max-w-2 max-h-2 transition-all text-transparent"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"

<span
className={"cursor-pointer font-bold"}
title={"Show/Hide advanced statuses"}
>
<circle cx="12" cy="12" r="12" />
</svg>
{showAdvanced ? "-" : "+"}
</span>
</td>
</tr>
);
Expand Down
15 changes: 6 additions & 9 deletions app/components/Group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@ export default function Group({
group,
instName,
showHiddenBlocks,
showSetpoints,
}: {
group: IfcGroup;
instName: string;
showHiddenBlocks: boolean;
showSetpoints: boolean;
}) {
if (!group) {
return <h1>Loading...</h1>;
Expand All @@ -30,22 +28,21 @@ export default function Group({
{group.name}
</h1>
<table className="text-sm table-fixed">
<thead>
<tr className="bg-blue-gray-100 text-gray-100">
<th className="py-3 px-4 text-left">Block</th>
<th className="py-3 px-4 text-left">Value</th>
<th className="py-3 px-4 text-left">In-Range</th>
<thead className="sticky">
<tr className="bg-blue-gray-100 text-gray-100 border-b-2 border-b-gray-400">
<th className="py-2 px-2 text-left w-1/3">Block</th>
<th className="py-2 px-2 text-left w-7/12">Value</th>
<th className="py-2 px-2 text-left"></th>
</tr>
</thead>
<tbody className="text-gray-200 ">
<tbody className="text-gray-200 sticky">
{group.blocks.map((pv) => {
return (
<Block
key={pv.human_readable_name}
pv={pv}
instName={instName}
showHiddenBlocks={showHiddenBlocks}
showSetpoints={showSetpoints}
/>
);
})}
Expand Down
5 changes: 1 addition & 4 deletions app/components/Groups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,24 @@ export default function Groups({
groupsMap,
instName,
showHiddenBlocks,
showSetpoints,
}: {
groupsMap: Array<IfcGroup>;
instName: string;
showHiddenBlocks: boolean;
showSetpoints: boolean;
}) {
if (!groupsMap) {
return <h1>Loading...</h1>;
}

return (
<div className="rounded-xl grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 mt-2">
<div className="rounded-xl grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4 mt-2">
{groupsMap.map((group) => {
return (
<Group
key={group.name}
group={group}
instName={instName}
showHiddenBlocks={showHiddenBlocks}
showSetpoints={showSetpoints}
/>
);
})}
Expand Down
Loading