Skip to content

Commit fd4bd44

Browse files
emmaling27Convex, Inc.
authored andcommitted
[dashboard] Show progress bar for schema validation (#40656)
Adds a progress bar to the dashboard for showing schema validation progress. <img width="987" height="739" alt="Screenshot 2025-09-04 at 5 17 41 PM" src="https://github.com/user-attachments/assets/8a24b558-57e5-41cf-a454-fc60620967a7" /> GitOrigin-RevId: 3e6e773f066e65a4085277866a6b468cea91ff4c
1 parent 58b14af commit fd4bd44

File tree

5 files changed

+81
-30
lines changed

5 files changed

+81
-30
lines changed

npm-packages/@convex-dev/design-system/src/ProgressBar.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,28 @@ export function ProgressBar({
4747
</div>
4848
);
4949
}
50+
51+
export function ProgressBarWithPercent({
52+
fraction,
53+
variant,
54+
ariaLabel,
55+
}: {
56+
fraction: number;
57+
variant: "stripes" | "solid";
58+
ariaLabel: string;
59+
}) {
60+
const percent = Math.round(fraction * 100);
61+
return (
62+
<div className="flex items-center gap-3">
63+
<ProgressBar
64+
fraction={fraction}
65+
ariaLabel={ariaLabel}
66+
variant={variant}
67+
className="grow"
68+
/>
69+
<span className="min-w-[4ch] text-right text-xs text-content-tertiary tabular-nums">
70+
{percent}%
71+
</span>
72+
</div>
73+
);
74+
}

npm-packages/dashboard-common/src/features/data/components/DataView.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ export function DataView() {
3535
componentId: componentId ?? null,
3636
});
3737

38+
const schemaValidationProgress = useQuery(
39+
udfs.getSchemas.schemaValidationProgress,
40+
{
41+
componentId: useNents().selectedNent?.id ?? null,
42+
},
43+
);
44+
3845
const { activeSchema, inProgressSchema } = useMemo(() => {
3946
if (!schemas) return {};
4047

@@ -80,6 +87,7 @@ export function DataView() {
8087
inProgressSchema={inProgressSchema}
8188
shapes={tables}
8289
hasShapeError={hadError}
90+
schemaValidationProgress={schemaValidationProgress}
8391
/>
8492
</Modal>
8593
)}

npm-packages/dashboard-common/src/features/data/components/IndexList.tsx

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Spinner } from "@ui/Spinner";
1212
import { useQuery } from "convex/react";
1313
import { api } from "system-udfs/convex/_generated/api";
1414
import { Fragment } from "react";
15-
import { ProgressBar } from "@ui/ProgressBar";
15+
import { ProgressBarWithPercent } from "@ui/ProgressBar";
1616
import { Tooltip } from "@ui/Tooltip";
1717
import { cn } from "@ui/cn";
1818
import { Callout } from "@ui/Callout";
@@ -241,7 +241,7 @@ function IndexListRow({ index }: { index: Index }) {
241241
Backfill in progress
242242
</div>
243243
{index.backfill.stats && index.backfill.stats.totalDocs !== null && (
244-
<IndexBackfillProgress
244+
<ProgressBarWithPercent
245245
fraction={Math.min(
246246
// numDocsIndexed is an estimate and can grow larger than totalDocs
247247
// (in particular because if new documents are added during the backfill,
@@ -251,14 +251,19 @@ function IndexListRow({ index }: { index: Index }) {
251251
index.backfill.stats.totalDocs,
252252
)}
253253
variant="stripes"
254+
ariaLabel="Index backfill progress"
254255
/>
255256
)}
256257
</div>
257258
)}
258259
{index.backfill.state === "backfilled" && (
259260
<div className="flex flex-col gap-1 pl-2">
260261
Backfill completed
261-
<IndexBackfillProgress fraction={1} variant="solid" />
262+
<ProgressBarWithPercent
263+
fraction={1}
264+
variant="solid"
265+
ariaLabel="Index backfill progress"
266+
/>
262267
</div>
263268
)}
264269
</article>
@@ -294,29 +299,6 @@ function FieldList({ fields }: { fields: string[] }) {
294299
);
295300
}
296301

