@burdenoff/microfe-cosmicintersection 2026.525.1 → 2026.704.1
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 +102 -44
- package/dist/cosmicintersection/CosmicIntersectionRoutes.js.map +1 -1
- package/dist/cosmicintersection/api/cosmicApi.js +853 -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/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 +11 -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 +340 -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 +164 -0
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js +117 -0
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js.map +1 -0
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js +103 -0
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -0
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js +244 -0
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js.map +1 -0
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +460 -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 +393 -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 +368 -0
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js.map +1 -0
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js +375 -0
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/runs/RunsPage.js +180 -0
- package/dist/cosmicintersection/pages/runs/RunsPage.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 +217 -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,484 @@
|
|
|
1
|
+
import { useCosmicIntersection as e } from "../../context/CosmicIntersectionContext.js";
|
|
2
|
+
import { notify as t } from "../../lib/toast.js";
|
|
3
|
+
import { useCosAnalysesQuery as n, useCosCompleteAnalysisMutation as r, useCosDatasetsQuery as i, useCosNotebooksQuery as a, useCosRunAnalysisMutation as o } from "../../api/cosmicApi.js";
|
|
4
|
+
import s from "../../components/ActionMenu.js";
|
|
5
|
+
import c from "../../components/EmptyState.js";
|
|
6
|
+
import l from "../../components/ErrorState.js";
|
|
7
|
+
import u, { useFileDownloadUrl as d } from "../../components/FileUploadField.js";
|
|
8
|
+
import f from "../../components/LoadingState.js";
|
|
9
|
+
import p from "../../components/PageLayout.js";
|
|
10
|
+
import m from "../../components/StatusBadge.js";
|
|
11
|
+
import "../../components/index.js";
|
|
12
|
+
import { useMemo as h, useState as g } from "react";
|
|
13
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
14
|
+
import { Beaker as y, Download as b, ExternalLink as x, Play as S, Sparkles as C } from "lucide-react";
|
|
15
|
+
import { Badge as w, Button as T, Dialog as E, DialogContent as D, DialogDescription as O, DialogFooter as k, DialogHeader as A, DialogTitle as j, Input as M, Label as N, Select as P, SelectContent as F, SelectItem as I, SelectTrigger as L, SelectValue as R, Switch as z, Table as B, TableBody as V, TableCell as H, TableHead as U, TableHeader as W, TableRow as G, Textarea as K } from "@burdenoff/fe-libs/ui";
|
|
16
|
+
//#region src/cosmicintersection/pages/analyses/AnalysesPage.tsx
|
|
17
|
+
var q = [
|
|
18
|
+
{
|
|
19
|
+
value: "PENDING",
|
|
20
|
+
label: "Pending"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
value: "RUNNING",
|
|
24
|
+
label: "Running"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
value: "COMPLETED",
|
|
28
|
+
label: "Completed"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
value: "FAILED",
|
|
32
|
+
label: "Failed"
|
|
33
|
+
}
|
|
34
|
+
], J = "ALL";
|
|
35
|
+
function Y(e) {
|
|
36
|
+
if (!e) return "—";
|
|
37
|
+
let t = new Date(e);
|
|
38
|
+
return Number.isNaN(t.getTime()) ? "—" : t.toLocaleString(void 0, {
|
|
39
|
+
year: "numeric",
|
|
40
|
+
month: "short",
|
|
41
|
+
day: "numeric",
|
|
42
|
+
hour: "2-digit",
|
|
43
|
+
minute: "2-digit"
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function X({ fileId: e }) {
|
|
47
|
+
let { data: t, loading: n } = d(e), r = t?.getFileDownloadUrl ?? null;
|
|
48
|
+
return n ? /* @__PURE__ */ _("span", {
|
|
49
|
+
className: "text-xs text-text-secondary",
|
|
50
|
+
children: "Resolving…"
|
|
51
|
+
}) : r ? /* @__PURE__ */ v("a", {
|
|
52
|
+
href: r,
|
|
53
|
+
target: "_blank",
|
|
54
|
+
rel: "noopener noreferrer",
|
|
55
|
+
className: "inline-flex items-center gap-1 text-sm text-text-primary underline-offset-2 hover:underline",
|
|
56
|
+
children: [/* @__PURE__ */ _(b, {
|
|
57
|
+
className: "size-3.5",
|
|
58
|
+
"aria-hidden": "true"
|
|
59
|
+
}), "Download"]
|
|
60
|
+
}) : /* @__PURE__ */ v("span", {
|
|
61
|
+
className: "text-xs text-text-secondary",
|
|
62
|
+
children: ["File ", e]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function Z(e) {
|
|
66
|
+
let t = e.trim();
|
|
67
|
+
if (!t) return {
|
|
68
|
+
ok: !0,
|
|
69
|
+
value: void 0
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
let e = JSON.parse(t);
|
|
73
|
+
return typeof e != "object" || !e || Array.isArray(e) ? {
|
|
74
|
+
ok: !1,
|
|
75
|
+
error: "Results must be a JSON object."
|
|
76
|
+
} : {
|
|
77
|
+
ok: !0,
|
|
78
|
+
value: e
|
|
79
|
+
};
|
|
80
|
+
} catch {
|
|
81
|
+
return {
|
|
82
|
+
ok: !1,
|
|
83
|
+
error: "Results are not valid JSON."
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function Q({ open: e, onOpenChange: n, onCompleted: r }) {
|
|
88
|
+
let [s, c] = g(""), [l, u] = g(""), [d, f] = g(!1), [p, m] = g("NOTEBOOK"), [h, y] = g(""), { data: b, loading: x } = a({ pagination: {
|
|
89
|
+
limit: 100,
|
|
90
|
+
offset: 0
|
|
91
|
+
} }), { data: C, loading: w } = i({ pagination: {
|
|
92
|
+
limit: 100,
|
|
93
|
+
offset: 0
|
|
94
|
+
} }), [B, { loading: V }] = o(), H = b?.cosListNotebooks.items ?? [], U = C?.cosListDatasets.items ?? [], W = () => {
|
|
95
|
+
c(""), u(""), f(!1), m("NOTEBOOK"), y("");
|
|
96
|
+
};
|
|
97
|
+
return /* @__PURE__ */ _(E, {
|
|
98
|
+
open: e,
|
|
99
|
+
onOpenChange: (e) => {
|
|
100
|
+
V || n(e);
|
|
101
|
+
},
|
|
102
|
+
children: /* @__PURE__ */ _(D, { children: /* @__PURE__ */ v("form", {
|
|
103
|
+
onSubmit: async (e) => {
|
|
104
|
+
e.preventDefault();
|
|
105
|
+
let i = s.trim();
|
|
106
|
+
if (!i) {
|
|
107
|
+
t.error("Title is required", "Give the analysis a descriptive title.");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (!h) {
|
|
111
|
+
t.error("Select a source", `Choose a ${p === "NOTEBOOK" ? "notebook" : "dataset"} to analyse.`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
let a = await B({ variables: { input: {
|
|
115
|
+
title: i,
|
|
116
|
+
method: l.trim() || void 0,
|
|
117
|
+
aiAssisted: d,
|
|
118
|
+
...p === "NOTEBOOK" ? { notebookId: h } : { datasetId: h }
|
|
119
|
+
} } });
|
|
120
|
+
a.error || !a.data?.cosRunAnalysis?.id || (t.success("Analysis started", `“${i}” is now running.`), W(), n(!1), r());
|
|
121
|
+
},
|
|
122
|
+
className: "space-y-4",
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ v(A, { children: [/* @__PURE__ */ _(j, { children: "Run analysis" }), /* @__PURE__ */ _(O, { children: "Launch a new analysis against a notebook or a dataset. Exactly one source is required." })] }),
|
|
125
|
+
/* @__PURE__ */ v("div", {
|
|
126
|
+
className: "space-y-1.5",
|
|
127
|
+
children: [/* @__PURE__ */ _(N, {
|
|
128
|
+
htmlFor: "run-title",
|
|
129
|
+
children: "Title"
|
|
130
|
+
}), /* @__PURE__ */ _(M, {
|
|
131
|
+
id: "run-title",
|
|
132
|
+
value: s,
|
|
133
|
+
onChange: (e) => c(e.target.value),
|
|
134
|
+
placeholder: "e.g. Spectral line fitting",
|
|
135
|
+
required: !0
|
|
136
|
+
})]
|
|
137
|
+
}),
|
|
138
|
+
/* @__PURE__ */ v("div", {
|
|
139
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
140
|
+
children: [/* @__PURE__ */ v("div", {
|
|
141
|
+
className: "space-y-1.5",
|
|
142
|
+
children: [/* @__PURE__ */ _(N, {
|
|
143
|
+
htmlFor: "run-source-kind",
|
|
144
|
+
children: "Source type"
|
|
145
|
+
}), /* @__PURE__ */ v(P, {
|
|
146
|
+
value: p,
|
|
147
|
+
onValueChange: (e) => {
|
|
148
|
+
m(e), y("");
|
|
149
|
+
},
|
|
150
|
+
children: [/* @__PURE__ */ _(L, {
|
|
151
|
+
id: "run-source-kind",
|
|
152
|
+
"aria-label": "Source type",
|
|
153
|
+
children: /* @__PURE__ */ _(R, {})
|
|
154
|
+
}), /* @__PURE__ */ v(F, { children: [/* @__PURE__ */ _(I, {
|
|
155
|
+
value: "NOTEBOOK",
|
|
156
|
+
children: "Notebook"
|
|
157
|
+
}), /* @__PURE__ */ _(I, {
|
|
158
|
+
value: "DATASET",
|
|
159
|
+
children: "Dataset"
|
|
160
|
+
})] })]
|
|
161
|
+
})]
|
|
162
|
+
}), /* @__PURE__ */ v("div", {
|
|
163
|
+
className: "space-y-1.5",
|
|
164
|
+
children: [/* @__PURE__ */ _(N, {
|
|
165
|
+
htmlFor: "run-source-id",
|
|
166
|
+
children: p === "NOTEBOOK" ? "Notebook" : "Dataset"
|
|
167
|
+
}), /* @__PURE__ */ v(P, {
|
|
168
|
+
value: h,
|
|
169
|
+
onValueChange: (e) => y(e),
|
|
170
|
+
children: [/* @__PURE__ */ _(L, {
|
|
171
|
+
id: "run-source-id",
|
|
172
|
+
"aria-label": "Analysis source",
|
|
173
|
+
children: /* @__PURE__ */ _(R, { placeholder: (p === "NOTEBOOK" ? x : w) ? "Loading…" : `Select a ${p === "NOTEBOOK" ? "notebook" : "dataset"}` })
|
|
174
|
+
}), /* @__PURE__ */ _(F, { children: p === "NOTEBOOK" ? H.map((e) => /* @__PURE__ */ _(I, {
|
|
175
|
+
value: e.id,
|
|
176
|
+
children: e.title
|
|
177
|
+
}, e.id)) : U.map((e) => /* @__PURE__ */ _(I, {
|
|
178
|
+
value: e.id,
|
|
179
|
+
children: e.name
|
|
180
|
+
}, e.id)) })]
|
|
181
|
+
})]
|
|
182
|
+
})]
|
|
183
|
+
}),
|
|
184
|
+
/* @__PURE__ */ v("div", {
|
|
185
|
+
className: "space-y-1.5",
|
|
186
|
+
children: [/* @__PURE__ */ _(N, {
|
|
187
|
+
htmlFor: "run-method",
|
|
188
|
+
children: "Method"
|
|
189
|
+
}), /* @__PURE__ */ _(M, {
|
|
190
|
+
id: "run-method",
|
|
191
|
+
value: l,
|
|
192
|
+
onChange: (e) => u(e.target.value),
|
|
193
|
+
placeholder: "e.g. gaussian-fit"
|
|
194
|
+
})]
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ v("div", {
|
|
197
|
+
className: "flex items-center gap-3",
|
|
198
|
+
children: [/* @__PURE__ */ _(z, {
|
|
199
|
+
id: "run-ai",
|
|
200
|
+
checked: d,
|
|
201
|
+
onCheckedChange: (e) => f(e)
|
|
202
|
+
}), /* @__PURE__ */ _(N, {
|
|
203
|
+
htmlFor: "run-ai",
|
|
204
|
+
className: "cursor-pointer",
|
|
205
|
+
children: "AI-assisted analysis"
|
|
206
|
+
})]
|
|
207
|
+
}),
|
|
208
|
+
/* @__PURE__ */ v(k, { children: [/* @__PURE__ */ _(T, {
|
|
209
|
+
type: "button",
|
|
210
|
+
variant: "outline",
|
|
211
|
+
onClick: () => n(!1),
|
|
212
|
+
disabled: V,
|
|
213
|
+
children: "Cancel"
|
|
214
|
+
}), /* @__PURE__ */ v(T, {
|
|
215
|
+
type: "submit",
|
|
216
|
+
disabled: V,
|
|
217
|
+
children: [/* @__PURE__ */ _(S, { className: "size-4" }), V ? "Starting…" : "Run analysis"]
|
|
218
|
+
})] })
|
|
219
|
+
]
|
|
220
|
+
}) })
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function $({ analysis: e, onOpenChange: n, onCompleted: i }) {
|
|
224
|
+
let [a, o] = g("COMPLETED"), [s, c] = g(""), [l, d] = g(""), [f, { loading: p }] = r();
|
|
225
|
+
return /* @__PURE__ */ _(E, {
|
|
226
|
+
open: !!e,
|
|
227
|
+
onOpenChange: (e) => {
|
|
228
|
+
p || n(e);
|
|
229
|
+
},
|
|
230
|
+
children: /* @__PURE__ */ _(D, { children: /* @__PURE__ */ v("form", {
|
|
231
|
+
onSubmit: async (r) => {
|
|
232
|
+
if (r.preventDefault(), !e) return;
|
|
233
|
+
let o = Z(s);
|
|
234
|
+
if (!o.ok) {
|
|
235
|
+
t.error("Invalid results", o.error);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
let c = await f({ variables: {
|
|
239
|
+
id: e.id,
|
|
240
|
+
status: a,
|
|
241
|
+
results: o.value,
|
|
242
|
+
outputFileId: l || void 0
|
|
243
|
+
} });
|
|
244
|
+
c.error || !c.data?.cosCompleteAnalysis || (t.success(a === "COMPLETED" ? "Analysis completed" : "Analysis marked failed", `“${e.title}” was updated.`), n(!1), i());
|
|
245
|
+
},
|
|
246
|
+
className: "space-y-4",
|
|
247
|
+
children: [
|
|
248
|
+
/* @__PURE__ */ v(A, { children: [/* @__PURE__ */ _(j, { children: "Complete analysis" }), /* @__PURE__ */ v(O, { children: [
|
|
249
|
+
"Record the outcome for ",
|
|
250
|
+
e ? `“${e.title}”` : "this analysis",
|
|
251
|
+
". Attach results or an output artifact if you have them."
|
|
252
|
+
] })] }),
|
|
253
|
+
/* @__PURE__ */ v("div", {
|
|
254
|
+
className: "space-y-1.5",
|
|
255
|
+
children: [/* @__PURE__ */ _(N, {
|
|
256
|
+
htmlFor: "complete-status",
|
|
257
|
+
children: "Outcome"
|
|
258
|
+
}), /* @__PURE__ */ v(P, {
|
|
259
|
+
value: a,
|
|
260
|
+
onValueChange: (e) => o(e),
|
|
261
|
+
children: [/* @__PURE__ */ _(L, {
|
|
262
|
+
id: "complete-status",
|
|
263
|
+
"aria-label": "Outcome",
|
|
264
|
+
children: /* @__PURE__ */ _(R, {})
|
|
265
|
+
}), /* @__PURE__ */ v(F, { children: [/* @__PURE__ */ _(I, {
|
|
266
|
+
value: "COMPLETED",
|
|
267
|
+
children: "Completed"
|
|
268
|
+
}), /* @__PURE__ */ _(I, {
|
|
269
|
+
value: "FAILED",
|
|
270
|
+
children: "Failed"
|
|
271
|
+
})] })]
|
|
272
|
+
})]
|
|
273
|
+
}),
|
|
274
|
+
/* @__PURE__ */ v("div", {
|
|
275
|
+
className: "space-y-1.5",
|
|
276
|
+
children: [
|
|
277
|
+
/* @__PURE__ */ _(N, {
|
|
278
|
+
htmlFor: "complete-results",
|
|
279
|
+
children: "Results (JSON)"
|
|
280
|
+
}),
|
|
281
|
+
/* @__PURE__ */ _(K, {
|
|
282
|
+
id: "complete-results",
|
|
283
|
+
value: s,
|
|
284
|
+
onChange: (e) => c(e.target.value),
|
|
285
|
+
rows: 4,
|
|
286
|
+
className: "font-mono text-xs",
|
|
287
|
+
placeholder: "{ \"snr\": 12.4, \"detections\": 3 }"
|
|
288
|
+
}),
|
|
289
|
+
/* @__PURE__ */ _("p", {
|
|
290
|
+
className: "text-xs text-text-secondary",
|
|
291
|
+
children: "Optional structured results as a JSON object."
|
|
292
|
+
})
|
|
293
|
+
]
|
|
294
|
+
}),
|
|
295
|
+
/* @__PURE__ */ _(u, {
|
|
296
|
+
value: l,
|
|
297
|
+
onChange: (e) => d(e),
|
|
298
|
+
label: "Attach output file",
|
|
299
|
+
hint: "Optional output artifact (plots, tables, exports). Stored in workspace files."
|
|
300
|
+
}),
|
|
301
|
+
/* @__PURE__ */ v(k, { children: [/* @__PURE__ */ _(T, {
|
|
302
|
+
type: "button",
|
|
303
|
+
variant: "outline",
|
|
304
|
+
onClick: () => n(!1),
|
|
305
|
+
disabled: p,
|
|
306
|
+
children: "Cancel"
|
|
307
|
+
}), /* @__PURE__ */ _(T, {
|
|
308
|
+
type: "submit",
|
|
309
|
+
disabled: p,
|
|
310
|
+
children: p ? "Saving…" : "Save outcome"
|
|
311
|
+
})] })
|
|
312
|
+
]
|
|
313
|
+
}) })
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function ee() {
|
|
317
|
+
let { navigate: t } = e(), [r, o] = g(void 0), [u, d] = g(!1), [b, E] = g(null), { data: D, loading: O, error: k, refetch: A } = n({ status: r }), { data: j } = a({ pagination: {
|
|
318
|
+
limit: 100,
|
|
319
|
+
offset: 0
|
|
320
|
+
} }), { data: M } = i({ pagination: {
|
|
321
|
+
limit: 100,
|
|
322
|
+
offset: 0
|
|
323
|
+
} }), N = D?.cosListAnalyses ?? [], z = h(() => {
|
|
324
|
+
let e = /* @__PURE__ */ new Map();
|
|
325
|
+
for (let t of j?.cosListNotebooks.items ?? []) e.set(t.id, t.title);
|
|
326
|
+
return e;
|
|
327
|
+
}, [j]), K = h(() => {
|
|
328
|
+
let e = /* @__PURE__ */ new Map();
|
|
329
|
+
for (let t of M?.cosListDatasets.items ?? []) e.set(t.id, t.name);
|
|
330
|
+
return e;
|
|
331
|
+
}, [M]);
|
|
332
|
+
return /* @__PURE__ */ v(p, {
|
|
333
|
+
title: "Analyses",
|
|
334
|
+
description: "Analysis runs executed over notebooks and federated datasets.",
|
|
335
|
+
actions: /* @__PURE__ */ v(T, {
|
|
336
|
+
type: "button",
|
|
337
|
+
onClick: () => d(!0),
|
|
338
|
+
children: [/* @__PURE__ */ _(S, { className: "size-4" }), "Run analysis"]
|
|
339
|
+
}),
|
|
340
|
+
children: [
|
|
341
|
+
/* @__PURE__ */ v("div", {
|
|
342
|
+
className: "space-y-4",
|
|
343
|
+
children: [/* @__PURE__ */ v("div", {
|
|
344
|
+
className: "flex flex-wrap items-center gap-3",
|
|
345
|
+
children: [/* @__PURE__ */ _("label", {
|
|
346
|
+
className: "text-sm text-text-secondary",
|
|
347
|
+
htmlFor: "analysis-status-filter",
|
|
348
|
+
children: "Status"
|
|
349
|
+
}), /* @__PURE__ */ v(P, {
|
|
350
|
+
value: r ?? J,
|
|
351
|
+
onValueChange: (e) => o(e === J ? void 0 : e),
|
|
352
|
+
children: [/* @__PURE__ */ _(L, {
|
|
353
|
+
id: "analysis-status-filter",
|
|
354
|
+
className: "w-48",
|
|
355
|
+
"aria-label": "Filter by status",
|
|
356
|
+
children: /* @__PURE__ */ _(R, {})
|
|
357
|
+
}), /* @__PURE__ */ v(F, { children: [/* @__PURE__ */ _(I, {
|
|
358
|
+
value: J,
|
|
359
|
+
children: "All statuses"
|
|
360
|
+
}), q.map((e) => /* @__PURE__ */ _(I, {
|
|
361
|
+
value: e.value,
|
|
362
|
+
children: e.label
|
|
363
|
+
}, e.value))] })]
|
|
364
|
+
})]
|
|
365
|
+
}), O ? /* @__PURE__ */ _(f, {
|
|
366
|
+
variant: "rows",
|
|
367
|
+
rows: 6,
|
|
368
|
+
label: "Loading analyses…"
|
|
369
|
+
}) : k ? /* @__PURE__ */ _(l, {
|
|
370
|
+
message: "We could not load analyses. Please try again.",
|
|
371
|
+
onRetry: () => void A()
|
|
372
|
+
}) : N.length === 0 ? /* @__PURE__ */ _(c, {
|
|
373
|
+
icon: y,
|
|
374
|
+
title: r ? "No analyses match this filter." : "No analyses yet.",
|
|
375
|
+
description: r ? "Try a different status filter." : "Run an analysis against a notebook or dataset to see results here.",
|
|
376
|
+
action: r ? void 0 : /* @__PURE__ */ v(T, {
|
|
377
|
+
type: "button",
|
|
378
|
+
onClick: () => d(!0),
|
|
379
|
+
children: [/* @__PURE__ */ _(S, { className: "size-4" }), "Run analysis"]
|
|
380
|
+
})
|
|
381
|
+
}) : /* @__PURE__ */ _("div", {
|
|
382
|
+
className: "rounded-card border border-border-default bg-bg-elevated",
|
|
383
|
+
children: /* @__PURE__ */ v(B, { children: [/* @__PURE__ */ _(W, { children: /* @__PURE__ */ v(G, { children: [
|
|
384
|
+
/* @__PURE__ */ _(U, { children: "Title" }),
|
|
385
|
+
/* @__PURE__ */ _(U, { children: "Method" }),
|
|
386
|
+
/* @__PURE__ */ _(U, { children: "AI" }),
|
|
387
|
+
/* @__PURE__ */ _(U, { children: "Status" }),
|
|
388
|
+
/* @__PURE__ */ _(U, { children: "Source" }),
|
|
389
|
+
/* @__PURE__ */ _(U, { children: "Started" }),
|
|
390
|
+
/* @__PURE__ */ _(U, { children: "Finished" }),
|
|
391
|
+
/* @__PURE__ */ _(U, { children: "Output" }),
|
|
392
|
+
/* @__PURE__ */ _(U, {
|
|
393
|
+
className: "w-12 text-right",
|
|
394
|
+
children: "Actions"
|
|
395
|
+
})
|
|
396
|
+
] }) }), /* @__PURE__ */ _(V, { children: N.map((e) => {
|
|
397
|
+
let n = e.status === "PENDING" || e.status === "RUNNING", r = e.notebookId ? z.get(e.notebookId) ?? "Notebook" : e.datasetId ? K.get(e.datasetId) ?? "Dataset" : null, i = e.notebookId ? `notebooks/${e.notebookId}` : e.datasetId ? `datasets/${e.datasetId}` : null;
|
|
398
|
+
return /* @__PURE__ */ v(G, { children: [
|
|
399
|
+
/* @__PURE__ */ _(H, {
|
|
400
|
+
className: "font-medium text-text-primary",
|
|
401
|
+
children: e.title
|
|
402
|
+
}),
|
|
403
|
+
/* @__PURE__ */ _(H, {
|
|
404
|
+
className: "text-text-secondary",
|
|
405
|
+
children: e.method ?? "—"
|
|
406
|
+
}),
|
|
407
|
+
/* @__PURE__ */ _(H, { children: e.aiAssisted ? /* @__PURE__ */ v(w, {
|
|
408
|
+
variant: "secondary",
|
|
409
|
+
className: "gap-1",
|
|
410
|
+
children: [/* @__PURE__ */ _(C, {
|
|
411
|
+
className: "size-3",
|
|
412
|
+
"aria-hidden": "true"
|
|
413
|
+
}), "AI"]
|
|
414
|
+
}) : /* @__PURE__ */ _("span", {
|
|
415
|
+
className: "text-text-secondary",
|
|
416
|
+
children: "—"
|
|
417
|
+
}) }),
|
|
418
|
+
/* @__PURE__ */ _(H, { children: /* @__PURE__ */ _(m, { status: e.status }) }),
|
|
419
|
+
/* @__PURE__ */ _(H, { children: r && i ? /* @__PURE__ */ v("button", {
|
|
420
|
+
type: "button",
|
|
421
|
+
onClick: () => t(i),
|
|
422
|
+
className: "inline-flex max-w-[12rem] items-center gap-1 truncate text-sm text-text-primary underline-offset-2 hover:underline",
|
|
423
|
+
children: [/* @__PURE__ */ _(x, {
|
|
424
|
+
className: "size-3.5 shrink-0",
|
|
425
|
+
"aria-hidden": "true"
|
|
426
|
+
}), /* @__PURE__ */ _("span", {
|
|
427
|
+
className: "truncate",
|
|
428
|
+
children: r
|
|
429
|
+
})]
|
|
430
|
+
}) : /* @__PURE__ */ _("span", {
|
|
431
|
+
className: "text-text-secondary",
|
|
432
|
+
children: "—"
|
|
433
|
+
}) }),
|
|
434
|
+
/* @__PURE__ */ _(H, {
|
|
435
|
+
className: "whitespace-nowrap text-text-secondary",
|
|
436
|
+
children: Y(e.startedAt)
|
|
437
|
+
}),
|
|
438
|
+
/* @__PURE__ */ _(H, {
|
|
439
|
+
className: "whitespace-nowrap text-text-secondary",
|
|
440
|
+
children: Y(e.finishedAt)
|
|
441
|
+
}),
|
|
442
|
+
/* @__PURE__ */ _(H, { children: e.outputFile?.id ? /* @__PURE__ */ _(X, { fileId: e.outputFile.id }) : e.results && Object.keys(e.results).length > 0 ? /* @__PURE__ */ _("span", {
|
|
443
|
+
className: "text-xs text-text-secondary",
|
|
444
|
+
children: "Results recorded"
|
|
445
|
+
}) : /* @__PURE__ */ _("span", {
|
|
446
|
+
className: "text-text-secondary",
|
|
447
|
+
children: "—"
|
|
448
|
+
}) }),
|
|
449
|
+
/* @__PURE__ */ _(H, {
|
|
450
|
+
className: "text-right",
|
|
451
|
+
children: /* @__PURE__ */ _(s, {
|
|
452
|
+
ariaLabel: `Actions for ${e.title}`,
|
|
453
|
+
onView: i ? () => t(i) : void 0,
|
|
454
|
+
extraItems: n ? [{
|
|
455
|
+
key: "complete",
|
|
456
|
+
label: "Complete…",
|
|
457
|
+
icon: y,
|
|
458
|
+
onSelect: () => E(e)
|
|
459
|
+
}] : []
|
|
460
|
+
})
|
|
461
|
+
})
|
|
462
|
+
] }, e.id);
|
|
463
|
+
}) })] })
|
|
464
|
+
})]
|
|
465
|
+
}),
|
|
466
|
+
/* @__PURE__ */ _(Q, {
|
|
467
|
+
open: u,
|
|
468
|
+
onOpenChange: d,
|
|
469
|
+
onCompleted: () => void A()
|
|
470
|
+
}),
|
|
471
|
+
/* @__PURE__ */ _($, {
|
|
472
|
+
analysis: b,
|
|
473
|
+
onOpenChange: (e) => {
|
|
474
|
+
e || E(null);
|
|
475
|
+
},
|
|
476
|
+
onCompleted: () => void A()
|
|
477
|
+
}, b?.id ?? "none")
|
|
478
|
+
]
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
//#endregion
|
|
482
|
+
export { ee as default };
|
|
483
|
+
|
|
484
|
+
//# sourceMappingURL=AnalysesPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnalysesPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/analyses/AnalysesPage.tsx"],"sourcesContent":["/**\n * AnalysesPage — every analysis run across the workspace.\n *\n * Lists `cosListAnalyses` (a plain array, no pagination) with a status filter.\n * A \"Run analysis\" dialog launches a new `cosRunAnalysis` against EITHER a\n * notebook OR a dataset (the schema requires one), chosen via a small selector.\n * In-flight (PENDING / RUNNING) analyses expose a \"Complete\" action that calls\n * `cosCompleteAnalysis` with COMPLETED | FAILED, optional results JSON, and an\n * optional output artifact uploaded through FileUploadField. All values are read\n * from the backend — nothing is fabricated.\n */\nimport { useMemo, useState, type FormEvent } from 'react';\nimport { Beaker, Download, ExternalLink, Play, Sparkles } from 'lucide-react';\nimport {\n Badge,\n Button,\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 Switch,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosAnalysesQuery,\n useCosCompleteAnalysisMutation,\n useCosDatasetsQuery,\n useCosNotebooksQuery,\n useCosRunAnalysisMutation,\n type CosAnalysis,\n type CosAnalysisStatus,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n EmptyState,\n ErrorState,\n FileUploadField,\n LoadingState,\n PageLayout,\n StatusBadge,\n useFileDownloadUrl,\n} from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst STATUS_OPTIONS: { value: CosAnalysisStatus; label: string }[] = [\n { value: 'PENDING', label: 'Pending' },\n { value: 'RUNNING', label: 'Running' },\n { value: 'COMPLETED', label: 'Completed' },\n { value: 'FAILED', label: 'Failed' },\n];\n\nconst ALL = 'ALL';\n\nfunction formatDateTime(value?: string | null): string {\n if (!value) {\n return '—';\n }\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return '—';\n }\n return date.toLocaleString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\n/** Presigned download link for an analysis output artifact. */\nfunction FileDownloadLink({ fileId }: { fileId: string }) {\n const { data, loading } = useFileDownloadUrl(fileId);\n const url = data?.getFileDownloadUrl ?? null;\n if (loading) {\n return <span className=\"text-xs text-text-secondary\">Resolving…</span>;\n }\n if (!url) {\n return <span className=\"text-xs text-text-secondary\">File {fileId}</span>;\n }\n return (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1 text-sm text-text-primary underline-offset-2 hover:underline\"\n >\n <Download className=\"size-3.5\" aria-hidden=\"true\" />\n Download\n </a>\n );\n}\n\n/** Parse optional results JSON; blank -> undefined, invalid -> error. */\nfunction parseResults(\n raw: string\n): { ok: true; value?: Record<string, unknown> } | { ok: false; error: string } {\n const trimmed = raw.trim();\n if (!trimmed) {\n return { ok: true, value: undefined };\n }\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return { ok: false, error: 'Results must be a JSON object.' };\n }\n return { ok: true, value: parsed as Record<string, unknown> };\n } catch {\n return { ok: false, error: 'Results are not valid JSON.' };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Run analysis dialog\n// ---------------------------------------------------------------------------\n\ntype RunSourceKind = 'NOTEBOOK' | 'DATASET';\n\ninterface RunDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCompleted: () => void;\n}\n\nfunction RunAnalysisDialog({ open, onOpenChange, onCompleted }: RunDialogProps) {\n const [title, setTitle] = useState('');\n const [method, setMethod] = useState('');\n const [aiAssisted, setAiAssisted] = useState(false);\n const [sourceKind, setSourceKind] = useState<RunSourceKind>('NOTEBOOK');\n const [sourceId, setSourceId] = useState('');\n\n const { data: notebooksData, loading: notebooksLoading } = useCosNotebooksQuery({\n pagination: { limit: 100, offset: 0 },\n });\n const { data: datasetsData, loading: datasetsLoading } = useCosDatasetsQuery({\n pagination: { limit: 100, offset: 0 },\n });\n const [runAnalysis, { loading }] = useCosRunAnalysisMutation();\n\n const notebooks = notebooksData?.cosListNotebooks.items ?? [];\n const datasets = datasetsData?.cosListDatasets.items ?? [];\n\n const reset = () => {\n setTitle('');\n setMethod('');\n setAiAssisted(false);\n setSourceKind('NOTEBOOK');\n setSourceId('');\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const trimmed = title.trim();\n if (!trimmed) {\n notify.error('Title is required', 'Give the analysis a descriptive title.');\n return;\n }\n if (!sourceId) {\n notify.error(\n 'Select a source',\n `Choose a ${sourceKind === 'NOTEBOOK' ? 'notebook' : 'dataset'} to analyse.`\n );\n return;\n }\n const response = await runAnalysis({\n variables: {\n input: {\n title: trimmed,\n method: method.trim() || undefined,\n aiAssisted,\n ...(sourceKind === 'NOTEBOOK' ? { notebookId: sourceId } : { datasetId: sourceId }),\n },\n },\n });\n if (response.error || !response.data?.cosRunAnalysis?.id) {\n return;\n }\n notify.success('Analysis started', `“${trimmed}” is now running.`);\n reset();\n onOpenChange(false);\n onCompleted();\n };\n\n const sourceLoading = sourceKind === 'NOTEBOOK' ? notebooksLoading : datasetsLoading;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!loading) {\n onOpenChange(next);\n }\n }}\n >\n <DialogContent>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>Run analysis</DialogTitle>\n <DialogDescription>\n Launch a new analysis against a notebook or a dataset. Exactly one source is required.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-title\">Title</Label>\n <Input\n id=\"run-title\"\n value={title}\n onChange={(event) => setTitle(event.target.value)}\n placeholder=\"e.g. Spectral line fitting\"\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=\"run-source-kind\">Source type</Label>\n <Select\n value={sourceKind}\n onValueChange={(value) => {\n setSourceKind(value as RunSourceKind);\n setSourceId('');\n }}\n >\n <SelectTrigger id=\"run-source-kind\" aria-label=\"Source type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"NOTEBOOK\">Notebook</SelectItem>\n <SelectItem value=\"DATASET\">Dataset</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-source-id\">\n {sourceKind === 'NOTEBOOK' ? 'Notebook' : 'Dataset'}\n </Label>\n <Select value={sourceId} onValueChange={(value) => setSourceId(value)}>\n <SelectTrigger id=\"run-source-id\" aria-label=\"Analysis source\">\n <SelectValue\n placeholder={\n sourceLoading\n ? 'Loading…'\n : `Select a ${sourceKind === 'NOTEBOOK' ? 'notebook' : 'dataset'}`\n }\n />\n </SelectTrigger>\n <SelectContent>\n {sourceKind === 'NOTEBOOK'\n ? notebooks.map((notebook) => (\n <SelectItem key={notebook.id} value={notebook.id}>\n {notebook.title}\n </SelectItem>\n ))\n : datasets.map((dataset) => (\n <SelectItem key={dataset.id} value={dataset.id}>\n {dataset.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-method\">Method</Label>\n <Input\n id=\"run-method\"\n value={method}\n onChange={(event) => setMethod(event.target.value)}\n placeholder=\"e.g. gaussian-fit\"\n />\n </div>\n\n <div className=\"flex items-center gap-3\">\n <Switch\n id=\"run-ai\"\n checked={aiAssisted}\n onCheckedChange={(checked) => setAiAssisted(checked)}\n />\n <Label htmlFor=\"run-ai\" className=\"cursor-pointer\">\n AI-assisted analysis\n </Label>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={loading}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={loading}>\n <Play className=\"size-4\" />\n {loading ? 'Starting…' : 'Run analysis'}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Complete analysis dialog\n// ---------------------------------------------------------------------------\n\ninterface CompleteDialogProps {\n analysis: CosAnalysis | null;\n onOpenChange: (open: boolean) => void;\n onCompleted: () => void;\n}\n\nfunction CompleteAnalysisDialog({ analysis, onOpenChange, onCompleted }: CompleteDialogProps) {\n const [status, setStatus] = useState<'COMPLETED' | 'FAILED'>('COMPLETED');\n const [results, setResults] = useState('');\n const [outputFileId, setOutputFileId] = useState('');\n const [completeAnalysis, { loading }] = useCosCompleteAnalysisMutation();\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!analysis) {\n return;\n }\n const parsed = parseResults(results);\n if (!parsed.ok) {\n notify.error('Invalid results', parsed.error);\n return;\n }\n const response = await completeAnalysis({\n variables: {\n id: analysis.id,\n status,\n results: parsed.value,\n outputFileId: outputFileId || undefined,\n },\n });\n if (response.error || !response.data?.cosCompleteAnalysis) {\n return;\n }\n notify.success(\n status === 'COMPLETED' ? 'Analysis completed' : 'Analysis marked failed',\n `“${analysis.title}” was updated.`\n );\n onOpenChange(false);\n onCompleted();\n };\n\n return (\n <Dialog\n open={Boolean(analysis)}\n onOpenChange={(next) => {\n if (!loading) {\n onOpenChange(next);\n }\n }}\n >\n <DialogContent>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>Complete analysis</DialogTitle>\n <DialogDescription>\n Record the outcome for {analysis ? `“${analysis.title}”` : 'this analysis'}. Attach\n results or an output artifact if you have them.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"complete-status\">Outcome</Label>\n <Select\n value={status}\n onValueChange={(value) => setStatus(value as 'COMPLETED' | 'FAILED')}\n >\n <SelectTrigger id=\"complete-status\" aria-label=\"Outcome\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"COMPLETED\">Completed</SelectItem>\n <SelectItem value=\"FAILED\">Failed</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"complete-results\">Results (JSON)</Label>\n <Textarea\n id=\"complete-results\"\n value={results}\n onChange={(event) => setResults(event.target.value)}\n rows={4}\n className=\"font-mono text-xs\"\n placeholder='{ \"snr\": 12.4, \"detections\": 3 }'\n />\n <p className=\"text-xs text-text-secondary\">\n Optional structured results as a JSON object.\n </p>\n </div>\n\n <FileUploadField\n value={outputFileId}\n onChange={(fileId) => setOutputFileId(fileId)}\n label=\"Attach output file\"\n hint=\"Optional output artifact (plots, tables, exports). Stored in workspace files.\"\n />\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={loading}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={loading}>\n {loading ? 'Saving…' : 'Save outcome'}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Page\n// ---------------------------------------------------------------------------\n\nexport default function AnalysesPage() {\n const { navigate } = useCosmicIntersection();\n const [statusFilter, setStatusFilter] = useState<CosAnalysisStatus | undefined>(undefined);\n const [runOpen, setRunOpen] = useState(false);\n const [completing, setCompleting] = useState<CosAnalysis | null>(null);\n\n const { data, loading, error, refetch } = useCosAnalysesQuery({ status: statusFilter });\n const { data: notebooksData } = useCosNotebooksQuery({ pagination: { limit: 100, offset: 0 } });\n const { data: datasetsData } = useCosDatasetsQuery({ pagination: { limit: 100, offset: 0 } });\n\n const analyses = data?.cosListAnalyses ?? [];\n\n const notebookNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const notebook of notebooksData?.cosListNotebooks.items ?? []) {\n map.set(notebook.id, notebook.title);\n }\n return map;\n }, [notebooksData]);\n\n const datasetNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const dataset of datasetsData?.cosListDatasets.items ?? []) {\n map.set(dataset.id, dataset.name);\n }\n return map;\n }, [datasetsData]);\n\n const actions = (\n <Button type=\"button\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\n );\n\n return (\n <PageLayout\n title=\"Analyses\"\n description=\"Analysis runs executed over notebooks and federated datasets.\"\n actions={actions}\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <label className=\"text-sm text-text-secondary\" htmlFor=\"analysis-status-filter\">\n Status\n </label>\n <Select\n value={statusFilter ?? ALL}\n onValueChange={(value) =>\n setStatusFilter(value === ALL ? undefined : (value as CosAnalysisStatus))\n }\n >\n <SelectTrigger\n id=\"analysis-status-filter\"\n className=\"w-48\"\n aria-label=\"Filter by status\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>All statuses</SelectItem>\n {STATUS_OPTIONS.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {loading ? (\n <LoadingState variant=\"rows\" rows={6} label=\"Loading analyses…\" />\n ) : error ? (\n <ErrorState\n message=\"We could not load analyses. Please try again.\"\n onRetry={() => void refetch()}\n />\n ) : analyses.length === 0 ? (\n <EmptyState\n icon={Beaker}\n title={statusFilter ? 'No analyses match this filter.' : 'No analyses yet.'}\n description={\n statusFilter\n ? 'Try a different status filter.'\n : 'Run an analysis against a notebook or dataset to see results here.'\n }\n action={\n statusFilter ? undefined : (\n <Button type=\"button\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\n )\n }\n />\n ) : (\n <div className=\"rounded-card border border-border-default bg-bg-elevated\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Title</TableHead>\n <TableHead>Method</TableHead>\n <TableHead>AI</TableHead>\n <TableHead>Status</TableHead>\n <TableHead>Source</TableHead>\n <TableHead>Started</TableHead>\n <TableHead>Finished</TableHead>\n <TableHead>Output</TableHead>\n <TableHead className=\"w-12 text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {analyses.map((analysis) => {\n const inFlight = analysis.status === 'PENDING' || analysis.status === 'RUNNING';\n const sourceLabel = analysis.notebookId\n ? (notebookNames.get(analysis.notebookId) ?? 'Notebook')\n : analysis.datasetId\n ? (datasetNames.get(analysis.datasetId) ?? 'Dataset')\n : null;\n const sourcePath = analysis.notebookId\n ? `notebooks/${analysis.notebookId}`\n : analysis.datasetId\n ? `datasets/${analysis.datasetId}`\n : null;\n return (\n <TableRow key={analysis.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {analysis.title}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {analysis.method ?? '—'}\n </TableCell>\n <TableCell>\n {analysis.aiAssisted ? (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Sparkles className=\"size-3\" aria-hidden=\"true\" />\n AI\n </Badge>\n ) : (\n <span className=\"text-text-secondary\">—</span>\n )}\n </TableCell>\n <TableCell>\n <StatusBadge status={analysis.status} />\n </TableCell>\n <TableCell>\n {sourceLabel && sourcePath ? (\n <button\n type=\"button\"\n onClick={() => navigate(sourcePath)}\n className=\"inline-flex max-w-[12rem] items-center gap-1 truncate text-sm text-text-primary underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{sourceLabel}</span>\n </button>\n ) : (\n <span className=\"text-text-secondary\">—</span>\n )}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-text-secondary\">\n {formatDateTime(analysis.startedAt)}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-text-secondary\">\n {formatDateTime(analysis.finishedAt)}\n </TableCell>\n <TableCell>\n {analysis.outputFile?.id ? (\n <FileDownloadLink fileId={analysis.outputFile.id} />\n ) : analysis.results && Object.keys(analysis.results).length > 0 ? (\n <span className=\"text-xs text-text-secondary\">Results recorded</span>\n ) : (\n <span className=\"text-text-secondary\">—</span>\n )}\n </TableCell>\n <TableCell className=\"text-right\">\n <ActionMenu\n ariaLabel={`Actions for ${analysis.title}`}\n onView={sourcePath ? () => navigate(sourcePath) : undefined}\n extraItems={\n inFlight\n ? [\n {\n key: 'complete',\n label: 'Complete…',\n icon: Beaker,\n onSelect: () => setCompleting(analysis),\n },\n ]\n : []\n }\n />\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n )}\n </div>\n\n <RunAnalysisDialog\n open={runOpen}\n onOpenChange={setRunOpen}\n onCompleted={() => void refetch()}\n />\n <CompleteAnalysisDialog\n key={completing?.id ?? 'none'}\n analysis={completing}\n onOpenChange={(open) => {\n if (!open) {\n setCompleting(null);\n }\n }}\n onCompleted={() => void refetch()}\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|