NORY-34: show oauth2 clients in a data table

This commit is contained in:
Markus Thielker 2024-12-27 17:17:46 +01:00
parent 502098d8ef
commit 6335036a04
No known key found for this signature in database
2 changed files with 141 additions and 1 deletions

View file

@ -0,0 +1,105 @@
'use client';
import { ColumnDef } from '@tanstack/react-table';
import { OAuth2Client } from '@ory/client';
import { DataTable } from '@/components/ui/data-table';
import { useEffect, useRef, useState } from 'react';
import { Spinner } from '@/components/ui/spinner';
import { FetchClientPageProps } from '@/app/(inside)/client/page';
interface ClientDataTableProps {
data: OAuth2Client[];
pageSize: number;
pageToken: string | undefined;
fetchClientPage: (props: FetchClientPageProps) => Promise<{
data: OAuth2Client[],
tokens: Map<string, string>
}>;
}
export function ClientDataTable(
{
data,
pageSize,
pageToken,
fetchClientPage,
}: ClientDataTableProps,
) {
console.log('OAuth2 client', data);
const columns: ColumnDef<OAuth2Client>[] = [
{
id: 'client_id',
accessorKey: 'client_id',
header: 'Client ID',
},
{
id: 'client_name',
accessorKey: 'client_name',
header: 'Client Name',
},
{
id: 'owner',
accessorKey: 'owner',
header: 'Owner',
},
];
const [items, setItems] = useState<OAuth2Client[]>(data);
const [nextToken, setNextToken] = useState<string | undefined>(pageToken);
// react on changes from ssr (query params)
useEffect(() => {
setItems(data);
setNextToken(pageToken);
}, [data, pageSize, pageToken]);
// infinite scroll handling
const infiniteScrollSensor = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
fetchMore();
}
},
{ threshold: 0.5 }, // Adjust threshold as needed
);
if (infiniteScrollSensor.current) {
observer.observe(infiniteScrollSensor.current);
}
return () => {
if (infiniteScrollSensor.current) {
observer.unobserve(infiniteScrollSensor.current);
}
};
}, [items]);
const fetchMore = async () => {
if (!nextToken) return;
const response = await fetchClientPage({
pageSize: pageSize,
pageToken: nextToken,
});
setItems([...items, ...response.data]);
setNextToken(response.tokens.get('next') ?? undefined);
};
return (
<>
<DataTable columns={columns} data={items}/>
{
nextToken && (
<div className="flex w-full justify-center">
<Spinner ref={infiniteScrollSensor} className="h-10"/>
</div>
)
}
</>
);
}

View file

@ -1,12 +1,47 @@
import { getOAuth2Api } from '@/ory/sdk/server';
import { parseTokens } from '@/app/(inside)/user/page';
import { ClientDataTable } from '@/app/(inside)/client/data-table';
export interface FetchClientPageProps {
pageSize: number;
pageToken: string;
}
async function fetchClientPage({ pageSize, pageToken }: FetchClientPageProps) {
'use server';
const oAuth2Api = await getOAuth2Api();
const response = await oAuth2Api.listOAuth2Clients({
pageSize: pageSize,
pageToken: pageToken,
});
return {
data: response.data,
tokens: parseTokens(response.headers.link),
};
}
export default async function ListClientPage() {
let pageSize = 100;
let pageToken: string = '00000000-0000-0000-0000-000000000000';
const initialFetch = await fetchClientPage({ pageSize, pageToken });
return (
<div className="space-y-4">
<div>
<p className="text-3xl font-bold leading-tight tracking-tight">OAuth2 Clients</p>
<p className="text-lg font-light">
Part of milestone v0.2.0
See and manage all OAuth2 clients registered with your Ory Hydra instance
</p>
</div>
<ClientDataTable
data={initialFetch.data}
pageSize={pageSize}
pageToken={initialFetch.tokens.get('next')}
fetchClientPage={fetchClientPage}/>
</div>
);
}