@burdenoff/microfe-cosmicintersection 2026.704.1 → 2026.704.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cosmicintersection/CosmicIntersectionRoutes.js +31 -23
  2. package/dist/cosmicintersection/CosmicIntersectionRoutes.js.map +1 -1
  3. package/dist/cosmicintersection/api/cosmicApi.js +131 -66
  4. package/dist/cosmicintersection/api/cosmicApi.js.map +1 -1
  5. package/dist/cosmicintersection/components/ActivityFeedPanel.js +68 -0
  6. package/dist/cosmicintersection/components/ActivityFeedPanel.js.map +1 -0
  7. package/dist/cosmicintersection/components/DiscussionPanel.js +57 -0
  8. package/dist/cosmicintersection/components/DiscussionPanel.js.map +1 -0
  9. package/dist/cosmicintersection/components/index.js +5 -3
  10. package/dist/cosmicintersection/pages/access/AccessPage.js +24 -17
  11. package/dist/cosmicintersection/pages/access/AccessPage.js.map +1 -1
  12. package/dist/cosmicintersection/pages/analyses/AnalysesPage.js +12 -12
  13. package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js +109 -96
  14. package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js.map +1 -1
  15. package/dist/cosmicintersection/pages/collections/CollectionFormPage.js +87 -61
  16. package/dist/cosmicintersection/pages/collections/CollectionFormPage.js.map +1 -1
  17. package/dist/cosmicintersection/pages/collections/CollectionsPage.js +51 -42
  18. package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -1
  19. package/dist/cosmicintersection/pages/dashboard/DashboardPage.js +5 -3
  20. package/dist/cosmicintersection/pages/dashboard/DashboardPage.js.map +1 -1
  21. package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +172 -152
  22. package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js.map +1 -1
  23. package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js +7 -7
  24. package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js +205 -196
  25. package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js.map +1 -1
  26. package/dist/cosmicintersection/pages/releases/ReleasesPage.js +211 -161
  27. package/dist/cosmicintersection/pages/releases/ReleasesPage.js.map +1 -1
  28. package/dist/cosmicintersection/pages/runs/RunDetailPage.js +113 -108
  29. package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -1
  30. package/dist/cosmicintersection/pages/runs/RunsPage.js +86 -101
  31. package/dist/cosmicintersection/pages/runs/RunsPage.js.map +1 -1
  32. package/dist/cosmicintersection/pages/sources/SourceDetailPage.js +205 -0
  33. package/dist/cosmicintersection/pages/sources/SourceDetailPage.js.map +1 -0
  34. package/dist/cosmicintersection/pages/sources/SourcesPage.js +110 -104
  35. package/dist/cosmicintersection/pages/sources/SourcesPage.js.map +1 -1
  36. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ReleasesPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/releases/ReleasesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { BookOpen, ExternalLink, Plus, Rocket } from 'lucide-react';\nimport {\n Badge,\n Button,\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosPublishReleaseMutation,\n useCosReleasesQuery,\n type CosRelease,\n type CosReleaseStatus,\n} from '../../api/cosmicApi';\nimport {\n EmptyState,\n ErrorState,\n LoadingState,\n PageLayout,\n Pagination,\n SafeLink,\n StatusBadge,\n formatEnumLabel,\n usePagination,\n} from '../../components';\nimport { ActionMenu } from '../../components/ActionMenu';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst ALL = 'ALL';\n\nconst RELEASE_STATUSES: CosReleaseStatus[] = ['DRAFT', 'UNDER_REVIEW', 'PUBLISHED', 'RETRACTED'];\n\n/** A release can be published only while it is still in a pre-publication state. */\nfunction canPublish(status: CosReleaseStatus): boolean {\n return status === 'DRAFT' || status === 'UNDER_REVIEW';\n}\n\nfunction formatDate(value?: string | null): string {\n if (!value) {\n return '—';\n }\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return '—';\n }\n return parsed.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\nfunction doiUrl(doi: string): string {\n const trimmed = doi.trim();\n return /^https?:\\/\\//i.test(trimmed)\n ? trimmed\n : `https://doi.org/${trimmed.replace(/^doi:/i, '')}`;\n}\n\nexport default function ReleasesPage() {\n const { navigate } = useCosmicIntersection();\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const pagination = usePagination({ pageSize: 20, resetKey: statusFilter });\n\n const { data, loading, error, refetch } = useCosReleasesQuery({\n status: statusFilter === ALL ? undefined : (statusFilter as CosReleaseStatus),\n pagination: { limit: pagination.limit, offset: pagination.offset },\n });\n\n const [publishRelease, { loading: publishing }] = useCosPublishReleaseMutation();\n\n const releases = useMemo(() => data?.cosListReleases.items ?? [], [data]);\n const pageInfo = data?.cosListReleases.pageInfo;\n\n // Detail (View) dialog — rendered from row data, no extra fetch needed.\n const [detail, setDetail] = useState<CosRelease | null>(null);\n\n // Publish dialog — captures an optional DOI before transitioning the release.\n const [publishTarget, setPublishTarget] = useState<CosRelease | null>(null);\n const [doiDraft, setDoiDraft] = useState('');\n\n const openPublish = (release: CosRelease) => {\n setDoiDraft(release.doi ?? '');\n setPublishTarget(release);\n };\n\n const submitPublish = async () => {\n if (!publishTarget) {\n return;\n }\n const doi = doiDraft.trim();\n const response = await publishRelease({\n variables: { id: publishTarget.id, doi: doi || undefined },\n });\n if (response.data?.cosPublishRelease?.id) {\n notify.success('Release published', `“${publishTarget.title}” is now public.`);\n setPublishTarget(null);\n setDoiDraft('');\n await refetch();\n }\n };\n\n const newButton = (\n <Button type=\"button\" onClick={() => navigate('releases/create')}>\n <Plus className=\"size-4\" />\n New release\n </Button>\n );\n\n const renderBody = () => {\n if (loading) {\n return <LoadingState variant=\"rows\" rows={6} label=\"Loading releases…\" />;\n }\n if (error) {\n return <ErrorState message={error.message} onRetry={() => void refetch()} />;\n }\n if (releases.length === 0) {\n const filtered = statusFilter !== ALL;\n return (\n <EmptyState\n icon={Rocket}\n title={filtered ? 'No releases match this filter' : 'No releases yet'}\n description={\n filtered\n ? 'Try clearing the status filter to see more releases.'\n : 'Package datasets and notebooks into a citable, versioned release for publication.'\n }\n action={filtered ? undefined : newButton}\n />\n );\n }\n\n return (\n <>\n <div className=\"overflow-x-auto rounded-card border border-border-default bg-bg-elevated\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Title</TableHead>\n <TableHead>Version</TableHead>\n <TableHead>Status</TableHead>\n <TableHead>DOI</TableHead>\n <TableHead>Authors</TableHead>\n <TableHead>Published</TableHead>\n <TableHead>License</TableHead>\n <TableHead className=\"text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {releases.map((release) => (\n <TableRow key={release.id}>\n <TableCell>\n <button\n type=\"button\"\n onClick={() => setDetail(release)}\n className=\"text-left font-medium text-text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border-focus\"\n >\n {release.title}\n </button>\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-sm text-text-secondary\">\n {release.version || '—'}\n </TableCell>\n <TableCell>\n <StatusBadge status={release.status} />\n </TableCell>\n <TableCell className=\"max-w-[14rem]\">\n {release.doi ? (\n <SafeLink\n href={doiUrl(release.doi)}\n className=\"inline-flex items-center gap-1 truncate text-sm text-text-primary underline-offset-2 hover:underline\"\n fallbackClassName=\"block truncate text-sm text-text-secondary\"\n >\n <span className=\"truncate\">{release.doi}</span>\n <ExternalLink className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n </SafeLink>\n ) : (\n <span className=\"text-sm text-text-secondary\">—</span>\n )}\n </TableCell>\n <TableCell className=\"max-w-[14rem]\">\n {release.authors.length === 0 ? (\n <span className=\"text-sm text-text-secondary\">—</span>\n ) : (\n <span className=\"line-clamp-1 text-sm text-text-secondary\">\n {release.authors.join(', ')}\n </span>\n )}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-sm text-text-secondary\">\n {formatDate(release.publishedAt)}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-sm text-text-secondary\">\n {release.license || '—'}\n </TableCell>\n <TableCell className=\"text-right\">\n <ActionMenu\n ariaLabel={`Actions for ${release.title}`}\n onView={() => setDetail(release)}\n extraItems={\n canPublish(release.status)\n ? [\n {\n key: 'publish',\n label: 'Publish',\n icon: Rocket,\n onSelect: () => openPublish(release),\n },\n ]\n : []\n }\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={releases.length}\n hasMore={pageInfo?.hasMore ?? false}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"releases\"\n loading={loading}\n />\n </>\n );\n };\n\n return (\n <PageLayout\n title=\"Releases\"\n description=\"Citable, versioned publications that bundle datasets and notebooks for the community.\"\n actions={newButton}\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"w-full max-w-[14rem]\">\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger aria-label=\"Filter by status\">\n <SelectValue placeholder=\"All statuses\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>All statuses</SelectItem>\n {RELEASE_STATUSES.map((status) => (\n <SelectItem key={status} value={status}>\n {formatEnumLabel(status)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {renderBody()}\n </div>\n\n {/* View / detail dialog */}\n <Dialog open={detail !== null} onOpenChange={(open) => (open ? undefined : setDetail(null))}>\n <DialogContent className=\"max-w-lg\">\n {detail ? (\n <>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <BookOpen className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n {detail.title}\n </DialogTitle>\n <DialogDescription>\n Version {detail.version || '—'} · <StatusBadge status={detail.status} />\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 text-sm\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Abstract\n </p>\n <p className=\"mt-1 whitespace-pre-wrap text-text-primary\">\n {detail.abstract?.trim() || 'No abstract provided.'}\n </p>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Authors\n </p>\n <p className=\"mt-1 text-text-primary\">\n {detail.authors.length ? detail.authors.join(', ') : '—'}\n </p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n License\n </p>\n <p className=\"mt-1 text-text-primary\">{detail.license || '—'}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Published\n </p>\n <p className=\"mt-1 text-text-primary\">{formatDate(detail.publishedAt)}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n DOI\n </p>\n <p className=\"mt-1\">\n {detail.doi ? (\n <SafeLink\n href={doiUrl(detail.doi)}\n className=\"inline-flex items-center gap-1 text-text-primary underline-offset-2 hover:underline\"\n fallbackClassName=\"text-text-secondary\"\n >\n {detail.doi}\n <ExternalLink className=\"size-3.5\" aria-hidden=\"true\" />\n </SafeLink>\n ) : (\n <span className=\"text-text-secondary\">Not assigned</span>\n )}\n </p>\n </div>\n </div>\n\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Datasets ({detail.datasetIds.length})\n </p>\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {detail.datasetIds.length === 0 ? (\n <span className=\"text-text-secondary\">None linked.</span>\n ) : (\n detail.datasetIds.map((id) => (\n <Badge key={id} variant=\"outline\" className=\"font-mono text-xs\">\n {id}\n </Badge>\n ))\n )}\n </div>\n </div>\n\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Notebook\n </p>\n <p className=\"mt-1\">\n {detail.notebookId ? (\n <Badge variant=\"outline\" className=\"font-mono text-xs\">\n {detail.notebookId}\n </Badge>\n ) : (\n <span className=\"text-text-secondary\">None linked.</span>\n )}\n </p>\n </div>\n </div>\n\n <DialogFooter>\n {canPublish(detail.status) ? (\n <Button\n type=\"button\"\n onClick={() => {\n const target = detail;\n setDetail(null);\n openPublish(target);\n }}\n >\n <Rocket className=\"size-4\" />\n Publish\n </Button>\n ) : null}\n <DialogClose asChild>\n <Button type=\"button\" variant=\"outline\">\n Close\n </Button>\n </DialogClose>\n </DialogFooter>\n </>\n ) : null}\n </DialogContent>\n </Dialog>\n\n {/* Publish dialog */}\n <Dialog\n open={publishTarget !== null}\n onOpenChange={(open) => (open || publishing ? undefined : setPublishTarget(null))}\n >\n <DialogContent className=\"max-w-md\">\n <DialogHeader>\n <DialogTitle>Publish release</DialogTitle>\n <DialogDescription>\n {publishTarget\n ? `Publish “${publishTarget.title}” to make it publicly citable. You can attach a DOI now or later.`\n : ''}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"release-doi\">DOI (optional)</Label>\n <Input\n id=\"release-doi\"\n value={doiDraft}\n onChange={(event) => setDoiDraft(event.target.value)}\n placeholder=\"10.1234/cosmic.2026.0001\"\n />\n <p className=\"text-xs text-text-secondary\">\n A Digital Object Identifier makes the release permanently referenceable.\n </p>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setPublishTarget(null)}\n disabled={publishing}\n >\n Cancel\n </Button>\n <Button type=\"button\" onClick={() => void submitPublish()} disabled={publishing}>\n <Rocket className=\"size-4\" />\n {publishing ? 'Publishing…' : 'Publish release'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ReleasesPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/releases/ReleasesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { BookOpen, Database, ExternalLink, NotebookPen, Plus, Rocket } from 'lucide-react';\nimport {\n Button,\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosDatasetsQuery,\n useCosNotebooksQuery,\n useCosPublishReleaseMutation,\n useCosReleasesQuery,\n type CosRelease,\n type CosReleaseStatus,\n} from '../../api/cosmicApi';\nimport {\n DiscussionPanel,\n EmptyState,\n ErrorState,\n LoadingState,\n PageLayout,\n Pagination,\n SafeLink,\n StatusBadge,\n formatEnumLabel,\n usePagination,\n} from '../../components';\nimport { ActionMenu } from '../../components/ActionMenu';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst ALL = 'ALL';\n\nconst RELEASE_STATUSES: CosReleaseStatus[] = ['DRAFT', 'UNDER_REVIEW', 'PUBLISHED', 'RETRACTED'];\n\n/** A release can be published only while it is still in a pre-publication state. */\nfunction canPublish(status: CosReleaseStatus): boolean {\n return status === 'DRAFT' || status === 'UNDER_REVIEW';\n}\n\nfunction formatDate(value?: string | null): string {\n if (!value) {\n return '—';\n }\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return '—';\n }\n return parsed.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\nfunction doiUrl(doi: string): string {\n const trimmed = doi.trim();\n return /^https?:\\/\\//i.test(trimmed)\n ? trimmed\n : `https://doi.org/${trimmed.replace(/^doi:/i, '')}`;\n}\n\nexport default function ReleasesPage() {\n const { navigate } = useCosmicIntersection();\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const pagination = usePagination({ pageSize: 20, resetKey: statusFilter });\n\n const { data, loading, error, refetch } = useCosReleasesQuery({\n status: statusFilter === ALL ? undefined : (statusFilter as CosReleaseStatus),\n pagination: { limit: pagination.limit, offset: pagination.offset },\n });\n\n const [publishRelease, { loading: publishing }] = useCosPublishReleaseMutation();\n\n const releases = useMemo(() => data?.cosListReleases.items ?? [], [data]);\n const pageInfo = data?.cosListReleases.pageInfo;\n\n // Resolve the release's linked dataset/notebook UUIDs to human names so the\n // detail dialog can render navigable buttons instead of raw ids.\n const datasetsQuery = useCosDatasetsQuery({ pagination: { limit: 100, offset: 0 } });\n const notebooksQuery = useCosNotebooksQuery({ pagination: { limit: 100, offset: 0 } });\n const datasetNameById = useMemo(() => {\n const map = new Map<string, string>();\n for (const dataset of datasetsQuery.data?.cosListDatasets.items ?? []) {\n map.set(dataset.id, dataset.name);\n }\n return map;\n }, [datasetsQuery.data]);\n const notebookTitleById = useMemo(() => {\n const map = new Map<string, string>();\n for (const notebook of notebooksQuery.data?.cosListNotebooks.items ?? []) {\n map.set(notebook.id, notebook.title);\n }\n return map;\n }, [notebooksQuery.data]);\n\n // Detail (View) dialog — rendered from row data, no extra fetch needed.\n const [detail, setDetail] = useState<CosRelease | null>(null);\n\n // Close the dialog before navigating to a linked entity.\n const goToLinked = (path: string) => {\n setDetail(null);\n navigate(path);\n };\n\n // Publish dialog — captures an optional DOI before transitioning the release.\n const [publishTarget, setPublishTarget] = useState<CosRelease | null>(null);\n const [doiDraft, setDoiDraft] = useState('');\n\n const openPublish = (release: CosRelease) => {\n setDoiDraft(release.doi ?? '');\n setPublishTarget(release);\n };\n\n const submitPublish = async () => {\n if (!publishTarget) {\n return;\n }\n const doi = doiDraft.trim();\n const response = await publishRelease({\n variables: { id: publishTarget.id, doi: doi || undefined },\n });\n if (response.data?.cosPublishRelease?.id) {\n notify.success('Release published', `“${publishTarget.title}” is now public.`);\n setPublishTarget(null);\n setDoiDraft('');\n await refetch();\n }\n };\n\n const newButton = (\n <Button type=\"button\" onClick={() => navigate('releases/create')}>\n <Plus className=\"size-4\" />\n New release\n </Button>\n );\n\n const renderBody = () => {\n if (loading) {\n return <LoadingState variant=\"rows\" rows={6} label=\"Loading releases…\" />;\n }\n if (error) {\n return <ErrorState message={error.message} onRetry={() => void refetch()} />;\n }\n if (releases.length === 0) {\n const filtered = statusFilter !== ALL;\n return (\n <EmptyState\n icon={Rocket}\n title={filtered ? 'No releases match this filter' : 'No releases yet'}\n description={\n filtered\n ? 'Try clearing the status filter to see more releases.'\n : 'Package datasets and notebooks into a citable, versioned release for publication.'\n }\n action={filtered ? undefined : newButton}\n />\n );\n }\n\n return (\n <>\n <div className=\"overflow-x-auto rounded-card border border-border-default bg-bg-elevated\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Title</TableHead>\n <TableHead>Version</TableHead>\n <TableHead>Status</TableHead>\n <TableHead>DOI</TableHead>\n <TableHead>Authors</TableHead>\n <TableHead>Published</TableHead>\n <TableHead>License</TableHead>\n <TableHead className=\"text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {releases.map((release) => (\n <TableRow key={release.id}>\n <TableCell>\n <button\n type=\"button\"\n onClick={() => setDetail(release)}\n className=\"text-left font-medium text-text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border-focus\"\n >\n {release.title}\n </button>\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-sm text-text-secondary\">\n {release.version || '—'}\n </TableCell>\n <TableCell>\n <StatusBadge status={release.status} />\n </TableCell>\n <TableCell className=\"max-w-[14rem]\">\n {release.doi ? (\n <SafeLink\n href={doiUrl(release.doi)}\n className=\"inline-flex items-center gap-1 truncate text-sm text-text-primary underline-offset-2 hover:underline\"\n fallbackClassName=\"block truncate text-sm text-text-secondary\"\n >\n <span className=\"truncate\">{release.doi}</span>\n <ExternalLink className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n </SafeLink>\n ) : (\n <span className=\"text-sm text-text-secondary\">—</span>\n )}\n </TableCell>\n <TableCell className=\"max-w-[14rem]\">\n {release.authors.length === 0 ? (\n <span className=\"text-sm text-text-secondary\">—</span>\n ) : (\n <span className=\"line-clamp-1 text-sm text-text-secondary\">\n {release.authors.join(', ')}\n </span>\n )}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-sm text-text-secondary\">\n {formatDate(release.publishedAt)}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-sm text-text-secondary\">\n {release.license || '—'}\n </TableCell>\n <TableCell className=\"text-right\">\n <ActionMenu\n ariaLabel={`Actions for ${release.title}`}\n onView={() => setDetail(release)}\n extraItems={\n canPublish(release.status)\n ? [\n {\n key: 'publish',\n label: 'Publish',\n icon: Rocket,\n onSelect: () => openPublish(release),\n },\n ]\n : []\n }\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={releases.length}\n hasMore={pageInfo?.hasMore ?? false}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"releases\"\n loading={loading}\n />\n </>\n );\n };\n\n return (\n <PageLayout\n title=\"Releases\"\n description=\"Citable, versioned publications that bundle datasets and notebooks for the community.\"\n actions={newButton}\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"w-full max-w-[14rem]\">\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger aria-label=\"Filter by status\">\n <SelectValue placeholder=\"All statuses\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>All statuses</SelectItem>\n {RELEASE_STATUSES.map((status) => (\n <SelectItem key={status} value={status}>\n {formatEnumLabel(status)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {renderBody()}\n </div>\n\n {/* View / detail dialog */}\n <Dialog open={detail !== null} onOpenChange={(open) => (open ? undefined : setDetail(null))}>\n <DialogContent className=\"max-h-[85vh] max-w-lg overflow-y-auto\">\n {detail ? (\n <>\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <BookOpen className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n {detail.title}\n </DialogTitle>\n <DialogDescription>\n Version {detail.version || '—'} · <StatusBadge status={detail.status} />\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 text-sm\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Abstract\n </p>\n <p className=\"mt-1 whitespace-pre-wrap text-text-primary\">\n {detail.abstract?.trim() || 'No abstract provided.'}\n </p>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Authors\n </p>\n <p className=\"mt-1 text-text-primary\">\n {detail.authors.length ? detail.authors.join(', ') : '—'}\n </p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n License\n </p>\n <p className=\"mt-1 text-text-primary\">{detail.license || '—'}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Published\n </p>\n <p className=\"mt-1 text-text-primary\">{formatDate(detail.publishedAt)}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n DOI\n </p>\n <p className=\"mt-1\">\n {detail.doi ? (\n <SafeLink\n href={doiUrl(detail.doi)}\n className=\"inline-flex items-center gap-1 text-text-primary underline-offset-2 hover:underline\"\n fallbackClassName=\"text-text-secondary\"\n >\n {detail.doi}\n <ExternalLink className=\"size-3.5\" aria-hidden=\"true\" />\n </SafeLink>\n ) : (\n <span className=\"text-text-secondary\">Not assigned</span>\n )}\n </p>\n </div>\n </div>\n\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Datasets ({detail.datasetIds.length})\n </p>\n <div className=\"mt-1 flex flex-wrap gap-1.5\">\n {detail.datasetIds.length === 0 ? (\n <span className=\"text-text-secondary\">None linked.</span>\n ) : (\n detail.datasetIds.map((datasetId) => {\n const name = datasetNameById.get(datasetId);\n return (\n <Button\n key={datasetId}\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-auto gap-1 px-2 py-1\"\n onClick={() => goToLinked(`datasets/${datasetId}`)}\n >\n <Database className=\"size-3.5\" aria-hidden=\"true\" />\n <span className={name ? '' : 'font-mono text-xs'}>\n {name ?? datasetId}\n </span>\n </Button>\n );\n })\n )}\n </div>\n </div>\n\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Notebook\n </p>\n <div className=\"mt-1\">\n {detail.notebookId ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-auto gap-1 px-2 py-1\"\n onClick={() => goToLinked(`notebooks/${detail.notebookId}`)}\n >\n <NotebookPen className=\"size-3.5\" aria-hidden=\"true\" />\n <span className={notebookTitleById.get(detail.notebookId) ? '' : 'font-mono text-xs'}>\n {notebookTitleById.get(detail.notebookId) ?? detail.notebookId}\n </span>\n </Button>\n ) : (\n <span className=\"text-text-secondary\">None linked.</span>\n )}\n </div>\n </div>\n\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n Discussion\n </p>\n <div className=\"mt-2\">\n <DiscussionPanel\n entityType=\"cosmicintersection-release\"\n entityId={detail.id}\n title={detail.title}\n widgetKey=\"release-discussion\"\n />\n </div>\n </div>\n </div>\n\n <DialogFooter>\n {canPublish(detail.status) ? (\n <Button\n type=\"button\"\n onClick={() => {\n const target = detail;\n setDetail(null);\n openPublish(target);\n }}\n >\n <Rocket className=\"size-4\" />\n Publish\n </Button>\n ) : null}\n <DialogClose asChild>\n <Button type=\"button\" variant=\"outline\">\n Close\n </Button>\n </DialogClose>\n </DialogFooter>\n </>\n ) : null}\n </DialogContent>\n </Dialog>\n\n {/* Publish dialog */}\n <Dialog\n open={publishTarget !== null}\n onOpenChange={(open) => (open || publishing ? undefined : setPublishTarget(null))}\n >\n <DialogContent className=\"max-w-md\">\n <DialogHeader>\n <DialogTitle>Publish release</DialogTitle>\n <DialogDescription>\n {publishTarget\n ? `Publish “${publishTarget.title}” to make it publicly citable. You can attach a DOI now or later.`\n : ''}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"release-doi\">DOI (optional)</Label>\n <Input\n id=\"release-doi\"\n value={doiDraft}\n onChange={(event) => setDoiDraft(event.target.value)}\n placeholder=\"10.1234/cosmic.2026.0001\"\n />\n <p className=\"text-xs text-text-secondary\">\n A Digital Object Identifier makes the release permanently referenceable.\n </p>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setPublishTarget(null)}\n disabled={publishing}\n >\n Cancel\n </Button>\n <Button type=\"button\" onClick={() => void submitPublish()} disabled={publishing}>\n <Rocket className=\"size-4\" />\n {publishing ? 'Publishing…' : 'Publish release'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,28 +1,29 @@
1
1
  import { useCosmicIntersection as e } from "../../context/CosmicIntersectionContext.js";
2
2
  import { notify as t } from "../../lib/toast.js";
3
- import { useCosAddRunStepMutation as n, useCosRunQuery as r, useCosRunStepsQuery as ee, useCosTransitionRunMutation as te } from "../../api/cosmicApi.js";
4
- import i from "../../components/EmptyState.js";
5
- import a from "../../components/ErrorState.js";
6
- import o from "../../components/LoadingState.js";
7
- import s from "../../components/PageLayout.js";
8
- import ne from "../../components/SafeLink.js";
9
- import c, { formatEnumLabel as l } from "../../components/StatusBadge.js";
3
+ import { useCosAddRunStepMutation as n, useCosRunQuery as r, useCosRunStepsQuery as ee, useCosTransitionRunMutation as i } from "../../api/cosmicApi.js";
4
+ import a from "../../components/EmptyState.js";
5
+ import o from "../../components/ErrorState.js";
6
+ import s from "../../components/LoadingState.js";
7
+ import c from "../../components/ActivityFeedPanel.js";
8
+ import l from "../../components/SafeLink.js";
9
+ import u from "../../components/PageLayout.js";
10
+ import d, { formatEnumLabel as f } from "../../components/StatusBadge.js";
10
11
  import "../../components/index.js";
11
- import { describeError as re, mutationSucceeded as u } from "../../lib/mutationResult.js";
12
- import { useMemo as ie, useState as d } from "react";
13
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
14
- import { useParams as m } from "react-router-dom";
15
- import { ListTree as h, Plus as g } from "lucide-react";
16
- import { Button as _, Card as v, CardContent as y, CardHeader as b, CardTitle as x, Dialog as S, DialogContent as ae, DialogDescription as oe, DialogFooter as C, DialogHeader as se, DialogTitle as ce, Input as w, Label as T, Select as E, SelectContent as D, SelectItem as le, SelectTrigger as ue, SelectValue as de, Textarea as fe } from "@burdenoff/fe-libs/ui";
12
+ import { describeError as te, mutationSucceeded as p } from "../../lib/mutationResult.js";
13
+ import { useMemo as ne, useState as m } from "react";
14
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
15
+ import { useParams as _ } from "react-router-dom";
16
+ import { ListTree as re, Plus as v } from "lucide-react";
17
+ import { Button as y, Card as b, CardContent as x, CardHeader as S, CardTitle as C, Dialog as ie, DialogContent as w, DialogDescription as ae, DialogFooter as oe, DialogHeader as T, DialogTitle as se, Input as E, Label as D, Select as ce, SelectContent as le, SelectItem as ue, SelectTrigger as de, SelectValue as fe, Textarea as pe } from "@burdenoff/fe-libs/ui";
17
18
  //#region src/cosmicintersection/pages/runs/RunDetailPage.tsx
18
- var pe = [
19
+ var me = [
19
20
  "INGEST",
20
21
  "CALIBRATE",
21
22
  "TRANSFORM",
22
23
  "ANALYZE",
23
24
  "EXPORT",
24
25
  "NOTIFY"
25
- ], me = {
26
+ ], he = {
26
27
  QUEUED: ["RUNNING", "CANCELLED"],
27
28
  RUNNING: [
28
29
  "SUCCEEDED",
@@ -45,37 +46,37 @@ function k(e) {
45
46
  return t < 60 ? `${t.toFixed(1)} s` : `${Math.floor(t / 60)}m ${Math.round(t % 60)}s`;
46
47
  }
47
48
  function A({ label: e, children: t }) {
48
- return /* @__PURE__ */ p("div", {
49
+ return /* @__PURE__ */ g("div", {
49
50
  className: "flex flex-col gap-1 border-b border-border-seam py-3 last:border-0 sm:flex-row sm:items-start sm:gap-4",
50
- children: [/* @__PURE__ */ f("span", {
51
+ children: [/* @__PURE__ */ h("span", {
51
52
  className: "w-40 shrink-0 text-sm font-medium text-text-secondary",
52
53
  children: e
53
- }), /* @__PURE__ */ f("span", {
54
+ }), /* @__PURE__ */ h("span", {
54
55
  className: "min-w-0 text-sm text-text-primary",
55
56
  children: t
56
57
  })]
57
58
  });
58
59
  }
59
60
  function j({ value: e }) {
60
- return !e || Object.keys(e).length === 0 ? /* @__PURE__ */ f("span", {
61
+ return !e || Object.keys(e).length === 0 ? /* @__PURE__ */ h("span", {
61
62
  className: "text-sm text-text-secondary",
62
63
  children: "—"
63
- }) : /* @__PURE__ */ f("pre", {
64
+ }) : /* @__PURE__ */ h("pre", {
64
65
  className: "overflow-x-auto rounded-card border border-border-default bg-bg-sunken p-3 font-mono text-xs text-text-primary",
65
66
  children: JSON.stringify(e, null, 2)
66
67
  });
67
68
  }
68
69
  function M() {
69
- let { id: M = "" } = m(), { navigate: N } = e(), { data: P, loading: F, error: I, refetch: L } = r(M), { data: R, loading: he, error: ge, refetch: z } = ee(M), [_e, { loading: ve }] = te(), [ye, { loading: B }] = n(), [be, V] = d(!1), [H, U] = d(""), [W, G] = d("INGEST"), [K, q] = d(""), [J, Y] = d(""), X = P?.cosRun, Z = ie(() => [...R?.cosListRunSteps ?? []].sort((e, t) => e.position - t.position), [R]), xe = async (e) => {
70
+ let { id: M = "" } = _(), { navigate: N } = e(), { data: P, loading: F, error: I, refetch: L } = r(M), { data: R, loading: ge, error: _e, refetch: z } = ee(M), [ve, { loading: ye }] = i(), [be, { loading: B }] = n(), [xe, V] = m(!1), [H, U] = m(""), [W, G] = m("INGEST"), [K, q] = m(""), [J, Y] = m(""), X = P?.cosRun, Z = ne(() => [...R?.cosListRunSteps ?? []].sort((e, t) => e.position - t.position), [R]), Se = async (e) => {
70
71
  if (!X) return;
71
- let n = await _e({ variables: {
72
+ let n = await ve({ variables: {
72
73
  id: X.id,
73
74
  status: e
74
75
  } });
75
- u(n, n.data?.cosTransitionRun?.id, "Could not update the run") && (t.success("Run updated", `Run #${X.runNumber} moved to ${l(e)}.`), await Promise.all([L(), z()]));
76
+ p(n, n.data?.cosTransitionRun?.id, "Could not update the run") && (t.success("Run updated", `Run #${X.runNumber} moved to ${f(e)}.`), await Promise.all([L(), z()]));
76
77
  }, Q = () => {
77
78
  U(""), G("INGEST"), q(""), Y("");
78
- }, Se = async () => {
79
+ }, Ce = async () => {
79
80
  if (!X) return;
80
81
  if (!H.trim()) {
81
82
  t.error("Step name is required", "Give the step a name before adding it.");
@@ -87,7 +88,7 @@ function M() {
87
88
  if (typeof t != "object" || !t || Array.isArray(t)) throw Error("Inputs must be a JSON object.");
88
89
  e = t;
89
90
  } catch (e) {
90
- t.error("Invalid inputs JSON", re(e) ?? "Please provide valid JSON.");
91
+ t.error("Invalid inputs JSON", te(e) ?? "Please provide valid JSON.");
91
92
  return;
92
93
  }
93
94
  let n = K.trim() ? Number(K.trim()) : void 0;
@@ -95,32 +96,32 @@ function M() {
95
96
  t.error("Invalid position", "Position must be a non-negative number.");
96
97
  return;
97
98
  }
98
- let r = await ye({ variables: { input: {
99
+ let r = await be({ variables: { input: {
99
100
  runId: X.id,
100
101
  name: H.trim(),
101
102
  kind: W,
102
103
  inputs: e,
103
104
  position: n
104
105
  } } });
105
- u(r, r.data?.cosAddRunStep?.id, "Could not add the step") && (t.success("Step added", `“${H.trim()}” was added to the run.`), V(!1), Q(), await z());
106
+ p(r, r.data?.cosAddRunStep?.id, "Could not add the step") && (t.success("Step added", `“${H.trim()}” was added to the run.`), V(!1), Q(), await z());
106
107
  };
107
- if (F) return /* @__PURE__ */ f(s, {
108
+ if (F) return /* @__PURE__ */ h(u, {
108
109
  title: "Run",
109
110
  backPath: "runs",
110
- children: /* @__PURE__ */ f(o, { label: "Loading run…" })
111
+ children: /* @__PURE__ */ h(s, { label: "Loading run…" })
111
112
  });
112
- if (I) return /* @__PURE__ */ f(s, {
113
+ if (I) return /* @__PURE__ */ h(u, {
113
114
  title: "Run",
114
115
  backPath: "runs",
115
- children: /* @__PURE__ */ f(a, { onRetry: () => void L() })
116
+ children: /* @__PURE__ */ h(o, { onRetry: () => void L() })
116
117
  });
117
- if (!X) return /* @__PURE__ */ f(s, {
118
+ if (!X) return /* @__PURE__ */ h(u, {
118
119
  title: "Run",
119
120
  backPath: "runs",
120
- children: /* @__PURE__ */ f(i, {
121
+ children: /* @__PURE__ */ h(a, {
121
122
  title: "Run not found",
122
123
  description: "This run may have been removed or you may not have access to it.",
123
- action: /* @__PURE__ */ f(_, {
124
+ action: /* @__PURE__ */ h(y, {
124
125
  type: "button",
125
126
  variant: "outline",
126
127
  onClick: () => N("runs"),
@@ -128,196 +129,200 @@ function M() {
128
129
  })
129
130
  })
130
131
  });
131
- let $ = me[X.status] ?? [];
132
- return /* @__PURE__ */ p(s, {
132
+ let $ = he[X.status] ?? [];
133
+ return /* @__PURE__ */ g(u, {
133
134
  title: `Run #${X.runNumber}`,
134
135
  description: X.pipeline ? `Pipeline: ${X.pipeline.name}` : void 0,
135
136
  backPath: "runs",
136
- actions: /* @__PURE__ */ p("div", {
137
+ actions: /* @__PURE__ */ g("div", {
137
138
  className: "flex flex-wrap items-center gap-2",
138
- children: [$.map((e) => /* @__PURE__ */ f(_, {
139
+ children: [$.map((e) => /* @__PURE__ */ h(y, {
139
140
  type: "button",
140
141
  variant: e === "CANCELLED" || e === "FAILED" ? "outline" : "default",
141
- onClick: () => void xe(e),
142
- disabled: ve,
143
- children: `Mark ${l(e)}`
144
- }, e)), /* @__PURE__ */ p(_, {
142
+ onClick: () => void Se(e),
143
+ disabled: ye,
144
+ children: `Mark ${f(e)}`
145
+ }, e)), /* @__PURE__ */ g(y, {
145
146
  type: "button",
146
147
  variant: "outline",
147
148
  onClick: () => V(!0),
148
- children: [/* @__PURE__ */ f(g, { className: "size-4" }), "Add step"]
149
+ children: [/* @__PURE__ */ h(v, { className: "size-4" }), "Add step"]
149
150
  })]
150
151
  }),
151
- children: [/* @__PURE__ */ p("div", {
152
+ children: [/* @__PURE__ */ g("div", {
152
153
  className: "space-y-6",
153
154
  children: [
154
- /* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(b, { children: /* @__PURE__ */ f(x, { children: "Overview" }) }), /* @__PURE__ */ p(y, { children: [
155
- /* @__PURE__ */ f(A, {
155
+ /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h(S, { children: /* @__PURE__ */ h(C, { children: "Overview" }) }), /* @__PURE__ */ g(x, { children: [
156
+ /* @__PURE__ */ h(A, {
156
157
  label: "Status",
157
- children: /* @__PURE__ */ f(c, { status: X.status })
158
+ children: /* @__PURE__ */ h(d, { status: X.status })
158
159
  }),
159
- /* @__PURE__ */ f(A, {
160
+ /* @__PURE__ */ h(A, {
160
161
  label: "Pipeline",
161
- children: X.pipeline ? /* @__PURE__ */ f("button", {
162
+ children: X.pipeline ? /* @__PURE__ */ h("button", {
162
163
  type: "button",
163
164
  className: "text-text-primary underline-offset-2 hover:underline",
164
165
  onClick: () => N(`pipelines/${X.pipelineId}`),
165
166
  children: X.pipeline.name
166
- }) : /* @__PURE__ */ f("span", {
167
+ }) : /* @__PURE__ */ h("span", {
167
168
  className: "font-mono text-xs",
168
169
  children: X.pipelineId
169
170
  })
170
171
  }),
171
- /* @__PURE__ */ f(A, {
172
+ /* @__PURE__ */ h(A, {
172
173
  label: "Dataset",
173
- children: X.datasetId ? /* @__PURE__ */ f("button", {
174
+ children: X.datasetId ? /* @__PURE__ */ h("button", {
174
175
  type: "button",
175
176
  className: "text-text-primary underline-offset-2 hover:underline",
176
177
  onClick: () => N(`datasets/${X.datasetId}`),
177
- children: /* @__PURE__ */ f("span", {
178
+ children: /* @__PURE__ */ h("span", {
178
179
  className: "font-mono text-xs",
179
180
  children: X.datasetId
180
181
  })
181
182
  }) : "—"
182
183
  }),
183
- /* @__PURE__ */ f(A, {
184
+ /* @__PURE__ */ h(A, {
184
185
  label: "Triggered by",
185
186
  children: X.triggeredBy || "—"
186
187
  }),
187
- /* @__PURE__ */ f(A, {
188
+ /* @__PURE__ */ h(A, {
188
189
  label: "Started",
189
190
  children: O(X.startedAt)
190
191
  }),
191
- /* @__PURE__ */ f(A, {
192
+ /* @__PURE__ */ h(A, {
192
193
  label: "Finished",
193
194
  children: O(X.finishedAt)
194
195
  }),
195
- /* @__PURE__ */ f(A, {
196
+ /* @__PURE__ */ h(A, {
196
197
  label: "Duration",
197
198
  children: k(X.durationMs)
198
199
  }),
199
- X.errorMessage ? /* @__PURE__ */ f(A, {
200
+ X.errorMessage ? /* @__PURE__ */ h(A, {
200
201
  label: "Error",
201
- children: /* @__PURE__ */ f("span", {
202
+ children: /* @__PURE__ */ h("span", {
202
203
  className: "text-status-error-text",
203
204
  children: X.errorMessage
204
205
  })
205
206
  }) : null,
206
- $.length === 0 ? /* @__PURE__ */ f(A, {
207
+ $.length === 0 ? /* @__PURE__ */ h(A, {
207
208
  label: "Discuss",
208
- children: /* @__PURE__ */ f(ne, {
209
+ children: /* @__PURE__ */ h(l, {
209
210
  href: "/conversations",
210
211
  className: "text-text-primary underline-offset-2 hover:underline",
211
212
  children: "Open discussions"
212
213
  })
213
214
  }) : null
214
215
  ] })] }),
215
- /* @__PURE__ */ p("div", {
216
+ /* @__PURE__ */ g("div", {
216
217
  className: "grid grid-cols-1 gap-6 lg:grid-cols-2",
217
- children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(b, { children: /* @__PURE__ */ f(x, { children: "Parameters" }) }), /* @__PURE__ */ f(y, { children: /* @__PURE__ */ f(j, { value: X.params }) })] }), /* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(b, { children: /* @__PURE__ */ f(x, { children: "Metrics" }) }), /* @__PURE__ */ f(y, { children: /* @__PURE__ */ f(j, { value: X.metrics }) })] })]
218
+ children: [/* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h(S, { children: /* @__PURE__ */ h(C, { children: "Parameters" }) }), /* @__PURE__ */ h(x, { children: /* @__PURE__ */ h(j, { value: X.params }) })] }), /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h(S, { children: /* @__PURE__ */ h(C, { children: "Metrics" }) }), /* @__PURE__ */ h(x, { children: /* @__PURE__ */ h(j, { value: X.metrics }) })] })]
218
219
  }),
219
- /* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(b, { children: /* @__PURE__ */ f(x, { children: "Steps" }) }), /* @__PURE__ */ f(y, { children: he ? /* @__PURE__ */ f(o, {
220
+ /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h(S, { children: /* @__PURE__ */ h(C, { children: "Steps" }) }), /* @__PURE__ */ h(x, { children: ge ? /* @__PURE__ */ h(s, {
220
221
  variant: "rows",
221
222
  rows: 4,
222
223
  label: "Loading steps…"
223
- }) : ge ? /* @__PURE__ */ f(a, {
224
+ }) : _e ? /* @__PURE__ */ h(o, {
224
225
  message: "Could not load steps.",
225
226
  onRetry: () => void z()
226
- }) : Z.length === 0 ? /* @__PURE__ */ f(i, {
227
- icon: h,
227
+ }) : Z.length === 0 ? /* @__PURE__ */ h(a, {
228
+ icon: re,
228
229
  title: "No steps yet",
229
230
  description: "Add steps to record the ingest, calibration, transform, analyze or export stages of this run.",
230
- action: /* @__PURE__ */ p(_, {
231
+ action: /* @__PURE__ */ g(y, {
231
232
  type: "button",
232
233
  onClick: () => V(!0),
233
- children: [/* @__PURE__ */ f(g, { className: "size-4" }), "Add step"]
234
+ children: [/* @__PURE__ */ h(v, { className: "size-4" }), "Add step"]
234
235
  })
235
- }) : /* @__PURE__ */ f("ol", {
236
+ }) : /* @__PURE__ */ h("ol", {
236
237
  className: "space-y-3",
237
- children: Z.map((e) => /* @__PURE__ */ p("li", {
238
+ children: Z.map((e) => /* @__PURE__ */ g("li", {
238
239
  className: "flex flex-col gap-2 rounded-card border border-border-default bg-bg-elevated p-4 sm:flex-row sm:items-start sm:justify-between",
239
- children: [/* @__PURE__ */ p("div", {
240
+ children: [/* @__PURE__ */ g("div", {
240
241
  className: "flex min-w-0 items-start gap-3",
241
- children: [/* @__PURE__ */ f("span", {
242
+ children: [/* @__PURE__ */ h("span", {
242
243
  className: "mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-xs font-semibold tabular-nums text-text-secondary",
243
244
  children: e.position
244
- }), /* @__PURE__ */ p("div", {
245
+ }), /* @__PURE__ */ g("div", {
245
246
  className: "min-w-0",
246
247
  children: [
247
- /* @__PURE__ */ p("div", {
248
+ /* @__PURE__ */ g("div", {
248
249
  className: "flex flex-wrap items-center gap-2",
249
- children: [/* @__PURE__ */ f("span", {
250
+ children: [/* @__PURE__ */ h("span", {
250
251
  className: "font-medium text-text-primary",
251
252
  children: e.name
252
- }), /* @__PURE__ */ f(c, {
253
+ }), /* @__PURE__ */ h(d, {
253
254
  status: e.kind,
254
255
  tone: "neutral"
255
256
  })]
256
257
  }),
257
- e.errorMessage ? /* @__PURE__ */ f("p", {
258
+ e.errorMessage ? /* @__PURE__ */ h("p", {
258
259
  className: "mt-1 text-xs text-status-error-text",
259
260
  children: e.errorMessage
260
261
  }) : null,
261
- /* @__PURE__ */ p("p", {
262
+ /* @__PURE__ */ g("p", {
262
263
  className: "mt-1 text-xs text-text-secondary",
263
264
  children: ["Duration: ", k(e.durationMs)]
264
265
  })
265
266
  ]
266
267
  })]
267
- }), /* @__PURE__ */ f("div", {
268
+ }), /* @__PURE__ */ h("div", {
268
269
  className: "shrink-0",
269
- children: /* @__PURE__ */ f(c, { status: e.status })
270
+ children: /* @__PURE__ */ h(d, { status: e.status })
270
271
  })]
271
272
  }, e.id))
273
+ }) })] }),
274
+ /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h(S, { children: /* @__PURE__ */ h(C, { children: "Activity" }) }), /* @__PURE__ */ h(x, { children: /* @__PURE__ */ h(c, {
275
+ resourceId: X.id,
276
+ resourceType: "cosmicintersection-run"
272
277
  }) })] })
273
278
  ]
274
- }), /* @__PURE__ */ f(S, {
275
- open: be,
279
+ }), /* @__PURE__ */ h(ie, {
280
+ open: xe,
276
281
  onOpenChange: (e) => {
277
282
  B || (V(e), e || Q());
278
283
  },
279
- children: /* @__PURE__ */ p(ae, { children: [
280
- /* @__PURE__ */ p(se, { children: [/* @__PURE__ */ f(ce, { children: "Add step" }), /* @__PURE__ */ f(oe, { children: "Record a stage of this run — its kind, order and optional inputs." })] }),
281
- /* @__PURE__ */ p("div", {
284
+ children: /* @__PURE__ */ g(w, { children: [
285
+ /* @__PURE__ */ g(T, { children: [/* @__PURE__ */ h(se, { children: "Add step" }), /* @__PURE__ */ h(ae, { children: "Record a stage of this run — its kind, order and optional inputs." })] }),
286
+ /* @__PURE__ */ g("div", {
282
287
  className: "space-y-4",
283
288
  children: [
284
- /* @__PURE__ */ p("div", {
289
+ /* @__PURE__ */ g("div", {
285
290
  className: "space-y-1",
286
- children: [/* @__PURE__ */ f(T, {
291
+ children: [/* @__PURE__ */ h(D, {
287
292
  htmlFor: "step-name",
288
293
  children: "Name"
289
- }), /* @__PURE__ */ f(w, {
294
+ }), /* @__PURE__ */ h(E, {
290
295
  id: "step-name",
291
296
  value: H,
292
297
  onChange: (e) => U(e.target.value),
293
298
  placeholder: "e.g. Calibrate flat fields"
294
299
  })]
295
300
  }),
296
- /* @__PURE__ */ p("div", {
301
+ /* @__PURE__ */ g("div", {
297
302
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
298
- children: [/* @__PURE__ */ p("div", {
303
+ children: [/* @__PURE__ */ g("div", {
299
304
  className: "space-y-1",
300
- children: [/* @__PURE__ */ f(T, {
305
+ children: [/* @__PURE__ */ h(D, {
301
306
  htmlFor: "step-kind",
302
307
  children: "Kind"
303
- }), /* @__PURE__ */ p(E, {
308
+ }), /* @__PURE__ */ g(ce, {
304
309
  value: W,
305
310
  onValueChange: (e) => G(e),
306
- children: [/* @__PURE__ */ f(ue, {
311
+ children: [/* @__PURE__ */ h(de, {
307
312
  id: "step-kind",
308
313
  "aria-label": "Step kind",
309
- children: /* @__PURE__ */ f(de, {})
310
- }), /* @__PURE__ */ f(D, { children: pe.map((e) => /* @__PURE__ */ f(le, {
314
+ children: /* @__PURE__ */ h(fe, {})
315
+ }), /* @__PURE__ */ h(le, { children: me.map((e) => /* @__PURE__ */ h(ue, {
311
316
  value: e,
312
- children: l(e)
317
+ children: f(e)
313
318
  }, e)) })]
314
319
  })]
315
- }), /* @__PURE__ */ p("div", {
320
+ }), /* @__PURE__ */ g("div", {
316
321
  className: "space-y-1",
317
- children: [/* @__PURE__ */ f(T, {
322
+ children: [/* @__PURE__ */ h(D, {
318
323
  htmlFor: "step-position",
319
324
  children: "Position"
320
- }), /* @__PURE__ */ f(w, {
325
+ }), /* @__PURE__ */ h(E, {
321
326
  id: "step-position",
322
327
  type: "number",
323
328
  min: "0",
@@ -327,14 +332,14 @@ function M() {
327
332
  })]
328
333
  })]
329
334
  }),
330
- /* @__PURE__ */ p("div", {
335
+ /* @__PURE__ */ g("div", {
331
336
  className: "space-y-1",
332
337
  children: [
333
- /* @__PURE__ */ f(T, {
338
+ /* @__PURE__ */ h(D, {
334
339
  htmlFor: "step-inputs",
335
340
  children: "Inputs (JSON)"
336
341
  }),
337
- /* @__PURE__ */ f(fe, {
342
+ /* @__PURE__ */ h(pe, {
338
343
  id: "step-inputs",
339
344
  value: J,
340
345
  onChange: (e) => Y(e.target.value),
@@ -343,7 +348,7 @@ function M() {
343
348
  className: "font-mono text-xs",
344
349
  placeholder: "{\n \"source\": \"raw-frames\"\n}"
345
350
  }),
346
- /* @__PURE__ */ f("p", {
351
+ /* @__PURE__ */ h("p", {
347
352
  className: "text-xs text-text-secondary",
348
353
  children: "Optional. A JSON object of step inputs."
349
354
  })
@@ -351,7 +356,7 @@ function M() {
351
356
  })
352
357
  ]
353
358
  }),
354
- /* @__PURE__ */ p(C, { children: [/* @__PURE__ */ f(_, {
359
+ /* @__PURE__ */ g(oe, { children: [/* @__PURE__ */ h(y, {
355
360
  type: "button",
356
361
  variant: "outline",
357
362
  onClick: () => {
@@ -359,11 +364,11 @@ function M() {
359
364
  },
360
365
  disabled: B,
361
366
  children: "Cancel"
362
- }), /* @__PURE__ */ p(_, {
367
+ }), /* @__PURE__ */ g(y, {
363
368
  type: "button",
364
- onClick: () => void Se(),
369
+ onClick: () => void Ce(),
365
370
  disabled: B,
366
- children: [/* @__PURE__ */ f(g, { className: "size-4" }), B ? "Adding…" : "Add step"]
371
+ children: [/* @__PURE__ */ h(v, { className: "size-4" }), B ? "Adding…" : "Add step"]
367
372
  })] })
368
373
  ] })
369
374
  })]