@burdenoff/microfe-cosmicintersection 2026.525.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.
- package/dist/cosmicintersection/CosmicIntersectionRoot.js +38 -113
- package/dist/cosmicintersection/CosmicIntersectionRoot.js.map +1 -1
- package/dist/cosmicintersection/CosmicIntersectionRoutes.js +110 -44
- package/dist/cosmicintersection/CosmicIntersectionRoutes.js.map +1 -1
- package/dist/cosmicintersection/api/cosmicApi.js +918 -0
- package/dist/cosmicintersection/api/cosmicApi.js.map +1 -0
- package/dist/cosmicintersection/components/ActionMenu.js +106 -0
- package/dist/cosmicintersection/components/ActionMenu.js.map +1 -0
- package/dist/cosmicintersection/components/ActivityFeedPanel.js +68 -0
- package/dist/cosmicintersection/components/ActivityFeedPanel.js.map +1 -0
- package/dist/cosmicintersection/components/DiscussionPanel.js +57 -0
- package/dist/cosmicintersection/components/DiscussionPanel.js.map +1 -0
- package/dist/cosmicintersection/components/EmptyState.js +35 -0
- package/dist/cosmicintersection/components/EmptyState.js.map +1 -0
- package/dist/cosmicintersection/components/EntityFormShell.js +57 -0
- package/dist/cosmicintersection/components/EntityFormShell.js.map +1 -0
- package/dist/cosmicintersection/components/EntityTagsField.js +77 -0
- package/dist/cosmicintersection/components/EntityTagsField.js.map +1 -0
- package/dist/cosmicintersection/components/ErrorState.js +40 -0
- package/dist/cosmicintersection/components/ErrorState.js.map +1 -0
- package/dist/cosmicintersection/components/FileUploadField.js +146 -0
- package/dist/cosmicintersection/components/FileUploadField.js.map +1 -0
- package/dist/cosmicintersection/components/LoadingState.js +23 -0
- package/dist/cosmicintersection/components/LoadingState.js.map +1 -0
- package/dist/cosmicintersection/components/PageLayout.js +46 -0
- package/dist/cosmicintersection/components/PageLayout.js.map +1 -0
- package/dist/cosmicintersection/components/Pagination.js +65 -0
- package/dist/cosmicintersection/components/Pagination.js.map +1 -0
- package/dist/cosmicintersection/components/SafeLink.js +35 -0
- package/dist/cosmicintersection/components/SafeLink.js.map +1 -0
- package/dist/cosmicintersection/components/StatusBadge.js +53 -0
- package/dist/cosmicintersection/components/StatusBadge.js.map +1 -0
- package/dist/cosmicintersection/components/index.js +13 -0
- package/dist/cosmicintersection/context/CosmicIntersectionContext.js +46 -0
- package/dist/cosmicintersection/context/CosmicIntersectionContext.js.map +1 -0
- package/dist/cosmicintersection/index.js +0 -2
- package/dist/cosmicintersection/lib/mutationResult.js +12 -0
- package/dist/cosmicintersection/lib/mutationResult.js.map +1 -0
- package/dist/cosmicintersection/lib/toast.js +36 -0
- package/dist/cosmicintersection/lib/toast.js.map +1 -0
- package/dist/cosmicintersection/pages/access/AccessPage.js +347 -0
- package/dist/cosmicintersection/pages/access/AccessPage.js.map +1 -0
- package/dist/cosmicintersection/pages/analyses/AnalysesPage.js +484 -0
- package/dist/cosmicintersection/pages/analyses/AnalysesPage.js.map +1 -0
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js +177 -0
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js +143 -0
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js +112 -0
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -0
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js +246 -0
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js.map +1 -0
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +480 -0
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js +218 -0
- package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/datasets/DatasetsPage.js +252 -0
- package/dist/cosmicintersection/pages/datasets/DatasetsPage.js.map +1 -0
- package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js +402 -0
- package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/notebooks/NotebookFormPage.js +313 -0
- package/dist/cosmicintersection/pages/notebooks/NotebookFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js +203 -0
- package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js.map +1 -0
- package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js +244 -0
- package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js +210 -0
- package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js +193 -0
- package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js.map +1 -0
- package/dist/cosmicintersection/pages/releases/ReleaseFormPage.js +184 -0
- package/dist/cosmicintersection/pages/releases/ReleaseFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js +418 -0
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js.map +1 -0
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js +380 -0
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/runs/RunsPage.js +165 -0
- package/dist/cosmicintersection/pages/runs/RunsPage.js.map +1 -0
- package/dist/cosmicintersection/pages/sources/SourceDetailPage.js +205 -0
- package/dist/cosmicintersection/pages/sources/SourceDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/sources/SourceFormPage.js +229 -0
- package/dist/cosmicintersection/pages/sources/SourceFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/sources/SourcesPage.js +223 -0
- package/dist/cosmicintersection/pages/sources/SourcesPage.js.map +1 -0
- package/dist/cosmicintersection/utils/cn.js +10 -0
- package/dist/cosmicintersection/utils/cn.js.map +1 -0
- package/dist/index.js +2 -4
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +2 -1
- package/dist/cosmicintersection/pages/AiDiscoveryPage.js +0 -363
- package/dist/cosmicintersection/pages/AiDiscoveryPage.js.map +0 -1
- package/dist/cosmicintersection/pages/DashboardPage.js +0 -306
- package/dist/cosmicintersection/pages/DashboardPage.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceCitizenPage.js +0 -287
- package/dist/cosmicintersection/pages/SpaceScienceCitizenPage.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceDataPage.js +0 -385
- package/dist/cosmicintersection/pages/SpaceScienceDataPage.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceDataPage1.js +0 -420
- package/dist/cosmicintersection/pages/SpaceScienceDataPage1.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceLearningPage.js +0 -309
- package/dist/cosmicintersection/pages/SpaceScienceLearningPage.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceLearningPage1.js +0 -361
- package/dist/cosmicintersection/pages/SpaceScienceLearningPage1.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceSciencePage.js +0 -194
- package/dist/cosmicintersection/pages/SpaceSciencePage.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceResearchPage.js +0 -290
- package/dist/cosmicintersection/pages/SpaceScienceResearchPage.js.map +0 -1
- package/dist/cosmicintersection/pages/SpaceScienceSimulationPage.js +0 -279
- package/dist/cosmicintersection/pages/SpaceScienceSimulationPage.js.map +0 -1
- package/dist/cosmicintersection/providers/CosmicIntersectionProvider.js +0 -27
- package/dist/cosmicintersection/providers/CosmicIntersectionProvider.js.map +0 -1
- package/dist/cosmicintersection/store/cosmicintersectionStore.js +0 -478
- package/dist/cosmicintersection/store/cosmicintersectionStore.js.map +0 -1
- package/dist/cosmicintersection/utils/i18n.js +0 -15
- package/dist/cosmicintersection/utils/i18n.js.map +0 -1
- package/dist/cosmicintersection/utils/navigation.js +0 -8
- package/dist/cosmicintersection/utils/navigation.js.map +0 -1
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { useCosmicIntersection as e } from "../../context/CosmicIntersectionContext.js";
|
|
2
|
+
import { notify as t } from "../../lib/toast.js";
|
|
3
|
+
import { useCosAddSchemaFieldMutation as n, useCosArchiveDatasetMutation as r, useCosDatasetQuery as i, useCosPublishDatasetMutation as a, useCosUpdateDatasetMutation as ee } from "../../api/cosmicApi.js";
|
|
4
|
+
import te from "../../components/ActionMenu.js";
|
|
5
|
+
import o from "../../components/EmptyState.js";
|
|
6
|
+
import ne from "../../components/ErrorState.js";
|
|
7
|
+
import re from "../../components/LoadingState.js";
|
|
8
|
+
import ie from "../../components/ActivityFeedPanel.js";
|
|
9
|
+
import ae from "../../components/DiscussionPanel.js";
|
|
10
|
+
import oe from "../../components/EntityTagsField.js";
|
|
11
|
+
import { useFileDownloadUrl as s } from "../../components/FileUploadField.js";
|
|
12
|
+
import c from "../../components/PageLayout.js";
|
|
13
|
+
import l, { formatEnumLabel as u } from "../../components/StatusBadge.js";
|
|
14
|
+
import "../../components/index.js";
|
|
15
|
+
import { useState as d } from "react";
|
|
16
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
17
|
+
import { useParams as se } from "react-router-dom";
|
|
18
|
+
import { Boxes as ce, Columns3 as m, Database as le, Download as ue, History as de, MessagesSquare as fe, Pencil as pe, Plus as h, Radar as me } from "lucide-react";
|
|
19
|
+
import { Badge as g, Button as _, Checkbox as he, Dialog as ge, DialogContent as _e, DialogDescription as ve, DialogFooter as ye, DialogHeader as be, DialogTitle as xe, Input as v, Label as y, Select as Se, SelectContent as Ce, SelectItem as we, SelectTrigger as Te, SelectValue as Ee, Table as De, TableBody as Oe, TableCell as b, TableHead as x, TableHeader as S, TableRow as C, Textarea as w } from "@burdenoff/fe-libs/ui";
|
|
20
|
+
//#region src/cosmicintersection/pages/datasets/DatasetDetailPage.tsx
|
|
21
|
+
var T = [
|
|
22
|
+
"STRING",
|
|
23
|
+
"INTEGER",
|
|
24
|
+
"FLOAT",
|
|
25
|
+
"BOOLEAN",
|
|
26
|
+
"TIMESTAMP",
|
|
27
|
+
"COORDINATE",
|
|
28
|
+
"SPECTRUM",
|
|
29
|
+
"GEOMETRY",
|
|
30
|
+
"IMAGE_REF",
|
|
31
|
+
"JSON"
|
|
32
|
+
];
|
|
33
|
+
function ke(e) {
|
|
34
|
+
if (!e) return "—";
|
|
35
|
+
let t = Number(e);
|
|
36
|
+
if (!Number.isFinite(t) || t <= 0) return "—";
|
|
37
|
+
let n = [
|
|
38
|
+
"B",
|
|
39
|
+
"KB",
|
|
40
|
+
"MB",
|
|
41
|
+
"GB",
|
|
42
|
+
"TB",
|
|
43
|
+
"PB"
|
|
44
|
+
], r = t, i = 0;
|
|
45
|
+
for (; r >= 1024 && i < n.length - 1;) r /= 1024, i += 1;
|
|
46
|
+
return `${r >= 10 || i === 0 ? Math.round(r) : r.toFixed(1)} ${n[i]}`;
|
|
47
|
+
}
|
|
48
|
+
function E(e) {
|
|
49
|
+
if (!e) return "—";
|
|
50
|
+
let t = new Date(e);
|
|
51
|
+
return Number.isNaN(t.getTime()) ? "—" : t.toLocaleString();
|
|
52
|
+
}
|
|
53
|
+
function D({ label: e, value: t }) {
|
|
54
|
+
return /* @__PURE__ */ p("div", {
|
|
55
|
+
className: "rounded-card border border-border-default bg-bg-elevated p-4",
|
|
56
|
+
children: [/* @__PURE__ */ f("p", {
|
|
57
|
+
className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
|
|
58
|
+
children: e
|
|
59
|
+
}), /* @__PURE__ */ f("div", {
|
|
60
|
+
className: "mt-1 text-sm text-text-primary",
|
|
61
|
+
children: t
|
|
62
|
+
})]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function O() {
|
|
66
|
+
let { id: O = "" } = se(), { navigate: k } = e(), { data: Ae, loading: je, error: Me, refetch: A } = i(O), j = Ae?.cosDataset ?? null, M = s(j?.file?.id).data?.getFileDownloadUrl ?? null, [Ne, { loading: N }] = a(), [Pe] = r(), [Fe, { loading: P }] = ee(), [Ie, { loading: F }] = n(), [I, L] = d([]), [Le, Re] = d(null), R = j ? `${j.id}:${j.updatedAt}` : null;
|
|
67
|
+
R && R !== Le && (Re(R), L(j?.tags ?? []));
|
|
68
|
+
let ze = j != null && (I.length !== j.tags.length || I.some((e, t) => e !== j.tags[t])), [Be, Ve] = d(!1), [z, B] = d(""), [V, H] = d("STRING"), [U, W] = d(""), [G, K] = d(""), [q, J] = d(""), [Y, X] = d(!0), He = () => {
|
|
69
|
+
B(""), H("STRING"), W(""), K(""), J(""), X(!0);
|
|
70
|
+
}, Z = (e) => {
|
|
71
|
+
Ve(e), e || He();
|
|
72
|
+
};
|
|
73
|
+
if (je) return /* @__PURE__ */ f(c, {
|
|
74
|
+
title: "Dataset",
|
|
75
|
+
backPath: "datasets",
|
|
76
|
+
children: /* @__PURE__ */ f(re, { label: "Loading dataset…" })
|
|
77
|
+
});
|
|
78
|
+
if (Me) return /* @__PURE__ */ f(c, {
|
|
79
|
+
title: "Dataset",
|
|
80
|
+
backPath: "datasets",
|
|
81
|
+
children: /* @__PURE__ */ f(ne, {
|
|
82
|
+
message: "We could not load this dataset.",
|
|
83
|
+
onRetry: () => void A()
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
if (!j) return /* @__PURE__ */ f(c, {
|
|
87
|
+
title: "Dataset",
|
|
88
|
+
backPath: "datasets",
|
|
89
|
+
children: /* @__PURE__ */ f(o, {
|
|
90
|
+
icon: le,
|
|
91
|
+
title: "Dataset not found.",
|
|
92
|
+
description: "This dataset may have been removed or is outside your current scope.",
|
|
93
|
+
action: /* @__PURE__ */ f(_, {
|
|
94
|
+
type: "button",
|
|
95
|
+
onClick: () => k("datasets"),
|
|
96
|
+
children: "Back to datasets"
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
});
|
|
100
|
+
let Q = [...j.schemaFields ?? []].sort((e, t) => e.position - t.position), Ue = j.status !== "AVAILABLE" && j.status !== "ARCHIVED", $ = async () => {
|
|
101
|
+
(await Ne({ variables: { id: j.id } })).data?.cosPublishDataset && (t.success("Dataset published", `“${j.name}” is now available.`), await A());
|
|
102
|
+
}, We = async () => {
|
|
103
|
+
let e = await Pe({ variables: { id: j.id } });
|
|
104
|
+
if (e.error) throw Error(e.error.message);
|
|
105
|
+
if (!e.data?.cosArchiveDataset) throw t.error("Could not archive dataset", "The server did not confirm the change."), Error("Archive not confirmed");
|
|
106
|
+
t.success("Dataset archived"), k("datasets");
|
|
107
|
+
}, Ge = async () => {
|
|
108
|
+
(await Fe({ variables: {
|
|
109
|
+
id: j.id,
|
|
110
|
+
input: { tags: I }
|
|
111
|
+
} })).data?.cosUpdateDataset && (t.success("Tags updated"), await A());
|
|
112
|
+
}, Ke = async () => {
|
|
113
|
+
if (!z.trim()) {
|
|
114
|
+
t.error("Field name is required");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
(await Ie({ variables: { input: {
|
|
118
|
+
datasetId: j.id,
|
|
119
|
+
name: z.trim(),
|
|
120
|
+
fieldType: V,
|
|
121
|
+
unit: U.trim() || void 0,
|
|
122
|
+
description: G.trim() || void 0,
|
|
123
|
+
provenance: q.trim() || void 0,
|
|
124
|
+
nullable: Y
|
|
125
|
+
} } })).data?.cosAddSchemaField && (t.success("Schema field added"), Z(!1), await A());
|
|
126
|
+
};
|
|
127
|
+
return /* @__PURE__ */ p(c, {
|
|
128
|
+
title: j.name,
|
|
129
|
+
description: j.description ?? void 0,
|
|
130
|
+
backPath: "datasets",
|
|
131
|
+
actions: /* @__PURE__ */ p("div", {
|
|
132
|
+
className: "flex items-center gap-2",
|
|
133
|
+
children: [
|
|
134
|
+
/* @__PURE__ */ p(_, {
|
|
135
|
+
type: "button",
|
|
136
|
+
variant: "outline",
|
|
137
|
+
onClick: () => k(`datasets/${j.id}/edit`),
|
|
138
|
+
children: [/* @__PURE__ */ f(pe, { className: "size-4" }), "Edit"]
|
|
139
|
+
}),
|
|
140
|
+
Ue ? /* @__PURE__ */ f(_, {
|
|
141
|
+
type: "button",
|
|
142
|
+
onClick: () => void $(),
|
|
143
|
+
disabled: N,
|
|
144
|
+
children: N ? "Publishing…" : "Publish"
|
|
145
|
+
}) : null,
|
|
146
|
+
/* @__PURE__ */ f(te, {
|
|
147
|
+
ariaLabel: `Actions for ${j.name}`,
|
|
148
|
+
entityName: j.name,
|
|
149
|
+
onDelete: () => We(),
|
|
150
|
+
deleteLabel: "Archive dataset"
|
|
151
|
+
})
|
|
152
|
+
]
|
|
153
|
+
}),
|
|
154
|
+
children: [/* @__PURE__ */ p("div", {
|
|
155
|
+
className: "space-y-6",
|
|
156
|
+
children: [
|
|
157
|
+
/* @__PURE__ */ p("div", {
|
|
158
|
+
className: "flex flex-wrap items-center gap-2",
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ f(l, { status: j.status }),
|
|
161
|
+
/* @__PURE__ */ f(l, {
|
|
162
|
+
status: j.accessLevel,
|
|
163
|
+
label: u(j.accessLevel)
|
|
164
|
+
}),
|
|
165
|
+
j.lineageCaptured ? /* @__PURE__ */ f(g, {
|
|
166
|
+
variant: "secondary",
|
|
167
|
+
children: "Lineage captured"
|
|
168
|
+
}) : null,
|
|
169
|
+
/* @__PURE__ */ p(g, {
|
|
170
|
+
variant: "secondary",
|
|
171
|
+
children: ["v", j.version]
|
|
172
|
+
})
|
|
173
|
+
]
|
|
174
|
+
}),
|
|
175
|
+
/* @__PURE__ */ p("div", {
|
|
176
|
+
className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4",
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ f(D, {
|
|
179
|
+
label: "Source",
|
|
180
|
+
value: j.source ? /* @__PURE__ */ p("button", {
|
|
181
|
+
type: "button",
|
|
182
|
+
onClick: () => k(`sources/${j.source?.id}`),
|
|
183
|
+
className: "inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline",
|
|
184
|
+
children: [/* @__PURE__ */ f(me, {
|
|
185
|
+
className: "size-4 text-text-secondary",
|
|
186
|
+
"aria-hidden": "true"
|
|
187
|
+
}), j.source.name]
|
|
188
|
+
}) : /* @__PURE__ */ f("span", {
|
|
189
|
+
className: "text-text-secondary",
|
|
190
|
+
children: "Not linked"
|
|
191
|
+
})
|
|
192
|
+
}),
|
|
193
|
+
/* @__PURE__ */ f(D, {
|
|
194
|
+
label: "Collection",
|
|
195
|
+
value: j.collection ? /* @__PURE__ */ p("button", {
|
|
196
|
+
type: "button",
|
|
197
|
+
onClick: () => k(`collections/${j.collection?.id}`),
|
|
198
|
+
className: "inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline",
|
|
199
|
+
children: [/* @__PURE__ */ f(ce, {
|
|
200
|
+
className: "size-4 text-text-secondary",
|
|
201
|
+
"aria-hidden": "true"
|
|
202
|
+
}), j.collection.name]
|
|
203
|
+
}) : /* @__PURE__ */ f("span", {
|
|
204
|
+
className: "text-text-secondary",
|
|
205
|
+
children: "Not in a collection"
|
|
206
|
+
})
|
|
207
|
+
}),
|
|
208
|
+
/* @__PURE__ */ f(D, {
|
|
209
|
+
label: "Format",
|
|
210
|
+
value: /* @__PURE__ */ f("span", { children: j.format || "Not specified" })
|
|
211
|
+
}),
|
|
212
|
+
/* @__PURE__ */ f(D, {
|
|
213
|
+
label: "Size",
|
|
214
|
+
value: /* @__PURE__ */ p("span", {
|
|
215
|
+
className: "tabular-nums",
|
|
216
|
+
children: [ke(j.sizeBytes), Number(j.rowCount) > 0 ? /* @__PURE__ */ p("span", {
|
|
217
|
+
className: "text-text-secondary",
|
|
218
|
+
children: [
|
|
219
|
+
" ",
|
|
220
|
+
"· ",
|
|
221
|
+
Number(j.rowCount).toLocaleString(),
|
|
222
|
+
" rows"
|
|
223
|
+
]
|
|
224
|
+
}) : null]
|
|
225
|
+
})
|
|
226
|
+
}),
|
|
227
|
+
/* @__PURE__ */ f(D, {
|
|
228
|
+
label: "Ingested",
|
|
229
|
+
value: /* @__PURE__ */ f("span", { children: E(j.ingestedAt) })
|
|
230
|
+
}),
|
|
231
|
+
/* @__PURE__ */ f(D, {
|
|
232
|
+
label: "Created",
|
|
233
|
+
value: /* @__PURE__ */ f("span", { children: E(j.createdAt) })
|
|
234
|
+
}),
|
|
235
|
+
/* @__PURE__ */ f(D, {
|
|
236
|
+
label: "Updated",
|
|
237
|
+
value: /* @__PURE__ */ f("span", { children: E(j.updatedAt) })
|
|
238
|
+
}),
|
|
239
|
+
/* @__PURE__ */ f(D, {
|
|
240
|
+
label: "Artifact",
|
|
241
|
+
value: j.file ? M ? /* @__PURE__ */ p("a", {
|
|
242
|
+
href: M,
|
|
243
|
+
target: "_blank",
|
|
244
|
+
rel: "noopener noreferrer",
|
|
245
|
+
className: "inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline",
|
|
246
|
+
children: [/* @__PURE__ */ f(ue, {
|
|
247
|
+
className: "size-4",
|
|
248
|
+
"aria-hidden": "true"
|
|
249
|
+
}), "Download file"]
|
|
250
|
+
}) : /* @__PURE__ */ f("span", {
|
|
251
|
+
className: "text-text-secondary",
|
|
252
|
+
children: "Resolving link…"
|
|
253
|
+
}) : /* @__PURE__ */ f("span", {
|
|
254
|
+
className: "text-text-secondary",
|
|
255
|
+
children: "No file attached"
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
]
|
|
259
|
+
}),
|
|
260
|
+
/* @__PURE__ */ p("section", {
|
|
261
|
+
className: "space-y-3",
|
|
262
|
+
children: [/* @__PURE__ */ p("div", {
|
|
263
|
+
className: "flex items-center justify-between gap-3",
|
|
264
|
+
children: [/* @__PURE__ */ p("div", {
|
|
265
|
+
className: "flex items-center gap-2",
|
|
266
|
+
children: [/* @__PURE__ */ f(m, {
|
|
267
|
+
className: "size-5 text-text-secondary",
|
|
268
|
+
"aria-hidden": "true"
|
|
269
|
+
}), /* @__PURE__ */ f("h2", {
|
|
270
|
+
className: "text-lg font-semibold text-text-primary",
|
|
271
|
+
children: "Schema fields"
|
|
272
|
+
})]
|
|
273
|
+
}), /* @__PURE__ */ p(_, {
|
|
274
|
+
type: "button",
|
|
275
|
+
variant: "outline",
|
|
276
|
+
size: "sm",
|
|
277
|
+
onClick: () => Z(!0),
|
|
278
|
+
children: [/* @__PURE__ */ f(h, { className: "size-4" }), "Add field"]
|
|
279
|
+
})]
|
|
280
|
+
}), Q.length === 0 ? /* @__PURE__ */ f(o, {
|
|
281
|
+
icon: m,
|
|
282
|
+
title: "No schema fields yet.",
|
|
283
|
+
description: "Describe the columns in this dataset so consumers know what each field means."
|
|
284
|
+
}) : /* @__PURE__ */ f("div", {
|
|
285
|
+
className: "rounded-card border border-border-default bg-bg-elevated",
|
|
286
|
+
children: /* @__PURE__ */ p(De, { children: [/* @__PURE__ */ f(S, { children: /* @__PURE__ */ p(C, { children: [
|
|
287
|
+
/* @__PURE__ */ f(x, { children: "Name" }),
|
|
288
|
+
/* @__PURE__ */ f(x, { children: "Type" }),
|
|
289
|
+
/* @__PURE__ */ f(x, { children: "Unit" }),
|
|
290
|
+
/* @__PURE__ */ f(x, { children: "Nullable" }),
|
|
291
|
+
/* @__PURE__ */ f(x, { children: "Provenance" })
|
|
292
|
+
] }) }), /* @__PURE__ */ f(Oe, { children: Q.map((e) => /* @__PURE__ */ p(C, { children: [
|
|
293
|
+
/* @__PURE__ */ p(b, { children: [/* @__PURE__ */ f("span", {
|
|
294
|
+
className: "font-medium text-text-primary",
|
|
295
|
+
children: e.name
|
|
296
|
+
}), e.description ? /* @__PURE__ */ f("p", {
|
|
297
|
+
className: "mt-0.5 line-clamp-1 max-w-xs text-xs text-text-secondary",
|
|
298
|
+
children: e.description
|
|
299
|
+
}) : null] }),
|
|
300
|
+
/* @__PURE__ */ f(b, { children: /* @__PURE__ */ f(g, {
|
|
301
|
+
variant: "secondary",
|
|
302
|
+
children: u(e.fieldType)
|
|
303
|
+
}) }),
|
|
304
|
+
/* @__PURE__ */ f(b, {
|
|
305
|
+
className: "text-sm text-text-secondary",
|
|
306
|
+
children: e.unit || "—"
|
|
307
|
+
}),
|
|
308
|
+
/* @__PURE__ */ f(b, {
|
|
309
|
+
className: "text-sm text-text-secondary",
|
|
310
|
+
children: e.nullable ? "Yes" : "No"
|
|
311
|
+
}),
|
|
312
|
+
/* @__PURE__ */ f(b, {
|
|
313
|
+
className: "text-sm text-text-secondary",
|
|
314
|
+
children: e.provenance || "—"
|
|
315
|
+
})
|
|
316
|
+
] }, e.id)) })] })
|
|
317
|
+
})]
|
|
318
|
+
}),
|
|
319
|
+
/* @__PURE__ */ p("section", {
|
|
320
|
+
className: "space-y-3 rounded-card border border-border-default bg-bg-elevated p-5",
|
|
321
|
+
children: [/* @__PURE__ */ f(oe, {
|
|
322
|
+
value: I,
|
|
323
|
+
onChange: L,
|
|
324
|
+
label: "Dataset tags"
|
|
325
|
+
}), ze ? /* @__PURE__ */ f("div", {
|
|
326
|
+
className: "flex justify-end",
|
|
327
|
+
children: /* @__PURE__ */ f(_, {
|
|
328
|
+
type: "button",
|
|
329
|
+
size: "sm",
|
|
330
|
+
onClick: () => void Ge(),
|
|
331
|
+
disabled: P,
|
|
332
|
+
children: P ? "Saving…" : "Save tags"
|
|
333
|
+
})
|
|
334
|
+
}) : null]
|
|
335
|
+
}),
|
|
336
|
+
/* @__PURE__ */ p("section", {
|
|
337
|
+
className: "space-y-3",
|
|
338
|
+
children: [/* @__PURE__ */ p("div", {
|
|
339
|
+
className: "flex items-center gap-2",
|
|
340
|
+
children: [/* @__PURE__ */ f(de, {
|
|
341
|
+
className: "size-5 text-text-secondary",
|
|
342
|
+
"aria-hidden": "true"
|
|
343
|
+
}), /* @__PURE__ */ f("h2", {
|
|
344
|
+
className: "text-lg font-semibold text-text-primary",
|
|
345
|
+
children: "Activity"
|
|
346
|
+
})]
|
|
347
|
+
}), /* @__PURE__ */ f(ie, {
|
|
348
|
+
resourceId: j.id,
|
|
349
|
+
resourceType: "cosmicintersection-dataset"
|
|
350
|
+
})]
|
|
351
|
+
}),
|
|
352
|
+
/* @__PURE__ */ p("section", {
|
|
353
|
+
className: "space-y-3",
|
|
354
|
+
children: [/* @__PURE__ */ p("div", {
|
|
355
|
+
className: "flex items-center gap-2",
|
|
356
|
+
children: [/* @__PURE__ */ f(fe, {
|
|
357
|
+
className: "size-5 text-text-secondary",
|
|
358
|
+
"aria-hidden": "true"
|
|
359
|
+
}), /* @__PURE__ */ f("h2", {
|
|
360
|
+
className: "text-lg font-semibold text-text-primary",
|
|
361
|
+
children: "Discussion"
|
|
362
|
+
})]
|
|
363
|
+
}), /* @__PURE__ */ f(ae, {
|
|
364
|
+
entityType: "cosmicintersection-dataset",
|
|
365
|
+
entityId: j.id,
|
|
366
|
+
title: j.name,
|
|
367
|
+
widgetKey: "dataset-discussion"
|
|
368
|
+
})]
|
|
369
|
+
})
|
|
370
|
+
]
|
|
371
|
+
}), /* @__PURE__ */ f(ge, {
|
|
372
|
+
open: Be,
|
|
373
|
+
onOpenChange: Z,
|
|
374
|
+
children: /* @__PURE__ */ p(_e, { children: [
|
|
375
|
+
/* @__PURE__ */ p(be, { children: [/* @__PURE__ */ f(xe, { children: "Add schema field" }), /* @__PURE__ */ p(ve, { children: [
|
|
376
|
+
"Document a column in “",
|
|
377
|
+
j.name,
|
|
378
|
+
"” — its type, unit and provenance."
|
|
379
|
+
] })] }),
|
|
380
|
+
/* @__PURE__ */ p("div", {
|
|
381
|
+
className: "space-y-4",
|
|
382
|
+
children: [
|
|
383
|
+
/* @__PURE__ */ p("div", {
|
|
384
|
+
className: "space-y-1.5",
|
|
385
|
+
children: [/* @__PURE__ */ f(y, {
|
|
386
|
+
htmlFor: "cos-field-name",
|
|
387
|
+
children: "Name"
|
|
388
|
+
}), /* @__PURE__ */ f(v, {
|
|
389
|
+
id: "cos-field-name",
|
|
390
|
+
value: z,
|
|
391
|
+
onChange: (e) => B(e.target.value),
|
|
392
|
+
placeholder: "e.g. right_ascension",
|
|
393
|
+
required: !0
|
|
394
|
+
})]
|
|
395
|
+
}),
|
|
396
|
+
/* @__PURE__ */ p("div", {
|
|
397
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
398
|
+
children: [/* @__PURE__ */ p("div", {
|
|
399
|
+
className: "space-y-1.5",
|
|
400
|
+
children: [/* @__PURE__ */ f(y, {
|
|
401
|
+
htmlFor: "cos-field-type",
|
|
402
|
+
children: "Type"
|
|
403
|
+
}), /* @__PURE__ */ p(Se, {
|
|
404
|
+
value: V,
|
|
405
|
+
onValueChange: (e) => H(e),
|
|
406
|
+
children: [/* @__PURE__ */ f(Te, {
|
|
407
|
+
id: "cos-field-type",
|
|
408
|
+
"aria-label": "Field type",
|
|
409
|
+
children: /* @__PURE__ */ f(Ee, {})
|
|
410
|
+
}), /* @__PURE__ */ f(Ce, { children: T.map((e) => /* @__PURE__ */ f(we, {
|
|
411
|
+
value: e,
|
|
412
|
+
children: u(e)
|
|
413
|
+
}, e)) })]
|
|
414
|
+
})]
|
|
415
|
+
}), /* @__PURE__ */ p("div", {
|
|
416
|
+
className: "space-y-1.5",
|
|
417
|
+
children: [/* @__PURE__ */ f(y, {
|
|
418
|
+
htmlFor: "cos-field-unit",
|
|
419
|
+
children: "Unit"
|
|
420
|
+
}), /* @__PURE__ */ f(v, {
|
|
421
|
+
id: "cos-field-unit",
|
|
422
|
+
value: U,
|
|
423
|
+
onChange: (e) => W(e.target.value),
|
|
424
|
+
placeholder: "e.g. deg, mag, Jy"
|
|
425
|
+
})]
|
|
426
|
+
})]
|
|
427
|
+
}),
|
|
428
|
+
/* @__PURE__ */ p("div", {
|
|
429
|
+
className: "space-y-1.5",
|
|
430
|
+
children: [/* @__PURE__ */ f(y, {
|
|
431
|
+
htmlFor: "cos-field-desc",
|
|
432
|
+
children: "Description"
|
|
433
|
+
}), /* @__PURE__ */ f(w, {
|
|
434
|
+
id: "cos-field-desc",
|
|
435
|
+
value: G,
|
|
436
|
+
onChange: (e) => K(e.target.value),
|
|
437
|
+
rows: 2
|
|
438
|
+
})]
|
|
439
|
+
}),
|
|
440
|
+
/* @__PURE__ */ p("div", {
|
|
441
|
+
className: "space-y-1.5",
|
|
442
|
+
children: [/* @__PURE__ */ f(y, {
|
|
443
|
+
htmlFor: "cos-field-prov",
|
|
444
|
+
children: "Provenance"
|
|
445
|
+
}), /* @__PURE__ */ f(v, {
|
|
446
|
+
id: "cos-field-prov",
|
|
447
|
+
value: q,
|
|
448
|
+
onChange: (e) => J(e.target.value),
|
|
449
|
+
placeholder: "Where this field comes from"
|
|
450
|
+
})]
|
|
451
|
+
}),
|
|
452
|
+
/* @__PURE__ */ p("label", {
|
|
453
|
+
className: "flex items-center gap-2 text-sm text-text-primary",
|
|
454
|
+
children: [/* @__PURE__ */ f(he, {
|
|
455
|
+
checked: Y,
|
|
456
|
+
onCheckedChange: (e) => X(e === !0)
|
|
457
|
+
}), "Nullable (may contain empty values)"]
|
|
458
|
+
})
|
|
459
|
+
]
|
|
460
|
+
}),
|
|
461
|
+
/* @__PURE__ */ p(ye, { children: [/* @__PURE__ */ f(_, {
|
|
462
|
+
type: "button",
|
|
463
|
+
variant: "outline",
|
|
464
|
+
onClick: () => Z(!1),
|
|
465
|
+
disabled: F,
|
|
466
|
+
children: "Cancel"
|
|
467
|
+
}), /* @__PURE__ */ f(_, {
|
|
468
|
+
type: "button",
|
|
469
|
+
onClick: () => void Ke(),
|
|
470
|
+
disabled: F,
|
|
471
|
+
children: F ? "Adding…" : "Add field"
|
|
472
|
+
})] })
|
|
473
|
+
] })
|
|
474
|
+
})]
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
//#endregion
|
|
478
|
+
export { O as default };
|
|
479
|
+
|
|
480
|
+
//# sourceMappingURL=DatasetDetailPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatasetDetailPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/datasets/DatasetDetailPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n Boxes,\n Columns3,\n Database,\n Download,\n History,\n MessagesSquare,\n Pencil,\n Plus,\n Radar,\n} from 'lucide-react';\nimport {\n Badge,\n Button,\n Checkbox,\n Dialog,\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 Textarea,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosAddSchemaFieldMutation,\n useCosArchiveDatasetMutation,\n useCosDatasetQuery,\n useCosPublishDatasetMutation,\n useCosUpdateDatasetMutation,\n type CosFieldType,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n ActivityFeedPanel,\n DiscussionPanel,\n EmptyState,\n EntityTagsField,\n ErrorState,\n LoadingState,\n PageLayout,\n StatusBadge,\n formatEnumLabel,\n useFileDownloadUrl,\n} from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst FIELD_TYPES: CosFieldType[] = [\n 'STRING',\n 'INTEGER',\n 'FLOAT',\n 'BOOLEAN',\n 'TIMESTAMP',\n 'COORDINATE',\n 'SPECTRUM',\n 'GEOMETRY',\n 'IMAGE_REF',\n 'JSON',\n];\n\nfunction formatBytes(raw: string | null | undefined): string {\n if (!raw) {\n return '—';\n }\n const bytes = Number(raw);\n if (!Number.isFinite(bytes) || bytes <= 0) {\n return '—';\n }\n const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n let value = bytes;\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n return `${value >= 10 || unit === 0 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;\n}\n\nfunction formatDateTime(raw: string | null | undefined): string {\n if (!raw) {\n return '—';\n }\n const date = new Date(raw);\n return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString();\n}\n\nfunction MetaTile({ label, value }: { label: string; value: React.ReactNode }) {\n return (\n <div className=\"rounded-card border border-border-default bg-bg-elevated p-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">{label}</p>\n <div className=\"mt-1 text-sm text-text-primary\">{value}</div>\n </div>\n );\n}\n\nexport default function DatasetDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useCosmicIntersection();\n\n const { data, loading, error, refetch } = useCosDatasetQuery(id);\n const dataset = data?.cosDataset ?? null;\n\n const download = useFileDownloadUrl(dataset?.file?.id);\n const downloadUrl = download.data?.getFileDownloadUrl ?? null;\n\n const [publishDataset, { loading: publishing }] = useCosPublishDatasetMutation();\n const [archiveDataset] = useCosArchiveDatasetMutation();\n const [updateDataset, { loading: savingTags }] = useCosUpdateDatasetMutation();\n const [addSchemaField, { loading: addingField }] = useCosAddSchemaFieldMutation();\n\n // Local, dirty-tracked copy of the tags array so we persist explicitly. Re-sync\n // from the server whenever the dataset (or its updatedAt, after a save) changes\n // — the documented derive-state-during-render pattern, no effect needed.\n const [tags, setTags] = useState<string[]>([]);\n const [syncedKey, setSyncedKey] = useState<string | null>(null);\n const datasetKey = dataset ? `${dataset.id}:${dataset.updatedAt}` : null;\n if (datasetKey && datasetKey !== syncedKey) {\n setSyncedKey(datasetKey);\n setTags(dataset?.tags ?? []);\n }\n const tagsDirty =\n dataset != null &&\n (tags.length !== dataset.tags.length || tags.some((tag, i) => tag !== dataset.tags[i]));\n\n // Add-schema-field dialog state.\n const [fieldOpen, setFieldOpen] = useState(false);\n const [fieldName, setFieldName] = useState('');\n const [fieldType, setFieldType] = useState<CosFieldType>('STRING');\n const [fieldUnit, setFieldUnit] = useState('');\n const [fieldDescription, setFieldDescription] = useState('');\n const [fieldProvenance, setFieldProvenance] = useState('');\n const [fieldNullable, setFieldNullable] = useState(true);\n\n const resetFieldForm = () => {\n setFieldName('');\n setFieldType('STRING');\n setFieldUnit('');\n setFieldDescription('');\n setFieldProvenance('');\n setFieldNullable(true);\n };\n\n const setFieldOpenAndReset = (open: boolean) => {\n setFieldOpen(open);\n if (!open) {\n resetFieldForm();\n }\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <LoadingState label=\"Loading dataset…\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <ErrorState message=\"We could not load this dataset.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!dataset) {\n return (\n <PageLayout title=\"Dataset\" backPath=\"datasets\">\n <EmptyState\n icon={Database}\n title=\"Dataset not found.\"\n description=\"This dataset may have been removed or is outside your current scope.\"\n action={\n <Button type=\"button\" onClick={() => navigate('datasets')}>\n Back to datasets\n </Button>\n }\n />\n </PageLayout>\n );\n }\n\n const schemaFields = [...(dataset.schemaFields ?? [])].sort((a, b) => a.position - b.position);\n const canPublish = dataset.status !== 'AVAILABLE' && dataset.status !== 'ARCHIVED';\n\n const handlePublish = async () => {\n const response = await publishDataset({ variables: { id: dataset.id } });\n if (response.data?.cosPublishDataset) {\n notify.success('Dataset published', `“${dataset.name}” is now available.`);\n await refetch();\n }\n };\n\n const handleArchive = async () => {\n const response = await archiveDataset({ variables: { id: dataset.id } });\n if (response.error) {\n throw new Error(response.error.message);\n }\n if (!response.data?.cosArchiveDataset) {\n notify.error('Could not archive dataset', 'The server did not confirm the change.');\n throw new Error('Archive not confirmed');\n }\n notify.success('Dataset archived');\n navigate('datasets');\n };\n\n const handleSaveTags = async () => {\n const response = await updateDataset({ variables: { id: dataset.id, input: { tags } } });\n if (response.data?.cosUpdateDataset) {\n notify.success('Tags updated');\n await refetch();\n }\n };\n\n const handleAddField = async () => {\n if (!fieldName.trim()) {\n notify.error('Field name is required');\n return;\n }\n const response = await addSchemaField({\n variables: {\n input: {\n datasetId: dataset.id,\n name: fieldName.trim(),\n fieldType,\n unit: fieldUnit.trim() || undefined,\n description: fieldDescription.trim() || undefined,\n provenance: fieldProvenance.trim() || undefined,\n nullable: fieldNullable,\n },\n },\n });\n if (response.data?.cosAddSchemaField) {\n notify.success('Schema field added');\n setFieldOpenAndReset(false);\n await refetch();\n }\n };\n\n return (\n <PageLayout\n title={dataset.name}\n description={dataset.description ?? undefined}\n backPath=\"datasets\"\n actions={\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`datasets/${dataset.id}/edit`)}\n >\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n {canPublish ? (\n <Button type=\"button\" onClick={() => void handlePublish()} disabled={publishing}>\n {publishing ? 'Publishing…' : 'Publish'}\n </Button>\n ) : null}\n <ActionMenu\n ariaLabel={`Actions for ${dataset.name}`}\n entityName={dataset.name}\n onDelete={() => handleArchive()}\n deleteLabel=\"Archive dataset\"\n />\n </div>\n }\n >\n <div className=\"space-y-6\">\n {/* Status + key facts */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={dataset.status} />\n <StatusBadge status={dataset.accessLevel} label={formatEnumLabel(dataset.accessLevel)} />\n {dataset.lineageCaptured ? <Badge variant=\"secondary\">Lineage captured</Badge> : null}\n <Badge variant=\"secondary\">v{dataset.version}</Badge>\n </div>\n\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n <MetaTile\n label=\"Source\"\n value={\n dataset.source ? (\n <button\n type=\"button\"\n onClick={() => navigate(`sources/${dataset.source?.id}`)}\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Radar className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {dataset.source.name}\n </button>\n ) : (\n <span className=\"text-text-secondary\">Not linked</span>\n )\n }\n />\n <MetaTile\n label=\"Collection\"\n value={\n dataset.collection ? (\n <button\n type=\"button\"\n onClick={() => navigate(`collections/${dataset.collection?.id}`)}\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Boxes className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n {dataset.collection.name}\n </button>\n ) : (\n <span className=\"text-text-secondary\">Not in a collection</span>\n )\n }\n />\n <MetaTile label=\"Format\" value={<span>{dataset.format || 'Not specified'}</span>} />\n <MetaTile\n label=\"Size\"\n value={\n <span className=\"tabular-nums\">\n {formatBytes(dataset.sizeBytes)}\n {Number(dataset.rowCount) > 0 ? (\n <span className=\"text-text-secondary\">\n {' '}\n · {Number(dataset.rowCount).toLocaleString()} rows\n </span>\n ) : null}\n </span>\n }\n />\n <MetaTile label=\"Ingested\" value={<span>{formatDateTime(dataset.ingestedAt)}</span>} />\n <MetaTile label=\"Created\" value={<span>{formatDateTime(dataset.createdAt)}</span>} />\n <MetaTile label=\"Updated\" value={<span>{formatDateTime(dataset.updatedAt)}</span>} />\n <MetaTile\n label=\"Artifact\"\n value={\n dataset.file ? (\n downloadUrl ? (\n <a\n href={downloadUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-text-primary underline-offset-2 hover:underline\"\n >\n <Download className=\"size-4\" aria-hidden=\"true\" />\n Download file\n </a>\n ) : (\n <span className=\"text-text-secondary\">Resolving link…</span>\n )\n ) : (\n <span className=\"text-text-secondary\">No file attached</span>\n )\n }\n />\n </div>\n\n {/* Schema fields */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <Columns3 className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Schema fields</h2>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setFieldOpenAndReset(true)}\n >\n <Plus className=\"size-4\" />\n Add field\n </Button>\n </div>\n\n {schemaFields.length === 0 ? (\n <EmptyState\n icon={Columns3}\n title=\"No schema fields yet.\"\n description=\"Describe the columns in this dataset so consumers know what each field means.\"\n />\n ) : (\n <div className=\"rounded-card border border-border-default bg-bg-elevated\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Type</TableHead>\n <TableHead>Unit</TableHead>\n <TableHead>Nullable</TableHead>\n <TableHead>Provenance</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {schemaFields.map((field) => (\n <TableRow key={field.id}>\n <TableCell>\n <span className=\"font-medium text-text-primary\">{field.name}</span>\n {field.description ? (\n <p className=\"mt-0.5 line-clamp-1 max-w-xs text-xs text-text-secondary\">\n {field.description}\n </p>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant=\"secondary\">{formatEnumLabel(field.fieldType)}</Badge>\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.unit || '—'}\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.nullable ? 'Yes' : 'No'}\n </TableCell>\n <TableCell className=\"text-sm text-text-secondary\">\n {field.provenance || '—'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </section>\n\n {/* Tags */}\n <section className=\"space-y-3 rounded-card border border-border-default bg-bg-elevated p-5\">\n <EntityTagsField value={tags} onChange={setTags} label=\"Dataset tags\" />\n {tagsDirty ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleSaveTags()}\n disabled={savingTags}\n >\n {savingTags ? 'Saving…' : 'Save tags'}\n </Button>\n </div>\n ) : null}\n </section>\n\n {/* Activity / history */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <History className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Activity</h2>\n </div>\n <ActivityFeedPanel resourceId={dataset.id} resourceType=\"cosmicintersection-dataset\" />\n </section>\n\n {/* Discussion */}\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <MessagesSquare className=\"size-5 text-text-secondary\" aria-hidden=\"true\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">Discussion</h2>\n </div>\n <DiscussionPanel\n entityType=\"cosmicintersection-dataset\"\n entityId={dataset.id}\n title={dataset.name}\n widgetKey=\"dataset-discussion\"\n />\n </section>\n </div>\n\n {/* Add schema field dialog */}\n <Dialog open={fieldOpen} onOpenChange={setFieldOpenAndReset}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Add schema field</DialogTitle>\n <DialogDescription>\n Document a column in “{dataset.name}” — its type, unit and provenance.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-name\">Name</Label>\n <Input\n id=\"cos-field-name\"\n value={fieldName}\n onChange={(event) => setFieldName(event.target.value)}\n placeholder=\"e.g. right_ascension\"\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-type\">Type</Label>\n <Select\n value={fieldType}\n onValueChange={(value) => setFieldType(value as CosFieldType)}\n >\n <SelectTrigger id=\"cos-field-type\" aria-label=\"Field type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FIELD_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {formatEnumLabel(type)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-unit\">Unit</Label>\n <Input\n id=\"cos-field-unit\"\n value={fieldUnit}\n onChange={(event) => setFieldUnit(event.target.value)}\n placeholder=\"e.g. deg, mag, Jy\"\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-desc\">Description</Label>\n <Textarea\n id=\"cos-field-desc\"\n value={fieldDescription}\n onChange={(event) => setFieldDescription(event.target.value)}\n rows={2}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"cos-field-prov\">Provenance</Label>\n <Input\n id=\"cos-field-prov\"\n value={fieldProvenance}\n onChange={(event) => setFieldProvenance(event.target.value)}\n placeholder=\"Where this field comes from\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <Checkbox\n checked={fieldNullable}\n onCheckedChange={(checked) => setFieldNullable(checked === true)}\n />\n Nullable (may contain empty values)\n </label>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setFieldOpenAndReset(false)}\n disabled={addingField}\n >\n Cancel\n </Button>\n <Button type=\"button\" onClick={() => void handleAddField()} disabled={addingField}>\n {addingField ? 'Adding…' : 'Add field'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|