Skip to content

Commit 0ac4640

Browse files
Console 1383 open non existing schema version results in infinite loading (#7316)
1 parent 114cd80 commit 0ac4640

File tree

14 files changed

+91
-66
lines changed

14 files changed

+91
-66
lines changed

packages/web/app/src/components/admin/AdminStats.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { CHART_PRIMARY_COLOR } from '@/constants';
2626
import { env } from '@/env/frontend';
2727
import { DocumentType, FragmentType, graphql, useFragment } from '@/gql';
2828
import { theme } from '@/lib/charts';
29-
import { useChartStyles } from '@/utils';
29+
import { useChartStyles } from '@/lib/utils';
3030
import { ChevronUpIcon } from '@radix-ui/react-icons';
3131
import {
3232
createColumnHelper,

packages/web/app/src/components/common/not-found-content.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,27 @@ import ghost from '../../../public/images/figures/ghost.svg?url';
22
import { useRouter } from '@tanstack/react-router';
33
import { Button } from '../ui/button';
44

5-
export function NotFoundContent(props: { heading: React.ReactNode; subheading: React.ReactNode }) {
5+
export function NotFoundContent({
6+
heading,
7+
subheading,
8+
includeBackButton = true,
9+
}: {
10+
heading: React.ReactNode;
11+
subheading: React.ReactNode;
12+
includeBackButton?: boolean;
13+
}) {
614
const router = useRouter();
715

816
return (
917
<div className="flex h-full flex-1 flex-col items-center justify-center gap-2.5 py-6">
1018
<img src={ghost} alt="Ghost illustration" width="200" height="200" className="drag-none" />
11-
<h2 className="text-xl font-bold">{props.heading}</h2>
12-
<h3 className="font-semibold">{props.subheading}</h3>
13-
<Button variant="secondary" className="mt-2" onClick={router.history.back}>
14-
Go back
15-
</Button>
19+
<h2 className="text-xl font-bold">{heading}</h2>
20+
<h3 className="font-semibold">{subheading}</h3>
21+
{includeBackButton && (
22+
<Button variant="secondary" className="mt-2" onClick={router.history.back}>
23+
Go back
24+
</Button>
25+
)}
1626
</div>
1727
);
1828
}

packages/web/app/src/components/organization/Permissions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
1010
import { OrganizationAccessScope, ProjectAccessScope, TargetAccessScope } from '@/gql/graphql';
1111
import { NoAccess, Scope } from '@/lib/access/common';
12-
import { truthy } from '@/utils';
12+
import { truthy } from '@/lib/utils';
1313

1414
function isLowerThen<T>(targetScope: T, sourceScope: T, scopesInLowerToHigherOrder: readonly T[]) {
1515
const sourceIndex = scopesInLowerToHigherOrder.indexOf(sourceScope);

packages/web/app/src/components/target/explorer/common.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
77
import { Markdown } from '@/components/v2/markdown';
88
import { FragmentType, graphql, useFragment } from '@/gql';
99
import { formatNumber, toDecimal } from '@/lib/hooks';
10-
import { cn } from '@/lib/utils';
11-
import { capitalize } from '@/utils';
10+
import { capitalize, cn } from '@/lib/utils';
1211
import { Link as NextLink, useRouter } from '@tanstack/react-router';
1312
import { useDescriptionsVisibleToggle } from './provider';
1413
import { SupergraphMetadataList } from './super-graph-metadata';

packages/web/app/src/components/target/insights/Stats.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
useFormattedThroughput,
2929
} from '@/lib/hooks';
3030
import { pick } from '@/lib/object';
31-
import { useChartStyles } from '@/utils';
31+
import { useChartStyles } from '@/lib/utils';
3232
import { useRouter } from '@tanstack/react-router';
3333
import { OperationsFallback } from './Fallback';
3434
import { resolutionToMilliseconds } from './utils';

packages/web/app/src/components/ui/copy-text.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function CopyText(props: { children: ReactNode; copy?: string; className?
1515
</div>
1616
<TooltipProvider delayDuration={0}>
1717
<Tooltip>
18-
<TooltipTrigger>
18+
<TooltipTrigger asChild>
1919
<Button
2020
className="invisible -my-3 p-2 py-3 group-hover:visible"
2121
variant="link"

packages/web/app/src/lib/utils.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
import { clsx, type ClassValue } from 'clsx';
22
import { twMerge } from 'tailwind-merge';
33

4+
// Style-related
45
export function cn(...inputs: ClassValue[]) {
56
return twMerge(clsx(inputs));
67
}
78

9+
const darkChartStyles = {
10+
backgroundColor: 'transparent',
11+
textStyle: { color: '#fff' },
12+
legend: {
13+
textStyle: { color: '#fff' },
14+
},
15+
};
16+
17+
export function useChartStyles() {
18+
return darkChartStyles;
19+
}
20+
21+
// Strings
822
export function pluralize(count: number, singular: string, plural: string): string {
923
if (count === 1) {
1024
return singular;
@@ -13,8 +27,24 @@ export function pluralize(count: number, singular: string, plural: string): stri
1327
return plural;
1428
}
1529

30+
export function capitalize(str: string) {
31+
return str.charAt(0).toUpperCase() + str.slice(1);
32+
}
33+
34+
// Errors
1635
export function exhaustiveGuard(_value: never): never {
1736
throw new Error(
1837
`Reached forbidden guard function with unexpected value: ${JSON.stringify(_value)}`,
1938
);
2039
}
40+
41+
// Validation
42+
export function isValidUUID(value: string): boolean {
43+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
44+
}
45+
46+
type Truthy<T> = T extends false | '' | 0 | null | undefined ? never : T; // from lodash
47+
48+
export function truthy<T>(value: T): value is Truthy<T> {
49+
return !!value;
50+
}

packages/web/app/src/pages/organization-subscription.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Card } from '@/components/v2/card';
1818
import Stat from '@/components/v2/stat';
1919
import { graphql, useFragment } from '@/gql';
2020
import { formatNumber } from '@/lib/hooks';
21-
import { useChartStyles } from '@/utils';
21+
import { useChartStyles } from '@/lib/utils';
2222
import { Link } from '@tanstack/react-router';
2323

2424
const DateFormatter = Intl.DateTimeFormat('en-US', {

packages/web/app/src/pages/target-history-version.tsx

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ReactElement, useMemo, useState } from 'react';
22
import { CheckIcon, GitCompareIcon } from 'lucide-react';
33
import { useQuery } from 'urql';
4+
import { NotFoundContent } from '@/components/common/not-found-content';
45
import {
56
ChangesBlock,
67
CompositionErrorsSection,
@@ -15,7 +16,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
1516
import { DiffEditor, TimeAgo } from '@/components/v2';
1617
import { FragmentType, graphql, useFragment } from '@/gql';
1718
import { ProjectType, SeverityLevelType } from '@/gql/graphql';
18-
import { cn } from '@/lib/utils';
19+
import { cn, isValidUUID } from '@/lib/utils';
1920
import {
2021
CheckCircledIcon,
2122
CrossCircledIcon,
@@ -242,15 +243,11 @@ const DefaultSchemaVersionView_SchemaVersionFragment = graphql(`
242243
log {
243244
... on PushedSchemaLog {
244245
id
245-
author
246-
service
247-
commit
248246
serviceSdl
249247
previousServiceSdl
250248
}
251249
... on DeletedSchemaLog {
252250
id
253-
deletedService
254251
previousServiceSdl
255252
}
256253
}
@@ -443,9 +440,6 @@ function DefaultSchemaVersionView(props: {
443440
const ContractVersionView_ContractVersionFragment = graphql(`
444441
fragment ContractVersionView_ContractVersionFragment on ContractVersion {
445442
id
446-
contractName
447-
isComposable
448-
hasSchemaChanges
449443
isFirstComposableVersion
450444
supergraphSDL
451445
compositeSchemaSDL
@@ -640,6 +634,8 @@ function ActiveSchemaVersion(props: {
640634
projectSlug: string;
641635
targetSlug: string;
642636
}) {
637+
const isValidVersionId = isValidUUID(props.versionId);
638+
643639
const [query] = useQuery({
644640
query: ActiveSchemaVersion_SchemaVersionQuery,
645641
variables: {
@@ -648,6 +644,7 @@ function ActiveSchemaVersion(props: {
648644
targetSlug: props.targetSlug,
649645
versionId: props.versionId,
650646
},
647+
pause: !isValidVersionId,
651648
});
652649

653650
const { error } = query;
@@ -657,7 +654,28 @@ function ActiveSchemaVersion(props: {
657654
const schemaVersion = project?.target?.schemaVersion;
658655
const projectType = query.data?.project?.type;
659656

660-
if (isLoading || !schemaVersion || !projectType) {
657+
// Order of these conditionals is important...relocate carefully!
658+
if (!isValidVersionId) {
659+
return (
660+
<NotFoundContent
661+
heading="Invalid version ID"
662+
subheading="The provided version ID is not a valid UUID format."
663+
includeBackButton={false}
664+
/>
665+
);
666+
}
667+
668+
if (!isLoading && !schemaVersion) {
669+
return (
670+
<NotFoundContent
671+
heading="Version ID does not exist"
672+
subheading="The provided version ID is not in our database."
673+
includeBackButton={false}
674+
/>
675+
);
676+
}
677+
678+
if (isLoading || !projectType) {
661679
return (
662680
<div className="flex size-full flex-col items-center justify-center self-center text-sm text-gray-500">
663681
<Spinner className="mb-3 size-8" />

packages/web/app/src/pages/target-history.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ const HistoryPage_VersionsPageQuery = graphql(`
4949
deletedService
5050
}
5151
}
52-
baseSchema
5352
githubMetadata {
5453
repository
5554
commit

0 commit comments

Comments
 (0)