Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion frontend/src/utils/helpers/apolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { GRAPHQL_URL } from 'utils/env.client'
import { getCsrfToken } from 'utils/utility'
const createApolloClient = () => {
if (!GRAPHQL_URL) {
const error = new AppError(500, 'Missing GraphQL URL')
const error = new AppError(
500,
'GraphQL client configuration is missing. Set NEXT_PUBLIC_GRAPHQL_URL and ensure the backend GraphQL service is running.'
)
handleAppError(error)
Comment thread
Saurabh-2607 marked this conversation as resolved.
Outdated
return null
}
Expand Down
93 changes: 82 additions & 11 deletions frontend/src/wrappers/provider.tsx
Comment thread
Saurabh-2607 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
'use client'
import { ApolloProvider } from '@apollo/client/react'
import { HeroUIProvider, ToastProvider } from '@heroui/react'
import { addToast } from '@heroui/toast'
import { useDjangoSession } from 'hooks/useDjangoSession'
import { SessionProvider } from 'next-auth/react'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import React, { Suspense } from 'react'
import apolloClient from 'utils/helpers/apolloClient'
import { ENVIRONMENT, GRAPHQL_URL } from 'utils/env.client'
import { getCsrfToken } from 'utils/utility'

// <AppInitializer> is a component that initializes the Django session.
// It ensures the session is synced with Django when the app starts.
Expand All @@ -22,24 +25,92 @@
}: Readonly<{
children: React.ReactNode
}>) {
if (!apolloClient) {
return (
<div className="flex min-h-screen items-center justify-center text-red-500">
Configuration Error: GraphQL Client failed to initialize
</div>
)
}
const isProduction = ENVIRONMENT === 'production'
const [isGraphQLEndpointUnreachable, setIsGraphQLEndpointUnreachable] = React.useState(false)
const lastToastMessageRef = React.useRef<string | null>(null)
Comment thread
Saurabh-2607 marked this conversation as resolved.
Outdated

React.useEffect(() => {
if (!apolloClient || !GRAPHQL_URL) {
return
}
const graphqlUrl = GRAPHQL_URL

const abortController = new AbortController()


const verifyGraphQLEndpoint = async () => {
try {
const csrfToken = await getCsrfToken()
const response = await fetch(graphqlUrl, {
body: JSON.stringify({ query: 'query { __typename }' }),
credentials: 'include',
headers: {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
method: 'POST',
signal: abortController.signal,
})
Comment thread
coderabbitai[bot] marked this conversation as resolved.

if (!response.ok) {
setIsGraphQLEndpointUnreachable(true)
return
}

setIsGraphQLEndpointUnreachable(false)
} catch {
if (!abortController.signal.aborted) {
setIsGraphQLEndpointUnreachable(true)
}
}
}

void verifyGraphQLEndpoint()

return () => {
abortController.abort()
}
}, [])

const graphQLErrorMessage = !apolloClient

Check warning on line 75 in frontend/src/wrappers/provider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unexpected negated condition.

See more on https://sonarcloud.io/project/issues?id=OWASP_Nest&issues=AZ0h87yIGkojc2Dthl4n&open=AZ0h87yIGkojc2Dthl4n&pullRequest=4361
? isProduction
? 'Something went wrong'
: 'GraphQL client setup required. Ensure backend is running and GraphQL environment variables are configured.'

Check warning on line 78 in frontend/src/wrappers/provider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=OWASP_Nest&issues=AZ0h87yIGkojc2Dthl4q&open=AZ0h87yIGkojc2Dthl4q&pullRequest=4361
: isGraphQLEndpointUnreachable
? isProduction
? 'Something went wrong'
: 'GraphQL endpoint is unreachable. Ensure the backend service is running and NEXT_PUBLIC_GRAPHQL_URL is correct.'

Check warning on line 82 in frontend/src/wrappers/provider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=OWASP_Nest&issues=AZ0h87yIGkojc2Dthl4o&open=AZ0h87yIGkojc2Dthl4o&pullRequest=4361
: null

Check warning on line 83 in frontend/src/wrappers/provider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=OWASP_Nest&issues=AZ0h87yIGkojc2Dthl4p&open=AZ0h87yIGkojc2Dthl4p&pullRequest=4361

React.useEffect(() => {
if (!graphQLErrorMessage || lastToastMessageRef.current === graphQLErrorMessage) {
return
}

addToast({
color: 'danger',
description: graphQLErrorMessage,
shouldShowTimeoutProgress: true,
timeout: 5000,
title: 'Configuration Error',
variant: 'solid',
})

lastToastMessageRef.current = graphQLErrorMessage
}, [graphQLErrorMessage])

return (
<Suspense>
<SessionProvider>
<HeroUIProvider>
<NextThemesProvider attribute="class" defaultTheme="dark">
<ToastProvider />
<ApolloProvider client={apolloClient}>
<AppInitializer />
{children}
</ApolloProvider>
{apolloClient ? (
<ApolloProvider client={apolloClient}>
<AppInitializer />
{children}
</ApolloProvider>
) : null}
</NextThemesProvider>
</HeroUIProvider>
</SessionProvider>
Expand Down