From 1314d8ae0a2017c525a802ecdc5b38522ea52230 Mon Sep 17 00:00:00 2001 From: Yousef Moazzam Date: Fri, 11 Sep 2026 11:18:32 +0100 Subject: [PATCH 01/24] Add skeleton plot component --- frontend/unified/src/App.tsx | 7 +- .../src/components/Plot/ArtifactSelector.tsx | 153 ++++++++++++++++++ frontend/unified/src/components/Plot/Plot.tsx | 81 ++++++++++ 3 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 frontend/unified/src/components/Plot/ArtifactSelector.tsx create mode 100644 frontend/unified/src/components/Plot/Plot.tsx diff --git a/frontend/unified/src/App.tsx b/frontend/unified/src/App.tsx index 1f7f38b..5131b96 100644 --- a/frontend/unified/src/App.tsx +++ b/frontend/unified/src/App.tsx @@ -14,6 +14,7 @@ import { WorkflowForm } from "./components/WorkflowForm"; import { DisplayLogMeta } from "./components/InspectLogMeta"; import { Beamline, Technique } from "./types"; import { ParameterConfiguration } from "./components/ParameterConfiguration/ParameterConfiguration"; +import { Plot } from "./components/Plot/Plot"; import { ApolloProvider, useQuery } from "@apollo/client/react"; import { apolloClientWorkflows } from "../../src/ApolloClient"; import { gql, type TypedDocumentNode } from "@apollo/client"; @@ -302,11 +303,7 @@ export const App: React.FC = () => { Plot - + Log diff --git a/frontend/unified/src/components/Plot/ArtifactSelector.tsx b/frontend/unified/src/components/Plot/ArtifactSelector.tsx new file mode 100644 index 0000000..7d3e979 --- /dev/null +++ b/frontend/unified/src/components/Plot/ArtifactSelector.tsx @@ -0,0 +1,153 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { + GetWorkflowArtifactsQuery, + GetWorkflowArtifactsQueryVariables, +} from "./__generated__/ArtifactSelector.generated"; +import { useSuspenseQuery } from "@apollo/client/react"; +import { Visit } from "../JobsViewer/JobsViewer"; +import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; +import { ReactElement, useState } from "react"; + +const GET_WORKFLOW_ARTIFACTS: TypedDocumentNode< + GetWorkflowArtifactsQuery, + GetWorkflowArtifactsQueryVariables +> = gql` + query GetWorkflowArtifacts($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + name + status { + __typename + ... on WorkflowPendingStatus { + message + } + ... on WorkflowRunningStatus { + tasks { + id + name + status + stepType + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowSucceededStatus { + __typename + startTime + tasks { + id + name + status + stepType + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowFailedStatus { + tasks { + id + name + status + stepType + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowErroredStatus { + tasks { + id + name + status + stepType + artifacts { + name + url + mimeType + } + } + } + } + } + } +`; + +type ArtifactSelectorProps = { + workflowName: string; + visit: Visit; + setArtifactUrl: (_: string | null) => void; + isPlottingEnabled: boolean; +}; + +export const ArtifactSelector: React.FC = ({ + workflowName, + visit, + setArtifactUrl, + isPlottingEnabled, +}: ArtifactSelectorProps) => { + const [selectedArtifact, setSelectedArtifact] = useState(""); + const { error, data } = useSuspenseQuery(GET_WORKFLOW_ARTIFACTS, { + variables: { + name: workflowName, + visit: visit, + }, + }); + + if (error) return

Error: {error.message}

; + + const generateArtifactList = (): ReactElement[] => { + switch (data.workflow?.status?.__typename) { + case "WorkflowSucceededStatus": { + const taskNamesAndImageArtifacts = data.workflow.status.tasks + .map((task) => [ + task.name, + task.artifacts.filter( + (artifact) => artifact.mimeType === "image/jpeg" + ), + ]) + .filter(([_, artifacts]) => artifacts.length > 0); + + return taskNamesAndImageArtifacts.map(([taskName, artifacts]) => { + return artifacts.map((artifact) => { + const label = `${taskName}: ${artifact.name}`; + return ( + + {label} + + ); + }); + }); + } + default: + console.log("Handle other workflow status cases"); + return [default]; + } + }; + + return ( + + Artifact +