"use client"; // Making an API token: a name, how long it lasts, and what it may do where (some of the person's own permissions). import { useActionState, useState } from "react"; import { ErrorText } from "@/components/forms"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select"; import type { TokenScope } from "@/lib/api"; import { createToken } from "./actions"; const keyOf = (s: TokenScope["scope"]) => (s.type === "hub" ? "hub" : `${s.type}:${s.id}`); const kindOf = { hub: "Everything", catalog: "Catalog", product: "Product" } as const; type Row = { scope: string; permissions: string[] }; export function TokenForm({ scopes, maxDays }: { scopes: TokenScope[]; maxDays: number }) { const [state, formAction, pending] = useActionState(createToken, null); const [rows, setRows] = useState([{ scope: keyOf(scopes[0]!.scope), permissions: [] }]); const [copied, setCopied] = useState(false); const byKey = new Map(scopes.map((s) => [keyOf(s.scope), s])); const grants = rows.flatMap((r) => r.permissions.map((permission) => ({ permission, scope: byKey.get(r.scope)!.scope }))); const set = (i: number, row: Row) => setRows(rows.map((r, j) => (j === i ? row : r))); const unused = scopes.find((s) => !rows.some((r) => r.scope === keyOf(s.scope))); return (
{[7, 30, 90, maxDays].map((d) => ( {d === 365 ? "1 year" : `${d} days`} ))}
{rows.map((row, i) => { const scope = byKey.get(row.scope)!; return (
set(i, { scope: e.target.value, permissions: [] })} aria-label="Where" className="min-w-56" > {scopes.map((s) => { const k = keyOf(s.scope); if (k !== row.scope && rows.some((r) => r.scope === k)) return null; return ( {s.scope.type === "hub" ? "Everything on T5DE" : `${kindOf[s.scope.type]}: ${s.name}`} ); })} {rows.length > 1 && ( )}
{scope.permissions.map((p) => ( ))}
); })}
{unused && ( )}
{state?.error && {state.error}} {state?.token && (

Your token {state.name}. Copy it now: it won't be shown again.

{state.token}

Send it as Authorization: Bearer <token>.

)}
); }