import React, { useMemo } from 'react'; import { Search } from '../../icons'; import type { CanaryTokenRow } from '../CanaryTokenDrawer'; import { STATE_COLOR } from './types'; import { INPUT_STYLE } from './ui'; export type StateFilter = 'all' | 'planted' | 'revoked' | 'failed'; export type ScopeFilter = 'all' | 'fleet' | 'topology'; interface Props { tokens: CanaryTokenRow[]; loading: boolean; error: string | null; filter: string; setFilter: (s: string) => void; stateFilter: StateFilter; setStateFilter: (s: StateFilter) => void; scopeFilter: ScopeFilter; setScopeFilter: (s: ScopeFilter) => void; onPick: (t: CanaryTokenRow) => void; } /** Tokens tab: text search + state/scope filter selectors over a * flat row grid. Clicking a row passes the token up to the page, * which opens the CanaryTokenDrawer. */ export const TokenListView: React.FC = ({ tokens, loading, error, filter, setFilter, stateFilter, setStateFilter, scopeFilter, setScopeFilter, onPick, }) => { const visibleTokens = useMemo(() => { return tokens.filter((t) => { if (stateFilter !== 'all' && t.state !== stateFilter) return false; if (scopeFilter === 'fleet' && t.topology_id) return false; if (scopeFilter === 'topology' && !t.topology_id) return false; if (!filter) return true; const f = filter.toLowerCase(); return ( t.decky_name.toLowerCase().includes(f) || t.placement_path.toLowerCase().includes(f) || t.callback_token.toLowerCase().includes(f) || (t.generator || '').toLowerCase().includes(f) || (t.instrumenter || '').toLowerCase().includes(f) || (t.topology_id || '').toLowerCase().includes(f) ); }); }, [tokens, filter, stateFilter, scopeFilter]); return ( <>
setFilter(e.target.value)} placeholder="Filter by decky / path / slug / generator…" style={{ ...INPUT_STYLE, paddingLeft: '32px', marginBottom: 0 }} />
{loading &&
loading…
} {error &&
{error}
} {!loading && visibleTokens.length === 0 && (
{tokens.length === 0 ? 'No canary tokens yet. Click NEW TOKEN to plant one, or UPLOAD ARTIFACT to start with an operator-supplied document.' : 'No tokens match the current filter.'}
)}
{visibleTokens.map((t) => ( ))}
); };