diff --git a/app/graphql/types/client_configuration_type.rb b/app/graphql/types/client_configuration_type.rb
index 7c1dc8ac12..249230d34b 100644
--- a/app/graphql/types/client_configuration_type.rb
+++ b/app/graphql/types/client_configuration_type.rb
@@ -1,14 +1,14 @@
class Types::ClientConfigurationType < Types::BaseObject
description "Client-side configuration values needed for frontend initialization"
- field :rails_default_active_storage_service_name, String, null: false,
- description: "The default Active Storage service name configured in Rails"
+ field :rails_default_active_storage_service_name,
+ String,
+ null: false,
+ description: "The default Active Storage service name configured in Rails"
# rubocop:disable GraphQL/ExtractType
- field :rails_direct_uploads_url, String, null: false,
- description: "The URL endpoint for Rails Direct Uploads"
+ field :rails_direct_uploads_url, String, null: false, description: "The URL endpoint for Rails Direct Uploads"
# rubocop:enable GraphQL/ExtractType
- field :recaptcha_site_key, String, null: false,
- description: "The reCAPTCHA site key for client-side verification"
+ field :recaptcha_site_key, String, null: false, description: "The reCAPTCHA site key for client-side verification"
def rails_default_active_storage_service_name
Rails.application.config.active_storage.service.to_s
diff --git a/app/javascript/AppWrapper.tsx b/app/javascript/AppWrapper.tsx
index 01955c3156..8558a3b91e 100644
--- a/app/javascript/AppWrapper.tsx
+++ b/app/javascript/AppWrapper.tsx
@@ -1,5 +1,4 @@
import { Suspense, useCallback, useRef, useEffect, ReactNode, useState, useMemo, useContext } from 'react';
-import * as React from 'react';
import { Outlet } from 'react-router';
import { i18n } from 'i18next';
import { I18nextProvider } from 'react-i18next';
@@ -75,37 +74,35 @@ export function ProviderStack(props: AppWrapperProps) {
);
return (
-
-
-
- {/* TODO bring this back when we re-add prompting getUserConfirmation={getUserConfirmation}> */}
-
- <>
- {!unauthenticatedError && (
- }>
-
- {(i18nInstance) => (
-
-
- DateTime.now().minus(Duration.fromMillis(timeAgo.milliseconds)).toRelative()
- }
- >
-
-
-
-
-
- )}
-
-
- )}
-
- >
-
-
-
-
+
+
+ {/* TODO bring this back when we re-add prompting getUserConfirmation={getUserConfirmation}> */}
+
+ <>
+ {!unauthenticatedError && (
+ }>
+
+ {(i18nInstance) => (
+
+
+ DateTime.now().minus(Duration.fromMillis(timeAgo.milliseconds)).toRelative()
+ }
+ >
+
+
+
+
+
+ )}
+
+
+ )}
+
+ >
+
+
+
);
}
diff --git a/app/javascript/packs/application.tsx b/app/javascript/packs/application.tsx
index 533e95fe24..3aa5af2d80 100644
--- a/app/javascript/packs/application.tsx
+++ b/app/javascript/packs/application.tsx
@@ -7,7 +7,6 @@ import AuthenticityTokensManager, {
getAuthenticityTokensURL,
} from 'AuthenticityTokensContext';
import { createBrowserRouter, RouterContextProvider, RouterProvider } from 'react-router';
-import { ProviderStack } from 'AppWrapper';
import { buildBrowserApolloClient } from 'useIntercodeApolloClient';
import {
apolloClientContext,
@@ -26,13 +25,13 @@ const refreshPromise = manager.refresh();
export type DataModeApplicationEntryProps = {
recaptchaSiteKey: string;
railsDefaultActiveStorageServiceName: string;
- railsDirectUploadsURL: string;
+ railsDirectUploadsUrl: string;
};
function DataModeApplicationEntry({
recaptchaSiteKey,
railsDefaultActiveStorageServiceName,
- railsDirectUploadsURL,
+ railsDirectUploadsUrl,
}: DataModeApplicationEntryProps) {
use(refreshPromise);
@@ -45,10 +44,10 @@ function DataModeApplicationEntry({
__typename: 'ClientConfiguration',
recaptcha_site_key: recaptchaSiteKey,
rails_default_active_storage_service_name: railsDefaultActiveStorageServiceName,
- rails_direct_uploads_url: railsDirectUploadsURL,
+ rails_direct_uploads_url: railsDirectUploadsUrl,
},
}),
- [recaptchaSiteKey, railsDefaultActiveStorageServiceName, railsDirectUploadsURL],
+ [recaptchaSiteKey, railsDefaultActiveStorageServiceName, railsDirectUploadsUrl],
);
const router = useMemo(
@@ -56,7 +55,7 @@ function DataModeApplicationEntry({
createBrowserRouter(
[
{
- Component: ProviderStack,
+ lazy: () => import('root'),
children: appRootRoutes,
},
],
diff --git a/app/javascript/root.tsx b/app/javascript/root.tsx
index 47fc9e6dc8..80d39c0596 100644
--- a/app/javascript/root.tsx
+++ b/app/javascript/root.tsx
@@ -1,14 +1,24 @@
import { ApolloProvider } from '@apollo/client/react';
+import { authenticityTokensManagerContext, clientConfigurationDataContext } from 'AppContexts';
import { ProviderStack } from 'AppWrapper';
-import AuthenticityTokensManager, {
- AuthenticityTokensContext,
- getAuthenticityTokensURL,
-} from 'AuthenticityTokensContext';
+import AuthenticityTokensManager, { AuthenticityTokensContext } from 'AuthenticityTokensContext';
import { ClientConfiguration } from 'graphqlTypes.generated';
-import { StrictMode, useContext, useMemo } from 'react';
-import { useLoaderData } from 'react-router';
+import { StrictMode, useMemo } from 'react';
+import { LoaderFunction, useLoaderData } from 'react-router';
+import { ClientConfigurationQueryData } from 'serverQueries.generated';
import { buildBrowserApolloClient } from 'useIntercodeApolloClient';
+type RootLoaderData = {
+ clientConfigurationData: ClientConfigurationQueryData;
+ authenticityTokensManager: AuthenticityTokensManager;
+};
+
+export const loader: LoaderFunction = ({ context }) => {
+ const clientConfigurationData = context.get(clientConfigurationDataContext);
+ const authenticityTokensManager = context.get(authenticityTokensManagerContext);
+ return { clientConfigurationData, authenticityTokensManager } satisfies RootLoaderData;
+};
+
function RootProviderStack({ clientConfiguration }: { clientConfiguration: ClientConfiguration }) {
return (
buildBrowserApolloClient(manager), [manager]);
-
- return (
-
-
-
+export default function Root() {
+ const loaderData = useLoaderData() as RootLoaderData;
+ const client = useMemo(
+ () => buildBrowserApolloClient(loaderData.authenticityTokensManager),
+ [loaderData.authenticityTokensManager],
);
-}
-
-export function ClientEntry() {
- const manager = useMemo(() => new AuthenticityTokensManager(fetch, undefined, getAuthenticityTokensURL()), []);
return (
-
-
+
+
+
+
);
}
+
+export const Component = Root;