SPB Git forge

spb/cancerindex

Public
37commits 1branches 0releases
2.9 MBsize
maindefault branch
10 days agolast push
TypeScript 97.2% SQL 1.5% CSS 0.6% JavaScript 0.5%
4.5 KB · 96 lines tsx
Raw Blame History
1import Link from 'next/link';2import { Section } from '@/components/ui/section';3import { Badge, StatusBadge } from '@/components/ui/badge';4import { EmptyState } from '@/components/ui/empty-state';5import { connectorHealth } from '@/lib/queries/admin';6import { fmtDateTime, fmtInt, relativeTime } from '@/lib/format';78export default async function AdminConnectorsPage() {9  const rows = await connectorHealth();10  return (11    <div className="space-y-6">12      <header className="pt-4">13        <h1 className="text-3xl">Connectors</h1>14        <p className="mt-1 text-[13.5px] text-ink-2">Health, last success and attempt, record counts of the last run, drift signals and license status per connector.</p>15      </header>16      <Section id="connectors" title="All connectors" kicker={`${rows.length} registered`}>17        {rows.length ? (18          <div className="ci-table-wrap">19            <table className="ci-table">20              <thead>21                <tr>22                  <th>Connector</th>23                  <th>Status</th>24                  <th>License</th>25                  <th>Health</th>26                  <th>Last success</th>27                  <th>Last attempt</th>28                  <th>Last run</th>29                  <th className="num">Fetched</th>30                  <th className="num">Created</th>31                  <th className="num">Updated</th>32                  <th className="num">Rejected</th>33                  <th>Drift</th>34                  <th className="num">Runs</th>35                </tr>36              </thead>37              <tbody>38                {rows.map((r) => (39                  <tr key={r.slug}>40                    <td>41                      <Link className="ci-link" href={`/source/${r.slug}`}>42                        {r.name}43                      </Link>44                      <span className="ci-mono block text-[10.5px] text-ink-4">{r.slug}</span>45                    </td>46                    <td>47                      <StatusBadge status={r.status} />48                    </td>49                    <td>50                      <Badge tone={r.license_status === 'approved' ? 'ok' : 'warn'}>{r.license_status}</Badge>51                    </td>52                    <td>53                      <StatusBadge status={r.health ?? 'unknown'} />54                      {r.paused ? <Badge tone="warn" className="ml-1">paused</Badge> : null}55                      {r.health_detail ? <span className="block max-w-[220px] text-[11.5px] text-ink-3">{r.health_detail}</span> : null}56                    </td>57                    <td className="whitespace-nowrap text-[12.5px]" title={r.last_success_at ? fmtDateTime(r.last_success_at) : ''}>58                      {r.last_success_at ? relativeTime(r.last_success_at) : '—'}59                    </td>60                    <td className="whitespace-nowrap text-[12.5px]" title={r.last_attempt_at ? fmtDateTime(r.last_attempt_at) : ''}>61                      {r.last_attempt_at ? relativeTime(r.last_attempt_at) : '—'}62                    </td>63                    <td>64                      {r.last_run_id ? (65                        <>66                          <Link className="ci-mono ci-link text-[11.5px]" href={`/admin/runs/${r.last_run_id}`}>67                            {r.last_run_id}68                          </Link>{' '}69                          <StatusBadge status={r.last_run_status} />70                        </>71                      ) : (72                        <span className="text-ink-4">—</span>73                      )}74                    </td>75                    <td className="num">{r.records_fetched == null ? '—' : fmtInt(r.records_fetched)}</td>76                    <td className="num">{r.records_created == null ? '—' : fmtInt(r.records_created)}</td>77                    <td className="num">{r.records_updated == null ? '—' : fmtInt(r.records_updated)}</td>78                    <td className="num">{r.records_rejected == null ? '—' : fmtInt(r.records_rejected)}</td>79                    <td>80                      {r.schema_drift?.length ? <Badge tone="warn">{r.schema_drift.length} drift</Badge> : <span className="text-ink-4">none</span>}81                      {r.drift_fields ? <span className="block text-[11px] text-ink-3">{fmtInt(r.drift_fields)} fields tracked</span> : null}82                    </td>83                    <td className="num">{fmtInt(r.runs_total)}</td>84                  </tr>85                ))}86              </tbody>87            </table>88          </div>89        ) : (90          <EmptyState compact>No connector registered.</EmptyState>91        )}92      </Section>93    </div>94  );95}96