diff --git a/apps/trust/src/components/DocumentRow.tsx b/apps/trust/src/components/DocumentRow.tsx
index edbf2c9bf..0a721499a 100644
--- a/apps/trust/src/components/DocumentRow.tsx
+++ b/apps/trust/src/components/DocumentRow.tsx
@@ -1,5 +1,6 @@
import { downloadFile, formatError } from "@probo/helpers";
import { useTranslate } from "@probo/i18n";
+import { UnAuthenticatedError } from "@probo/relay";
import {
Button,
IconArrowInbox,
@@ -8,12 +9,12 @@ import {
Spinner,
useToast,
} from "@probo/ui";
-import { use, useState } from "react";
+import { useState } from "react";
import { useFragment, useMutation } from "react-relay";
+import { useLocation, useNavigate } from "react-router";
import { graphql } from "relay-runtime";
import { useMutationWithToasts } from "#/hooks/useMutationWithToast";
-import { Viewer } from "#/providers/Viewer";
import type { DocumentRow_requestAccessMutation } from "./__generated__/DocumentRow_requestAccessMutation.graphql";
import type { DocumentRowDownloadMutation } from "./__generated__/DocumentRowDownloadMutation.graphql";
@@ -50,8 +51,9 @@ const documentRowFragment = graphql`
export function DocumentRow(props: { document: DocumentRowFragment$key }) {
const { __ } = useTranslate();
- const viewer = use(Viewer);
const { toast } = useToast();
+ const navigate = useNavigate();
+ const location = useLocation();
const document = useFragment(documentRowFragment, props.document);
const [hasRequested, setHasRequested] = useState(
@@ -87,6 +89,13 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) {
});
},
onError: (error) => {
+ if (error instanceof UnAuthenticatedError) {
+ const searchParams = new URLSearchParams([[
+ "continue", window.location.origin + location.pathname + location.search,
+ ]]);
+ void navigate(`/connect?${searchParams.toString()}`);
+ }
+
toast({
title: __("Error"),
description: error.message ?? __("Cannot request access"),
@@ -127,28 +136,17 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) {
{downloading ? __("Downloading") : __("Download")}
)
- : viewer
- ? (
-
- )
- : (
-
- )}
+ : (
+
+ )}
);
}
diff --git a/apps/trust/src/components/RootErrorBoundary.tsx b/apps/trust/src/components/RootErrorBoundary.tsx
new file mode 100644
index 000000000..d1b2013a0
--- /dev/null
+++ b/apps/trust/src/components/RootErrorBoundary.tsx
@@ -0,0 +1,41 @@
+import { NDASignatureRequiredError, UnAuthenticatedError } from "@probo/relay";
+import { Navigate, useLocation, useRouteError } from "react-router";
+
+import { getPathPrefix } from "#/utils/pathPrefix";
+
+import { PageError } from "./PageError";
+
+export function RootErrorBoundary() {
+ const error = useRouteError();
+ const location = useLocation();
+
+ const search = new URLSearchParams();
+
+ if (location.pathname !== getPathPrefix() || location.search !== "") {
+ search.set("continue", window.location.href);
+ }
+
+ const queryString = search.toString();
+
+ if (error instanceof UnAuthenticatedError) {
+ return (
+
+ );
+ }
+
+ if (error instanceof NDASignatureRequiredError) {
+ return (
+
+ );
+ }
+
+ return ;
+}
diff --git a/apps/trust/src/pages/NDAPage.tsx b/apps/trust/src/pages/NDAPage.tsx
index 4bc0703be..a4b6c30e3 100644
--- a/apps/trust/src/pages/NDAPage.tsx
+++ b/apps/trust/src/pages/NDAPage.tsx
@@ -8,13 +8,14 @@ import {
usePreloadedQuery,
useRefetchableFragment,
} from "react-relay";
-import { Navigate, useNavigate } from "react-router";
+import { Navigate, useSearchParams } from "react-router";
import { graphql } from "relay-runtime";
import { useWindowSize } from "usehooks-ts";
import { z } from "zod";
import { PDFPreview } from "#/components/PDFPreview";
import { useFormWithSchema } from "#/hooks/useFormWithSchema";
+import { getPathPrefix } from "#/utils/pathPrefix";
import type { NDAPageAcceptElectronicSignatureMutation } from "./__generated__/NDAPageAcceptElectronicSignatureMutation.graphql";
import type { NDAPageFragment$key } from "./__generated__/NDAPageFragment.graphql";
@@ -88,8 +89,11 @@ export function NDAPage(props: {
queryRef: PreloadedQuery;
}) {
const { __ } = useTranslate();
- const navigate = useNavigate();
+ const [searchParams] = useSearchParams();
const documentViewedRef = useRef(false);
+ const { width } = useWindowSize();
+ const isMobile = width < 1100;
+ const isDesktop = !isMobile;
const queryData = usePreloadedQuery(ndaPageQuery, props.queryRef);
const trustCenter = queryData.currentTrustCenter;
@@ -101,19 +105,14 @@ export function NDAPage(props: {
);
const ndaSignature = data.nonDisclosureAgreement.viewerSignature;
- const { width } = useWindowSize();
- const isMobile = width < 1100;
- const isDesktop = !isMobile;
-
- const {
- handleSubmit: handleSubmitWrapper,
- register,
- formState,
- } = useFormWithSchema(schema, {
- defaultValues: {
- fullName: viewer?.fullName,
- },
- });
+ const continueUrlParam = searchParams.get("continue");
+ let safeContinueUrl: string;
+ if (continueUrlParam) {
+ const continueUrl = new URL(continueUrlParam);
+ safeContinueUrl = window.location.origin + continueUrl.pathname + continueUrl.search;
+ } else {
+ safeContinueUrl = window.location.origin + getPathPrefix();
+ }
const [acceptSignature, isAccepting] = useMutation(
acceptElectronicSignatureMutation,
@@ -130,11 +129,21 @@ export function NDAPage(props: {
const isFailed = ndaSignature?.status === "FAILED";
const isCompleted = ndaSignature?.status === "COMPLETED";
+ const {
+ handleSubmit: handleSubmitWrapper,
+ register,
+ formState,
+ } = useFormWithSchema(schema, {
+ defaultValues: {
+ fullName: viewer?.fullName,
+ },
+ });
+
useEffect(() => {
if (isCompleted) {
- void navigate("/overview", { replace: true });
+ window.location.href = safeContinueUrl;
}
- }, [isCompleted, navigate]);
+ }, [isCompleted, safeContinueUrl]);
useEffect(() => {
if (!isProcessing) return;
diff --git a/apps/trust/src/providers/RelayProviders.tsx b/apps/trust/src/providers/RelayProviders.tsx
index 7283d8008..7ffae5d3c 100644
--- a/apps/trust/src/providers/RelayProviders.tsx
+++ b/apps/trust/src/providers/RelayProviders.tsx
@@ -70,7 +70,7 @@ const store = new Store(source, {
});
export const consoleEnvironment = new Environment({
- configName: "trust",
+ configName: "compliance-page",
network: Network.create(makeFetchQuery(buildEndpoint())),
store,
});
diff --git a/apps/trust/src/routes.tsx b/apps/trust/src/routes.tsx
index 4595adf58..0401cec4d 100644
--- a/apps/trust/src/routes.tsx
+++ b/apps/trust/src/routes.tsx
@@ -7,7 +7,7 @@ import {
} from "@probo/routes";
import { Fragment } from "react";
import { loadQuery } from "react-relay";
-import { createBrowserRouter, redirect, useRouteError } from "react-router";
+import { createBrowserRouter, redirect } from "react-router";
import { MainLayout } from "#/layouts/MainLayout";
import { DocumentsPage } from "#/pages/DocumentsPage";
@@ -20,19 +20,11 @@ import {
} from "#/queries/TrustGraph";
import { PageError } from "./components/PageError";
+import { RootErrorBoundary } from "./components/RootErrorBoundary";
import { MainSkeleton } from "./components/Skeletons/MainSkeleton";
import { TabSkeleton } from "./components/Skeletons/TabSkeleton";
import { consoleEnvironment } from "./providers/RelayProviders";
-/**
- * Top level error boundary
- */
-function ErrorBoundary() {
- const error = useRouteError();
-
- return ;
-}
-
const routes = [
{
Component: lazy(() => import("#/pages/auth/AuthLayoutLoader")),
@@ -54,12 +46,12 @@ const routes = [
throw redirect("/overview");
},
Component: Fragment,
- ErrorBoundary: ErrorBoundary,
+ ErrorBoundary: RootErrorBoundary,
},
{
path: "/nda",
Component: lazy(() => import("#/pages/NDAPageLoader")),
- ErrorBoundary: ErrorBoundary,
+ ErrorBoundary: RootErrorBoundary,
},
// Custom domain routes (subdomain-based)
{
@@ -69,7 +61,7 @@ const routes = [
),
Component: withQueryRef(MainLayout),
Fallback: MainSkeleton,
- ErrorBoundary: ErrorBoundary,
+ ErrorBoundary: RootErrorBoundary,
children: [
{
path: "",
@@ -85,7 +77,7 @@ const routes = [
),
Component: withQueryRef(MainLayout),
Fallback: MainSkeleton,
- ErrorBoundary: ErrorBoundary,
+ ErrorBoundary: RootErrorBoundary,
children: [
{
path: "",
@@ -104,7 +96,7 @@ const routes = [
),
Component: withQueryRef(MainLayout),
Fallback: MainSkeleton,
- ErrorBoundary: ErrorBoundary,
+ ErrorBoundary: RootErrorBoundary,
children: [
{
path: "",
diff --git a/packages/relay/src/errors.ts b/packages/relay/src/errors.ts
index dadf7b36a..ee15363a5 100644
--- a/packages/relay/src/errors.ts
+++ b/packages/relay/src/errors.ts
@@ -6,6 +6,14 @@ export class UnAuthenticatedError extends Error {
}
}
+export class NDASignatureRequiredError extends Error {
+ constructor(message?: string) {
+ super(message || "NDA_SIGNATURE_REQUIRED");
+ this.name = "NDASignatureRequiredError";
+ Object.setPrototypeOf(this, NDASignatureRequiredError.prototype);
+ }
+}
+
export class InternalServerError extends Error {
constructor() {
super("INTERNAL_SERVER_ERROR");