1
0
Fork 0
mirror of https://codeberg.org/MarkusThielker/next-ory.git synced 2025-04-18 00:21:18 +00:00

NORY-15: implement pagination mechanics

This commit is contained in:
Markus Thielker 2024-12-08 07:44:50 +01:00
parent 3378fee9ec
commit 2eb4b80607
No known key found for this signature in database
2 changed files with 78 additions and 9 deletions

View file

@ -5,12 +5,18 @@ import { Identity } from '@ory/client';
import { DataTable } from '@/components/ui/data-table'; import { DataTable } from '@/components/ui/data-table';
import { CircleCheck, CircleX } from 'lucide-react'; import { CircleCheck, CircleX } from 'lucide-react';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card';
import { useState } from 'react';
import { FetchIdentityPageProps } from '@/app/user/page';
interface IdentityDataTableProps { interface IdentityDataTableProps {
data: Identity[]; data: Identity[];
pageSize: number;
pageToken: string | undefined;
query: string;
fetchIdentityPage: (props: FetchIdentityPageProps) => Promise<{ data: Identity[], tokens: Map<string, string> }>;
} }
export function IdentityDataTable({ data }: IdentityDataTableProps) { export function IdentityDataTable({ data, pageSize, pageToken, query, fetchIdentityPage }: IdentityDataTableProps) {
const columns: ColumnDef<Identity>[] = [ const columns: ColumnDef<Identity>[] = [
{ {
@ -80,5 +86,23 @@ export function IdentityDataTable({ data }: IdentityDataTableProps) {
}, },
]; ];
return <DataTable columns={columns} data={data}/>; const [items, setItems] = useState<Identity[]>(data);
const [nextToken, setNextToken] = useState<string | undefined>(pageToken);
const fetchMore = async () => {
if (!nextToken) return;
const response = await fetchIdentityPage({
pageSize: pageSize,
pageToken: nextToken,
query: query,
});
setItems([...items, ...response.data]);
setNextToken(response.tokens.get('next') ?? undefined);
};
// TODO: fetch more when scrolling to the end of list
return <DataTable columns={columns} data={items}/>;
} }

View file

@ -3,6 +3,48 @@ import { IdentityDataTable } from '@/app/user/data-table';
import { getIdentityApi } from '@/ory/sdk/server'; import { getIdentityApi } from '@/ory/sdk/server';
import { SearchInput } from '@/components/search-input'; import { SearchInput } from '@/components/search-input';
export interface FetchIdentityPageProps {
pageSize: number;
pageToken: string;
query: string;
}
async function fetchIdentityPage({ pageSize, pageToken, query }: FetchIdentityPageProps) {
'use server';
const identityApi = await getIdentityApi();
const response = await identityApi.listIdentities({
pageSize: pageSize,
pageToken: pageToken,
previewCredentialsIdentifierSimilar: query,
});
return {
data: response.data,
tokens: parseTokens(response.headers.link),
};
}
function parseTokens(link: string) {
const parsed = link.split(',').map((it) => {
const startRel = it.lastIndexOf('rel="');
const endRel = it.lastIndexOf('"');
const rel = it.slice(startRel, endRel);
const startToken = it.lastIndexOf('page_token=');
const endToken = it.lastIndexOf('&');
const token = it.slice(startToken, endToken);
return [rel, token];
});
return new Map(parsed.map(obj => [
obj[0].replace('rel="', ''),
obj[1].replace('page_token=', ''),
]));
}
export default async function UserPage( export default async function UserPage(
{ {
searchParams, searchParams,
@ -11,15 +53,13 @@ export default async function UserPage(
}, },
) { ) {
const identityApi = await getIdentityApi();
const params = await searchParams; const params = await searchParams;
const query = params.query ? params.query as string : ''; const query = params.query ? params.query as string : '';
const data = await identityApi.listIdentities({ let pageSize = 200;
pageSize: 100, let pageToken: string = '00000000-0000-0000-0000-000000000000';
previewCredentialsIdentifierSimilar: query,
}).then(response => response.data); const initialFetch = await fetchIdentityPage({ pageSize, pageToken, query: '' });
return ( return (
<div className="space-y-4"> <div className="space-y-4">
@ -31,7 +71,12 @@ export default async function UserPage(
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<SearchInput queryParamKey="query" placeholder="Search"/> <SearchInput queryParamKey="query" placeholder="Search"/>
<IdentityDataTable data={data}/> <IdentityDataTable
data={initialFetch.data}
pageSize={pageSize}
pageToken={initialFetch.tokens.get('next')}
query={query}
fetchIdentityPage={fetchIdentityPage}/>
</div> </div>
</div> </div>
); );