Fork Horse repository, listed by its owner. Publisher snapshot.

packages/forkhorse-dashboard/src/freshness.tsx

Snapshot at 34e3175

Containing directory

1,838 bytes · textView raw
1import type { ReactNode } from "react";
2import { Button, Tooltip } from "@cloudflare/kumo";
3import type { ViewModel } from "./model.ts";
4import { relativeTime } from "./time.ts";
5
6export function snapshotAge(view: ViewModel, now = Date.now()): string {
7  const age = view.updatedAt && relativeTime(view.updatedAt, now);
8  return age === "Just now" ? "just now" : age || "an unknown time";
9}
10
11export function staleReason(view: ViewModel): string | undefined {
12  return view.stale ? `Refresh first. This data is from ${snapshotAge(view)}.` : undefined;
13}
14
15/** Disabled controls still have a focusable tooltip target, including in open dialogs. */
16export function WriteHint({ reason, children }: { reason?: string; children: ReactNode }) {
17  return reason ? (
18    <Tooltip content={reason} render={<span className="write-hint" tabIndex={0} />}>
19      {children}
20    </Tooltip>
21  ) : <>{children}</>;
22}
23
24export function FreshnessStamp({ view, retry }: { view: ViewModel; retry?: () => Promise<void> }) {
25  if (!view.state || !view.updatedAt) return null;
26  const time = <Tooltip content={new Date(view.updatedAt).toLocaleString()} render={<time dateTime={view.updatedAt} />}>
27    {snapshotAge(view)}
28  </Tooltip>;
29  // A retry of a failed read stays stale, with its time visible, until it succeeds.
30  return <div className="freshness-stamp caption muted" data-freshness="stamp">
31    {view.stale ? <>
32      <span role="status">Couldn't refresh. Last updated {time}.</span>
33      {retry && <Button variant="ghost" size="sm" disabled={view.refreshing || view.busy}
34        onClick={() => void retry()}>Try again</Button>}
35    </> : view.refreshing ? <Tooltip content={`Updated ${snapshotAge(view)} · ${new Date(view.updatedAt).toLocaleString()}`} render={<span />}>
36      Refreshing…
37    </Tooltip> : <span>Updated {time}</span>}
38  </div>;
39}
40