Skip to content

Commit fbbd062

Browse files
committed
Use tanstack/query for logs and accounts pagination. Remove searchParam manipulation from Table component.
1 parent ea7f09d commit fbbd062

File tree

12 files changed

+328
-169
lines changed

12 files changed

+328
-169
lines changed

trailbase-assets/js/admin/src/components/FilterBar.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ export function FilterBar(props: {
99
example?: JSX.Element;
1010
}) {
1111
let ref: HTMLInputElement | undefined;
12-
const onSubmit = () => {
12+
const onSubmit = (ev: SubmitEvent) => {
13+
ev.preventDefault();
14+
1315
const value = ref?.value;
1416
console.debug("set filter: ", value);
1517
if (value !== undefined) {

trailbase-assets/js/admin/src/components/IndexPage.tsx

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { createResource, For } from "solid-js";
1+
import { For } from "solid-js";
2+
import { useQuery } from "@tanstack/solid-query";
23
import type { IconTypes } from "solid-icons";
34
import {
45
TbDatabase,
@@ -131,59 +132,62 @@ function FactCard(props: { title: string; content: string; href?: string }) {
131132
);
132133
}
133134

134-
export function IndexPage() {
135-
const [fetchResult, { refetch: _ }] = createResource(
136-
`
135+
async function fetchDashboardData(): Promise<Data> {
136+
const sql = `
137137
SELECT
138138
page_count * page_size, num_tables, num_views, num_users
139139
FROM
140140
pragma_page_count AS page_count,
141141
pragma_page_size AS page_size,
142142
(SELECT COUNT(*) AS num_tables FROM sqlite_master WHERE type = 'table'),
143143
(SELECT COUNT(*) AS num_views FROM sqlite_master WHERE type = 'view'),
144-
(SELECT COUNT(*) AS num_users FROM _user);
145-
`,
146-
async (sql) => {
147-
const response = await executeSql(sql);
148-
const error = response.error;
149-
if (error) {
150-
throw Error(JSON.stringify(error));
151-
}
152-
153-
const data = response.data;
154-
if (!data || data.rows.length < 1) {
155-
throw Error(`Missing data: ${data}`);
156-
}
157-
const row = data.rows[0];
158-
return {
159-
dbSize: row[0] as number,
160-
numTables: row[1] as number,
161-
numViews: row[2] as number,
162-
numUsers: row[3] as number,
163-
} as Data;
164-
},
165-
);
144+
(SELECT COUNT(*) AS num_users FROM _user);`;
145+
146+
const response = await executeSql(sql);
147+
const error = response.error;
148+
if (error) {
149+
throw Error(JSON.stringify(error));
150+
}
151+
152+
const data = response.data;
153+
if (!data || data.rows.length < 1) {
154+
throw Error(`Missing data: ${data}`);
155+
}
156+
const row = data.rows[0];
157+
return {
158+
dbSize: row[0] as number,
159+
numTables: row[1] as number,
160+
numViews: row[2] as number,
161+
numUsers: row[3] as number,
162+
} as Data;
163+
}
164+
165+
export function IndexPage() {
166+
const dashboardFetch = useQuery(() => ({
167+
queryKey: ["dashboard"],
168+
queryFn: fetchDashboardData,
169+
}));
166170

167171
return (
168172
<div class="h-dvh overflow-y-auto">
169173
<Header title="TrailBase" />
170174

171175
<div class="prose m-4 flex grow flex-col gap-4">
172-
{fetchResult.state === "ready" && (
176+
{dashboardFetch.data && (
173177
<div class="flex grow gap-4">
174178
<FactCard
175179
title="Users"
176-
content={`${fetchResult().numUsers}`}
180+
content={`${dashboardFetch.data!.numUsers}`}
177181
href={`${BASE}/auth`}
178182
/>
179183
<FactCard
180184
title="Tables & Views"
181-
content={`${fetchResult().numTables + fetchResult().numViews}`}
185+
content={`${dashboardFetch.data!.numTables + dashboardFetch.data!.numViews}`}
182186
href={`${BASE}/table`}
183187
/>
184188
<FactCard
185189
title="Size"
186-
content={`${(fetchResult().dbSize / 1024 / 1024).toPrecision(2)} MB`}
190+
content={`${(dashboardFetch.data!.dbSize / 1024 / 1024).toPrecision(2)} MB`}
187191
/>
188192
</div>
189193
)}

trailbase-assets/js/admin/src/components/Table.tsx

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import {
22
For,
33
Show,
4-
createEffect,
54
createMemo,
65
createSignal,
76
splitProps,
87
type Accessor,
98
} from "solid-js";
109
import { createWritableMemo } from "@solid-primitives/memo";
11-
import { useSearchParams } from "@solidjs/router";
1210
import {
1311
flexRender,
1412
createSolidTable,
@@ -40,11 +38,6 @@ import {
4038
import { Checkbox } from "@/components/ui/checkbox";
4139
import { createWindowWidth } from "@/components/SplitView";
4240

43-
type SearchParams = {
44-
pageIndex: string;
45-
pageSize: string;
46-
};
47-
4841
export function safeParseInt(v: string | undefined): number | undefined {
4942
if (v !== undefined) {
5043
try {
@@ -74,7 +67,7 @@ type Props<TData, TValue> = {
7467
data: Accessor<TData[] | undefined>;
7568

7669
rowCount?: number;
77-
initialPagination?: PaginationState;
70+
pagination?: PaginationState;
7871
onPaginationChange?: OnChangeFn<PaginationState>;
7972

8073
onRowSelection?: (idx: number, row: TData, value: boolean) => void;
@@ -85,36 +78,19 @@ export function DataTable<TData, TValue>(props: Props<TData, TValue>) {
8578
const [local] = splitProps(props, ["columns", "data"]);
8679
const [rowSelection, setRowSelection] = createSignal({});
8780

88-
const [searchParams, setSearchParams] = useSearchParams<SearchParams>();
8981
const paginationEnabled = () => props.onPaginationChange !== undefined;
90-
91-
function initPaginationState(): PaginationState {
92-
return {
93-
pageIndex:
94-
safeParseInt(searchParams.pageIndex) ??
95-
props.initialPagination?.pageIndex ??
96-
0,
97-
pageSize:
98-
safeParseInt(searchParams.pageSize) ??
99-
props.initialPagination?.pageSize ??
100-
20,
101-
};
102-
}
103-
10482
const [paginationState, setPaginationState] =
10583
createWritableMemo<PaginationState>(() => {
10684
// Whenever column definitions change, reset pagination state.
10785
//
108-
// FIXME: column definition is an insufficient proxy, we should also reset
109-
// when switching between tables/views with matching schemas. Maybe we
110-
// should just inject a Signal<PaginationState>
86+
// FIXME: We should probably just not use a memo and and receive columns/data by value to rebuild instead.
11187
const _c = props.columns();
11288

113-
return initPaginationState();
89+
return {
90+
pageIndex: props.pagination?.pageIndex ?? 0,
91+
pageSize: props.pagination?.pageSize ?? 20,
92+
};
11493
});
115-
createEffect(() => {
116-
setSearchParams({ ...paginationState() });
117-
});
11894

11995
const columns = createMemo(() => {
12096
const onRowSelection = props.onRowSelection;
@@ -409,6 +385,9 @@ function PaginationControl<TData>(props: {
409385
/>
410386
</svg>
411387
</Button>
388+
389+
{/*
390+
// Doesn't work for cursors.
412391
<Button
413392
aria-label="Go to last page"
414393
variant="outline"
@@ -433,6 +412,7 @@ function PaginationControl<TData>(props: {
433412
/>
434413
</svg>
435414
</Button>
415+
*/}
436416
</div>
437417

438418
<div class="flex items-center justify-center whitespace-nowrap text-sm font-medium">

0 commit comments

Comments
 (0)