From 98f6dfc7c28135c66ffe1bb2544732aca7aee812 Mon Sep 17 00:00:00 2001 From: Kacper Wojciechowski <39823706+jog1t@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:11:14 +0100 Subject: [PATCH] fix: invalid group query --- .../components/breadcrumbs/breadcrumbs.tsx | 14 ++++--- .../breadcrumbs/group-breadcrumb.tsx | 4 ++ apps/hub/src/components/error-component.tsx | 29 ++++++++++++++- .../src/components/header/header-sub-nav.tsx | 11 ++---- .../header/links/header-group-links.tsx | 3 ++ .../src/components/not-found-component.tsx | 17 +++++++-- .../domains/project/queries/query-options.tsx | 37 +++++++++++++++---- apps/hub/src/lib/ls.ts | 3 ++ apps/hub/src/queries/global.ts | 1 - .../_authenticated/_layout/teams/$groupId.tsx | 7 +++- 10 files changed, 99 insertions(+), 27 deletions(-) diff --git a/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx b/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx index 981338dc..849dbc62 100644 --- a/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx +++ b/apps/hub/src/components/breadcrumbs/breadcrumbs.tsx @@ -1,7 +1,8 @@ import { useAuth } from "@/domains/auth/contexts/auth"; -import { RestOnRouteChange } from "@/lib/utils"; + import { Skeleton, cn } from "@rivet-gg/components"; -import { CatchBoundary, useMatchRoute } from "@tanstack/react-router"; +import { ErrorBoundary } from "@sentry/react"; +import { useMatchRoute } from "@tanstack/react-router"; import { Suspense, useContext } from "react"; import { EnvironmentBreadcrumb } from "./environment-breadcrumb"; import { GroupBreadcrumb } from "./group-breadcrumb"; @@ -58,9 +59,10 @@ export function Breadcrumbs() { !isMobile && "items-center gap-2", )} > - Date.now()} - errorComponent={RestOnRouteChange} + { + console.log("Error occurred while rendering breadcrumbs.", ...args); + }} > - + ); } diff --git a/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx b/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx index 37fdf789..1ac7eeb8 100644 --- a/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx +++ b/apps/hub/src/components/breadcrumbs/group-breadcrumb.tsx @@ -32,6 +32,10 @@ export function GroupBreadcrumb({ groupId }: GroupBreadcrumbProps) { const Element = isMobile ? NavItem : Fragment; + if (!data) { + return null; + } + return ( + + + + Unauthorized + + + + You are not a member of this group. + + + + + + ); + } if (error.statusCode === 404) { return ; } @@ -65,6 +91,7 @@ export const ErrorComponent = ({ diff --git a/apps/hub/src/domains/project/queries/query-options.tsx b/apps/hub/src/domains/project/queries/query-options.tsx index f6bdef94..bcfd937c 100644 --- a/apps/hub/src/domains/project/queries/query-options.tsx +++ b/apps/hub/src/domains/project/queries/query-options.tsx @@ -1,5 +1,7 @@ +import { isRivetError } from "@/lib/utils"; import { rivetClient, rivetEeClient } from "@/queries/global"; import { getMetaWatchIndex } from "@/queries/utils"; +import { RivetError } from "@rivet-gg/api"; import { loadModuleCategories } from "@rivet-gg/components"; import { queryOptions } from "@tanstack/react-query"; @@ -42,10 +44,31 @@ export const groupsCountQueryOptions = () => { export const groupProjectsQueryOptions = (groupId: string) => { return queryOptions({ - ...projectsByGroupQueryOptions(), - select: (data) => { - // biome-ignore lint/style/noNonNullAssertion: when we get here, we know the group exists - const group = data.groups.find((group) => group.groupId === groupId)!; + queryKey: ["team", groupId, "projects"], + retry(failureCount, error) { + if (isRivetError(error) && error.statusCode === 404) { + return false; + } + return failureCount < 3; + }, + queryFn: async ({ signal, meta }) => { + const data = await rivetClient.cloud.games.getGames( + { + watchIndex: getMetaWatchIndex(meta), + }, + { abortSignal: signal }, + ); + + const group = data.groups.find((group) => group.groupId === groupId); + if (!group) { + throw new RivetError({ + statusCode: 404, + body: { + message: "Group not found", + }, + }); + } + const projects = data.games.filter( (game) => game.developer.groupId === group.groupId, ); @@ -60,16 +83,14 @@ export const groupProjectsQueryOptions = (groupId: string) => { export const groupOnwerQueryOptions = (groupId: string) => { return queryOptions({ ...groupProjectsQueryOptions(groupId), - select: (data) => { - return groupProjectsQueryOptions(groupId).select?.(data).ownerIdentityId; - }, + select: (data) => data.ownerIdentityId, }); }; export const projectsCountQueryOptions = (groupId: string) => { return queryOptions({ ...groupProjectsQueryOptions(groupId), - select: (data) => data.games.length, + select: (data) => data.projects.length, }); }; diff --git a/apps/hub/src/lib/ls.ts b/apps/hub/src/lib/ls.ts index f6078827..07fbd991 100644 --- a/apps/hub/src/lib/ls.ts +++ b/apps/hub/src/lib/ls.ts @@ -11,4 +11,7 @@ export const ls = { remove: (key: LSKey) => { localStorage.removeItem(key); }, + clear: () => { + localStorage.clear(); + }, }; diff --git a/apps/hub/src/queries/global.ts b/apps/hub/src/queries/global.ts index f1697228..af58c460 100644 --- a/apps/hub/src/queries/global.ts +++ b/apps/hub/src/queries/global.ts @@ -56,7 +56,6 @@ const queryCache = new QueryCache({ onError: (error) => { if (isRivetError(error)) { if ( - error.statusCode === 403 || error.body.code === "TOKEN_REVOKED" || error.body.code === "TOKEN_INVALID" ) { diff --git a/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx b/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx index 7637c529..8d924507 100644 --- a/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx +++ b/apps/hub/src/routes/_authenticated/_layout/teams/$groupId.tsx @@ -1,5 +1,6 @@ import { ErrorComponent } from "@/components/error-component"; import * as Layout from "@/domains/project/layouts/group-layout"; +import { groupProjectsQueryOptions } from "@/domains/project/queries"; import { useDialog } from "@/hooks/use-dialog"; import { ls } from "@/lib/ls"; import { @@ -82,7 +83,11 @@ export const Route = createFileRoute("/_authenticated/_layout/teams/$groupId")({ component: GroupIdView, errorComponent: GroupIdErrorComponent, pendingComponent: Layout.Root.Skeleton, - beforeLoad: ({ params: { groupId }, context: { auth } }) => { + beforeLoad: async ({ + params: { groupId }, + context: { auth, queryClient }, + }) => { + await queryClient.ensureQueryData(groupProjectsQueryOptions(groupId)); ls.set(`rivet-lastteam-${auth.profile?.identity.identityId}`, groupId); }, });