import type { ReactNode } from "react"; import { useTranslation } from "react-i18next"; import { nextPageOnClick } from "../../lib/nextPage"; import type { HistoryList as HistoryListState } from "../../lib/useHistoryList"; import NavGrid from "../../components/ui/NavGrid"; import { Button } from "../../components/ui/Button"; import { LoadingState, StateMessage } from "../../components/ui/QueryState"; // The frame of a history list on the activity page — the runs, the admin actions, the server log: // its own bar (if any), the rows or the honest state instead of them (a failed read is an error with a // retry, never an empty list), a read that failed over rows still on screen, the count, and "Older". // `HistoryFrame` draws it; each list says only what its failure and its "Older" are — the server log's // count its filter facets and stop while Live (AdminLogs), the others not (HistoryList, below). /** What a read that failed while rows stayed on screen means, and how to try it again. */ export interface FrameFailure { text: string; onRetry: () => void; } export function HistoryFrame({ list, rowCount, header, failure, older, count, empty, rowsClassName = "", testId, children, }: { /** The list's read. */ list: { data?: unknown; isError: boolean; isLoading: boolean; isPlaceholderData: boolean; refetch: () => unknown; }; rowCount: number; /** The list's own bar above the rows. */ header?: ReactNode; failure: FrameFailure | null; /** "Older", when there is an older page to ask for. */ older: { label: string; onClick: () => void; disabled: boolean } | null; /** "N runs shown", for the footer. */ count: string; /** Shown when the filters match nothing. */ empty: string; rowsClassName?: string; testId?: string; /** The rows. */ children: ReactNode; }) { const { t } = useTranslation(); return (
{header} {failure && ( {failure.text} )}
{list.isError && !list.data ? ( void list.refetch()}> {t("common.loadError")} ) : list.isLoading ? ( ) : rowCount === 0 ? ( {empty} ) : ( {children} )}
{count} {older && ( )}
); } /** A history list read through `useHistoryList` (the runs, the admin actions). */ export default function HistoryList({ state, empty, count, children, }: { state: HistoryListState; /** Shown when the filters match nothing. */ empty: string; /** "N runs shown", for the footer. */ count: string; /** The rows, drawn from `state.rows`. */ children: ReactNode; }) { const { t } = useTranslation(); const { list, rows, hasOlder } = state; const fetchOlder = () => void list.fetchNextPage(nextPageOnClick(list.isFetchingNextPage)); // A read that failed while rows were on screen keeps them, and says what the failure means. const failure: FrameFailure | null = !list.data ? null : list.isFetchNextPageError ? { text: t("activity.olderFailed"), onRetry: fetchOlder } : list.isError ? { text: t("activity.stale"), onRetry: () => void list.refetch() } : null; return ( {children} ); }