Skip to content

Commit 52acb66

Browse files
emmaling27Convex, Inc.
authored andcommitted
Index backfill progress UI (#39191)
Adds UI for showing index backfill progress. https://github.com/user-attachments/assets/2890b316-3dc7-4075-8121-5e251d8ea8b6 GitOrigin-RevId: d0276f60686437855c8783e8316810377ba1b00f
1 parent 5db78ca commit 52acb66

File tree

6 files changed

+56
-19
lines changed

6 files changed

+56
-19
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export function DataContent({
185185
const indexes =
186186
useQuery(api._system.frontend.indexes.default, {
187187
tableName,
188-
tableNamespace: selectedNent?.id ? selectedNent.id : null,
188+
tableNamespace: selectedNent?.id ?? null,
189189
}) ?? undefined;
190190
const sortField =
191191
(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export function DataFilters({
8181
const indexes =
8282
useQuery(api._system.frontend.indexes.default, {
8383
tableName,
84-
tableNamespace: selectedNent?.id ? selectedNent.id : null,
84+
tableNamespace: selectedNent?.id ?? null,
8585
}) ?? undefined;
8686
const {
8787
isDirty,

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

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import { Index } from "@common/features/data/lib/api";
3-
import { Spinner } from "@ui/Spinner";
43
import { Tooltip } from "@ui/Tooltip";
4+
import { ProgressBar } from "@ui/ProgressBar";
55
import { useQuery } from "convex/react";
66
import { api } from "system-udfs/convex/_generated/api";
77
import { useNents } from "@common/lib/useNents";
@@ -18,11 +18,19 @@ function IndexRow({ index }: { index: Index }) {
1818
</td>
1919
<td className="ml-auto w-full py-2 text-sm text-content-secondary">
2020
{index.backfill.state !== "done" ? (
21-
<Tooltip tip="This index is currently backfilling, and is not yet ready to use.">
22-
<span className="h-5 w-5">
23-
<Spinner />
24-
</span>
25-
</Tooltip>
21+
<div className="flex items-center gap-2">
22+
<Tooltip tip="This index is currently backfilling, and is not yet ready to use.">
23+
{index.backfill.stats?.totalDocs !== null &&
24+
index.backfill.stats?.totalDocs !== undefined &&
25+
index.backfill.stats?.totalDocs > 0 &&
26+
index.backfill.stats?.numDocsIndexed !== undefined && (
27+
<IndexBackfillProgress
28+
numDocsIndexed={index.backfill.stats.numDocsIndexed}
29+
totalDocs={index.backfill.stats.totalDocs}
30+
/>
31+
)}
32+
</Tooltip>
33+
</div>
2634
) : (
2735
type
2836
)}
@@ -31,6 +39,28 @@ function IndexRow({ index }: { index: Index }) {
3139
);
3240
}
3341

42+
function IndexBackfillProgress({
43+
numDocsIndexed,
44+
totalDocs,
45+
}: {
46+
numDocsIndexed: number;
47+
totalDocs: number;
48+
}) {
49+
const fraction = Math.min(numDocsIndexed / totalDocs, 0.99);
50+
const percent = Math.round(fraction * 100);
51+
return (
52+
<div className="flex items-center gap-2">
53+
<ProgressBar
54+
fraction={fraction}
55+
ariaLabel={`Index backfill progress: ${percent}% of documents`}
56+
variant="stripes"
57+
className="w-24"
58+
/>
59+
<span className="text-xs text-content-tertiary">{percent}%</span>
60+
</div>
61+
);
62+
}
63+
3464
function getIndexDescription(index: Index) {
3565
if (index.fields instanceof Array) {
3666
return { type: "", fields: index.fields.join(", ") };
@@ -42,9 +72,11 @@ function getIndexDescription(index: Index) {
4272
}
4373

4474
export function IndexesList({ indexes }: { indexes?: Index[] }) {
45-
return !indexes || indexes.length === 0 ? (
46-
<>This table has no indexes</>
47-
) : (
75+
if (!indexes || indexes.length === 0) {
76+
return <>This table has no indexes</>;
77+
}
78+
79+
return (
4880
<table className="table-auto">
4981
<thead>
5082
<tr className="border-b">
@@ -59,8 +91,8 @@ export function IndexesList({ indexes }: { indexes?: Index[] }) {
5991
</thead>
6092

6193
<tbody>
62-
{indexes.map((index) => (
63-
<IndexRow key={index.name} index={index} />
94+
{indexes.map((index, i) => (
95+
<IndexRow key={`${index.name}-${i}`} index={index} />
6496
))}
6597
</tbody>
6698
</table>
@@ -72,7 +104,7 @@ export function IndexList({ tableName }: { tableName: string }) {
72104
const indexes =
73105
useQuery(api._system.frontend.indexes.default, {
74106
tableName,
75-
tableNamespace: selectedNent?.id ? selectedNent.id : null,
107+
tableNamespace: selectedNent?.id ?? null,
76108
}) ?? undefined;
77109

78110
return <IndexesList indexes={indexes} />;

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ export function TableSchemaAndIndexes({
3333

3434
function SchemaAndIndexBody({ tableName }: { tableName: string }) {
3535
const tableSchemaStatus = useSingleTableSchemaStatus(tableName);
36-
if (
37-
tableSchemaStatus === undefined ||
38-
tableSchemaStatus.isValidationRunning
39-
) {
36+
if (tableSchemaStatus === undefined) {
4037
return <Loading />;
4138
}
4239
return (

npm-packages/dashboard-common/src/features/data/lib/useDataToolbarActions.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Cursor, GenericDocument } from "convex/server";
2+
import { useRouter } from "next/router";
23
import { ConvexError } from "convex/values";
34
import { useMutation } from "convex/react";
45
import udfs from "@common/udfs";
@@ -11,6 +12,7 @@ import { useNents } from "@common/lib/useNents";
1112
import { toast } from "@common/lib/utils";
1213
import { useContext } from "react";
1314
import { DeploymentInfoContext } from "@common/lib/deploymentContext";
15+
import { shallowNavigate } from "@common/lib/useTableMetadata";
1416

1517
export function useDataToolbarActions({
1618
handleAddDocuments,
@@ -92,9 +94,15 @@ export function useDataToolbarActions({
9294
): Promise<{ continueCursor: Cursor; deleted: number; hasMore: boolean }> =>
9395
tableClear({ tableName, cursor, componentId: selectedNent?.id ?? null });
9496

97+
const router = useRouter();
9598
const tableDelete = useDeleteTables();
9699
const deleteTable = async () => {
97100
try {
101+
void shallowNavigate(router, {
102+
...router.query,
103+
table: undefined,
104+
filters: undefined,
105+
});
98106
const resp = await tableDelete([tableName], selectedNent?.id ?? null);
99107
if (!resp?.success) {
100108
toast("error", resp.error);

npm-packages/dashboard-common/src/lib/useTableMetadata.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function useTableMetadataAndUpdateURL(): TableMetadata | undefined {
7979
return tableMetadata;
8080
}
8181

82-
function shallowNavigate(
82+
export function shallowNavigate(
8383
router: NextRouter,
8484
newQuery: Record<string, string | undefined>,
8585
) {

0 commit comments

Comments
 (0)