diff --git a/apps/i15-1/README.md b/apps/i15-1/README.md index 9b036460..45788698 100644 --- a/apps/i15-1/README.md +++ b/apps/i15-1/README.md @@ -7,8 +7,66 @@ The initial aim of this app to provide a science facing UI for the waffle projec To run this locally: 1. Start the devcontainer in VSCode -2. To make sure you have the most up-to-date environment either run `pnpm install` in the container or rebuild the container (via the Ctrl+Shift+P menu in VSCode) -3. In a terminal in this devcontainer run either: +1. To make sure you have the most up-to-date environment either run `pnpm install` in the container or rebuild the container (via the Ctrl+Shift+P menu in VSCode) +1. In a terminal in this devcontainer run either: - `VITE_QUEUE_MODE=local turbo dev --filter @atlas/i15-1` if running a local queue server on http://127.0.0.1:8001, **OR** - `turbo dev --filter @atlas/i15-1` to use mocked backends -4. Navigate to http://localhost:5173/ +1. Navigate to http://localhost:5173/ + +## Updating Supergraph Schema Types + +1. Navigate to app containing folder (i.e. `.../atlas/apps/i15-1`) +1. Update the `supergraph.graphql` schema from most recent `supergraph.graphql` schema from https://github.com/DiamondLightSource/graph-federation/releases +1. Generate types by running `pnpm run generate:graphql` + +The available types are generated based on queries detected in the documents (`[./src/**/*.ts*]`), so if a new query is added you will need to generate the types again. Type names will be automatically generated based on your query name. To use, follow the example below: + +1. Add a new query + +```ts +import { gql } from "@apollo/client"; + +export const myNewQuery = gql` + query GetSessionPlaylist($proposal: Int!, $session: Int!) { + instrumentSession( + proposalNumber: $proposal + instrumentSessionNumber: $session + ) { + state + } + } +`; +``` + +2. Generate types by running `pnpm run generate:graphql`. This will generate a new `.generated.ts` file with the types. +3. Use query and types in your component. + +```ts +import { useQuery } from "@apollo/client/react"; +import type { TypedDocumentNode } from "@apollo/client"; + +import { myNewQuery } from "../graphql/myNewQuery"; +import type { + myNewQueryVariables, + myNewQuery, +} from "../graphql/getSessionPlaylistQuery.generated"; + +const GET_EXPERIMENTS: TypedDocumentNode< + myNewQuery, + myNewQueryVariables +> = myNewQuery; + +export function QueryData() { + const { data, loading, error } = useQuery(GET_EXPERIMENTS, { + variables: { + proposal: 44163, + session: 3, + }, + }); + + if (loading) return

Loading...

; + if (error) return

Error: {error.message}

; + + return data?.instrumentSession?.state || []; +} +``` diff --git a/apps/i15-1/graphqlCodegen.ts b/apps/i15-1/graphqlCodegen.ts new file mode 100644 index 00000000..4d249c9c --- /dev/null +++ b/apps/i15-1/graphqlCodegen.ts @@ -0,0 +1,30 @@ +import type { CodegenConfig } from "@graphql-codegen/cli"; + +const config: CodegenConfig = { + overwrite: true, + + schema: "./src/graphql/supergraph.graphql", + documents: ["./src/**/*.{ts,tsx}"], + ignoreNoDocuments: true, + + generates: { + "./src/graphql/__generated__/": { + plugins: ["typescript-operations"], + config: { + generateOperationTypes: false, + }, + }, + + "./src/": { + preset: "near-operation-file", + plugins: ["typescript-operations"], + config: { + importSchemaTypesFrom: "./src/graphql/__generated__/", + nonOptionalTypename: true, + skipTypeNameForRoot: true, + }, + }, + }, +}; + +export default config; diff --git a/apps/i15-1/package.json b/apps/i15-1/package.json index 3f2b1e31..bee45f7f 100644 --- a/apps/i15-1/package.json +++ b/apps/i15-1/package.json @@ -8,6 +8,7 @@ "build": "tsc && vite build", "preview": "vite preview", "lint": "eslint .", + "generate:graphql": "graphql-codegen --config graphqlCodegen.ts", "generate:queue": "npx @hey-api/openapi-ts -i https://raw.githubusercontent.com/DiamondLightSource/daq-queuing-service/main/docs/reference/rest_api.json -o /workspaces/atlas/apps/i15-1/generated/queue", "test": "vitest run", "coverage": "vitest run --coverage" @@ -32,6 +33,9 @@ }, "devDependencies": { "@atlas/vitest-conf": "workspace:*", + "@graphql-codegen/cli": "^7.1.2", + "@graphql-codegen/near-operation-file-preset": "^5.2.1", + "@graphql-codegen/typescript-operations": "^6.0.3", "@types/react-redux": "7.1.34", "@vitejs/plugin-react-swc": "^3.11.0", "eslint-plugin-react-hooks": "^5.2.0", diff --git a/apps/i15-1/src/components/ExperimentDefinitions.tsx b/apps/i15-1/src/components/ExperimentDefinitions.tsx index ac9acdee..ba92f818 100644 --- a/apps/i15-1/src/components/ExperimentDefinitions.tsx +++ b/apps/i15-1/src/components/ExperimentDefinitions.tsx @@ -1,67 +1,16 @@ import { useQuery } from "@apollo/client/react"; -import { gql } from "@apollo/client"; - import type { TypedDocumentNode } from "@apollo/client"; -type ExperimentDefinitionNode = { - name: string; - data: string; -}; - -type SampleNode = { - name: string; - data: string; -}; - -type ExperimentNode = { - name: string; - sample: SampleNode; - experimentDefinition: ExperimentDefinitionNode; -}; - -// TODO: Autogenerate these from the schema, see https://github.com/DiamondLightSource/atlas/issues/63 -type GetExperimentQueryData = { - instrumentSession: { - experiments: { - edges: { - node: ExperimentNode; - }[]; - }; - }; -}; - -type GetExperimentQueryVariables = { - proposal: number; - session: number; -}; +import { getSessionPlaylistQuery } from "../graphql/getSessionPlaylistQuery"; +import type { + GetSessionPlaylistQueryVariables, + GetSessionPlaylistQuery, +} from "../graphql/getSessionPlaylistQuery.generated"; const GET_EXPERIMENTS: TypedDocumentNode< - GetExperimentQueryData, - GetExperimentQueryVariables -> = gql` - query GetSessionPlaylist($proposal: Int!, $session: Int!) { - instrumentSession( - proposalNumber: $proposal - instrumentSessionNumber: $session - ) { - experiments { - edges { - node { - name - sample { - name - data - } - experimentDefinition { - name - data - } - } - } - } - } - } -`; + GetSessionPlaylistQuery, + GetSessionPlaylistQueryVariables +> = getSessionPlaylistQuery; export function ExperimentList() { const { data, loading, error } = useQuery(GET_EXPERIMENTS, { @@ -74,7 +23,7 @@ export function ExperimentList() { if (loading) return

Loading...

; if (error) return

Error: {error.message}

; - const experiments = data?.instrumentSession.experiments.edges || []; + const experiments = data?.instrumentSession?.experiments.edges || []; return (