From 0215e17bb494d9b9dfd7a8974fa92b8a6d7d06b8 Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Tue, 13 Oct 2026 15:04:57 +0000 Subject: [PATCH 1/8] add omitOperationSuffix to codegen config --- frontend/graphqlCodegen.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/graphqlCodegen.ts b/frontend/graphqlCodegen.ts index 79947e16..1ba0c795 100644 --- a/frontend/graphqlCodegen.ts +++ b/frontend/graphqlCodegen.ts @@ -22,6 +22,7 @@ const config: CodegenConfig = { importSchemaTypesFrom: "./src/__generated__/types.ts", nonOptionalTypename: true, skipTypeNameForRoot: true, + omitOperationSuffix: true, }, presetConfig: { folder: "__generated__", From 062c3c91993a034aa0b0d40b55ab7195ab53898e Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 08:02:47 +0000 Subject: [PATCH 2/8] remove unnecessary imports --- frontend/unified/src/App.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/unified/src/App.tsx b/frontend/unified/src/App.tsx index 57a4001d..c6cbd3e0 100644 --- a/frontend/unified/src/App.tsx +++ b/frontend/unified/src/App.tsx @@ -3,9 +3,6 @@ import { gql, type TypedDocumentNode } from "@apollo/client"; import { ApolloProvider, useQuery } from "@apollo/client/react"; import { - Accordion, - AccordionDetails, - AccordionSummary, Box, Chip, Drawer, @@ -13,14 +10,12 @@ import { Stack, Typography, } from "@mui/material"; -import { ChevronDown } from "lucide-react"; import { InstrumentSession, SessionSelectionMode, SessionSelector, } from "./components/SessionSelector"; -import { ScanSelector } from "./components/ScanSelector"; import WorkflowsDataFetcher from "./components/WorkflowsDataFetcher/WorkflowsDataFetcher"; import { Beamline } from "./types"; From abca02f8ae62d216ad639c768135377b62091d65 Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 08:13:26 +0000 Subject: [PATCH 3/8] add graphql folder to list of documents --- frontend/graphqlCodegen.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/graphqlCodegen.ts b/frontend/graphqlCodegen.ts index 1ba0c795..2df78a1e 100644 --- a/frontend/graphqlCodegen.ts +++ b/frontend/graphqlCodegen.ts @@ -4,7 +4,11 @@ const config: CodegenConfig = { overwrite: true, schema: ["./src/instrument_sessions.graphql", "./src/workflows.graphql"], - documents: ["./*/src/components/**/*.{ts,tsx}", "./unified/src/App.tsx"], + documents: [ + "./*/src/components/**/*.{ts,tsx}", + "./unified/src/App.tsx", + "./unified/src/graphql/**/*.ts", + ], ignoreNoDocuments: true, generates: { From c67bcca7d6ba97240e030740c6334834b90bc1a1 Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 08:15:50 +0000 Subject: [PATCH 4/8] move SessionQuery to graphql --- frontend/unified/src/App.tsx | 42 +------------------- frontend/unified/src/graphql/SessionQuery.ts | 32 +++++++++++++++ 2 files changed, 34 insertions(+), 40 deletions(-) create mode 100644 frontend/unified/src/graphql/SessionQuery.ts diff --git a/frontend/unified/src/App.tsx b/frontend/unified/src/App.tsx index c6cbd3e0..507843a2 100644 --- a/frontend/unified/src/App.tsx +++ b/frontend/unified/src/App.tsx @@ -1,15 +1,7 @@ import { useState } from "react"; -import { gql, type TypedDocumentNode } from "@apollo/client"; import { ApolloProvider, useQuery } from "@apollo/client/react"; -import { - Box, - Chip, - Drawer, - Grid, - Stack, - Typography, -} from "@mui/material"; +import { Box, Chip, Drawer, Grid, Stack, Typography } from "@mui/material"; import { InstrumentSession, @@ -21,43 +13,13 @@ import WorkflowsDataFetcher from "./components/WorkflowsDataFetcher/WorkflowsDat import { Beamline } from "./types"; import { apolloClientWorkflows } from "../../src/ApolloClient"; import { useAuth } from "@diamondlightsource/sci-react-ui"; -import { - SessionQueryQuery, - SessionQueryQueryVariables, -} from "./__generated__/App.generated"; import { Sidebar } from "./components/Sidebar"; import ProcessingView from "./components/ProcessingView/ProcessingView"; +import { SESSION_QUERY } from "./graphql/SessionQuery"; const VERTICAL_SPACING = 2; const HORIZONTAL_SPACING = 2; -export const SESSION_QUERY: TypedDocumentNode< - SessionQueryQuery, - SessionQueryQueryVariables -> = gql` - query sessionQuery($username: String!) { - account(username: $username) { - instrumentSessionRoles(first: 1) { - edges { - node { - instrumentSession { - proposal { - proposalNumber - proposalCategory - } - instrumentSessionNumber - instrument { - name - } - startTime - } - } - } - } - } - } -`; - const useFedid = (): string => { const token = useAuth().getToken(); const parseToken = JSON.parse(atob(token.split(".")[1])); diff --git a/frontend/unified/src/graphql/SessionQuery.ts b/frontend/unified/src/graphql/SessionQuery.ts new file mode 100644 index 00000000..5336aa68 --- /dev/null +++ b/frontend/unified/src/graphql/SessionQuery.ts @@ -0,0 +1,32 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { + SessionQuery, + SessionQueryVariables, +} from "./__generated__/SessionQuery.generated"; + +export const SESSION_QUERY: TypedDocumentNode< + SessionQuery, + SessionQueryVariables +> = gql` + query sessionQuery($username: String!) { + account(username: $username) { + instrumentSessionRoles(first: 1) { + edges { + node { + instrumentSession { + proposal { + proposalNumber + proposalCategory + } + instrumentSessionNumber + instrument { + name + } + startTime + } + } + } + } + } + } +`; From fc59d79232dd1328cc630c4ab80260d14a6141f0 Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 08:25:00 +0000 Subject: [PATCH 5/8] move SessionSelectorQuery to graphql --- .../src/components/SessionSelector.tsx | 31 +++---------------- .../src/graphql/SessionSelectorQuery.ts | 24 ++++++++++++++ 2 files changed, 28 insertions(+), 27 deletions(-) create mode 100644 frontend/unified/src/graphql/SessionSelectorQuery.ts diff --git a/frontend/unified/src/components/SessionSelector.tsx b/frontend/unified/src/components/SessionSelector.tsx index 63f8c6d9..6bb2347e 100644 --- a/frontend/unified/src/components/SessionSelector.tsx +++ b/frontend/unified/src/components/SessionSelector.tsx @@ -7,40 +7,17 @@ import { Button, Tooltip, } from "@mui/material"; -import { SessionQueryQuery } from "../__generated__/App.generated"; -import { - GetSessionByReferenceQuery, - GetSessionByReferenceQueryVariables, -} from "./__generated__/SessionSelector.generated"; import { visitRegex } from "@diamondlightsource/sci-react-ui"; -import { gql, TypedDocumentNode } from "@apollo/client"; import { useSuspenseQuery } from "@apollo/client/react"; - -export const GET_SESSION_BY_REFERENCE: TypedDocumentNode< - GetSessionByReferenceQuery, - GetSessionByReferenceQueryVariables -> = gql` - query GetSessionByReference($reference: String!) { - instrumentSessionByReference(reference: $reference) { - instrument { - name - } - instrumentSessionNumber - proposal { - proposalNumber - proposalCategory - } - startTime - } - } -`; +import { SessionQuery } from "../graphql/__generated__/SessionQuery.generated"; +import { SESSIONSELECTOR_QUERY } from "../graphql/SessionSelectorQuery"; export enum SessionSelectionMode { Latest = "Latest", Custom = "Custom", } -type NonNullAccount = NonNullable; +type NonNullAccount = NonNullable; export type InstrumentSession = NonNullAccount["instrumentSessionRoles"]["edges"][0]["node"]["instrumentSession"]; @@ -119,7 +96,7 @@ const SelectSessionButton: React.FC = ({ sessionSelectionMode, setSession, }) => { - const { data } = useSuspenseQuery(GET_SESSION_BY_REFERENCE, { + const { data } = useSuspenseQuery(SESSIONSELECTOR_QUERY, { variables: { reference: sessionInputValue }, }); diff --git a/frontend/unified/src/graphql/SessionSelectorQuery.ts b/frontend/unified/src/graphql/SessionSelectorQuery.ts new file mode 100644 index 00000000..396a0711 --- /dev/null +++ b/frontend/unified/src/graphql/SessionSelectorQuery.ts @@ -0,0 +1,24 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { + SessionSelectorQuery, + SessionSelectorQueryVariables, +} from "./__generated__/SessionSelectorQuery.generated"; + +export const SESSIONSELECTOR_QUERY: TypedDocumentNode< + SessionSelectorQuery, + SessionSelectorQueryVariables +> = gql` + query SessionSelectorQuery($reference: String!) { + instrumentSessionByReference(reference: $reference) { + instrument { + name + } + instrumentSessionNumber + proposal { + proposalNumber + proposalCategory + } + startTime + } + } +`; From 6270c42c5ea545e46731f107c1d7102355038b7c Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 08:47:39 +0000 Subject: [PATCH 6/8] move WorkflowDataViewerQuery to graphql --- .../WorkflowsDataFetcher/InspectLogMeta.tsx | 53 ++-------------- .../LogStreamer/LogStreamContent.tsx | 22 +------ .../LogStreamer/LogStreamer.tsx | 44 ++----------- .../Plot/ArtifactSelector.tsx | 63 +------------------ .../WorkflowDataViewer.tsx | 29 +-------- .../ArtifactSelectorFragment.ts | 59 +++++++++++++++++ .../InspectLogMetaFragment.ts | 46 ++++++++++++++ .../LogStreamContentSubscription.ts | 21 +++++++ .../LogStreamerFragment.ts | 38 +++++++++++ .../WorkflowDataViewerQuery.ts | 26 ++++++++ 10 files changed, 205 insertions(+), 196 deletions(-) create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/ArtifactSelectorFragment.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/InspectLogMetaFragment.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamContentSubscription.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamerFragment.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowDataViewerQuery.ts diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/InspectLogMeta.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/InspectLogMeta.tsx index 95ffd925..79b66546 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/InspectLogMeta.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/InspectLogMeta.tsx @@ -10,53 +10,8 @@ import { } from "@mui/material"; import { useSuspenseFragment } from "@apollo/client/react"; -import { gql, type TypedDocumentNode } from "@apollo/client"; - -import { InspectLogMetaFragmentFragment } from "./__generated__/InspectLogMeta.generated"; - -export const INSPECTLOGMETA_FRAGMENT: TypedDocumentNode = gql` - fragment InspectLogMetaFragment on Workflow { - status { - __typename - ... on WorkflowSucceededStatus { - startTime - message - tasks { - name - artifacts { - name - url - mimeType - } - } - } - ... on WorkflowErroredStatus { - startTime - message - tasks { - name - artifacts { - name - url - mimeType - } - } - } - ... on WorkflowFailedStatus { - startTime - message - tasks { - name - artifacts { - name - url - mimeType - } - } - } - } - } -`; +import { InspectLogMetaFragment } from "../../graphql/WorkflowDataFetcher/__generated__/InspectLogMetaFragment.generated"; +import { INSPECTLOGMETA_FRAGMENT } from "../../graphql/WorkflowDataFetcher/InspectLogMetaFragment"; type Artifact = { name: string; @@ -69,7 +24,7 @@ type Task = { artifacts: Artifact[]; }; -const getTasks = (data: InspectLogMetaFragmentFragment): Task[] => { +const getTasks = (data: InspectLogMetaFragment): Task[] => { if ( data.status && (data.status.__typename === "WorkflowSucceededStatus" || @@ -84,7 +39,7 @@ const getTasks = (data: InspectLogMetaFragmentFragment): Task[] => { const InspectLogMeta = ({ queryData, }: { - queryData: InspectLogMetaFragmentFragment; + queryData: InspectLogMetaFragment; }) => { const [logUrl, setLogUrl] = useState(null); const { data } = useSuspenseFragment({ diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamContent.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamContent.tsx index dca75f9d..9f2e4e01 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamContent.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamContent.tsx @@ -1,4 +1,3 @@ -import { gql, TypedDocumentNode } from "@apollo/client"; import { Visit } from "@diamondlightsource/sci-react-ui"; import { Box } from "@mui/material"; import { @@ -11,26 +10,7 @@ import { } from "react"; import { LogLine } from "./LogLine"; import { useSubscription } from "@apollo/client/react"; -import { - LogStreamContentSubscriptionSubscription, - LogStreamContentSubscriptionSubscriptionVariables, -} from "./__generated__/LogStreamContent.generated"; - -const LOGSTREAMCONTENT_SUBSCRIPTION: TypedDocumentNode< - LogStreamContentSubscriptionSubscription, - LogStreamContentSubscriptionSubscriptionVariables -> = gql` - subscription LogStreamContentSubscription( - $visit: VisitInput! - $workflowName: String! - $taskId: String! - ) { - logs(visit: $visit, workflowName: $workflowName, taskId: $taskId) { - content - podName - } - } -`; +import { LOGSTREAMCONTENT_SUBSCRIPTION } from "../../../graphql/WorkflowDataFetcher/LogStreamContentSubscription"; const LogStreamContent = ({ visit, diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamer.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamer.tsx index fa7f1acc..fc0224b3 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamer.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/LogStreamer/LogStreamer.tsx @@ -1,4 +1,3 @@ -import { gql, TypedDocumentNode } from "@apollo/client"; import { Visit } from "@diamondlightsource/sci-react-ui"; import { useSuspenseFragment } from "@apollo/client/react"; import { @@ -12,45 +11,10 @@ import { } from "@mui/material"; import { useState } from "react"; import { setFetchedTasks } from "./utils"; -import LogStreamContent from "./LogStreamContent"; -import { LogStreamerFragmentFragment } from "./__generated__/LogStreamer.generated"; import { getTaskStatusIcon } from "./getTaskStatusIcon"; - -export const LOGSTREAMER_FRAGMENT: TypedDocumentNode = gql` - fragment LogStreamerFragment on Workflow { - status { - __typename - ... on WorkflowRunningStatus { - tasks { - id - name - status - } - } - ... on WorkflowSucceededStatus { - tasks { - id - name - status - } - } - ... on WorkflowFailedStatus { - tasks { - id - name - status - } - } - ... on WorkflowErroredStatus { - tasks { - id - name - status - } - } - } - } -`; +import { LogStreamerFragment } from "../../../graphql/WorkflowDataFetcher/__generated__/LogStreamerFragment.generated"; +import { LOGSTREAMER_FRAGMENT } from "../../../graphql/WorkflowDataFetcher/LogStreamerFragment"; +import LogStreamContent from "./LogStreamContent"; const LogStreamer = ({ visit, @@ -59,7 +23,7 @@ const LogStreamer = ({ }: { visit: Visit; selectedWorkflow: string; - queryData: LogStreamerFragmentFragment; + queryData: LogStreamerFragment; }) => { const [selectedTaskId, setSelectedTaskId] = useState(null); const { data } = useSuspenseFragment({ diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/Plot/ArtifactSelector.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/Plot/ArtifactSelector.tsx index 9062128f..22ab4f75 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/Plot/ArtifactSelector.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/Plot/ArtifactSelector.tsx @@ -1,65 +1,8 @@ -import { gql, TypedDocumentNode } from "@apollo/client"; -import { ArtifactSelectorFragmentFragment } from "./__generated__/ArtifactSelector.generated"; import { useSuspenseFragment } from "@apollo/client/react"; import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; import { useState } from "react"; - -export const ARTIFACTSELECTOR_FRAGMENT: TypedDocumentNode = gql` - fragment ArtifactSelectorFragment on Workflow { - name - status { - __typename - ... on WorkflowRunningStatus { - startTime - tasks { - id - name - artifacts { - name - url - mimeType - } - } - } - ... on WorkflowSucceededStatus { - startTime - tasks { - id - name - artifacts { - name - url - mimeType - } - } - } - ... on WorkflowFailedStatus { - startTime - tasks { - id - name - artifacts { - name - url - mimeType - } - } - } - ... on WorkflowErroredStatus { - startTime - tasks { - id - name - artifacts { - name - url - mimeType - } - } - } - } - } -`; +import { ArtifactSelectorFragment } from "../../../graphql/WorkflowDataFetcher/__generated__/ArtifactSelectorFragment.generated"; +import { ARTIFACTSELECTOR_FRAGMENT } from "../../../graphql/WorkflowDataFetcher/ArtifactSelectorFragment"; export type Artifact = { name: string; @@ -72,7 +15,7 @@ type TaskNameAndArtifactTuple = [taskName: string, artifacts: Artifact[]]; type ArtifactSelectorProps = { setArtifact: (_: Artifact | null) => void; isPlottingEnabled: boolean; - queryData: ArtifactSelectorFragmentFragment; + queryData: ArtifactSelectorFragment; }; const IMAGE_ARTIFACT_MIME_TYPES = ["image/jpeg", "image/tiff"]; diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowDataViewer.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowDataViewer.tsx index 4f3678fd..6921bb69 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowDataViewer.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowDataViewer.tsx @@ -5,35 +5,12 @@ import { Typography, } from "@mui/material"; import { Visit } from "@diamondlightsource/sci-react-ui"; -import LogStreamer, { LOGSTREAMER_FRAGMENT } from "./LogStreamer/LogStreamer"; +import LogStreamer from "./LogStreamer/LogStreamer"; import { Plot } from "./Plot/Plot"; -import { gql, TypedDocumentNode } from "@apollo/client"; import { useSuspenseQuery } from "@apollo/client/react"; -import InspectLogMeta, { INSPECTLOGMETA_FRAGMENT } from "./InspectLogMeta"; +import InspectLogMeta from "./InspectLogMeta"; import { ChevronDown } from "lucide-react"; -import { ARTIFACTSELECTOR_FRAGMENT } from "./Plot/ArtifactSelector"; -import { - WorkflowDataViewerQueryQuery, - WorkflowDataViewerQueryQueryVariables, -} from "./__generated__/WorkflowDataViewer.generated"; - -const WORKFLOWDATAVIEWER_QUERY: TypedDocumentNode< - WorkflowDataViewerQueryQuery, - WorkflowDataViewerQueryQueryVariables -> = gql` - query WorkflowDataViewerQuery($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - name - id - ...LogStreamerFragment - ...InspectLogMetaFragment - ...ArtifactSelectorFragment - } - } - ${LOGSTREAMER_FRAGMENT} - ${INSPECTLOGMETA_FRAGMENT} - ${ARTIFACTSELECTOR_FRAGMENT} -`; +import { WORKFLOWDATAVIEWER_QUERY } from "../../graphql/WorkflowDataFetcher/WorkflowDataViewerQuery"; const WorkflowDataViewer = ({ visit, diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/ArtifactSelectorFragment.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/ArtifactSelectorFragment.ts new file mode 100644 index 00000000..cd6824e9 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/ArtifactSelectorFragment.ts @@ -0,0 +1,59 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { ArtifactSelectorFragment } from "./__generated__/ArtifactSelectorFragment.generated"; + +export const ARTIFACTSELECTOR_FRAGMENT: TypedDocumentNode = gql` + fragment ArtifactSelectorFragment on Workflow { + name + status { + __typename + ... on WorkflowRunningStatus { + startTime + tasks { + id + name + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowSucceededStatus { + startTime + tasks { + id + name + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowFailedStatus { + startTime + tasks { + id + name + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowErroredStatus { + startTime + tasks { + id + name + artifacts { + name + url + mimeType + } + } + } + } + } +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/InspectLogMetaFragment.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/InspectLogMetaFragment.ts new file mode 100644 index 00000000..8e07747b --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/InspectLogMetaFragment.ts @@ -0,0 +1,46 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { InspectLogMetaFragment } from "./__generated__/InspectLogMetaFragment.generated"; + +export const INSPECTLOGMETA_FRAGMENT: TypedDocumentNode = gql` + fragment InspectLogMetaFragment on Workflow { + status { + __typename + ... on WorkflowSucceededStatus { + startTime + message + tasks { + name + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowErroredStatus { + startTime + message + tasks { + name + artifacts { + name + url + mimeType + } + } + } + ... on WorkflowFailedStatus { + startTime + message + tasks { + name + artifacts { + name + url + mimeType + } + } + } + } + } +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamContentSubscription.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamContentSubscription.ts new file mode 100644 index 00000000..8e4d30d8 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamContentSubscription.ts @@ -0,0 +1,21 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { + LogStreamContentSubscription, + LogStreamContentSubscriptionVariables, +} from "./__generated__/LogStreamContentSubscription.generated"; + +export const LOGSTREAMCONTENT_SUBSCRIPTION: TypedDocumentNode< + LogStreamContentSubscription, + LogStreamContentSubscriptionVariables +> = gql` + subscription LogStreamContentSubscription( + $visit: VisitInput! + $workflowName: String! + $taskId: String! + ) { + logs(visit: $visit, workflowName: $workflowName, taskId: $taskId) { + content + podName + } + } +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamerFragment.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamerFragment.ts new file mode 100644 index 00000000..511a6224 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/LogStreamerFragment.ts @@ -0,0 +1,38 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { LogStreamerFragment } from "./__generated__/LogStreamerFragment.generated"; + +export const LOGSTREAMER_FRAGMENT: TypedDocumentNode = gql` + fragment LogStreamerFragment on Workflow { + status { + __typename + ... on WorkflowRunningStatus { + tasks { + id + name + status + } + } + ... on WorkflowSucceededStatus { + tasks { + id + name + status + } + } + ... on WorkflowFailedStatus { + tasks { + id + name + status + } + } + ... on WorkflowErroredStatus { + tasks { + id + name + status + } + } + } + } +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowDataViewerQuery.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowDataViewerQuery.ts new file mode 100644 index 00000000..cc1a7e65 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowDataViewerQuery.ts @@ -0,0 +1,26 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { INSPECTLOGMETA_FRAGMENT } from "./InspectLogMetaFragment"; +import { ARTIFACTSELECTOR_FRAGMENT } from "./ArtifactSelectorFragment"; +import { LOGSTREAMER_FRAGMENT } from "./LogStreamerFragment"; +import { + WorkflowDataViewerQuery, + WorkflowDataViewerQueryVariables, +} from "./__generated__/WorkflowDataViewerQuery.generated"; + +export const WORKFLOWDATAVIEWER_QUERY: TypedDocumentNode< + WorkflowDataViewerQuery, + WorkflowDataViewerQueryVariables +> = gql` + query WorkflowDataViewerQuery($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + name + id + ...LogStreamerFragment + ...InspectLogMetaFragment + ...ArtifactSelectorFragment + } + } + ${LOGSTREAMER_FRAGMENT} + ${INSPECTLOGMETA_FRAGMENT} + ${ARTIFACTSELECTOR_FRAGMENT} +`; From 0b5edeb13ad5fdf203d9b40dbcd94b4d0f087227 Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 09:28:52 +0000 Subject: [PATCH 7/8] move WorkflowsTable queries to graphql --- .../WorkflowsTable/BaseTableRow.tsx | 24 +++----------- .../WorkflowsTable/LiveTableRow.tsx | 31 +++---------------- .../WorkflowsTable/TableContent.tsx | 22 +++---------- .../WorkflowsTable/TableRowWrapper.tsx | 24 +++----------- .../WorkflowsTable/WorkflowsTable.tsx | 23 +++----------- .../WorkflowsTable/BaseTableRowFragment.ts | 14 +++++++++ .../LiveTableRowSubscription.ts | 24 ++++++++++++++ .../WorkflowsTable/TableContentFragment.ts | 17 ++++++++++ .../WorkflowsTable/TableRowWrapperFragment.ts | 19 ++++++++++++ .../WorkflowsTable/WorkflowsTableQuery.ts | 18 +++++++++++ 10 files changed, 113 insertions(+), 103 deletions(-) create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/BaseTableRowFragment.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/LiveTableRowSubscription.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableContentFragment.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableRowWrapperFragment.ts create mode 100644 frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/WorkflowsTableQuery.ts diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/BaseTableRow.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/BaseTableRow.tsx index ee223afd..ebad8861 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/BaseTableRow.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/BaseTableRow.tsx @@ -1,37 +1,23 @@ -import { gql, TypedDocumentNode } from "@apollo/client"; import { Box, TableCell, Typography } from "@mui/material"; import { Eye } from "lucide-react"; import { useFragment } from "@apollo/client/react"; -import { BaseTableRowFragmentFragment } from "./__generated__/BaseTableRow.generated"; import { getWorkflowStatusIcon } from "./StatusIcons"; import { DeepPartial } from "@apollo/client/utilities"; -import { TableRowWrapperFragmentFragment } from "./__generated__/TableRowWrapper.generated"; import { WorkflowsTableRow } from "./WorkflowsTableRow"; - -export const BASETABLEROW_FRAGMENT: TypedDocumentNode = gql` - fragment BaseTableRowFragment on Workflow { - name - status { - __typename - ... on WorkflowSucceededStatus { - startTime - } - } - } -`; +import { BASETABLEROW_FRAGMENT } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/BaseTableRowFragment"; +import { TableRowWrapperFragment } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/__generated__/TableRowWrapperFragment.generated"; +import { BaseTableRowFragment } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/__generated__/BaseTableRowFragment.generated"; const BaseTableRow = ({ queryData, selectedWorkflow, setSelectedWorkflow, }: { - queryData: - | TableRowWrapperFragmentFragment - | DeepPartial; + queryData: TableRowWrapperFragment | DeepPartial; selectedWorkflow: string | null; setSelectedWorkflow: (_: string | null) => void; }) => { - const { data } = useFragment({ + const { data } = useFragment({ fragment: BASETABLEROW_FRAGMENT, fragmentName: "BaseTableRowFragment", from: queryData, diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/LiveTableRow.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/LiveTableRow.tsx index e94b6138..7a26b1cb 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/LiveTableRow.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/LiveTableRow.tsx @@ -1,31 +1,9 @@ -import { gql, TypedDocumentNode } from "@apollo/client"; -import BaseTableRow, { BASETABLEROW_FRAGMENT } from "./BaseTableRow"; +import BaseTableRow from "./BaseTableRow"; import { useState } from "react"; -import { BaseTableRowFragmentFragment } from "./__generated__/BaseTableRow.generated"; import { apolloClientWorkflows } from "../../../../../src/ApolloClient"; -import { - LiveTableRowSubscriptionSubscription, - LiveTableRowSubscriptionSubscriptionVariables, -} from "./__generated__/LiveTableRow.generated"; import { Visit } from "@diamondlightsource/sci-react-ui"; - -export const LIVETABLEROW_SUBSCRIPTION: TypedDocumentNode< - LiveTableRowSubscriptionSubscription, - LiveTableRowSubscriptionSubscriptionVariables -> = gql` - subscription LiveTableRowSubscription($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - status { - __typename - ... on WorkflowSucceededStatus { - startTime - } - } - ...BaseTableRowFragment - } - } - ${BASETABLEROW_FRAGMENT} -`; +import { BaseTableRowFragment } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/__generated__/BaseTableRowFragment.generated"; +import { LIVETABLEROW_SUBSCRIPTION } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/LiveTableRowSubscription"; interface LiveTableRowProps { workflowName: string; @@ -42,8 +20,7 @@ const LiveTableRow = ({ selectedWorkflow, setSelectedWorkflow, }: LiveTableRowProps) => { - const [queryData, setQueryData] = - useState(null); + const [queryData, setQueryData] = useState(null); apolloClientWorkflows .subscribe({ query: LIVETABLEROW_SUBSCRIPTION, diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableContent.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableContent.tsx index 7eb58d29..d49fd3e2 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableContent.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableContent.tsx @@ -11,28 +11,14 @@ import { TableRow, } from "@mui/material"; import { useFragment } from "@apollo/client/react"; -import { TableContentFragmentFragment } from "./__generated__/TableContent.generated"; import { ChangeEvent, MouseEvent } from "react"; import { ChevronLeft, ChevronRight } from "lucide-react"; -import { gql, TypedDocumentNode } from "@apollo/client"; -import TableRowWrapper, { TABLEROWWRAPPER_FRAGMENT } from "./TableRowWrapper"; - -export const TABLECONTENT_FRAGMENT: TypedDocumentNode = gql` - fragment TableContentFragment on WorkflowConnection { - pageInfo { - hasNextPage - startCursor - endCursor - } - nodes { - ...TableRowWrapperFragment @unmask - } - } - ${TABLEROWWRAPPER_FRAGMENT} -`; +import TableRowWrapper from "./TableRowWrapper"; +import { TABLECONTENT_FRAGMENT } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/TableContentFragment"; +import { TableContentFragment } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/__generated__/TableContentFragment.generated"; interface TableContentProps { - queryData: TableContentFragmentFragment; + queryData: TableContentFragment; currentPage: number; setCurrentPage: (newPage: number) => void; selectedLimit: number; diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableRowWrapper.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableRowWrapper.tsx index b97fa705..16efc813 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableRowWrapper.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/TableRowWrapper.tsx @@ -1,30 +1,14 @@ -import { gql, TypedDocumentNode } from "@apollo/client"; import { TableCell, TableRow } from "@mui/material"; -import { TableRowWrapperFragmentFragment } from "./__generated__/TableRowWrapper.generated"; import { useFragment } from "@apollo/client/react"; -import BaseTableRow, { BASETABLEROW_FRAGMENT } from "./BaseTableRow"; +import BaseTableRow from "./BaseTableRow"; import { finishedStatuses } from "./utils/utils"; import { useState } from "react"; import LiveTableRow from "./LiveTableRow"; - -export const TABLEROWWRAPPER_FRAGMENT: TypedDocumentNode = gql` - fragment TableRowWrapperFragment on Workflow { - ...BaseTableRowFragment - status { - __typename - } - visit { - proposalCode - proposalNumber - number - } - name - } - ${BASETABLEROW_FRAGMENT} -`; +import { TABLEROWWRAPPER_FRAGMENT } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/TableRowWrapperFragment"; +import { TableRowWrapperFragment } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/__generated__/TableRowWrapperFragment.generated"; interface TableRowWrapperProps { - queryData: TableRowWrapperFragmentFragment; + queryData: TableRowWrapperFragment; selectedWorkflow: string | null; setSelectedWorkflow: (_: string | null) => void; } diff --git a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/WorkflowsTable.tsx b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/WorkflowsTable.tsx index 66deadb9..0f284f93 100644 --- a/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/WorkflowsTable.tsx +++ b/frontend/unified/src/components/WorkflowsDataFetcher/WorkflowsTable/WorkflowsTable.tsx @@ -1,24 +1,9 @@ import { Suspense, useCallback, useState } from "react"; import { Visit } from "@diamondlightsource/sci-react-ui"; -import TableContent, { TABLECONTENT_FRAGMENT } from "./TableContent"; -import { gql, TypedDocumentNode } from "@apollo/client"; +import TableContent from "./TableContent"; import { useQuery } from "@apollo/client/react"; -import { - WorkflowsTableQueryQuery, - WorkflowsTableQueryQueryVariables, -} from "./__generated__/WorkflowsTable.generated"; - -export const WORKFLOWSTABLE_QUERY: TypedDocumentNode< - WorkflowsTableQueryQuery, - WorkflowsTableQueryQueryVariables -> = gql` - query WorkflowsTableQuery($visit: VisitInput!, $limit: Int, $cursor: String) { - workflows(visit: $visit, limit: $limit, cursor: $cursor) { - ...TableContentFragment @unmask - } - } - ${TABLECONTENT_FRAGMENT} -`; +import { WORKFLOWSTABLE_QUERY } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/WorkflowsTableQuery"; +import { WorkflowsTableQueryVariables } from "../../../graphql/WorkflowDataFetcher/WorkflowsTable/__generated__/WorkflowsTableQuery.generated"; const WorkflowsTable = ({ visit, @@ -39,7 +24,7 @@ const WorkflowsTable = ({ setCursor(null); }, []); - const queryVariables: WorkflowsTableQueryQueryVariables = { + const queryVariables: WorkflowsTableQueryVariables = { visit, limit: selectedLimit, cursor, diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/BaseTableRowFragment.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/BaseTableRowFragment.ts new file mode 100644 index 00000000..d2737534 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/BaseTableRowFragment.ts @@ -0,0 +1,14 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { BaseTableRowFragment } from "./__generated__/BaseTableRowFragment.generated"; + +export const BASETABLEROW_FRAGMENT: TypedDocumentNode = gql` + fragment BaseTableRowFragment on Workflow { + name + status { + __typename + ... on WorkflowSucceededStatus { + startTime + } + } + } +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/LiveTableRowSubscription.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/LiveTableRowSubscription.ts new file mode 100644 index 00000000..bd65caaf --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/LiveTableRowSubscription.ts @@ -0,0 +1,24 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { BASETABLEROW_FRAGMENT } from "./BaseTableRowFragment"; +import { + LiveTableRowSubscription, + LiveTableRowSubscriptionVariables, +} from "./__generated__/LiveTableRowSubscription.generated"; + +export const LIVETABLEROW_SUBSCRIPTION: TypedDocumentNode< + LiveTableRowSubscription, + LiveTableRowSubscriptionVariables +> = gql` + subscription LiveTableRowSubscription($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + status { + __typename + ... on WorkflowSucceededStatus { + startTime + } + } + ...BaseTableRowFragment + } + } + ${BASETABLEROW_FRAGMENT} +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableContentFragment.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableContentFragment.ts new file mode 100644 index 00000000..8e61deb0 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableContentFragment.ts @@ -0,0 +1,17 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { TABLEROWWRAPPER_FRAGMENT } from "./TableRowWrapperFragment"; +import { TableContentFragment } from "./__generated__/TableContentFragment.generated"; + +export const TABLECONTENT_FRAGMENT: TypedDocumentNode = gql` + fragment TableContentFragment on WorkflowConnection { + pageInfo { + hasNextPage + startCursor + endCursor + } + nodes { + ...TableRowWrapperFragment @unmask + } + } + ${TABLEROWWRAPPER_FRAGMENT} +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableRowWrapperFragment.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableRowWrapperFragment.ts new file mode 100644 index 00000000..c5ef895b --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/TableRowWrapperFragment.ts @@ -0,0 +1,19 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { BASETABLEROW_FRAGMENT } from "./BaseTableRowFragment"; +import { TableRowWrapperFragment } from "./__generated__/TableRowWrapperFragment.generated"; + +export const TABLEROWWRAPPER_FRAGMENT: TypedDocumentNode = gql` + fragment TableRowWrapperFragment on Workflow { + ...BaseTableRowFragment + status { + __typename + } + visit { + proposalCode + proposalNumber + number + } + name + } + ${BASETABLEROW_FRAGMENT} +`; diff --git a/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/WorkflowsTableQuery.ts b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/WorkflowsTableQuery.ts new file mode 100644 index 00000000..b5962435 --- /dev/null +++ b/frontend/unified/src/graphql/WorkflowDataFetcher/WorkflowsTable/WorkflowsTableQuery.ts @@ -0,0 +1,18 @@ +import { gql, TypedDocumentNode } from "@apollo/client"; +import { TABLECONTENT_FRAGMENT } from "./TableContentFragment"; +import { + WorkflowsTableQuery, + WorkflowsTableQueryVariables, +} from "./__generated__/WorkflowsTableQuery.generated"; + +export const WORKFLOWSTABLE_QUERY: TypedDocumentNode< + WorkflowsTableQuery, + WorkflowsTableQueryVariables +> = gql` + query WorkflowsTableQuery($visit: VisitInput!, $limit: Int, $cursor: String) { + workflows(visit: $visit, limit: $limit, cursor: $cursor) { + ...TableContentFragment @unmask + } + } + ${TABLECONTENT_FRAGMENT} +`; From d390cdb919c422e26dd74112ebcd77babe0246d2 Mon Sep 17 00:00:00 2001 From: NatLeung96 Date: Wed, 14 Oct 2026 10:52:52 +0000 Subject: [PATCH 8/8] fixed SessionSelector test --- frontend/unified/tests/SessionSelector.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/unified/tests/SessionSelector.test.tsx b/frontend/unified/tests/SessionSelector.test.tsx index 9a626ac9..23e4629b 100644 --- a/frontend/unified/tests/SessionSelector.test.tsx +++ b/frontend/unified/tests/SessionSelector.test.tsx @@ -3,11 +3,11 @@ import "@testing-library/jest-dom"; import { expect, test, vi, afterEach } from "vitest"; import { act, render, screen } from "@testing-library/react"; import { - GET_SESSION_BY_REFERENCE, SessionSelectionMode, SessionSelector, } from "../src/components/SessionSelector"; import { MockedProvider } from "@apollo/client/testing/react"; +import { SESSIONSELECTOR_QUERY } from "../src/graphql/SessionSelectorQuery"; afterEach(() => { vi.clearAllMocks(); @@ -16,7 +16,7 @@ afterEach(() => { const mocks = [ { request: { - query: GET_SESSION_BY_REFERENCE, + query: SESSIONSELECTOR_QUERY, variables: { reference: "", },