diff --git a/apps/p99/helm/values.yaml b/apps/p99/helm/values.yaml index e6da9b5f..d9a5d9cd 100644 --- a/apps/p99/helm/values.yaml +++ b/apps/p99/helm/values.yaml @@ -13,13 +13,15 @@ ui-base: rewriteTarget: / target: external: - uri: https://p99-blueapi.diamond.ac.uk/ + uri: https://p99-blueapi.diamond.ac.uk - id: supergraph path: /api/supergraph + rewriteTarget: /graphql target: external: - uri: https://graph.diamond.ac.uk + uri: https://graph-nightly.diamond.ac.uk + passHostHeader: false authConfigFlags: | skip_auth_routes = ["GET=^/$", "GET=^/assets"] diff --git a/apps/p99/src/components/workflows/SubmittedMessagesList.test.tsx b/apps/p99/src/components/workflows/SubmittedMessagesList.test.tsx index 1e3e3bce..09724237 100644 --- a/apps/p99/src/components/workflows/SubmittedMessagesList.test.tsx +++ b/apps/p99/src/components/workflows/SubmittedMessagesList.test.tsx @@ -2,7 +2,7 @@ import { render, screen } from "@testing-library/react"; import type { SubmissionData } from "../../utils/types"; import { MemoryRouter } from "react-router-dom"; import { RelayEnvironmentProvider } from "react-relay"; -import { RelayEnvironment } from "../../context/workflows/RelayEnvironment"; +import { RelayEnvironment } from "../../context/supergraph/RelayEnvironment"; import SubmittedMessagesList from "./SubmittedMessagesList"; import { userEvent } from "@atlas/vitest-conf"; diff --git a/apps/p99/src/components/workflows/__generated__/RenderSubmittedMessageTestQuery.graphql.ts b/apps/p99/src/components/workflows/__generated__/RenderSubmittedMessageTestQuery.graphql.ts index 0d91121e..e4b4ba14 100644 --- a/apps/p99/src/components/workflows/__generated__/RenderSubmittedMessageTestQuery.graphql.ts +++ b/apps/p99/src/components/workflows/__generated__/RenderSubmittedMessageTestQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<9c473f603b589c9fd2fab1aa81f93533>> * @lightSyntaxTransform * @nogrep */ @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConcreteRequest } from 'relay-runtime'; +import { ConcreteRequest } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type VisitInput = { number: number; @@ -20,124 +20,121 @@ export type RenderSubmittedMessageTestQuery$variables = { visit: VisitInput; }; export type RenderSubmittedMessageTestQuery$data = { - readonly workflow: { - readonly " $fragmentSpreads": FragmentRefs<"renderSubmittedMessageFragment">; - }; + readonly workflow: + | { + readonly " $fragmentSpreads": FragmentRefs<"renderSubmittedMessageFragment">; + } + | null + | undefined; }; export type RenderSubmittedMessageTestQuery = { response: RenderSubmittedMessageTestQuery$data; variables: RenderSubmittedMessageTestQuery$variables; }; -const node: ConcreteRequest = (function(){ -var v0 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "name" -}, -v1 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "visit" -}, -v2 = [ - { - "kind": "Variable", - "name": "name", - "variableName": "name" - }, - { - "kind": "Variable", - "name": "visit", - "variableName": "visit" - } -]; -return { - "fragment": { - "argumentDefinitions": [ - (v0/*: any*/), - (v1/*: any*/) - ], - "kind": "Fragment", - "metadata": null, - "name": "RenderSubmittedMessageTestQuery", - "selections": [ +const node: ConcreteRequest = (function () { + var v0 = { + defaultValue: null, + kind: "LocalArgument", + name: "name", + }, + v1 = { + defaultValue: null, + kind: "LocalArgument", + name: "visit", + }, + v2 = [ { - "alias": null, - "args": (v2/*: any*/), - "concreteType": "Workflow", - "kind": "LinkedField", - "name": "workflow", - "plural": false, - "selections": [ - { - "args": null, - "kind": "FragmentSpread", - "name": "renderSubmittedMessageFragment" - } - ], - "storageKey": null - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [ - (v1/*: any*/), - (v0/*: any*/) - ], - "kind": "Operation", - "name": "RenderSubmittedMessageTestQuery", - "selections": [ + kind: "Variable", + name: "name", + variableName: "name", + }, { - "alias": null, - "args": (v2/*: any*/), - "concreteType": "Workflow", - "kind": "LinkedField", - "name": "workflow", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": null, - "kind": "LinkedField", - "name": "status", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "5ca78f304d1729649dbb93c2a951718a", - "id": null, - "metadata": {}, - "name": "RenderSubmittedMessageTestQuery", - "operationKind": "query", - "text": "query RenderSubmittedMessageTestQuery(\n $visit: VisitInput!\n $name: String!\n) {\n workflow(visit: $visit, name: $name) {\n ...renderSubmittedMessageFragment\n id\n }\n}\n\nfragment renderSubmittedMessageFragment on Workflow {\n status {\n __typename\n }\n}\n" - } -}; + kind: "Variable", + name: "visit", + variableName: "visit", + }, + ]; + return { + fragment: { + argumentDefinitions: [v0 /*: any*/, v1 /*: any*/], + kind: "Fragment", + metadata: null, + name: "RenderSubmittedMessageTestQuery", + selections: [ + { + alias: null, + args: v2 /*: any*/, + concreteType: "Workflow", + kind: "LinkedField", + name: "workflow", + plural: false, + selections: [ + { + args: null, + kind: "FragmentSpread", + name: "renderSubmittedMessageFragment", + }, + ], + storageKey: null, + }, + ], + type: "Query", + abstractKey: null, + }, + kind: "Request", + operation: { + argumentDefinitions: [v1 /*: any*/, v0 /*: any*/], + kind: "Operation", + name: "RenderSubmittedMessageTestQuery", + selections: [ + { + alias: null, + args: v2 /*: any*/, + concreteType: "Workflow", + kind: "LinkedField", + name: "workflow", + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: null, + kind: "LinkedField", + name: "status", + plural: false, + selections: [ + { + alias: null, + args: null, + kind: "ScalarField", + name: "__typename", + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "id", + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: "5ca78f304d1729649dbb93c2a951718a", + id: null, + metadata: {}, + name: "RenderSubmittedMessageTestQuery", + operationKind: "query", + text: "query RenderSubmittedMessageTestQuery(\n $visit: VisitInput!\n $name: String!\n) {\n workflow(visit: $visit, name: $name) {\n ...renderSubmittedMessageFragment\n id\n }\n}\n\nfragment renderSubmittedMessageFragment on Workflow {\n status {\n __typename\n }\n}\n", + }, + }; })(); (node as any).hash = "bcee8b4885b894a415baa73e47a2a0ff"; diff --git a/apps/p99/src/components/workflows/__generated__/SubmissionFormTestQuery.graphql.ts b/apps/p99/src/components/workflows/__generated__/SubmissionFormTestQuery.graphql.ts index 0d72110e..9ffcdc46 100644 --- a/apps/p99/src/components/workflows/__generated__/SubmissionFormTestQuery.graphql.ts +++ b/apps/p99/src/components/workflows/__generated__/SubmissionFormTestQuery.graphql.ts @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConcreteRequest } from 'relay-runtime'; +import { ConcreteRequest } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type SubmissionFormTestQuery$variables = Record; export type SubmissionFormTestQuery$data = { @@ -21,118 +21,118 @@ export type SubmissionFormTestQuery = { variables: SubmissionFormTestQuery$variables; }; -const node: ConcreteRequest = (function(){ -var v0 = [ - { - "kind": "Literal", - "name": "name", - "value": "ptypy-p99-from-config" - } -]; -return { - "fragment": { - "argumentDefinitions": [], - "kind": "Fragment", - "metadata": null, - "name": "SubmissionFormTestQuery", - "selections": [ - { - "alias": null, - "args": (v0/*: any*/), - "concreteType": "WorkflowTemplate", - "kind": "LinkedField", - "name": "workflowTemplate", - "plural": false, - "selections": [ - { - "args": null, - "kind": "FragmentSpread", - "name": "workflowTemplateFragment" - } - ], - "storageKey": "workflowTemplate(name:\"ptypy-p99-from-config\")" - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [], - "kind": "Operation", - "name": "SubmissionFormTestQuery", - "selections": [ - { - "alias": null, - "args": (v0/*: any*/), - "concreteType": "WorkflowTemplate", - "kind": "LinkedField", - "name": "workflowTemplate", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "maintainer", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "description", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "arguments", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "uiSchema", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "repository", - "storageKey": null - } - ], - "storageKey": "workflowTemplate(name:\"ptypy-p99-from-config\")" - } - ] - }, - "params": { - "cacheID": "4d401cb76dd7347f2e3f617f3b6170ae", - "id": null, - "metadata": {}, - "name": "SubmissionFormTestQuery", - "operationKind": "query", - "text": "query SubmissionFormTestQuery {\n workflowTemplate(name: \"ptypy-p99-from-config\") {\n ...workflowTemplateFragment\n }\n}\n\nfragment workflowTemplateFragment on WorkflowTemplate {\n name\n maintainer\n title\n description\n arguments\n uiSchema\n repository\n}\n" - } -}; +const node: ConcreteRequest = (function () { + var v0 = [ + { + kind: "Literal", + name: "name", + value: "ptypy-p99-from-config", + }, + ]; + return { + fragment: { + argumentDefinitions: [], + kind: "Fragment", + metadata: null, + name: "SubmissionFormTestQuery", + selections: [ + { + alias: null, + args: v0 /*: any*/, + concreteType: "WorkflowTemplate", + kind: "LinkedField", + name: "workflowTemplate", + plural: false, + selections: [ + { + args: null, + kind: "FragmentSpread", + name: "workflowTemplateFragment", + }, + ], + storageKey: 'workflowTemplate(name:"ptypy-p99-from-config")', + }, + ], + type: "Query", + abstractKey: null, + }, + kind: "Request", + operation: { + argumentDefinitions: [], + kind: "Operation", + name: "SubmissionFormTestQuery", + selections: [ + { + alias: null, + args: v0 /*: any*/, + concreteType: "WorkflowTemplate", + kind: "LinkedField", + name: "workflowTemplate", + plural: false, + selections: [ + { + alias: null, + args: null, + kind: "ScalarField", + name: "name", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "maintainer", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "title", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "description", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "arguments", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "uiSchema", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "repository", + storageKey: null, + }, + ], + storageKey: 'workflowTemplate(name:"ptypy-p99-from-config")', + }, + ], + }, + params: { + cacheID: "4d401cb76dd7347f2e3f617f3b6170ae", + id: null, + metadata: {}, + name: "SubmissionFormTestQuery", + operationKind: "query", + text: 'query SubmissionFormTestQuery {\n workflowTemplate(name: "ptypy-p99-from-config") {\n ...workflowTemplateFragment\n }\n}\n\nfragment workflowTemplateFragment on WorkflowTemplate {\n name\n maintainer\n title\n description\n arguments\n uiSchema\n repository\n}\n', + }, + }; })(); (node as any).hash = "5bc0a249228ca92dcbce2d40e75ee1dd"; diff --git a/apps/p99/src/context/workflows/RelayEnvironment.ts b/apps/p99/src/context/supergraph/RelayEnvironment.ts similarity index 96% rename from apps/p99/src/context/workflows/RelayEnvironment.ts rename to apps/p99/src/context/supergraph/RelayEnvironment.ts index 44991c9d..768081f6 100644 --- a/apps/p99/src/context/workflows/RelayEnvironment.ts +++ b/apps/p99/src/context/supergraph/RelayEnvironment.ts @@ -10,6 +10,7 @@ const HTTP_ENDPOINT = "/api/supergraph"; const fetchFn: FetchFunction = async (request, variables) => { const resp = await fetch(HTTP_ENDPOINT, { method: "POST", + credentials: "include", headers: { Accept: "application/graphql-response+json; charset=utf-8, application/json; charset=utf-8", diff --git a/apps/p99/src/graphql/__generated__/renderSubmittedMessageFragment.graphql.ts b/apps/p99/src/graphql/__generated__/renderSubmittedMessageFragment.graphql.ts index 6d7dc910..78170ae4 100644 --- a/apps/p99/src/graphql/__generated__/renderSubmittedMessageFragment.graphql.ts +++ b/apps/p99/src/graphql/__generated__/renderSubmittedMessageFragment.graphql.ts @@ -8,12 +8,15 @@ /* eslint-disable */ // @ts-nocheck -import { ReaderFragment } from 'relay-runtime'; +import { ReaderFragment } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type renderSubmittedMessageFragment$data = { - readonly status: { - readonly __typename: string; - } | null | undefined; + readonly status: + | { + readonly __typename: string; + } + | null + | undefined; readonly " $fragmentType": "renderSubmittedMessageFragment"; }; export type renderSubmittedMessageFragment$key = { @@ -22,32 +25,32 @@ export type renderSubmittedMessageFragment$key = { }; const node: ReaderFragment = { - "argumentDefinitions": [], - "kind": "Fragment", - "metadata": null, - "name": "renderSubmittedMessageFragment", - "selections": [ + argumentDefinitions: [], + kind: "Fragment", + metadata: null, + name: "renderSubmittedMessageFragment", + selections: [ { - "alias": null, - "args": null, - "concreteType": null, - "kind": "LinkedField", - "name": "status", - "plural": false, - "selections": [ + alias: null, + args: null, + concreteType: null, + kind: "LinkedField", + name: "status", + plural: false, + selections: [ { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null - } + alias: null, + args: null, + kind: "ScalarField", + name: "__typename", + storageKey: null, + }, ], - "storageKey": null - } + storageKey: null, + }, ], - "type": "Workflow", - "abstractKey": null + type: "Workflow", + abstractKey: null, }; (node as any).hash = "03e612be6ddc650f978d56b8e18a9818"; diff --git a/apps/p99/src/graphql/__generated__/submitWorkflowTemplateMutation.graphql.ts b/apps/p99/src/graphql/__generated__/submitWorkflowTemplateMutation.graphql.ts index 896a25d9..f056a2de 100644 --- a/apps/p99/src/graphql/__generated__/submitWorkflowTemplateMutation.graphql.ts +++ b/apps/p99/src/graphql/__generated__/submitWorkflowTemplateMutation.graphql.ts @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConcreteRequest } from 'relay-runtime'; +import { ConcreteRequest } from "relay-runtime"; export type VisitInput = { number: number; proposalCode: string; @@ -29,113 +29,103 @@ export type submitWorkflowTemplateMutation = { variables: submitWorkflowTemplateMutation$variables; }; -const node: ConcreteRequest = (function(){ -var v0 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "parameters" -}, -v1 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "templateName" -}, -v2 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "visit" -}, -v3 = [ - { - "kind": "Variable", - "name": "name", - "variableName": "templateName" - }, - { - "kind": "Variable", - "name": "parameters", - "variableName": "parameters" - }, - { - "kind": "Variable", - "name": "visit", - "variableName": "visit" - } -], -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}; -return { - "fragment": { - "argumentDefinitions": [ - (v0/*: any*/), - (v1/*: any*/), - (v2/*: any*/) - ], - "kind": "Fragment", - "metadata": null, - "name": "submitWorkflowTemplateMutation", - "selections": [ +const node: ConcreteRequest = (function () { + var v0 = { + defaultValue: null, + kind: "LocalArgument", + name: "parameters", + }, + v1 = { + defaultValue: null, + kind: "LocalArgument", + name: "templateName", + }, + v2 = { + defaultValue: null, + kind: "LocalArgument", + name: "visit", + }, + v3 = [ { - "alias": null, - "args": (v3/*: any*/), - "concreteType": "Workflow", - "kind": "LinkedField", - "name": "submitWorkflowTemplate", - "plural": false, - "selections": [ - (v4/*: any*/) - ], - "storageKey": null - } - ], - "type": "Mutation", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [ - (v1/*: any*/), - (v2/*: any*/), - (v0/*: any*/) - ], - "kind": "Operation", - "name": "submitWorkflowTemplateMutation", - "selections": [ + kind: "Variable", + name: "name", + variableName: "templateName", + }, { - "alias": null, - "args": (v3/*: any*/), - "concreteType": "Workflow", - "kind": "LinkedField", - "name": "submitWorkflowTemplate", - "plural": false, - "selections": [ - (v4/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "4c13758cbc0d34e6d9a014c9f36e641a", - "id": null, - "metadata": {}, - "name": "submitWorkflowTemplateMutation", - "operationKind": "mutation", - "text": "mutation submitWorkflowTemplateMutation(\n $templateName: String!\n $visit: VisitInput!\n $parameters: JSON!\n) {\n submitWorkflowTemplate(name: $templateName, visit: $visit, parameters: $parameters) {\n name\n id\n }\n}\n" - } -}; + kind: "Variable", + name: "parameters", + variableName: "parameters", + }, + { + kind: "Variable", + name: "visit", + variableName: "visit", + }, + ], + v4 = { + alias: null, + args: null, + kind: "ScalarField", + name: "name", + storageKey: null, + }; + return { + fragment: { + argumentDefinitions: [v0 /*: any*/, v1 /*: any*/, v2 /*: any*/], + kind: "Fragment", + metadata: null, + name: "submitWorkflowTemplateMutation", + selections: [ + { + alias: null, + args: v3 /*: any*/, + concreteType: "Workflow", + kind: "LinkedField", + name: "submitWorkflowTemplate", + plural: false, + selections: [v4 /*: any*/], + storageKey: null, + }, + ], + type: "Mutation", + abstractKey: null, + }, + kind: "Request", + operation: { + argumentDefinitions: [v1 /*: any*/, v2 /*: any*/, v0 /*: any*/], + kind: "Operation", + name: "submitWorkflowTemplateMutation", + selections: [ + { + alias: null, + args: v3 /*: any*/, + concreteType: "Workflow", + kind: "LinkedField", + name: "submitWorkflowTemplate", + plural: false, + selections: [ + v4 /*: any*/, + { + alias: null, + args: null, + kind: "ScalarField", + name: "id", + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: "4c13758cbc0d34e6d9a014c9f36e641a", + id: null, + metadata: {}, + name: "submitWorkflowTemplateMutation", + operationKind: "mutation", + text: "mutation submitWorkflowTemplateMutation(\n $templateName: String!\n $visit: VisitInput!\n $parameters: JSON!\n) {\n submitWorkflowTemplate(name: $templateName, visit: $visit, parameters: $parameters) {\n name\n id\n }\n}\n", + }, + }; })(); (node as any).hash = "e2ff0d748606ea7f1c8e6dd7daae9206"; diff --git a/apps/p99/src/graphql/__generated__/subscribeAndRenderSubscription.graphql.ts b/apps/p99/src/graphql/__generated__/subscribeAndRenderSubscription.graphql.ts index ad072f52..fa9e1a61 100644 --- a/apps/p99/src/graphql/__generated__/subscribeAndRenderSubscription.graphql.ts +++ b/apps/p99/src/graphql/__generated__/subscribeAndRenderSubscription.graphql.ts @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConcreteRequest } from 'relay-runtime'; +import { ConcreteRequest } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type VisitInput = { number: number; @@ -29,115 +29,109 @@ export type subscribeAndRenderSubscription = { variables: subscribeAndRenderSubscription$variables; }; -const node: ConcreteRequest = (function(){ -var v0 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "name" -}, -v1 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "visit" -}, -v2 = [ - { - "kind": "Variable", - "name": "name", - "variableName": "name" - }, - { - "kind": "Variable", - "name": "visit", - "variableName": "visit" - } -]; -return { - "fragment": { - "argumentDefinitions": [ - (v0/*: any*/), - (v1/*: any*/) - ], - "kind": "Fragment", - "metadata": null, - "name": "subscribeAndRenderSubscription", - "selections": [ +const node: ConcreteRequest = (function () { + var v0 = { + defaultValue: null, + kind: "LocalArgument", + name: "name", + }, + v1 = { + defaultValue: null, + kind: "LocalArgument", + name: "visit", + }, + v2 = [ { - "alias": null, - "args": (v2/*: any*/), - "concreteType": "Workflow", - "kind": "LinkedField", - "name": "workflow", - "plural": false, - "selections": [ - { - "args": null, - "kind": "FragmentSpread", - "name": "renderSubmittedMessageFragment" - } - ], - "storageKey": null - } - ], - "type": "Subscription", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [ - (v1/*: any*/), - (v0/*: any*/) - ], - "kind": "Operation", - "name": "subscribeAndRenderSubscription", - "selections": [ + kind: "Variable", + name: "name", + variableName: "name", + }, { - "alias": null, - "args": (v2/*: any*/), - "concreteType": "Workflow", - "kind": "LinkedField", - "name": "workflow", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": null, - "kind": "LinkedField", - "name": "status", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "1ca97628bb694c4d5fe00452a2a1d3f8", - "id": null, - "metadata": {}, - "name": "subscribeAndRenderSubscription", - "operationKind": "subscription", - "text": "subscription subscribeAndRenderSubscription(\n $visit: VisitInput!\n $name: String!\n) {\n workflow(visit: $visit, name: $name) {\n ...renderSubmittedMessageFragment\n id\n }\n}\n\nfragment renderSubmittedMessageFragment on Workflow {\n status {\n __typename\n }\n}\n" - } -}; + kind: "Variable", + name: "visit", + variableName: "visit", + }, + ]; + return { + fragment: { + argumentDefinitions: [v0 /*: any*/, v1 /*: any*/], + kind: "Fragment", + metadata: null, + name: "subscribeAndRenderSubscription", + selections: [ + { + alias: null, + args: v2 /*: any*/, + concreteType: "Workflow", + kind: "LinkedField", + name: "workflow", + plural: false, + selections: [ + { + args: null, + kind: "FragmentSpread", + name: "renderSubmittedMessageFragment", + }, + ], + storageKey: null, + }, + ], + type: "Subscription", + abstractKey: null, + }, + kind: "Request", + operation: { + argumentDefinitions: [v1 /*: any*/, v0 /*: any*/], + kind: "Operation", + name: "subscribeAndRenderSubscription", + selections: [ + { + alias: null, + args: v2 /*: any*/, + concreteType: "Workflow", + kind: "LinkedField", + name: "workflow", + plural: false, + selections: [ + { + alias: null, + args: null, + concreteType: null, + kind: "LinkedField", + name: "status", + plural: false, + selections: [ + { + alias: null, + args: null, + kind: "ScalarField", + name: "__typename", + storageKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "id", + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: "1ca97628bb694c4d5fe00452a2a1d3f8", + id: null, + metadata: {}, + name: "subscribeAndRenderSubscription", + operationKind: "subscription", + text: "subscription subscribeAndRenderSubscription(\n $visit: VisitInput!\n $name: String!\n) {\n workflow(visit: $visit, name: $name) {\n ...renderSubmittedMessageFragment\n id\n }\n}\n\nfragment renderSubmittedMessageFragment on Workflow {\n status {\n __typename\n }\n}\n", + }, + }; })(); (node as any).hash = "c3057cb3b2ce67c2a8d0cf51ff221958"; diff --git a/apps/p99/src/graphql/__generated__/templateViewQuery.graphql.ts b/apps/p99/src/graphql/__generated__/templateViewQuery.graphql.ts index aa796364..d284293c 100644 --- a/apps/p99/src/graphql/__generated__/templateViewQuery.graphql.ts +++ b/apps/p99/src/graphql/__generated__/templateViewQuery.graphql.ts @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConcreteRequest } from 'relay-runtime'; +import { ConcreteRequest } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type templateViewQuery$variables = { templateName: string; @@ -23,125 +23,125 @@ export type templateViewQuery = { variables: templateViewQuery$variables; }; -const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "templateName" - } -], -v1 = [ - { - "kind": "Variable", - "name": "name", - "variableName": "templateName" - } -]; -return { - "fragment": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Fragment", - "metadata": null, - "name": "templateViewQuery", - "selections": [ +const node: ConcreteRequest = (function () { + var v0 = [ { - "alias": null, - "args": (v1/*: any*/), - "concreteType": "WorkflowTemplate", - "kind": "LinkedField", - "name": "workflowTemplate", - "plural": false, - "selections": [ - { - "args": null, - "kind": "FragmentSpread", - "name": "workflowTemplateFragment" - } - ], - "storageKey": null - } + defaultValue: null, + kind: "LocalArgument", + name: "templateName", + }, ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": (v0/*: any*/), - "kind": "Operation", - "name": "templateViewQuery", - "selections": [ + v1 = [ { - "alias": null, - "args": (v1/*: any*/), - "concreteType": "WorkflowTemplate", - "kind": "LinkedField", - "name": "workflowTemplate", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "maintainer", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "description", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "arguments", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "uiSchema", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "repository", - "storageKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "19fc0d9ac63aa4eab9e10aefa178227c", - "id": null, - "metadata": {}, - "name": "templateViewQuery", - "operationKind": "query", - "text": "query templateViewQuery(\n $templateName: String!\n) {\n workflowTemplate(name: $templateName) {\n ...workflowTemplateFragment\n }\n}\n\nfragment workflowTemplateFragment on WorkflowTemplate {\n name\n maintainer\n title\n description\n arguments\n uiSchema\n repository\n}\n" - } -}; + kind: "Variable", + name: "name", + variableName: "templateName", + }, + ]; + return { + fragment: { + argumentDefinitions: v0 /*: any*/, + kind: "Fragment", + metadata: null, + name: "templateViewQuery", + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: "WorkflowTemplate", + kind: "LinkedField", + name: "workflowTemplate", + plural: false, + selections: [ + { + args: null, + kind: "FragmentSpread", + name: "workflowTemplateFragment", + }, + ], + storageKey: null, + }, + ], + type: "Query", + abstractKey: null, + }, + kind: "Request", + operation: { + argumentDefinitions: v0 /*: any*/, + kind: "Operation", + name: "templateViewQuery", + selections: [ + { + alias: null, + args: v1 /*: any*/, + concreteType: "WorkflowTemplate", + kind: "LinkedField", + name: "workflowTemplate", + plural: false, + selections: [ + { + alias: null, + args: null, + kind: "ScalarField", + name: "name", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "maintainer", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "title", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "description", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "arguments", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "uiSchema", + storageKey: null, + }, + { + alias: null, + args: null, + kind: "ScalarField", + name: "repository", + storageKey: null, + }, + ], + storageKey: null, + }, + ], + }, + params: { + cacheID: "19fc0d9ac63aa4eab9e10aefa178227c", + id: null, + metadata: {}, + name: "templateViewQuery", + operationKind: "query", + text: "query templateViewQuery(\n $templateName: String!\n) {\n workflowTemplate(name: $templateName) {\n ...workflowTemplateFragment\n }\n}\n\nfragment workflowTemplateFragment on WorkflowTemplate {\n name\n maintainer\n title\n description\n arguments\n uiSchema\n repository\n}\n", + }, + }; })(); (node as any).hash = "a095c2f1a9314457db4bf9b26bc541a2"; diff --git a/apps/p99/src/graphql/__generated__/workflowTemplateFragment.graphql.ts b/apps/p99/src/graphql/__generated__/workflowTemplateFragment.graphql.ts index f519396d..5427ec99 100644 --- a/apps/p99/src/graphql/__generated__/workflowTemplateFragment.graphql.ts +++ b/apps/p99/src/graphql/__generated__/workflowTemplateFragment.graphql.ts @@ -8,7 +8,7 @@ /* eslint-disable */ // @ts-nocheck -import { ReaderFragment } from 'relay-runtime'; +import { ReaderFragment } from "relay-runtime"; import { FragmentRefs } from "relay-runtime"; export type workflowTemplateFragment$data = { readonly arguments: any; @@ -26,63 +26,63 @@ export type workflowTemplateFragment$key = { }; const node: ReaderFragment = { - "argumentDefinitions": [], - "kind": "Fragment", - "metadata": null, - "name": "workflowTemplateFragment", - "selections": [ + argumentDefinitions: [], + kind: "Fragment", + metadata: null, + name: "workflowTemplateFragment", + selections: [ { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null + alias: null, + args: null, + kind: "ScalarField", + name: "name", + storageKey: null, }, { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "maintainer", - "storageKey": null + alias: null, + args: null, + kind: "ScalarField", + name: "maintainer", + storageKey: null, }, { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null + alias: null, + args: null, + kind: "ScalarField", + name: "title", + storageKey: null, }, { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "description", - "storageKey": null + alias: null, + args: null, + kind: "ScalarField", + name: "description", + storageKey: null, }, { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "arguments", - "storageKey": null + alias: null, + args: null, + kind: "ScalarField", + name: "arguments", + storageKey: null, }, { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "uiSchema", - "storageKey": null + alias: null, + args: null, + kind: "ScalarField", + name: "uiSchema", + storageKey: null, }, { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "repository", - "storageKey": null - } + alias: null, + args: null, + kind: "ScalarField", + name: "repository", + storageKey: null, + }, ], - "type": "WorkflowTemplate", - "abstractKey": null + type: "WorkflowTemplate", + abstractKey: null, }; (node as any).hash = "959850317e316a423e70b0c89c011f27"; diff --git a/apps/p99/src/main.tsx b/apps/p99/src/main.tsx index 2450c5bd..5f60515d 100644 --- a/apps/p99/src/main.tsx +++ b/apps/p99/src/main.tsx @@ -10,7 +10,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { BlueapiProvider } from "@atlas/blueapi-query"; import { createApi } from "@atlas/blueapi"; import { RelayEnvironmentProvider } from "react-relay"; -import { RelayEnvironment } from "./context/workflows/RelayEnvironment.ts"; +import { RelayEnvironment } from "./context/supergraph/RelayEnvironment.ts"; import { UserAuthProvider } from "./context/userAuth/UserAuthProvider.tsx"; import { router } from "./router.tsx"; import { InstrumentSessionProvider } from "@atlas/app-shell"; diff --git a/apps/p99/src/routes/Dashboard.test.tsx b/apps/p99/src/routes/Dashboard.test.tsx new file mode 100644 index 00000000..dd2030ca --- /dev/null +++ b/apps/p99/src/routes/Dashboard.test.tsx @@ -0,0 +1,33 @@ +import { act, render, screen } from "@atlas/vitest-conf"; +import Dashboard from "./Dashboard"; +import { UserAuthProvider } from "../context/userAuth/UserAuthProvider"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { MemoryRouter } from "react-router-dom"; + +describe("Dashboard", () => { + it("renders the correct input", async () => { + act(() => + render( + + + + + + + , + ), + ); + expect(screen.getByText("Welcome to P99!")).toBeInTheDocument(); + + const loginButton = screen.getByRole("button", {name: "Login"}); + expect(loginButton).toBeInTheDocument(); + + const plansButton = screen.getByRole("link", {name: "Plans"}); + expect(plansButton).toBeInTheDocument(); + expect(plansButton).toHaveAttribute("href", "/Acquisition/Plans") + + const workflowsButton = screen.getByRole("link", {name: "Workflows"}); + expect(workflowsButton).toBeInTheDocument(); + expect(workflowsButton).toHaveAttribute("href", "/Workflows/Workflows") + }); +}); diff --git a/apps/p99/src/routes/Dashboard.tsx b/apps/p99/src/routes/Dashboard.tsx index 94d72028..83206f0c 100644 --- a/apps/p99/src/routes/Dashboard.tsx +++ b/apps/p99/src/routes/Dashboard.tsx @@ -1,31 +1,49 @@ import { Container, Typography, Stack, Button } from "@mui/material"; import { FileText, ServerCog } from "lucide-react"; import { Link } from "react-router-dom"; +import { useUserAuth } from "../context/userAuth/useUserAuth"; +import { User } from "@diamondlightsource/sci-react-ui"; -const Dashboard = () => ( - - - Welcome to P99! - - - - -); +const Dashboard = () => { + const user = useUserAuth(); + + const handleLogIn = () => window.location.assign("/oauth2/sign_in"); + const handleLogOut = () => window.location.assign("/oauth2/sign_out"); + + return ( + + + Welcome to P99! + + + + + + ); +}; export default Dashboard; diff --git a/apps/p99/supergraph.graphql b/apps/p99/supergraph.graphql index 6fe95ee4..ae96cbe7 100644 --- a/apps/p99/supergraph.graphql +++ b/apps/p99/supergraph.graphql @@ -26,6 +26,18 @@ scalar JSON """A scalar that can represent any JSON Object value.""" scalar JSONObject +"""Represents a label selector for filtering workflows based on labels""" +input LabelSelector { + """The label key to filter on""" + key: String! + + """The operator to use for the label selection""" + operator: WorkflowLabelSelectorOperator! + + """The values to match against the label key (if applicable)""" + values: [String!] +} + """A single log line streamed from a pod""" type LogEntry { """The log line content""" @@ -39,12 +51,45 @@ type LogEntry { type Mutation { """submit specific workflow template""" submitWorkflowTemplate(name: String!, visit: VisitInput!, parameters: JSON!): Workflow! + + """ + Submit a manifest (YAML) as a one-off Workflow within a visit's namespace. + + The input is typically a `WorkflowTemplate` (the manifest developers author and + store in their repository). It is submitted via the Argo Server API so the graph + remains the single source of truth for submissions. To match the behaviour of the + workflows CLI, the manifest is coerced into a one-off Workflow: `kind` is set to + `Workflow`, and a fixed `metadata.name` is rewritten to a `metadata.generateName` + (suffixed with `-`) so repeated submissions yield fresh, uniquely named Workflows. + """ + submitWorkflow(visit: VisitInput!, manifest: String!): Workflow! + + """Create a Trigger from a template""" + createTrigger(templateRef: String!, name: String, visit: VisitInput): Trigger + createExperimentDefinition(input: CreateExperimentDefinitionInput!): CreateExperimentDefinitionResponse + experimentDefinition(id: UUID!): ExperimentDefinitionMutations + deleteExperiment(id: UUID!): DeleteExperimentResponse + restoreExperiment(id: UUID!): DeleteExperimentResponse + deleteExperimentDefinition(id: UUID!): DeletedExperimentDefinitionResponse + restoreExperimentDefinition(id: UUID!): DeletedExperimentDefinitionResponse + createInstrumentSession(input: CreateInstrumentSessionInput!): InstrumentSession! instrumentSession(proposalNumber: Int!, instrumentSessionNumber: Int!): InstrumentSessionMutations createOrValidateSamples(input: CreateOrValidateSampleInput!): CreateSamplesResponse! - createSamples(input: CreateSampleInput!): [Sample!]! @deprecated(reason: "Will be replaced by createOrValidateSamples") sample(sampleId: UUID!): SampleMutations - createExperimentDefinition(input: CreateExperimentDefinitionInput!): ExperimentDefinition - experimentDefinition(id: UUID!): ExperimentDefinitionMutations + deleteSample(sampleId: UUID!): DeleteSampleResponse! + restoreSample(sampleId: UUID!): RestoreSampleResponse! + + """Create a new container type""" + createContainerType(input: CreateContainerTypeInput!): CreateContainerTypeResponse! + + """Mutations relating to a specific container type""" + containerType(name: String!): ContainerTypeMutations! + + """Create a new container""" + createContainer(input: CreateContainerInput!): CreateContainerResponse! + + """Muatations relating to a specific container""" + container(id: UUID = null, barcode: String = null): ContainerMutations! } """Represents Relay Node types""" @@ -69,8 +114,15 @@ type PageInfo { type Query { node(id: ID!): NodeValue - """Get a single [`Workflow`] by proposal, visit, and name""" - workflow(visit: VisitInput!, name: String!): Workflow! + """ + Get a single [`Workflow`] by proposal, visit, and name. + + In case of two workflows with the same name, returns the most recent. + """ + workflow(visit: VisitInput!, name: String!): Workflow @deprecated(reason: "Use workflowById instead") + + """Get a single [`Workflow`] by unique ID.""" + workflowById(id: ID!): Workflow """Find all workflows available for a given visit""" workflows(visit: VisitInput!, cursor: String, limit: Int, filter: WorkflowFilter): WorkflowConnection! @@ -83,38 +135,69 @@ type Query { """ workflowTemplates(cursor: String, limit: Int, filter: WorkflowTemplatesFilter): WorkflowTemplateConnection! + """Get a specific Trigger by name and visit""" + trigger(name: String!, visit: String): Trigger + + """Get multiple Triggers across namespaces""" + triggers(cursor: String, limit: Int): TriggerConnection! + jsonSchema(url: String!): JSONSchema + jsonSchemas(type: String = null, instrument: String = null): [JSONSchema!]! + experimentDefinition(id: UUID!): ExperimentDefinition + experimentDefinitions(instrumentSessions: [InstrumentSessionInput!]!, filter: ExperimentDefinitionFilterInput = null, first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentDefinitionConnection + experiment(id: UUID!): Experiment + experiments(instrumentSessions: [InstrumentSessionInput!]!, first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentConnection + """Get a proposal by its number""" proposal(proposalNumber: Int!): Proposal """Get a list of proposals""" - proposals(proposalCategory: String = null, first: Int = null, last: Int = null, after: String = null, before: String = null): ProposalConnection! + proposals(first: Int = null, last: Int = null, after: String = null, before: String = null, sortBy: [ProposalSortInput!] = null, filterBy: ProposalFilterInput = null): ProposalConnection! + + """ + Get a proposal by its reference string e.g. 'MX12345'. The lookup is case-insensitive. + """ + proposalByReference(reference: String!): Proposal """Get a instrument session""" instrumentSession(proposalNumber: Int!, instrumentSessionNumber: Int!): InstrumentSession - """Get a instrument session""" - instrumentSessions(proposalNumber: Int = null, proposalCategory: String = null): [InstrumentSession!] + """ + Get an instrument session by its reference string e.g. 'MX12345-1'. The lookup is case-insensitive. + """ + instrumentSessionByReference(reference: String!): InstrumentSession + + """Get a list of instrument sessions""" + instrumentSessions(proposalNumber: Int = null, proposalCategory: String = null, first: Int = null, last: Int = null, after: String = null, before: String = null, sortBy: [InstrumentSessionSortInput!] = null, filterBy: InstrumentSessionFilterInput = null): InstrumentSessionConnection! - """Get an instrument""" - instrument(instrumentName: String!): Instrument + """Get an instrument by name""" + instrumentByName(name: String!): Instrument + + """Get an instrument by key""" + instrumentByKey(key: String!): Instrument """Get a list of instruments""" instruments(scienceGroup: String = null): [Instrument!]! """Get an account""" account(username: String!): Account - jsonSchema(url: String!): JSONSchema - jsonSchemas(type: String = null, instrument: String = null): [JSONSchema!]! """Get a sample by its id""" sample(sampleId: UUID!): Sample """Get a list of samples associated with a given instrument session""" - samples(first: Int!, instrumentSessions: [InstrumentSessionInput!] = null, filter: SampleFilterInput! = {schemaUrl: null, createdTime: null, updatedTime: null, name: null, data: null}, before: String = null, after: String = null, last: Int = null, orderBy: SampleOrder! = {name: null, createdTime: null, updatedTime: null}): SampleConnection! - experimentDefinition(id: UUID!): ExperimentDefinition - experimentDefinitions(instrumentSessions: [InstrumentSessionInput!]!, first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentDefinitionConnection - experiment(id: UUID!): Experiment - experiments(instrumentSessions: [InstrumentSessionInput!]!, first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentConnection + samples(first: Int = null, instrumentSessions: [InstrumentSessionInput!] = null, filter: SampleFilterInput! = {schemaUrl: null, createdTime: null, updatedTime: null, name: null, data: null}, before: String = null, after: String = null, last: Int = null, orderBy: SampleOrder! = {name: null, createdTime: null, updatedTime: null}): SampleConnection! + + """Fetch a single container type, by specifying its name""" + containerType(name: String!): ContainerType + + """Fetch multiple container types, by specifying associated instruments""" + containerTypes(instrumentKeys: [String!]!, first: Int = 20, last: Int = null, before: String = null, after: String = null): ContainerTypeConnection! + + """Fetch a single container, by specifying either its id or barcode""" + container(id: UUID = null, barcode: String = null): Container + + "\n Fetch multiple containers, by specifying either its parent, a child, an\n associated instrument, or associated instrument sessions" + containers(instrumentSessions: [InstrumentSessionInput!] = null, instrumentKeys: [String!] = null, filter: ContainerFilterInput = null, first: Int = 20, last: Int = null, before: String = null, after: String = null): ContainerConnection! } """Supported DLS science groups""" @@ -214,6 +297,38 @@ type TemplateSource { targetRevision: String! } +"""A Trigger for creating automated workflows""" +type Trigger { + """The name of the Trigger""" + name: String + + """The name of a ClusterTriggerTemplate that the Trigger is created from""" + templateRef: String + + """The beamline that the Trigger monitors""" + beamline: String +} + +type TriggerConnection { + """Information to aid in pagination.""" + pageInfo: PageInfo! + + """A list of edges.""" + edges: [TriggerEdge!]! + + """A list of nodes.""" + nodes: [Trigger!]! +} + +"""An edge in a connection.""" +type TriggerEdge { + """The item at the end of the edge""" + node: Trigger! + + """A cursor for use in pagination""" + cursor: String! +} + """ URL is a String implementing the [URL Standard](http://url.spec.whatwg.org/) """ @@ -244,7 +359,7 @@ input VisitInput { } type Workflow { - """The unique ID derived from the visit and name""" + """The unique ID derived from the visit, name and uid""" id: ID! """The name given to the workflow, unique within a given visit""" @@ -331,14 +446,44 @@ type WorkflowFailedStatus { """All the supported Workflows filters""" input WorkflowFilter { - """The status field for a workflow""" + """ + The status of the workflow (e.g., pending, running, succeeded, failed, error) + """ workflowStatusFilter: WorkflowStatusFilter """The fedid of the user who created the workflow""" creator: Creator - """The name of the workflow template""" + """The workflow template""" template: Template + + """Additional label selectors for filtering workflows""" + labelSelectors: [LabelSelector!] +} + +"""Supported operators for label selection in workflows""" +enum WorkflowLabelSelectorOperator { + """Match resources with an exact label value.""" + EQ + + """ + Match resources with a label value that is not equal to a specified value. + """ + NE + + """Match resources with a label value in a set of values.""" + IN + + """Match resources with a label value not in a set of values.""" + NOT_IN + + """ + Match resources that have a specific label key, regardless of its value. + """ + EXISTS + + """Match resources that do not have a specific label key.""" + DOES_NOT_EXIST } type WorkflowPendingStatus { @@ -444,108 +589,6 @@ input WorkflowTemplatesFilter { scienceGroup: [ScienceGroup!] } -type Account { - accountId: Int! - username: String! - emailAddress: String - title: String - givenName: String - familyName: String - type: AccountType! - state: AccountState! - proposalRoles: [ProposalAccount!]! - instrumentSessionRoles: [InstrumentSessionRole!]! -} - -enum AccountState { - enabled - disabled -} - -enum AccountType { - user - staff - functional -} - -type Instrument { - name: String! - scienceGroup: String - description: String - proposals: [Proposal!]! - instrumentSessions: [InstrumentSession!]! -} - -type InstrumentSession { - instrumentSessionId: Int! - instrumentSessionNumber: Int! - startTime: DateTime - endTime: DateTime - type: String - state: String - riskRating: String - proposal: Proposal - instrument: Instrument! - roles: [InstrumentSessionRole!]! - - """Samples associated with a given instrument session""" - samples(first: Int!, filter: SampleFilterInput! = {schemaUrl: null, createdTime: null, updatedTime: null, name: null, data: null}, before: String = null, after: String = null, last: Int = null, orderBy: SampleOrder! = {name: null, createdTime: null, updatedTime: null}): SampleConnection! - - """Experiment Definitions""" - experimentDefinitions(first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentDefinitionConnection! - - """Experiments associated with this session""" - experiments(first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentConnection! -} - -type InstrumentSessionMutations { - instrumentSessionNumber: Int! - proposalNumber: Int! - - """Create or validate samples associated with this instrument session""" - createOrValidateSamples(input: CreateOrValidateSampleInputBase!): CreateSamplesResponse! -} - -type InstrumentSessionRole { - instrumentSession: InstrumentSession! - account: Account! - role: String! - onSite: Boolean! -} - -type Proposal { - proposalNumber: Int! - proposalCategory: String - title: String - summary: String - state: ProposalState! - instrumentSessions: [InstrumentSession!]! - instruments: [Instrument!]! - roles: [ProposalAccount!]! -} - -type ProposalAccount { - proposal: Proposal! - account: Account! - role: String! -} - -type ProposalConnection { - edges: [ProposalEdge!]! - pageInfo: PageInfo! -} - -type ProposalEdge { - cursor: String! - node: Proposal! -} - -enum ProposalState { - Open - Closed - Cancelled -} - """A JSON schema""" type JSONSchema { """The identifier of the schema""" @@ -570,80 +613,63 @@ type JSONSchema { description: String } -input AddSampleEventInput { - description: String! -} - -input CreateOrValidateSampleInput { - """URL of the JSON schema the samples' `data` should be validated against""" +"""Values required to create an experiment definition""" +input CreateExperimentDefinitionInput { + name: String! + data: JSON! dataSchemaUrl: String! - - """Samples to be created""" - samples: [SampleIn!]! - - """ - Whether or not the provided samples should only be validated and not created - """ - validateOnly: Boolean! = false - - """Number of the proposal the samples should be associated with""" proposalNumber: Int! - - """Number of the instrument session the samples should be associated with""" instrumentSessionNumber: Int! } -input CreateOrValidateSampleInputBase { - """URL of the JSON schema the samples' `data` should be validated against""" - dataSchemaUrl: String! +"""Return type when creating an experiment definition""" +type CreateExperimentDefinitionResponse { + """Whether the operation has succeeded without validation errors""" + success: Boolean! - """Samples to be created""" - samples: [SampleIn!]! + """Experiment Definition that has been created""" + experimentDefinition: ExperimentDefinition - """ - Whether or not the provided samples should only be validated and not created - """ - validateOnly: Boolean! = false + """Errors that occurred during validation""" + errors: [ExperimentDefinitionErrorDetails!]! } -input CreateSampleInput { - proposalNumber: Int! - instrumentSessionNumber: Int! - samples: [SampleInLegacy!]! - validateOnly: Boolean! = false +"""Values required for the createExperiments mutation""" +input CreateExperimentsInput { + experiments: [ExperimentInput!]! } -"""Return type when creating or validating samples""" -type CreateSamplesResponse { - """Whether the operation has succeeded without validation errors""" +"""Return type when updating an experiment definition""" +type CreateExperimentsResponse { + """Whether the operation has succeeded without errors""" success: Boolean! - """Samples that have been created""" - samples: [Sample!]! + """Experiments created""" + experiments: [Experiment!] - """Errors that occurred during sample validation""" - errors: [SampleValidationError!]! + """Errors that occurred during experiments creation""" + errors: [String!]! } -input DatetimeOperatorInput { +input DatetimeFilterInputV2 { """ Will filter to items where the `DateTime` field is greater than (i.e. after) the provided value """ - gt: DateTime = null + greaterThan: DateTime = null """ Will filter to items where the `DateTime` field is less than (i.e. before) the provided value """ - lt: DateTime = null + lessThan: DateTime = null } -"""The details of sample validation error""" -type ErrorDetails { +"""The details of an deleted record validation error""" +type DeleteErrorDetails { """The type of error that occurred""" type: String! """ - Tuple of strings identifying where in the sample schema the error occurred. + Tuple of strings identifying where in the record schema the error occurred. """ location: [String!]! @@ -651,62 +677,612 @@ type ErrorDetails { message: String! } -"""Values required to uniquely identify an instrument session""" -input InstrumentSessionInput { - proposalNumber: Int! - instrumentSessionNumber: Int! -} - -input JSONOperator @oneOf { - stringOperator: StringOperatorInput = null - datetimeOperator: DatetimeOperatorInput = null - numericOperator: NumericOperatorInput = null -} - -input JSONOperatorInput { - """A JSON path specifying the value to filter. Must start with '$.'""" - path: String! +"""Return type when marking an record as deleted""" +type DeleteExperimentResponse { + """Whether the operation has succeeded without validation errors""" + success: Boolean! - """The operator to apply to the JSON field""" - operator: JSONOperator! + """Errors that occurred during validation""" + errors: [DeleteErrorDetails!]! } -input NumericOperatorInput { - """ - Will filter to items where the numeric field is greater than the provided value - """ - gt: Float = null +"""Return type when marking an record as deleted""" +type DeletedExperimentDefinitionResponse { + """Whether the operation has succeeded without validation errors""" + success: Boolean! - """ - Will filter to items where the numeric field is less than the provided value - """ - lt: Float = null + """Errors that occurred during validation""" + errors: [DeleteErrorDetails!]! } -type Sample { +type Experiment { id: UUID! name: String! + createdTime: DateTime! + updatedTime: DateTime! + deleted: Boolean! + experimentDefinition: ExperimentDefinition! + createdBy: String! + modifiedBy: String! + + """The sample that this experiment is associated with""" + sample: Sample! +} + +type ExperimentConnection { + edges: [ExperimentEdge!]! + pageInfo: PageInfo! +} + +type ExperimentDefinition { + id: UUID! + name: String! + createdTime: DateTime! + updatedTime: DateTime! + data: JSON! + dataSchemaUrl: String! + proposalNumber: Int! + instrumentSessionNumber: Int! + deleted: Boolean! + createdBy: String! + modifiedBy: String! + + """ + The instrument session that this experiment definition is associated with + """ + instrumentSession: InstrumentSession! + + """Experiments associated with this experiment definition""" + experiments: [Experiment!]! +} + +type ExperimentDefinitionConnection { + edges: [ExperimentDefinitionEdge!]! + pageInfo: PageInfo! +} + +type ExperimentDefinitionEdge { + cursor: String! + node: ExperimentDefinition! +} + +"""The details of an experiment definition validation error""" +type ExperimentDefinitionErrorDetails { + """The type of error that occurred""" + type: String! + + """ + Tuple of strings identifying where in the experiment definition schema the error occurred. + """ + location: [String!]! + + """A human readable error message.""" + message: String! +} + +"""Values required to filter a list of experiment definitions""" +input ExperimentDefinitionFilterInput { + """Filter by the name of experiment definitions""" + name: StringFilterInputV2 = null + + """Filter by the created datetime of experiment definitions""" + createdTime: DatetimeFilterInputV2 = null + + """Filter by the update datetime of experiment definitions""" + updatedTime: DatetimeFilterInputV2 = null + + """Filter by the data schema URL of experiment definitions""" + dataSchemaUrl: StringFilterInputV2 = null + + """Filter within the JSON data of experiment definitions""" + data: [JSONFilterInputV2!] = null +} + +"""Mutations for a given experiment defintion""" +type ExperimentDefinitionMutations { + updateExperimentDefinition(input: UpdateExperimentDefinitionInput!): UpdateExperimentDefinitionResponse! + createExperiments(input: CreateExperimentsInput!): CreateExperimentsResponse! +} + +type ExperimentEdge { + cursor: String! + node: Experiment! +} + +"""Values required to create an experiment""" +input ExperimentInput { + name: String! + sampleId: UUID! +} + +type InstrumentSession { + instrumentSessionNumber: Int! + proposal: Proposal + + """Experiment Definitions""" + experimentDefinitions(first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentDefinitionConnection! + + """Experiments associated with this session""" + experiments(first: Int = null, last: Int = null, after: String = null, before: String = null): ExperimentConnection! + instrumentSessionId: Int! @deprecated(reason: "instrument_session_id is deprecated and will be removed in a future version.") + instrumentSessionReference: String + startTime: DateTime + endTime: DateTime + type: String + state: String + riskRating: String + instrument: Instrument! + roles: [InstrumentSessionRole!]! + + """Samples associated with a given instrument session""" + samples(first: Int = null, filter: SampleFilterInput! = {schemaUrl: null, createdTime: null, updatedTime: null, name: null, data: null}, before: String = null, after: String = null, last: Int = null, orderBy: SampleOrder! = {name: null, createdTime: null, updatedTime: null}): SampleConnection! +} + +"""Values required to uniquely identify an instrument session""" +input InstrumentSessionInput { + proposalNumber: Int! + instrumentSessionNumber: Int! +} + +input JSONFilterConditionInput @oneOf { + stringFilter: StringFilterInputV2 = null + datetimeFilter: DatetimeFilterInputV2 = null + numericFilter: NumericFilterInputV2 = null +} + +input JSONFilterInputV2 { + """The JSON path to the field to filter. Must start with '$.'""" + path: String! + + """The filter operation to apply to the field""" + condition: JSONFilterConditionInput! +} + +input NumericFilterInputV2 { + """ + Will filter to items where the numeric field is greater than the provided value + """ + greaterThan: Float = null + + """ + Will filter to items where the numeric field is less than the provided value + """ + lessThan: Float = null +} + +type Proposal { + proposalNumber: Int! + proposalCategory: String + title: String + summary: String + state: ProposalState! + proposalReference: String + instrumentSessions(first: Int = null, last: Int = null, after: String = null, before: String = null, sortBy: [InstrumentSessionSortInput!] = null, filterBy: InstrumentSessionFilterInput = null): InstrumentSessionConnection! + instruments: [Instrument!]! + roles: [ProposalAccount!]! +} + +type Sample { + id: UUID! + experiments: [Experiment!]! + name: String! data: JSON! createdTime: DateTime! updatedTime: DateTime! dataSchemaUrl: String! + deleted: Boolean! + + """Samples from which this sample is derived""" + parents(first: Int = null, before: String = null, after: String = null, last: Int = null): SampleConnection! + + """Samples derived from this sample""" + children(first: Int = null, before: String = null, after: String = null, last: Int = null): SampleConnection! + + """Events linked to this sample""" + events(first: Int = null, before: String = null, after: String = null, last: Int = null): SampleEventConnection! + + """The JSON schema that the sample's `data` conforms to""" + dataSchema: JSON! + + """The instrument sessions that this sample is associated with""" + instrumentSessions: [InstrumentSession!]! + images: [SampleImage!]! + + """The container containing the sample""" + container: Container + + """The sample's position within a container""" + positionInContainer: ContainerPosition +} + +input StringFilterInputV2 { + """ + Will filter to items where the `String` field is a member of the provided value + """ + in: [String!] = null + + """ + Will filter to items where the `String` field is equal to the provided value + """ + equalTo: String = null + + """ + Will filter to items where the `String` field is not equal to the provided value + """ + notEqualTo: String = null + + """ + Will filter to items where the `String` field is not a member of the provided value + """ + notIn: [String!] = null + + """ + Will filter to items where the `String` field is contains the provided value + """ + contains: String = null +} + +scalar UUID + +"""Values that can be updated on experiment definition""" +input UpdateExperimentDefinitionInput { + name: String + data: JSON + dataSchemaUrl: String +} + +"""Return type when updating an experiment definition""" +type UpdateExperimentDefinitionResponse { + """Whether the operation has succeeded without validation errors""" + success: Boolean! + + """Experiment Definition that has been updated""" + experimentDefinition: ExperimentDefinition + + """Errors that occurred during validation""" + errors: [ExperimentDefinitionErrorDetails!]! +} + +type Account { + username: String! + emailAddress: String + title: String + givenName: String + familyName: String + type: AccountType! + state: AccountState! + accountId: Int! @deprecated(reason: "account_id is deprecated and will be removed in a future version.") + proposalRoles: [ProposalAccount!]! + instrumentSessionRoles: [InstrumentSessionRole!]! +} + +input AccountFilterInput { + emailAddress: StringFilterInput = null + givenName: StringFilterInput = null + familyName: StringFilterInput = null +} + +enum AccountSortField { + family_name + given_name +} + +input AccountSortInput { + field: AccountSortField! + orderBy: SortOrder! +} + +enum AccountState { + enabled + disabled +} + +enum AccountType { + user + staff + functional +} + +input CreateInstrumentSessionInput { + """Number of the proposal the session is for""" + proposalNumber: Int! + + """Name of the instrument the session is for""" + instrumentName: String! + + """ + Instrument Session information that isn't needed by the Session Service but should be passed through the UAS + """ + additionalInfo: JSON = null +} + +input DateTimeFilterInput { + eq: DateTime = null + neq: DateTime = null + gt: DateTime = null + lt: DateTime = null + gte: DateTime = null + lte: DateTime = null +} + +type Instrument { + name: String! + key: String! + scienceGroup: String + description: String + proposals(first: Int = null, last: Int = null, after: String = null, before: String = null, sortBy: [ProposalSortInput!] = null, filterBy: ProposalFilterInput = null): ProposalConnection! + instrumentSessions(first: Int = null, last: Int = null, after: String = null, before: String = null, sortBy: [InstrumentSessionSortInput!] = null, filterBy: InstrumentSessionFilterInput = null): InstrumentSessionConnection! + + """ + Get paginated staff accounts for this instrument. Trusted users see all accounts; fedid users see only accounts linked to sessions or instruments they are associated with. + """ + staff(first: Int = null, last: Int = null, after: String = null, before: String = null, sortBy: [AccountSortInput!] = null, filterBy: AccountFilterInput = null): StaffConnection! +} + +type InstrumentSessionConnection { + edges: [InstrumentSessionEdge!]! + pageInfo: PageInfo! +} + +type InstrumentSessionEdge { + cursor: String! + node: InstrumentSession! +} + +input InstrumentSessionFilterInput { + instrumentSessionNumber: IntFilterInput = null + startTime: DateTimeFilterInput = null + endTime: DateTimeFilterInput = null + type: StringFilterInput = null + state: InstrumentSessionStateFilterInput = null + riskRating: StringFilterInput = null + proposalNumber: IntFilterInput = null +} + +type InstrumentSessionMutations { + instrumentSessionNumber: Int! + proposalNumber: Int! + + """Create or validate samples associated with this instrument session""" + createOrValidateSamples(input: CreateOrValidateSampleInputBase!): CreateSamplesResponse! +} + +type InstrumentSessionRole { + instrumentSession: InstrumentSession! + account: Account! + role: String! + onSite: Boolean! +} + +enum InstrumentSessionSortField { + instrumentSessionNumber + startTime + endTime + type + state + riskRating + proposalNumber +} + +input InstrumentSessionSortInput { + field: InstrumentSessionSortField! + orderBy: SortOrder! +} + +enum InstrumentSessionState { + CANCELLED + COMPLETED + FUTURE + IN_PROGRESS +} + +input InstrumentSessionStateFilterInput { + eq: InstrumentSessionState = null + neq: InstrumentSessionState = null +} + +input IntFilterInput { + eq: Int = null + neq: Int = null + gt: Int = null + lt: Int = null + gte: Int = null + lte: Int = null +} + +type ProposalAccount { + proposal: Proposal! + account: Account! + role: String! +} + +type ProposalConnection { + edges: [ProposalEdge!]! + pageInfo: PageInfo! +} + +type ProposalEdge { + cursor: String! + node: Proposal! +} + +input ProposalFilterInput { + proposalNumber: IntFilterInput = null + proposalCategory: StringFilterInput = null + title: StringFilterInput = null + state: ProposalStateFilterInput = null +} + +enum ProposalSortField { + proposalNumber +} + +input ProposalSortInput { + field: ProposalSortField! + orderBy: SortOrder! +} + +enum ProposalState { + OPEN + CLOSED + CANCELLED +} + +input ProposalStateFilterInput { + eq: ProposalState = null + neq: ProposalState = null +} + +enum SortOrder { + ASC + DESC +} + +type Staff { + username: String! + emailAddress: String + title: String + givenName: String + familyName: String + type: AccountType! + state: AccountState! +} + +type StaffConnection { + edges: [StaffEdge!]! + pageInfo: PageInfo! +} + +type StaffEdge { + cursor: String! + node: Staff! +} + +input StringFilterInput { + eq: String = null + neq: String = null + contains: String = null + notContains: String = null + startsWith: String = null + endsWith: String = null +} + +input AddSampleEventInput { + description: String! +} + +input CreateOrValidateSampleInput { + """URL of the JSON schema the samples' `data` should be validated against""" + dataSchemaUrl: String! + + """Samples to be created""" + samples: [SampleIn!]! + + """ + Whether or not the provided samples should only be validated and not created + """ + validateOnly: Boolean! = false + + """Number of the proposal the samples should be associated with""" + proposalNumber: Int! + + """Number of the instrument session the samples should be associated with""" + instrumentSessionNumber: Int! +} + +input CreateOrValidateSampleInputBase { + """URL of the JSON schema the samples' `data` should be validated against""" + dataSchemaUrl: String! + + """Samples to be created""" + samples: [SampleIn!]! + + """ + Whether or not the provided samples should only be validated and not created + """ + validateOnly: Boolean! = false +} + +"""Return type when creating or validating samples""" +type CreateSamplesResponse { + """Whether the operation has succeeded without validation errors""" + success: Boolean! + + """Samples that have been created""" + samples: [Sample!]! + + """Errors that occurred during sample validation""" + errors: [SampleValidationError!]! +} + +input DatetimeOperatorInput { + """ + Will filter to items where the `DateTime` field is greater than (i.e. after) the provided value + """ + gt: DateTime = null + + """ + Will filter to items where the `DateTime` field is less than (i.e. before) the provided value + """ + lt: DateTime = null +} - """Samples from which this sample is derived""" - parents(first: Int = null, before: String = null, after: String = null, last: Int = null): SampleConnection! +"""Return type when deleting a sample""" +type DeleteSampleResponse { + """Whether the operation has succeeded""" + success: Boolean! - """Samples derived from this sample""" - children(first: Int = null, before: String = null, after: String = null, last: Int = null): SampleConnection! + """Errors that occurred during the operation""" + errors: [String!]! +} - """Events linked to this sample""" - events(first: Int = null, before: String = null, after: String = null, last: Int = null): SampleEventConnection! +"""The details of sample validation error""" +type ErrorDetails { + """The type of error that occurred""" + type: String! - """The JSON schema that the sample's `data` conforms to""" - dataSchema: JSON! + """ + Tuple of strings identifying where in the sample schema the error occurred. + """ + location: [String!]! - """The instrument sessions that this sample is associated with""" - instrumentSessions: [InstrumentSession!]! - images: [SampleImage!]! - experiments: [Experiment!]! + """A human readable error message.""" + message: String! +} + +input JSONOperator @oneOf { + stringOperator: StringOperatorInput = null + datetimeOperator: DatetimeOperatorInput = null + numericOperator: NumericOperatorInput = null +} + +input JSONOperatorInput { + """A JSON path specifying the value to filter. Must start with '$.'""" + path: String! + + """The operator to apply to the JSON field""" + operator: JSONOperator! +} + +input NumericOperatorInput { + """ + Will filter to items where the numeric field is greater than the provided value + """ + gt: Float = null + + """ + Will filter to items where the numeric field is less than the provided value + """ + lt: Float = null +} + +"""Return type when restoring a deleted sample""" +type RestoreSampleResponse { + """Whether the operation has succeeded""" + success: Boolean! + + """Errors that occurred during the operation""" + errors: [String!]! } type SampleConnection { @@ -765,20 +1341,15 @@ input SampleIn { data: JSON! } -input SampleInLegacy { - name: String! - data: JSON! - dataSchemaUrl: String! - parentIds: [Int!] = null - children: [SampleInLegacy!] = null -} - type SampleMutations { sampleId: UUID! updateSample(input: UpdateSampleInput!): UpdateSampleResponse! linkInstrumentSessionToSample(proposalNumber: Int!, instrumentSessionNumber: Int!): Void addSampleEvent(sampleEvent: AddSampleEventInput!): SampleEvent! createSampleImageUploadUrl(filename: String!, contentType: String!, contentLength: Int!): String! + + """Assign this sample to a container""" + addSampleToContainer(input: AddSampleToContainerInput!): AddSampleToContainerResponse! } input SampleOrder { @@ -831,8 +1402,6 @@ input StringOperatorInput { contains: String = null } -scalar UUID - input UpdateSampleInput { """Name of the sample""" name: String @@ -844,92 +1413,414 @@ input UpdateSampleInput { dataSchemaUrl: String } -"""Return type when creating or validating samples""" +"""Return type when updating a sample""" type UpdateSampleResponse { - """Whether the operation has succeeded without validation errors""" + """Whether the operation has succeeded""" success: Boolean! """Sample that has been updated""" sample: Sample - """Errors that occurred during sample validation""" + """Errors that occurred during the operation""" errors: [SampleValidationError!]! } """Represents NULL values""" scalar Void -"""Values required to create an experiment definition""" -input CreateExperimentDefinitionInput { - name: String! - data: JSON! - dataSchemaUrl: String! - proposalNumber: Int! - instrumentSessionNumber: Int! +"""Values required to set a container's children""" +input AddContainersToContainerInput { + containerPositions: [ChildContainerPositionInput!]! } -"""Values required for the createExperiments mutation""" -input CreateExperimentsInput { - experiments: [ExperimentInput!]! +type AddContainersToContainerResponse { + success: Boolean! + containerPositions: [ContainerPosition!] + errors: [String!]! } -type Experiment { - id: UUID! - name: String! - createdTime: DateTime! - updatedTime: DateTime! - experimentDefinition: ExperimentDefinition! +input AddSampleToContainerInput { + containerPosition: ContainerPositionInput! +} - """The sample that this experiment is associated with""" - sample: Sample! +type AddSampleToContainerResponse { + success: Boolean! + samplePosition: SamplePostion + errors: [String!]! } -type ExperimentConnection { - edges: [ExperimentEdge!]! - pageInfo: PageInfo! +input AddSamplesToContainerInput { + samplePositions: [SamplePositionInput!]! } -type ExperimentDefinition { +type AddSamplesToContainerResponse { + success: Boolean! + samplePositions: [SamplePostion!] + errors: [String!]! +} + +"""Values required to assign a contianer to an instrument""" +input AssignContainerToInstrumentInput { + """The unique key of the instrument this container should be assigned to""" + instrumentKey: String! +} + +type AssignContainerToInstrumentResponse { + success: Boolean! + errors: [String!]! +} + +"""Values required to assign a contianer to an instrument session""" +input AssignContainerToInstrumentSessionInput { + """The instrument session this container should be assigned to""" + instrumentSession: InstrumentSessionInput! +} + +type AssignContainerToInstrumentSessionResponse { + success: Boolean! + errors: [String!]! +} + +"""Values required to specify a container's position within a container""" +input ChildContainerPositionInput { + childContainerId: UUID! + position: Int = null +} + +"""A container that can store samples and/or other containers""" +type Container { + """The unique identifier of this container""" id: UUID! - name: String! + + """When the container was created in the service""" createdTime: DateTime! + + """When the container was last updated in the service""" updatedTime: DateTime! - data: JSON! - dataSchemaUrl: String! - proposalNumber: Int! - instrumentSessionNumber: Int! + + """The name of the container""" + name: String! + + """The type of this container""" + type: ContainerType! + + """The manufacturer's serial number of the container""" + serialNumber: String + + """The facility barcode for the container""" + barcode: String + + """Whether or not the container has been marked as discarded""" + deleted: Boolean! + + """The user that created the container""" + createdBy: String! + + """The user that last modified the container""" + modifiedBy: String! """ - The instrument session that this experiment definition is associated with + The instrument sessions that this container is currently associated with """ - instrumentSession: InstrumentSession! + instrumentSessions: [InstrumentSession!]! - """Experiments associated with this experiment definition""" - experiments: [Experiment!]! + """Sample positions within this container""" + samplePositions: [SamplePostion!]! + + """The top-level fixed location where this container is stored""" + location: Container + parent: Container + + """The container position occupied by this container""" + positionInParent: ContainerPosition + children: [Container!]! + + """Container positions within this container""" + containerPositions: [ContainerPosition!]! } -type ExperimentDefinitionConnection { - edges: [ExperimentDefinitionEdge!]! +type ContainerConnection { + edges: [ContainerEdge!]! pageInfo: PageInfo! } -type ExperimentDefinitionEdge { +type ContainerEdge { cursor: String! - node: ExperimentDefinition! + node: Container! } -"""Mutations for a given experiment defintion""" -type ExperimentDefinitionMutations { - createExperiments(input: CreateExperimentsInput!): [Experiment!]! +"""Values required to filter a list of containers""" +input ContainerFilterInput { + """Filter using the id of the container's parent""" + parentId: UUIDFilterInputV2 = null + + """Filter using the of the container's children""" + childId: UUIDFilterInputV2 = null + + """Include/exclude 'deleted' containers""" + includeDeleted: Boolean! = false + + """Filter to containers with/without child containers""" + hasChildren: Boolean = null + + """Filter to containers with/without a parent""" + hasParent: Boolean = null } -type ExperimentEdge { +type ContainerMutations { + """Update this container""" + updateContainer(input: UpdateContainerInput!): UpdateContainerResponse! + + """Add containers to this container""" + addContainersToContainer(input: AddContainersToContainerInput!): AddContainersToContainerResponse! + + """Remove containers from this container""" + removeContainersFromContainer(input: RemoveContainersFromContainerInput!): RemoveContainersFromContainerResponse! + + """Set the container that this container is contained within""" + setParentContainer(input: SetParentContainerInput!): SetParentContainerResponse! + + """Add samples to this container""" + addSamplesToContainer(input: AddSamplesToContainerInput!): AddSamplesToContainerResponse! + + """Remove samples from this container""" + removeSamplesFromContainer(input: RemoveSamplesFromContainerInput!): RemoveSamplesFromContainerResponse! + + """Associate this container with an instrument session""" + assignContainerToInstrumentSession(input: AssignContainerToInstrumentSessionInput!): AssignContainerToInstrumentSessionResponse! + + """Unassign this container from an instrument session""" + unassignContainerFromInstrumentSession(input: UnassignContainerFromInstrumentSessionInput!): UnassignContainerFromInstrumentSessionResponse! + + """Associate this container with an instrument""" + assignContainerToInstrument(input: AssignContainerToInstrumentInput!): AssignContainerToInstrumentResponse! + + """Unassign this container from an instrument""" + unassignContainerFromInstrument(input: UnassignContainerFromInstrumentInput!): UnassignContainerFromInstrumentResponse! +} + +type ContainerPosition { + position: Int + container: Container +} + +"""Values required to specify a position within a container""" +input ContainerPositionInput { + parentContainerId: UUID! + position: Int = null +} + +"""A type of container""" +type ContainerType { + """The unique name of the container type""" + name: String! + + """A description of this type of container""" + description: String! + + """The number of containers the container can hold""" + numberOfContainerPositions: Int + + """The number of samples the container can hold""" + numberOfSamplePositions: Int + + """Used to distingush storage locations from moveable containers""" + isFixedLocation: Boolean! + + """The user that created the container type""" + createdBy: String! + + """The user user that last modified the container type""" + modifiedBy: String! +} + +type ContainerTypeConnection { + edges: [ContainerTypeEdge!]! + pageInfo: PageInfo! +} + +type ContainerTypeEdge { cursor: String! - node: Experiment! + node: ContainerType! } -"""Values required to create an experiment""" -input ExperimentInput { +type ContainerTypeMutations { + """Update this container type""" + updateContainerType(input: UpdateContainerTypeInput!): UpdateContainerTypeResponse! +} + +"""Values required to create a container""" +input CreateContainerInput { + """The unique key of an instrument associated with this container""" + instrumentKey: String = null + + """An instrument session associated with this container""" + instrumentSession: InstrumentSessionInput = null + + """The name of the type of this container""" + type: String! + + """The name of the container""" + name: String! + + """The serial number of this container""" + serialNumber: String = null + + """The facility barcode of the container""" + barcode: String = null +} + +type CreateContainerResponse { + success: Boolean! + container: Container + errors: [String!]! +} + +"""Values required to create a container type""" +input CreateContainerTypeInput { + """The unique key of an instrument associated with this container type""" + instrumentKey: String! + + """The unique name of this container type""" name: String! + + """A description of this container type""" + description: String! + + """Whether or not this container type is a fixed storage location""" + isFixedLocation: Boolean! + + """The number of container positions within this container""" + numberOfContainerPositions: Int = 0 + + """The number of sample positions within this container""" + numberOfSamplePositions: Int = 0 +} + +type CreateContainerTypeResponse { + success: Boolean! + containerType: ContainerType + errors: [String!]! +} + +"""Values required to remove containers from a container""" +input RemoveContainersFromContainerInput { + containerIds: [UUID!]! +} + +type RemoveContainersFromContainerResponse { + success: Boolean! +} + +"""Values required to remove samples from a container""" +input RemoveSamplesFromContainerInput { + sampleIds: [UUID!]! +} + +type RemoveSamplesFromContainerResponse { + success: Boolean! +} + +"""Values required to specify a sample's position within a container""" +input SamplePositionInput { sampleId: UUID! + position: Int = null +} + +type SamplePostion { + position: Int + sample: Sample +} + +"""Values required to set a container's parent""" +input SetParentContainerInput { + containerPosition: ContainerPositionInput! +} + +type SetParentContainerResponse { + success: Boolean! + containerPosition: ContainerPosition + errors: [String!]! +} + +input UUIDFilterInputV2 { + """ + Will filter to items where the `UUID` field is a member of the provided value + """ + in: [UUID!] = null + + """ + Will filter to items where the `UUID` field is equal to the provided value + """ + equalTo: UUID = null + + """ + Will filter to items where the `UUID` field is not equal to the provided value + """ + notEqualTo: UUID = null + + """ + Will filter to items where the `UUID` field is not a member of the provided value + """ + notIn: [UUID!] = null +} + +"""Values required to unassign a contianer from an instrument""" +input UnassignContainerFromInstrumentInput { + """ + The unique key of the instrument this container should be unassigned from + """ + instrumentKey: String! +} + +type UnassignContainerFromInstrumentResponse { + success: Boolean! + errors: [String!]! +} + +"""Values required to unassign a contianer from an instrument session""" +input UnassignContainerFromInstrumentSessionInput { + """The instrument session this container should be unassigned from""" + instrumentSession: InstrumentSessionInput! +} + +type UnassignContainerFromInstrumentSessionResponse { + success: Boolean! + errors: [String!]! +} + +"""Values required to update a container""" +input UpdateContainerInput { + """The name of the container""" + name: String + + """The serial number of this container""" + serialNumber: String + + """The facility barcode of the container""" + barcode: String +} + +type UpdateContainerResponse { + success: Boolean! + container: Container + errors: [String!]! +} + +"""Values required to update a container type""" +input UpdateContainerTypeInput { + """The unique name of the container type""" + name: String + + """A description of this container type""" + description: String + + """Used to distingush storage locations from moveable containers""" + isFixedLocation: Boolean +} + +type UpdateContainerTypeResponse { + success: Boolean! + containerType: ContainerType + errors: [String!]! } \ No newline at end of file diff --git a/helm/templates/oauth2-alpha-secret.yaml b/helm/templates/oauth2-alpha-secret.yaml index 787c9fbd..860b65ce 100644 --- a/helm/templates/oauth2-alpha-secret.yaml +++ b/helm/templates/oauth2-alpha-secret.yaml @@ -30,7 +30,7 @@ stringData: id: {{ .Values.identityProvider }} clientID: ${OAUTH2_PROXY_CLIENT_ID} clientSecret: ${OAUTH2_PROXY_CLIENT_SECRET} - scope: openid email profile offline_access + scope: openid email profile offline_access posix-uid oidcConfig: issuerURL: {{ include "ui-base.identityIssuerURL" . | quote }} insecureAllowUnverifiedEmail: true