Skip to content

Commit 7fa8b21

Browse files
feat(frontend): use accordion for artifact list
1 parent fd3bca2 commit 7fa8b21

File tree

6 files changed

+109
-80
lines changed

6 files changed

+109
-80
lines changed

frontend/dashboard/src/routes/SingleWorkflowPage.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function SingleWorkflowPage() {
1414
}>();
1515

1616
const [searchParams] = useSearchParams();
17-
const taskParam = searchParams.get("tasks")
17+
const taskParam = searchParams.get("tasks");
1818

1919
const tasknames = useMemo(() => {
2020
if (!taskParam) return [];
@@ -35,7 +35,13 @@ function SingleWorkflowPage() {
3535
<Breadcrumbs path={window.location.pathname} linkComponent={Link} />
3636
{visit && workflowName ? (
3737
<Container maxWidth="lg">
38-
<Box display="flex" flexDirection="column" alignItems="center" mt={2}>
38+
<Box
39+
display="flex"
40+
flexDirection="column"
41+
alignItems="center"
42+
mt={2}
43+
mb={4}
44+
>
3945
<WorkflowsErrorBoundary>
4046
<Suspense>
4147
<SingleWorkflowView
@@ -48,7 +54,13 @@ function SingleWorkflowPage() {
4854
</Box>
4955
</Container>
5056
) : (
51-
<Box display="flex" flexDirection="column" alignItems="center" mt={2}>
57+
<Box
58+
display="flex"
59+
flexDirection="column"
60+
alignItems="center"
61+
mt={2}
62+
mb={4}
63+
>
5264
<Typography>No valid workflow selected</Typography>
5365
{/* Go to instrumentSession or home page */}
5466
</Box>

frontend/workflows-lib/lib/components/workflow/ArtifactFilteredList.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ export const ArtifactFilteredList: React.FC<ArtifactFilteredListProps> = ({
5252
}, [artifactFilter, artifactList, imageArtifacts]);
5353
return (
5454
<>
55-
<Typography variant="h5" sx={{ marginTop: 2, marginBottom: 2 }}>
56-
Artefacts
57-
</Typography>
5855
<ToggleButtonGroup
5956
value={artifactFilter}
6057
exclusive

frontend/workflows-lib/lib/components/workflow/ImageGallery.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,71 @@
1-
import React from "react";
2-
import { Box } from "@mui/material";
3-
import type { Artifact } from "workflows-lib";
4-
import { ImageGallery } from "./ImageGallery";
1+
import {
2+
Accordion,
3+
AccordionSummary,
4+
AccordionDetails,
5+
Typography,
6+
Box,
7+
} from "@mui/material";
8+
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
59
import { ArtifactFilteredList } from "./ArtifactFilteredList";
10+
import type { Artifact } from "workflows-lib";
11+
import { ImageInfo, ScrollableImages } from "./ScrollableImages";
12+
import { useMemo } from "react";
613

714
interface TaskInfoProps {
815
artifactList: Artifact[];
916
}
1017

1118
export const TaskInfo: React.FC<TaskInfoProps> = ({ artifactList }) => {
19+
const imageArtifactsInfos: ImageInfo[] = useMemo(() => {
20+
return artifactList
21+
.filter((artifact) => artifact.mimeType === "image/png")
22+
.map((artifact, index) => ({
23+
src: artifact.url,
24+
alt: `Gallery Image ${String(index + 1)}`,
25+
}));
26+
}, [artifactList]);
27+
1228
return (
13-
<Box
14-
sx={{
15-
display: "flex",
16-
flexDirection: {
17-
xs: "column",
18-
sm: "row",
19-
},
20-
flexWrap: "wrap",
21-
gap: 2,
22-
width: "100%",
23-
boxSizing: "border-box",
24-
}}
25-
>
26-
<Box sx={{ flex: 1, minWidth: "300px" }}>
27-
<ArtifactFilteredList artifactList={artifactList} />
28-
</Box>
29+
<Accordion sx={{ width: "100%", my: 0 }} defaultExpanded>
30+
<AccordionSummary expandIcon={<ArrowDropDownIcon />}>
31+
<Typography variant="h6">Output Information</Typography>
32+
</AccordionSummary>
33+
<AccordionDetails>
34+
<Box
35+
sx={{
36+
display: "flex",
37+
flexDirection: {
38+
xs: "column",
39+
sm: "row",
40+
},
41+
flexWrap: "wrap",
42+
gap: 2,
43+
width: "100%",
44+
boxSizing: "border-box",
45+
}}
46+
>
47+
<Box sx={{ flex: 1, minWidth: "300px" }}>
48+
<ArtifactFilteredList artifactList={artifactList} />
49+
</Box>
2950

30-
<Box
31-
sx={{
32-
flex: 1,
33-
minWidth: "300px",
34-
}}
35-
>
36-
<ImageGallery artifactList={artifactList} />
37-
</Box>
38-
</Box>
51+
<Box
52+
sx={{
53+
flex: 1,
54+
minWidth: "300px",
55+
visibility: imageArtifactsInfos.length > 0 ? "visible" : "hidden",
56+
mt: 8,
57+
paddingLeft: 7,
58+
}}
59+
>
60+
{imageArtifactsInfos.length > 0 && (
61+
<ScrollableImages
62+
images={imageArtifactsInfos}
63+
backgroundColor="#FFF"
64+
/>
65+
)}
66+
</Box>
67+
</Box>
68+
</AccordionDetails>
69+
</Accordion>
3970
);
4071
};
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { render, screen, fireEvent } from "@testing-library/react";
2-
import { ImageGallery } from "../../lib/components/workflow/ImageGallery";
2+
import { ScrollableImages } from "../../lib/components/workflow/ScrollableImages";
33
import "@testing-library/jest-dom";
4-
import { mockArtifacts } from "./data";
4+
import { mockImages } from "./data";
55

66
describe("ImageGallery", () => {
77
it("renders the first image by default", () => {
8-
render(<ImageGallery artifactList={mockArtifacts} />);
8+
render(<ScrollableImages images={mockImages} />);
99
const imgElement = screen.getByAltText("Gallery Image 1");
1010
expect(imgElement).toBeInTheDocument();
1111
expect(imgElement).toHaveAttribute("src", "fakepath/to/image1.png");
1212
});
1313

1414
it("renders the next image when the next button is clicked", async () => {
15-
render(<ImageGallery artifactList={mockArtifacts} />);
15+
render(<ScrollableImages images={mockImages} />);
1616
const nextButton = await screen.findByTestId("next-button");
1717
fireEvent.click(nextButton);
1818
const imgElement = screen.getByAltText("Gallery Image 2");
@@ -21,7 +21,7 @@ describe("ImageGallery", () => {
2121
});
2222

2323
it("renders the previous image when the previous button is clicked", async () => {
24-
render(<ImageGallery artifactList={mockArtifacts} />);
24+
render(<ScrollableImages images={mockImages} />);
2525
const nextButton = await screen.findByTestId("next-button");
2626
fireEvent.click(nextButton);
2727
const prevButton = await screen.findByTestId("prev-button");
@@ -32,26 +32,22 @@ describe("ImageGallery", () => {
3232
});
3333

3434
it("cycles to the last image when the previous button is clicked on the first image", async () => {
35-
render(<ImageGallery artifactList={mockArtifacts} />);
35+
render(<ScrollableImages images={mockImages} />);
3636
const prevButton = await screen.findByTestId("prev-button");
3737
fireEvent.click(prevButton);
38-
const imgElement = screen.getByAltText("Gallery Image 2");
38+
const imgElement = screen.getByAltText("Gallery Image 3");
3939
expect(imgElement).toBeInTheDocument();
40-
expect(imgElement).toHaveAttribute("src", "fakepath/to/image2.png");
40+
expect(imgElement).toHaveAttribute("src", "fakepath/to/image3.png");
4141
});
4242

4343
it("cycles to the first image when the next button is clicked on the last image", async () => {
44-
render(<ImageGallery artifactList={mockArtifacts} />);
44+
render(<ScrollableImages images={mockImages} />);
4545
const nextButton = await screen.findByTestId("next-button");
4646
fireEvent.click(nextButton);
4747
fireEvent.click(nextButton);
48+
fireEvent.click(nextButton);
4849
const imgElement = screen.getByAltText("Gallery Image 1");
4950
expect(imgElement).toBeInTheDocument();
5051
expect(imgElement).toHaveAttribute("src", "fakepath/to/image1.png");
5152
});
52-
53-
it("does not render anything if there are no image artifacts", () => {
54-
render(<ImageGallery artifactList={[]} />);
55-
expect(screen.queryByTestId("scrollable-images")).not.toBeInTheDocument();
56-
});
5753
});

frontend/workflows-lib/tests/components/data.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { ImageInfo } from "../../lib/components/workflow/ScrollableImages";
12
import { Artifact, TaskStatus } from "../../lib/types";
23
import { Visit } from "@diamondlightsource/sci-react-ui";
34

45
export const logArtifact: Artifact = {
56
name: "main.log",
67
url: "fakepath/to/main.log",
78
mimeType: "text/plain",
8-
parentTask: "task"
9+
parentTask: "task",
910
};
1011

1112
export const mockArtifacts: Artifact[] = [
@@ -14,20 +15,36 @@ export const mockArtifacts: Artifact[] = [
1415
name: "image1.png",
1516
mimeType: "image/png",
1617
url: "fakepath/to/image1.png",
17-
parentTask: "task1"
18+
parentTask: "task1",
1819
},
1920

2021
{
2122
name: "textfile.txt",
2223
mimeType: "text/plain",
2324
url: "fakepath/to/textfile.txt",
24-
parentTask: "task2"
25+
parentTask: "task2",
2526
},
2627
{
2728
name: "image2.png",
2829
mimeType: "image/png",
2930
url: "fakepath/to/image2.png",
30-
parentTask: "task3"
31+
parentTask: "task3",
32+
},
33+
];
34+
35+
export const mockImages: ImageInfo[] = [
36+
{
37+
src: "fakepath/to/image1.png",
38+
alt: "Gallery Image 1",
39+
},
40+
41+
{
42+
src: "fakepath/to/image2.png",
43+
alt: "Gallery Image 2",
44+
},
45+
{
46+
src: "fakepath/to/image3.png",
47+
alt: "Gallery Image 3",
3148
},
3249
];
3350

@@ -45,7 +62,7 @@ export const mockTasks = [
4562
artifacts: [logArtifact],
4663
workflow: "workflow-test",
4764
instrumentSession: instrumentSession,
48-
stepType: "POD"
65+
stepType: "POD",
4966
},
5067
{
5168
id: "task-2",
@@ -55,7 +72,7 @@ export const mockTasks = [
5572
workflow: "workflow-test",
5673
instrumentSession: instrumentSession,
5774
depends: ["task-1"],
58-
stepType: "POD"
75+
stepType: "POD",
5976
},
6077
{
6178
id: "task-3",
@@ -64,6 +81,6 @@ export const mockTasks = [
6481
artifacts: [logArtifact],
6582
workflow: "workflow-test",
6683
instrumentSession: instrumentSession,
67-
stepType: "POD"
84+
stepType: "POD",
6885
},
6986
];

0 commit comments

Comments
 (0)