From cfbc537a65c5bb634f35a354a401b9cf2162023a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Tue, 21 Jul 2026 19:13:54 +0100 Subject: [PATCH 1/7] add publicDataPlanes query + usePublicDataPlanes hook for pre-tenant onboarding The authenticated dataPlanes query returns nothing for a brand-new signup (no grants yet), so the onboarding plane picker needs the control-plane API's unauthenticated publicDataPlanes query instead. --- src/api/gql/dataPlanes.ts | 21 +++++++++++++++++ src/gql-types/gql.ts | 6 +++++ src/gql-types/graphql.ts | 8 +++++++ src/hooks/dataPlanes/usePublicDataPlanes.ts | 25 +++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 src/hooks/dataPlanes/usePublicDataPlanes.ts diff --git a/src/api/gql/dataPlanes.ts b/src/api/gql/dataPlanes.ts index dc496e9322..de54c23fcc 100644 --- a/src/api/gql/dataPlanes.ts +++ b/src/api/gql/dataPlanes.ts @@ -28,6 +28,27 @@ export const DATA_PLANES_QUERY = graphql(` } `); +// Unauthenticated query for the pre-tenant onboarding flow. The +// authenticated `dataPlanes` query returns nothing until the user +// has grants, which a brand-new signup does not. +export const PUBLIC_DATA_PLANES_QUERY = graphql(` + query PublicDataPlanes($after: String) { + publicDataPlanes(first: 100, after: $after) { + edges { + node { + name + cloudProvider + region + } + } + pageInfo { + hasNextPage + endCursor + } + } + } +`); + type DataPlaneGqlNode = DataPlanesQuery['dataPlanes']['edges'][number]['node']; export interface DataPlaneNode extends Omit { diff --git a/src/gql-types/gql.ts b/src/gql-types/gql.ts index f3bf218a46..d6728d1315 100644 --- a/src/gql-types/gql.ts +++ b/src/gql-types/gql.ts @@ -22,6 +22,7 @@ type Documents = { "\n query ConnectorsGrid($filter: ConnectorsFilter, $after: String) {\n connectors(first: 500, after: $after, filter: $filter) {\n edges {\n cursor\n node {\n id\n imageName\n logoUrl\n title\n recommended\n detail\n defaultSpec {\n id\n imageTag\n documentationUrl\n protocol\n }\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n": typeof types.ConnectorsGridDocument, "\n query ConnectorTagData($imageName: String!, $fullImageName: String!) {\n connector(imageName: $imageName) {\n id\n imageName\n logoUrl\n title\n }\n connectorSpec(fullImageName: $fullImageName) {\n id\n imageTag\n defaultCaptureInterval\n disableBackfill\n documentationUrl\n endpointSpecSchema\n resourceSpecSchema\n protocol\n }\n }\n": typeof types.ConnectorTagDataDocument, "\n query DataPlanes($after: String) {\n dataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n isPublic\n fqdn\n cidrBlocks\n awsIamUserArn\n gcpServiceAccountEmail\n azureApplicationClientId\n azureApplicationName\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n": typeof types.DataPlanesDocument, + "\n query PublicDataPlanes($after: String) {\n publicDataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n": typeof types.PublicDataPlanesDocument, "\n query InviteLinks($first: Int, $after: String) {\n inviteLinks(first: $first, after: $after) {\n edges {\n node {\n token\n ssoProviderId\n catalogPrefix\n capability\n singleUse\n detail\n createdAt\n }\n cursor\n }\n pageInfo {\n ...PageInfoFields\n }\n }\n }\n": typeof types.InviteLinksDocument, "\n mutation CreateInviteLink(\n $catalogPrefix: Prefix!\n $capability: Capability!\n $singleUse: Boolean!\n $detail: String\n ) {\n createInviteLink(\n catalogPrefix: $catalogPrefix\n capability: $capability\n singleUse: $singleUse\n detail: $detail\n ) {\n token\n catalogPrefix\n capability\n singleUse\n detail\n createdAt\n }\n }\n": typeof types.CreateInviteLinkDocument, "\n mutation DeleteInviteLink($token: UUID!) {\n deleteInviteLink(token: $token)\n }\n": typeof types.DeleteInviteLinkDocument, @@ -50,6 +51,7 @@ const documents: Documents = { "\n query ConnectorsGrid($filter: ConnectorsFilter, $after: String) {\n connectors(first: 500, after: $after, filter: $filter) {\n edges {\n cursor\n node {\n id\n imageName\n logoUrl\n title\n recommended\n detail\n defaultSpec {\n id\n imageTag\n documentationUrl\n protocol\n }\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n": types.ConnectorsGridDocument, "\n query ConnectorTagData($imageName: String!, $fullImageName: String!) {\n connector(imageName: $imageName) {\n id\n imageName\n logoUrl\n title\n }\n connectorSpec(fullImageName: $fullImageName) {\n id\n imageTag\n defaultCaptureInterval\n disableBackfill\n documentationUrl\n endpointSpecSchema\n resourceSpecSchema\n protocol\n }\n }\n": types.ConnectorTagDataDocument, "\n query DataPlanes($after: String) {\n dataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n isPublic\n fqdn\n cidrBlocks\n awsIamUserArn\n gcpServiceAccountEmail\n azureApplicationClientId\n azureApplicationName\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n": types.DataPlanesDocument, + "\n query PublicDataPlanes($after: String) {\n publicDataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n": types.PublicDataPlanesDocument, "\n query InviteLinks($first: Int, $after: String) {\n inviteLinks(first: $first, after: $after) {\n edges {\n node {\n token\n ssoProviderId\n catalogPrefix\n capability\n singleUse\n detail\n createdAt\n }\n cursor\n }\n pageInfo {\n ...PageInfoFields\n }\n }\n }\n": types.InviteLinksDocument, "\n mutation CreateInviteLink(\n $catalogPrefix: Prefix!\n $capability: Capability!\n $singleUse: Boolean!\n $detail: String\n ) {\n createInviteLink(\n catalogPrefix: $catalogPrefix\n capability: $capability\n singleUse: $singleUse\n detail: $detail\n ) {\n token\n catalogPrefix\n capability\n singleUse\n detail\n createdAt\n }\n }\n": types.CreateInviteLinkDocument, "\n mutation DeleteInviteLink($token: UUID!) {\n deleteInviteLink(token: $token)\n }\n": types.DeleteInviteLinkDocument, @@ -116,6 +118,10 @@ export function graphql(source: "\n query ConnectorTagData($imageName: String * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "\n query DataPlanes($after: String) {\n dataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n isPublic\n fqdn\n cidrBlocks\n awsIamUserArn\n gcpServiceAccountEmail\n azureApplicationClientId\n azureApplicationName\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n"): (typeof documents)["\n query DataPlanes($after: String) {\n dataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n isPublic\n fqdn\n cidrBlocks\n awsIamUserArn\n gcpServiceAccountEmail\n azureApplicationClientId\n azureApplicationName\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n query PublicDataPlanes($after: String) {\n publicDataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n"): (typeof documents)["\n query PublicDataPlanes($after: String) {\n publicDataPlanes(first: 100, after: $after) {\n edges {\n node {\n name\n cloudProvider\n region\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/src/gql-types/graphql.ts b/src/gql-types/graphql.ts index fc207e4b76..fa5e841770 100644 --- a/src/gql-types/graphql.ts +++ b/src/gql-types/graphql.ts @@ -2443,6 +2443,13 @@ export type DataPlanesQueryVariables = Exact<{ export type DataPlanesQuery = { __typename?: 'QueryRoot', dataPlanes: { __typename?: 'DataPlaneConnection', edges: Array<{ __typename?: 'DataPlaneEdge', node: { __typename?: 'DataPlane', name: string, cloudProvider: DataPlaneCloudProvider, region: string, isPublic: boolean, fqdn: string, cidrBlocks: Array, awsIamUserArn?: string | null, gcpServiceAccountEmail?: string | null, azureApplicationClientId?: string | null, azureApplicationName?: string | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null } } }; +export type PublicDataPlanesQueryVariables = Exact<{ + after?: InputMaybe; +}>; + + +export type PublicDataPlanesQuery = { __typename?: 'QueryRoot', publicDataPlanes: { __typename?: 'PublicDataPlaneConnection', edges: Array<{ __typename?: 'PublicDataPlaneEdge', node: { __typename?: 'PublicDataPlane', name: string, cloudProvider: DataPlaneCloudProvider, region: string } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null } } }; + export type InviteLinksQueryVariables = Exact<{ first?: InputMaybe; after?: InputMaybe; @@ -2589,6 +2596,7 @@ export const AlertTypeDocument = {"kind":"Document","definitions":[{"kind":"Oper export const ConnectorsGridDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ConnectorsGrid"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ConnectorsFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"connectors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"500"}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"imageName"}},{"kind":"Field","name":{"kind":"Name","value":"logoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"recommended"}},{"kind":"Field","name":{"kind":"Name","value":"detail"}},{"kind":"Field","name":{"kind":"Name","value":"defaultSpec"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"imageTag"}},{"kind":"Field","name":{"kind":"Name","value":"documentationUrl"}},{"kind":"Field","name":{"kind":"Name","value":"protocol"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode; export const ConnectorTagDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ConnectorTagData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"imageName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fullImageName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"connector"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"imageName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"imageName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"imageName"}},{"kind":"Field","name":{"kind":"Name","value":"logoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"title"}}]}},{"kind":"Field","name":{"kind":"Name","value":"connectorSpec"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"fullImageName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fullImageName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"imageTag"}},{"kind":"Field","name":{"kind":"Name","value":"defaultCaptureInterval"}},{"kind":"Field","name":{"kind":"Name","value":"disableBackfill"}},{"kind":"Field","name":{"kind":"Name","value":"documentationUrl"}},{"kind":"Field","name":{"kind":"Name","value":"endpointSpecSchema"}},{"kind":"Field","name":{"kind":"Name","value":"resourceSpecSchema"}},{"kind":"Field","name":{"kind":"Name","value":"protocol"}}]}}]}}]} as unknown as DocumentNode; export const DataPlanesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DataPlanes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"dataPlanes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"cloudProvider"}},{"kind":"Field","name":{"kind":"Name","value":"region"}},{"kind":"Field","name":{"kind":"Name","value":"isPublic"}},{"kind":"Field","name":{"kind":"Name","value":"fqdn"}},{"kind":"Field","name":{"kind":"Name","value":"cidrBlocks"}},{"kind":"Field","name":{"kind":"Name","value":"awsIamUserArn"}},{"kind":"Field","name":{"kind":"Name","value":"gcpServiceAccountEmail"}},{"kind":"Field","name":{"kind":"Name","value":"azureApplicationClientId"}},{"kind":"Field","name":{"kind":"Name","value":"azureApplicationName"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode; +export const PublicDataPlanesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"PublicDataPlanes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"publicDataPlanes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"cloudProvider"}},{"kind":"Field","name":{"kind":"Name","value":"region"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode; export const InviteLinksDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"InviteLinks"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteLinks"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"token"}},{"kind":"Field","name":{"kind":"Name","value":"ssoProviderId"}},{"kind":"Field","name":{"kind":"Name","value":"catalogPrefix"}},{"kind":"Field","name":{"kind":"Name","value":"capability"}},{"kind":"Field","name":{"kind":"Name","value":"singleUse"}},{"kind":"Field","name":{"kind":"Name","value":"detail"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PageInfoFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PageInfoFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PageInfo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]} as unknown as DocumentNode; export const CreateInviteLinkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateInviteLink"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"catalogPrefix"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Prefix"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"capability"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Capability"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"singleUse"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"detail"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createInviteLink"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"catalogPrefix"},"value":{"kind":"Variable","name":{"kind":"Name","value":"catalogPrefix"}}},{"kind":"Argument","name":{"kind":"Name","value":"capability"},"value":{"kind":"Variable","name":{"kind":"Name","value":"capability"}}},{"kind":"Argument","name":{"kind":"Name","value":"singleUse"},"value":{"kind":"Variable","name":{"kind":"Name","value":"singleUse"}}},{"kind":"Argument","name":{"kind":"Name","value":"detail"},"value":{"kind":"Variable","name":{"kind":"Name","value":"detail"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"token"}},{"kind":"Field","name":{"kind":"Name","value":"catalogPrefix"}},{"kind":"Field","name":{"kind":"Name","value":"capability"}},{"kind":"Field","name":{"kind":"Name","value":"singleUse"}},{"kind":"Field","name":{"kind":"Name","value":"detail"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]} as unknown as DocumentNode; export const DeleteInviteLinkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteInviteLink"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteInviteLink"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}]}]}}]} as unknown as DocumentNode; diff --git a/src/hooks/dataPlanes/usePublicDataPlanes.ts b/src/hooks/dataPlanes/usePublicDataPlanes.ts new file mode 100644 index 0000000000..39d133ba66 --- /dev/null +++ b/src/hooks/dataPlanes/usePublicDataPlanes.ts @@ -0,0 +1,25 @@ +import type { PublicDataPlanesQuery } from 'src/gql-types/graphql'; + +import { PUBLIC_DATA_PLANES_QUERY } from 'src/api/gql/dataPlanes'; +import { useAllPages } from 'src/api/gql/useAllPages'; + +type PublicDataPlaneGqlNode = + PublicDataPlanesQuery['publicDataPlanes']['edges'][number]['node']; + +export interface PublicDataPlaneNode extends PublicDataPlaneGqlNode {} + +// Public planes for the pre-tenant onboarding flow. The authenticated +// `dataPlanes` query is useless here: a brand-new user has no grants yet, +// so it returns nothing until the tenant is provisioned. +export function usePublicDataPlanes() { + const { + data: dataPlanes, + loading, + error, + } = useAllPages(PUBLIC_DATA_PLANES_QUERY, { + getConnection: (data) => data.publicDataPlanes, + transform: (node): PublicDataPlaneNode => node, + }); + + return { dataPlanes, loading, error }; +} From 684cdb8069e445b80d62db628de9e3e8021a7c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Tue, 21 Jul 2026 19:14:55 +0100 Subject: [PATCH 2/7] onboarding store: track selected data plane --- src/directives/Onboard/Store/create.ts | 12 ++++++++++++ src/directives/Onboard/Store/hooks.ts | 14 ++++++++++++++ src/directives/Onboard/Store/types.ts | 3 +++ 3 files changed, 29 insertions(+) diff --git a/src/directives/Onboard/Store/create.ts b/src/directives/Onboard/Store/create.ts index f179b49c9b..a44f25ee64 100644 --- a/src/directives/Onboard/Store/create.ts +++ b/src/directives/Onboard/Store/create.ts @@ -17,6 +17,7 @@ const getInitialStateData = (): Pick< | 'nameProblematic' | 'nameMissing' | 'requestedTenant' + | 'requestedDataPlane' | 'surveyResponse' | 'surveyMissing' | 'serverError' @@ -25,6 +26,7 @@ const getInitialStateData = (): Pick< nameProblematic: false, nameMissing: false, requestedTenant: '', + requestedDataPlane: null, surveyResponse: { origin: '', details: '' }, surveyMissing: false, serverError: null, @@ -63,6 +65,16 @@ const getInitialState = (set: NamedSet): OnboardingState => ({ ); }, + setRequestedDataPlane: (value) => { + set( + () => ({ + requestedDataPlane: value, + }), + false, + 'setRequestedDataPlane' + ); + }, + setServerError: (value) => { set( (state) => ({ diff --git a/src/directives/Onboard/Store/hooks.ts b/src/directives/Onboard/Store/hooks.ts index 0ca47d5c56..34bd4cb59f 100644 --- a/src/directives/Onboard/Store/hooks.ts +++ b/src/directives/Onboard/Store/hooks.ts @@ -17,6 +17,20 @@ export const useOnboardingStore_setRequestedTenant = () => { >(OnboardingStoreNames.GENERAL, (state) => state.setRequestedTenant); }; +export const useOnboardingStore_requestedDataPlane = () => { + return useLocalZustandStore< + OnboardingState, + OnboardingState['requestedDataPlane'] + >(OnboardingStoreNames.GENERAL, (state) => state.requestedDataPlane); +}; + +export const useOnboardingStore_setRequestedDataPlane = () => { + return useLocalZustandStore< + OnboardingState, + OnboardingState['setRequestedDataPlane'] + >(OnboardingStoreNames.GENERAL, (state) => state.setRequestedDataPlane); +}; + export const useOnboardingStore_nameInvalid = () => { return useLocalZustandStore< OnboardingState, diff --git a/src/directives/Onboard/Store/types.ts b/src/directives/Onboard/Store/types.ts index 024164f69a..51a2889b3c 100644 --- a/src/directives/Onboard/Store/types.ts +++ b/src/directives/Onboard/Store/types.ts @@ -7,6 +7,9 @@ export interface OnboardingState { requestedTenant: string; setRequestedTenant: (value: string) => void; + requestedDataPlane: string | null; + setRequestedDataPlane: (value: string | null) => void; + nameInvalid: boolean; setNameInvalid: (value: boolean) => void; From bd3f6f6437686c33cc60dc1369a640409fbfbee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Tue, 21 Jul 2026 20:10:06 +0100 Subject: [PATCH 3/7] onboarding: data-plane picker wired to publicDataPlanes and betaOnboard claims Adds a plane picker between the organization name field and the survey, backed by the unauthenticated publicDataPlanes query (a brand-new signup has no grants yet, so the authenticated dataPlanes query returns nothing). Auto-preselects aws-us-east-1-c1 (falling back to the first available plane) so submitting without touching the picker still records an explicit, valid choice; fails safe to no picker + an omitted claim if the plane list can't be loaded, letting the backend apply its own default. generateUserClaim now forwards requestedDataPlane only when set, never as an explicit null, so older backends that don't know the field are unaffected. Also registers PublicDataPlane in the urql cache's keys config (alongside the existing DataPlane entry) to silence a normalization warning for the new unkeyed type. Verified end-to-end against a real local stack: picker lists the seeded public plane, auto-selects it, and a completed registration produced a storage_mappings row with the picked plane in data_planes. --- src/context/URQL.tsx | 1 + src/directives/BetaOnboard.tsx | 14 ++- src/directives/Onboard/DataPlaneSelector.tsx | 97 ++++++++++++++++++++ src/directives/shared.ts | 9 ++ src/directives/types.ts | 1 + src/lang/en-US/Authentication.ts | 2 + 6 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 src/directives/Onboard/DataPlaneSelector.tsx diff --git a/src/context/URQL.tsx b/src/context/URQL.tsx index a2b5a42271..06d6bd272b 100644 --- a/src/context/URQL.tsx +++ b/src/context/URQL.tsx @@ -64,6 +64,7 @@ function UrqlConfigProvider({ children }: BaseComponentProps) { RefreshTokenInfo: (_data) => null, StorageMapping: (data) => null, DataPlane: (data) => null, + PublicDataPlane: (data) => null, }, updates: { Mutation: { diff --git a/src/directives/BetaOnboard.tsx b/src/directives/BetaOnboard.tsx index 739bcd6f54..a8cf271fe4 100644 --- a/src/directives/BetaOnboard.tsx +++ b/src/directives/BetaOnboard.tsx @@ -12,9 +12,11 @@ import { submitDirective } from 'src/api/directives'; import RegistrationProgress from 'src/app/guards/RegistrationProgress'; import BetaWarningAndError from 'src/components/transformation/create/BetaWarningAndError'; import Actions from 'src/directives/Actions'; +import DataPlaneSelector from 'src/directives/Onboard/DataPlaneSelector'; import OrganizationNameField from 'src/directives/Onboard/OrganizationName'; import { useOnboardingStore_nameInvalid, + useOnboardingStore_requestedDataPlane, useOnboardingStore_requestedTenant, useOnboardingStore_resetState, useOnboardingStore_setNameMissing, @@ -39,13 +41,15 @@ const EVENT_NAME = 'Tenant:Create'; const submit_onboard = async ( requestedTenant: string, directive: any, - surveyResponse: any + surveyResponse: any, + requestedDataPlane: string | null ) => { return submitDirective( directiveName, directive, requestedTenant, - surveyResponse + surveyResponse, + requestedDataPlane ); }; @@ -60,6 +64,7 @@ const BetaOnboard = ({ directive, mutate, status }: DirectiveProps) => { const setNameMissing = useOnboardingStore_setNameMissing(); const setSurveyMissing = useOnboardingStore_setSurveyMissing(); const surveyResponse = useOnboardingStore_surveyResponse(); + const requestedDataPlane = useOnboardingStore_requestedDataPlane(); const resetOnboardingState = useOnboardingStore_resetState(); const setServerError = useOnboardingStore_setServerError(); @@ -100,7 +105,8 @@ const BetaOnboard = ({ directive, mutate, status }: DirectiveProps) => { const onboardingResponse = await submit_onboard( requestedTenant, directive, - surveyResponse + surveyResponse, + requestedDataPlane ); if (onboardingResponse.error) { @@ -194,6 +200,8 @@ const BetaOnboard = ({ directive, mutate, status }: DirectiveProps) => { > + + [...dataPlanes].sort((a, b) => a.name.localeCompare(b.name)), + [dataPlanes] + ); + + // Preselect the platform default so submitting without touching the + // picker still records an explicit, valid choice. + useEffect(() => { + if (!selected && options.length > 0) { + const preferred = + options.find((option) => option.name === PREFERRED_DEFAULT) ?? + options[0]; + setSelected(preferred.name); + } + }, [options, selected, setSelected]); + + // Fail safe: if the plane list can't be fetched, render nothing. The + // claim simply omits requestedDataPlane and the backend applies its + // own default instead of blocking signup on this field. + if (error || (!loading && options.length === 0)) { + return null; + } + + const currentOption = options.find((option) => option.name === selected); + + return ( + + + {intl.formatMessage({ id: 'tenant.dataPlane.label' })} + + + setSelected(value?.name ?? null)} + groupBy={(option) => option.cloudProvider} + getOptionLabel={(option) => `${option.region} (${option.name})`} + isOptionEqualToValue={(option, value) => + option.name === value.name + } + renderOption={(props, option) => { + const { key, ...rest } = props; + return ( +
  • + + + {option.region} ({option.name}) + +
  • + ); + }} + renderInput={(params) => ( + + )} + /> +
    + ); +} + +export default DataPlaneSelector; diff --git a/src/directives/shared.ts b/src/directives/shared.ts index eb0fcd5903..8433094c81 100644 --- a/src/directives/shared.ts +++ b/src/directives/shared.ts @@ -80,9 +80,18 @@ export const DIRECTIVES: Directives = { return queryBuilder; }, generateUserClaim: (args: any[]) => { + const requestedDataPlane = args[2]; return { requestedTenant: args[0], survey: args.length > 1 ? args[1] : null, + // Omitted (never sent as null) when unset: the agent's + // claims parser rejects unknown keys, and older agents + // don't know this one — leaving it out lets the backend + // fall back to its own default plane. + ...(typeof requestedDataPlane === 'string' && + requestedDataPlane.length > 0 + ? { requestedDataPlane } + : {}), }; }, calculateStatus: (appliedDirective) => { diff --git a/src/directives/types.ts b/src/directives/types.ts index 71c7b9be97..33b6f1a2e1 100644 --- a/src/directives/types.ts +++ b/src/directives/types.ts @@ -42,6 +42,7 @@ interface ClickToAcceptClaim { interface OnboardClaim { requestedTenant: string; survey: any; + requestedDataPlane?: string; } interface StorageMappingsClaim { diff --git a/src/lang/en-US/Authentication.ts b/src/lang/en-US/Authentication.ts index 76460be753..aea3ff10cf 100644 --- a/src/lang/en-US/Authentication.ts +++ b/src/lang/en-US/Authentication.ts @@ -106,6 +106,8 @@ export const Authentication: Record = { 'tenant.input.label': `Organization Name`, 'tenant.input.placeholder': `acmeCo`, 'tenant.errorMessage.empty': `You must provide an organization name before continuing.`, + 'tenant.dataPlane.label': `Data Plane`, + 'tenant.dataPlane.helper': `Where your data is processed and stored. Pick the region closest to your data sources.`, 'tenant.errorMessage.invalid': `Your organization name is invalid.`, 'tenant.origin.errorMessage.empty': `Please let us know where you heard about us.`, 'tenant.warningMessage.problematic': `Looks like your organization name contains "test". This is generally not recommended as you cannot rename your organization later.`, From b87c84a685f944609b82a0f41aa519ff274cf0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Tue, 21 Jul 2026 21:25:02 +0100 Subject: [PATCH 4/7] code-review cleanup: match sibling conventions in the picker code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move PublicDataPlaneNode + a named toPublicDataPlaneNode transform into src/api/gql/dataPlanes.ts, alongside the existing DataPlaneNode / toDataPlaneNode pair the sibling useDataPlanes() hook uses. The hook previously defined its own type and inlined an identity transform, diverging from where this codebase already models data-plane nodes. - Destructure betaOnboard's generateUserClaim args by name instead of indexing (args[0], args[1], args[2]) — same positional-args signature (shared across all directive types), just clearer at the read site. - Rename DataPlaneSelector's PREFERRED_DEFAULT to DEFAULT_PUBLIC_DATA_PLANE, matching the backend's constant of the same meaning and making the value's type (a plane name) obvious from the name. No behavior change: tsc and lint both pass clean. --- src/api/gql/dataPlanes.ts | 20 +++++++++++++++++++- src/directives/Onboard/DataPlaneSelector.tsx | 4 ++-- src/directives/shared.ts | 6 +++--- src/hooks/dataPlanes/usePublicDataPlanes.ts | 14 +++++--------- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/api/gql/dataPlanes.ts b/src/api/gql/dataPlanes.ts index de54c23fcc..6de42da5af 100644 --- a/src/api/gql/dataPlanes.ts +++ b/src/api/gql/dataPlanes.ts @@ -1,4 +1,4 @@ -import type { DataPlanesQuery } from 'src/gql-types/graphql'; +import type { DataPlanesQuery, PublicDataPlanesQuery } from 'src/gql-types/graphql'; import type { CloudProvider } from 'src/utils/cloudRegions'; import { graphql } from 'src/gql-types'; @@ -65,3 +65,21 @@ export const toDataPlaneNode = (node: DataPlaneGqlNode): DataPlaneNode => { scope: node.isPublic ? 'public' : 'private', }; }; + +type PublicDataPlaneGqlNode = + PublicDataPlanesQuery['publicDataPlanes']['edges'][number]['node']; + +export interface PublicDataPlaneNode + extends Omit { + // Narrower than the schema's DataPlaneCloudProvider, which also allows LOCAL + cloudProvider: CloudProvider; +} + +export const toPublicDataPlaneNode = ( + node: PublicDataPlaneGqlNode +): PublicDataPlaneNode => { + return { + ...node, + cloudProvider: node.cloudProvider as CloudProvider, + }; +}; diff --git a/src/directives/Onboard/DataPlaneSelector.tsx b/src/directives/Onboard/DataPlaneSelector.tsx index a9f88d8547..01c3294693 100644 --- a/src/directives/Onboard/DataPlaneSelector.tsx +++ b/src/directives/Onboard/DataPlaneSelector.tsx @@ -13,7 +13,7 @@ import { usePublicDataPlanes } from 'src/hooks/dataPlanes/usePublicDataPlanes'; // Matches est-dry-dock's phased rollout of colocated trial buckets: this is // the plane new tenants land on when nothing else is picked. -const PREFERRED_DEFAULT = 'ops/dp/public/aws-us-east-1-c1'; +const DEFAULT_PUBLIC_DATA_PLANE = 'ops/dp/public/aws-us-east-1-c1'; function DataPlaneSelector() { const intl = useIntl(); @@ -32,7 +32,7 @@ function DataPlaneSelector() { useEffect(() => { if (!selected && options.length > 0) { const preferred = - options.find((option) => option.name === PREFERRED_DEFAULT) ?? + options.find((option) => option.name === DEFAULT_PUBLIC_DATA_PLANE) ?? options[0]; setSelected(preferred.name); } diff --git a/src/directives/shared.ts b/src/directives/shared.ts index 8433094c81..996b54107e 100644 --- a/src/directives/shared.ts +++ b/src/directives/shared.ts @@ -80,10 +80,10 @@ export const DIRECTIVES: Directives = { return queryBuilder; }, generateUserClaim: (args: any[]) => { - const requestedDataPlane = args[2]; + const [requestedTenant, survey, requestedDataPlane] = args; return { - requestedTenant: args[0], - survey: args.length > 1 ? args[1] : null, + requestedTenant, + survey: survey ?? null, // Omitted (never sent as null) when unset: the agent's // claims parser rejects unknown keys, and older agents // don't know this one — leaving it out lets the backend diff --git a/src/hooks/dataPlanes/usePublicDataPlanes.ts b/src/hooks/dataPlanes/usePublicDataPlanes.ts index 39d133ba66..52a29c8256 100644 --- a/src/hooks/dataPlanes/usePublicDataPlanes.ts +++ b/src/hooks/dataPlanes/usePublicDataPlanes.ts @@ -1,13 +1,9 @@ -import type { PublicDataPlanesQuery } from 'src/gql-types/graphql'; - -import { PUBLIC_DATA_PLANES_QUERY } from 'src/api/gql/dataPlanes'; +import { + PUBLIC_DATA_PLANES_QUERY, + toPublicDataPlaneNode, +} from 'src/api/gql/dataPlanes'; import { useAllPages } from 'src/api/gql/useAllPages'; -type PublicDataPlaneGqlNode = - PublicDataPlanesQuery['publicDataPlanes']['edges'][number]['node']; - -export interface PublicDataPlaneNode extends PublicDataPlaneGqlNode {} - // Public planes for the pre-tenant onboarding flow. The authenticated // `dataPlanes` query is useless here: a brand-new user has no grants yet, // so it returns nothing until the tenant is provisioned. @@ -18,7 +14,7 @@ export function usePublicDataPlanes() { error, } = useAllPages(PUBLIC_DATA_PLANES_QUERY, { getConnection: (data) => data.publicDataPlanes, - transform: (node): PublicDataPlaneNode => node, + transform: toPublicDataPlaneNode, }); return { dataPlanes, loading, error }; From 1473e778d003ee5e57acecd92dc4ca06b9d451cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Tue, 4 Aug 2026 17:19:24 +0100 Subject: [PATCH 5/7] onboarding: match the org-name field's input border radius in the picker The Organization Name field overrides the 2px theme default to borderRadius: 3 (6px). The picker sat right below it inheriting the theme default, so the two adjacent inputs had visibly different corners. Apply the same override. --- src/directives/Onboard/DataPlaneSelector.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/directives/Onboard/DataPlaneSelector.tsx b/src/directives/Onboard/DataPlaneSelector.tsx index 01c3294693..540d19fb26 100644 --- a/src/directives/Onboard/DataPlaneSelector.tsx +++ b/src/directives/Onboard/DataPlaneSelector.tsx @@ -1,6 +1,12 @@ import { useEffect, useMemo } from 'react'; -import { Autocomplete, FormControl, FormLabel, TextField } from '@mui/material'; +import { + Autocomplete, + FormControl, + FormLabel, + inputBaseClasses, + TextField, +} from '@mui/material'; import { useIntl } from 'react-intl'; @@ -86,7 +92,12 @@ function DataPlaneSelector() { helperText={intl.formatMessage({ id: 'tenant.dataPlane.helper', })} - sx={{ maxWidth: 424 }} + sx={{ + maxWidth: 424, + [`& .${inputBaseClasses.root}`]: { + borderRadius: 3, + }, + }} /> )} /> From 22c132c2825154edd8616fc8dbd5e1b8f8d6c94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Tue, 4 Aug 2026 19:06:34 +0100 Subject: [PATCH 6/7] simplify: dedup the picker's option label, sort by provider for grouping - Sort options by cloudProvider then region: groupBy only groups correctly when the list is ordered by group, which previously worked only because plane names embed the provider. - Extract the region/name label used by both getOptionLabel and renderOption so the two can't drift. - Drop isOptionEqualToValue; value is always drawn from options, so MUI's default reference comparison already matches. - Hoist the input sx to a module const, and reuse hasLength for the claim's non-empty check. --- src/directives/Onboard/DataPlaneSelector.tsx | 36 +++++++++++++------- src/directives/shared.ts | 3 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/directives/Onboard/DataPlaneSelector.tsx b/src/directives/Onboard/DataPlaneSelector.tsx index 540d19fb26..a532c51475 100644 --- a/src/directives/Onboard/DataPlaneSelector.tsx +++ b/src/directives/Onboard/DataPlaneSelector.tsx @@ -1,3 +1,5 @@ +import type { PublicDataPlaneNode } from 'src/api/gql/dataPlanes'; + import { useEffect, useMemo } from 'react'; import { @@ -21,6 +23,16 @@ import { usePublicDataPlanes } from 'src/hooks/dataPlanes/usePublicDataPlanes'; // the plane new tenants land on when nothing else is picked. const DEFAULT_PUBLIC_DATA_PLANE = 'ops/dp/public/aws-us-east-1-c1'; +const INPUT_SX = { + maxWidth: 424, + [`& .${inputBaseClasses.root}`]: { borderRadius: 3 }, +}; + +// The region and full catalog name are both shown: multiple public planes can +// share a region, so the name is what makes the choice unambiguous. +const optionLabel = (option: PublicDataPlaneNode) => + `${option.region} (${option.name})`; + function DataPlaneSelector() { const intl = useIntl(); const { dataPlanes, loading, error } = usePublicDataPlanes(); @@ -28,8 +40,16 @@ function DataPlaneSelector() { const selected = useOnboardingStore_requestedDataPlane(); const setSelected = useOnboardingStore_setRequestedDataPlane(); + // Sorted by provider first because groupBy only groups correctly when the + // list is already ordered by group; sorting on name alone worked only + // because the names happen to embed the provider. const options = useMemo( - () => [...dataPlanes].sort((a, b) => a.name.localeCompare(b.name)), + () => + [...dataPlanes].sort( + (a, b) => + a.cloudProvider.localeCompare(b.cloudProvider) || + a.region.localeCompare(b.region) + ), [dataPlanes] ); @@ -65,10 +85,7 @@ function DataPlaneSelector() { value={currentOption ?? null} onChange={(_event, value) => setSelected(value?.name ?? null)} groupBy={(option) => option.cloudProvider} - getOptionLabel={(option) => `${option.region} (${option.name})`} - isOptionEqualToValue={(option, value) => - option.name === value.name - } + getOptionLabel={optionLabel} renderOption={(props, option) => { const { key, ...rest } = props; return ( @@ -79,7 +96,7 @@ function DataPlaneSelector() { size={20} /> - {option.region} ({option.name}) + {optionLabel(option)} ); @@ -92,12 +109,7 @@ function DataPlaneSelector() { helperText={intl.formatMessage({ id: 'tenant.dataPlane.helper', })} - sx={{ - maxWidth: 424, - [`& .${inputBaseClasses.root}`]: { - borderRadius: 3, - }, - }} + sx={INPUT_SX} /> )} /> diff --git a/src/directives/shared.ts b/src/directives/shared.ts index 996b54107e..0e5d4ecad4 100644 --- a/src/directives/shared.ts +++ b/src/directives/shared.ts @@ -88,8 +88,7 @@ export const DIRECTIVES: Directives = { // claims parser rejects unknown keys, and older agents // don't know this one — leaving it out lets the backend // fall back to its own default plane. - ...(typeof requestedDataPlane === 'string' && - requestedDataPlane.length > 0 + ...(hasLength(requestedDataPlane) ? { requestedDataPlane } : {}), }; From c1f79e908cc4bcb9d447e0c241cb5a386e085b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Whelan?= Date: Thu, 6 Aug 2026 10:58:59 +0100 Subject: [PATCH 7/7] format: prettier CI's Check Quality runs prettier, which I hadn't run locally. Formatting only, no functional change. --- src/api/gql/dataPlanes.ts | 5 ++++- src/directives/Onboard/DataPlaneSelector.tsx | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/api/gql/dataPlanes.ts b/src/api/gql/dataPlanes.ts index 6de42da5af..84db2db9b7 100644 --- a/src/api/gql/dataPlanes.ts +++ b/src/api/gql/dataPlanes.ts @@ -1,4 +1,7 @@ -import type { DataPlanesQuery, PublicDataPlanesQuery } from 'src/gql-types/graphql'; +import type { + DataPlanesQuery, + PublicDataPlanesQuery, +} from 'src/gql-types/graphql'; import type { CloudProvider } from 'src/utils/cloudRegions'; import { graphql } from 'src/gql-types'; diff --git a/src/directives/Onboard/DataPlaneSelector.tsx b/src/directives/Onboard/DataPlaneSelector.tsx index a532c51475..117a544ce3 100644 --- a/src/directives/Onboard/DataPlaneSelector.tsx +++ b/src/directives/Onboard/DataPlaneSelector.tsx @@ -58,8 +58,9 @@ function DataPlaneSelector() { useEffect(() => { if (!selected && options.length > 0) { const preferred = - options.find((option) => option.name === DEFAULT_PUBLIC_DATA_PLANE) ?? - options[0]; + options.find( + (option) => option.name === DEFAULT_PUBLIC_DATA_PLANE + ) ?? options[0]; setSelected(preferred.name); } }, [options, selected, setSelected]);