Skip to content

Commit 6665121

Browse files
committed
fix: 403 breaking ux (#3081)
1 parent a6d9831 commit 6665121

File tree

13 files changed

+128
-41
lines changed

13 files changed

+128
-41
lines changed

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"@radix-ui/react-toggle-group": "^1.1.11",
5959
"@radix-ui/react-tooltip": "^1.2.8",
6060
"@radix-ui/react-visually-hidden": "^1.2.3",
61-
"@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@7090780",
61+
"@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@bf2ebb2",
6262
"@rivet-gg/icons": "workspace:*",
6363
"@rivetkit/engine-api-full": "workspace:*",
6464
"@sentry/react": "^8.55.0",

frontend/src/app/data-providers/engine-data-provider.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ export const createGlobalContext = (opts: {
7878
return lastPage.pagination.cursor;
7979
},
8080
select: (data) => data.pages.flatMap((page) => page.namespaces),
81+
retry: shouldRetryAllExpect403,
82+
throwOnError: noThrow,
83+
meta: {
84+
mightRequireAuth,
85+
},
8186
});
8287
},
8388
createNamespaceMutationOptions(opts: {

frontend/src/app/inspector-root.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
Route,
2+
CatchBoundary,
33
useNavigate,
44
useRouteContext,
55
useSearch,
@@ -50,7 +50,14 @@ export function InspectorRoot() {
5050
<InspectorCredentialsProvider value={ctxValue}>
5151
<RouteLayout>
5252
<Actors actorId={search.actorId} />
53-
{!search.n ? <BuildPrefiller /> : null}
53+
<CatchBoundary
54+
getResetKey={() =>
55+
search.n?.join(",") ?? "no-build-name"
56+
}
57+
errorComponent={() => null}
58+
>
59+
{!search.n ? <BuildPrefiller /> : null}
60+
</CatchBoundary>
5461
</RouteLayout>
5562
</InspectorCredentialsProvider>
5663
);

frontend/src/app/layout.tsx

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ import {
4141
ScrollArea,
4242
Skeleton,
4343
} from "@/components";
44-
import { useInspectorDataProvider } from "@/components/actors";
44+
import {
45+
useDataProviderCheck,
46+
useInspectorDataProvider,
47+
} from "@/components/actors";
4548
import type { HeaderLinkProps } from "@/components/header/header-link";
4649
import { ensureTrailingSlash } from "@/lib/utils";
4750
import { ActorBuildsList } from "./actor-builds-list";
@@ -388,6 +391,7 @@ const Subnav = () => {
388391
}
389392
: { to: "/", fuzzy: true },
390393
);
394+
const hasDataProvider = useDataProviderCheck();
391395

392396
if (nsMatch === false) {
393397
return null;
@@ -405,12 +409,14 @@ const Subnav = () => {
405409
Connect
406410
</HeaderLink>
407411
) : null}
408-
<div className="w-full">
409-
<span className="block text-muted-foreground text-xs px-2 py-1 transition-colors mb-0.5">
410-
Instances
411-
</span>
412-
<ActorBuildsList />
413-
</div>
412+
{hasDataProvider ? (
413+
<div className="w-full">
414+
<span className="block text-muted-foreground text-xs px-2 py-1 transition-colors mb-0.5">
415+
Instances
416+
</span>
417+
<ActorBuildsList />
418+
</div>
419+
) : null}
414420
</div>
415421
);
416422
};
@@ -535,6 +541,8 @@ function CloudSidebarContent() {
535541
fuzzy: true,
536542
});
537543