297-
function IndexBackfillProgress({
298-
fraction,
299-
variant,
300-
}: {
301-
fraction: number;
302-
variant: "stripes" | "solid";
303-
}) {
304-
const percent = Math.round(fraction * 100);
305-
return (
306-
<div className="flex items-center gap-3">
307-
<ProgressBar
308-
fraction={fraction}
309-
ariaLabel="Index backfill progress"
310-
variant={variant}
311-
className="grow"
312-
/>
313-
<span className="min-w-[4ch] text-right text-xs text-content-tertiary tabular-nums">
314-
{percent}%
315-
</span>
316-
</div>
317-
);
318-
}
319-
320302
function getIndexType(
321303
index: Index,
322304
): "database" | "search" | "vector" | "unknown" {

npm-packages/dashboard-common/src/features/data/components/ShowSchema.stories.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,13 @@ export const EnforcedSchema: Story = {
9292
activeSchema: sampleSchema,
9393
},
9494
};
95+
96+
export const SchemaValidationInProgress: Story = {
97+
args: {
98+
inProgressSchema: sampleSchema,
99+
schemaValidationProgress: {
100+
numDocsValidated: 1,
101+
totalDocs: 2,
102+
},
103+
},
104+
};

npm-packages/dashboard-common/src/features/data/components/ShowSchema.tsx

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { SchemaJson, displaySchema } from "@common/lib/format";
1212
import { ReadonlyCode } from "@common/elements/ReadonlyCode";
1313
import { Spinner } from "@ui/Spinner";
14+
import { ProgressBarWithPercent } from "@ui/ProgressBar";
1415

1516
export function ShowSchema({
1617
activeSchema,
@@ -20,6 +21,7 @@ export function ShowSchema({
2021
lineHighlighter = undefined,
2122
codeTransformation = (code) => code,
2223
showLearnMoreLink = true,
24+
schemaValidationProgress = undefined,
2325
}: {
2426
activeSchema: SchemaJson | null | undefined;
2527
inProgressSchema: SchemaJson | null | undefined;
@@ -28,6 +30,10 @@ export function ShowSchema({
2830
lineHighlighter?: LineHighlighter;
2931
codeTransformation?: CodeTransformation;
3032
showLearnMoreLink?: boolean;
33+
schemaValidationProgress?: {
34+
numDocsValidated: number;
35+
totalDocs: number | null;
36+
} | null;
3137
}) {
3238
const displayedSchema = useMemo(() => {
3339
if (!activeSchema) {
@@ -87,10 +93,30 @@ export function ShowSchema({
8793

8894
{inProgressSchema && (
8995
<div className="mt-4 flex items-center gap-1 text-sm text-content-secondary">
90-
<div>
91-
<Spinner />
92-
</div>{" "}
93-
Code push in progress...
96+
{!schemaValidationProgress && (
97+
<div>
98+
<Spinner />
99+
</div>
100+
)}
101+
{schemaValidationProgress
102+
? "Schema validation in progress..."
103+
: "Code push in progress..."}
104+
{schemaValidationProgress &&
105+
schemaValidationProgress.totalDocs !== null && (
106+
<div className="grow sm:px-6">
107+
<ProgressBarWithPercent
108+
// totalDocs is not necessarily taken from the same snapshot as the snapshot being iterated over to increment numDocsValidated
109+
// so we cap the progress at 99%
110+
fraction={Math.min(
111+
0.99,
112+
schemaValidationProgress.numDocsValidated /
113+
schemaValidationProgress.totalDocs,
114+
)}
115+
variant="stripes"
116+
ariaLabel="Schema validation progress"
117+
/>
118+
</div>
119+
)}
94120
</div>
95121
)}
96122
</HeadlessTab.Panel>

0 commit comments

Comments
 (0)