import type { ModuleUiHostContext } from "@ekklesia/module-ui-sdk"; import { Badge, EmptyState, Panel, Table, TableBody, TableCell, TableHead, TableRow, } from "@ekklesia/ui"; import type { ReactElement } from "react"; import type { SignageApi } from "../api.js"; import { useResource } from "../hooks.js"; import type { ProviderHealth, SettingsResponse } from "../types.js"; import { formatInstant, renderLoadable } from "./shared.js"; const SLIDE_RENDERER_CAPABILITY = "signage.slide-renderer"; /** * Provider health, and the one thing only a browser can tell an operator. * * A registration is a **running fact**: a provider that was uninstalled or disabled simply is not * here, and there is no stored row claiming otherwise. Everything shown is either the provider's own * declared identity or a count Signage kept — never a provider's exception, message, or payload. * * Renderer availability is checked here rather than on the server because the server genuinely * cannot know it: whether the platform published a module's contribution is a fact the *host* holds, * and `context.contributions` is where it is legible. A provider whose renderer was not published — * because the module is missing, disabled, or outside Signage's compatible range — is reported as * exactly that, which is the difference between "this is broken" and "this needs an update". */ export function ProvidersPanel({ api, context, settings, }: { readonly api: SignageApi; readonly context: ModuleUiHostContext; readonly settings: SettingsResponse; }): ReactElement { const providers = useResource( () => api.get<{ providers: readonly ProviderHealth[] }>("providers"), [], ); const published = new Set( context.contributions .list(SLIDE_RENDERER_CAPABILITY) .map((contribution) => contribution.id), ); return ( {`Contract ${settings.rendererInputVersion}`} } description="Running content sources available to timelines." title="Content providers" > {renderLoadable( providers.state, (value) => value.providers.length === 0 ? ( ) : ( Provider Contract Renderer Health Last success {value.providers.map((provider) => { const rendererPublished = published.has( provider.renderer.contributionId, ); const isNative = provider.renderer.contributionId === "signage.native-image"; return ( {provider.providerId} {`v${provider.providerVersion}`} {provider.contractVersion} {isNative ? ( Built in ) : rendererPublished ? ( {provider.renderer.contributionId} ) : ( Renderer not published )} {provider.consecutiveFailures === 0 ? ( Healthy ) : ( {`${provider.consecutiveFailures} failures · ${provider.lastFailureCode ?? "unknown"}`} )} {formatInstant( provider.lastSuccessAt, settings.timezone, )} ); })}
), { label: "Loading providers…", onRetry: providers.reload }, )}
); }