544+
const hasDataProvider = useDataProviderCheck();
545+
538546
if (matchNamespace) {
539547
return (
540548
<div className="flex gap-1.5 flex-col">
@@ -546,12 +554,14 @@ function CloudSidebarContent() {
546554
>
547555
Connect
548556
</HeaderLink>
549-
<div className="w-full pt-1.5">
550-
<span className="block text-muted-foreground text-xs px-1 py-1 transition-colors mb-0.5">
551-
Instances
552-
</span>
553-
<ActorBuildsList />
554-
</div>
557+
{hasDataProvider ? (
558+
<div className="w-full pt-1.5">
559+
<span className="block text-muted-foreground text-xs px-1 py-1 transition-colors mb-0.5">
560+
Instances
561+
</span>
562+
<ActorBuildsList />
563+
</div>
564+
) : null}
555565
</div>
556566
);
557567
}

frontend/src/components/actors/data-provider.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {
22
type RegisteredRouter,
33
type RouteIds,
4+
useMatches,
5+
useMatchRoute,
46
useRouteContext,
57
} from "@tanstack/react-router";
68
import { match } from "ts-pattern";
@@ -34,6 +36,26 @@ export const useDataProvider = () =>
3436
})
3537
.exhaustive();
3638

39+
export const useDataProviderCheck = () => {
40+
const matchRoute = useMatchRoute();
41+
42+
return matchRoute({
43+
to: match(__APP_TYPE__)
44+
.with("cloud", () => {
45+
return "/orgs/$organization/projects/$project/ns/$namespace" as const;
46+
})
47+
.with("engine", () => {
48+
return "/ns/$namespace" as const;
49+
})
50+
.with("inspector", () => {
51+
return "/" as const;
52+
})
53+
.otherwise(() => {
54+
throw new Error("Not in a valid context");
55+
}),
56+
});
57+
};
58+
3759
export const useEngineDataProvider = () => {
3860
return useRouteContext({
3961
from: "/_context/_engine",

frontend/src/components/hooks/use-dialog.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,24 @@ export const createDialogHook = <
4646

4747
return (
4848
<IsInModalContext.Provider value={true}>
49-
<Dialog {...dialogProps}>
49+
<Dialog
50+
{...dialogProps}
51+
onOpenChange={
52+
props.dismissible
53+
? () => {}
54+
: props.dialogProps?.onOpenChange
55+
}
56+
>
5057
<DialogContent
5158
{...dialogContentProps}
59+
hideClose={
60+
props.dismissible === false ||
61+
dialogContentProps?.hideClose
62+
}
63+
disableOutsidePointerEvents={
64+
props.dismissible === false ||
65+
dialogContentProps?.disableOutsidePointerEvents
66+
}
5267
onOpenAutoFocus={(e) => {
5368
if (opts.autoFocus === false) {
5469
return e.preventDefault();

frontend/src/components/modal-renderer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function ModalRenderer() {
3434

3535
function getDialogComponent(dialogKey: string) {
3636
const dialogs = useDialog;
37-
const dialog = dialogs[dialogKey];
37+
const dialog = dialogs[dialogKey as keyof typeof dialogs];
3838

3939
if (!dialog || typeof dialog !== "function") {
4040
return null;

frontend/src/queries/global.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const queryCache = new QueryCache({
1515
"statusCode" in error &&
1616
error.statusCode === 403
1717
) {
18-
modal.open("ProvideEngineCredentials");
18+
modal.open("ProvideEngineCredentials", { dismissible: false });
1919
return;
2020
}
2121
},

frontend/src/routes/_context.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const Route = createFileRoute("/_context")({
4343
return match(__APP_TYPE__)
4444
.with("engine", () => ({
4545
dataProvider: createGlobalEngineContext({
46-
engineToken:
46+
engineToken: () =>
4747
ls.engineCredentials.get(getConfig().apiUrl) || "",
4848
}),
4949
__type: "engine" as const,

frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ export function RouteComponent() {
4545
<>
4646
<CatchBoundary getResetKey={() => actorId ?? "no-actor-id"}>
4747
<Actors actorId={actorId} />
48-
{!n ? <BuildPrefiller /> : null}
48+
<CatchBoundary
49+
getResetKey={() => n?.join(",") ?? "no-build-name"}
50+
errorComponent={() => null}
51+
>
52+
{!n ? <BuildPrefiller /> : null}
53+
</CatchBoundary>
4954
</CatchBoundary>
5055
</>
5156
);

0 commit comments

Comments
 (0)