@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
@@ -4,10 +4,10 @@ import { useCosAnalysesQuery as n, useCosArchiveNotebookMutation as r, useCosNot
4
4
  import o from "../../components/ActionMenu.js";
5
5
  import s from "../../components/EmptyState.js";
6
6
  import c from "../../components/ErrorState.js";
7
- import { useFileDownloadUrl as l } from "../../components/FileUploadField.js";
8
- import u from "../../components/LoadingState.js";
9
- import d from "../../components/PageLayout.js";
10
- import f from "../../components/SafeLink.js";
7
+ import l from "../../components/LoadingState.js";
8
+ import u from "../../components/DiscussionPanel.js";
9
+ import { useFileDownloadUrl as d } from "../../components/FileUploadField.js";
10
+ import f from "../../components/PageLayout.js";
11
11
  import p from "../../components/StatusBadge.js";
12
12
  import "../../components/index.js";
13
13
  import { useState as m } from "react";
@@ -28,7 +28,7 @@ function U(e) {
28
28
  });
29
29
  }
30
30
  function W({ fileId: e, label: t }) {
31
- let { data: n, loading: r } = l(e), i = n?.getFileDownloadUrl ?? null;
31
+ let { data: n, loading: r } = d(e), i = n?.getFileDownloadUrl ?? null;
32
32
  return r ? /* @__PURE__ */ h("span", {
33
33
  className: "text-xs text-text-secondary",
34
34
  children: "Resolving link…"
@@ -127,19 +127,19 @@ function G({ notebookId: e, open: n, onOpenChange: r, onCompleted: i }) {
127
127
  });
128
128
  }
129
129
  function K() {
130
- let { id: a = "" } = _(), { navigate: l } = e(), [y, O] = m(!1), { data: k, loading: A, error: j, refetch: M } = i(a), { data: N, loading: P, error: F, refetch: I } = n({ notebookId: a }), [K] = r(), q = k?.cosNotebook ?? null, J = N?.cosListAnalyses ?? [], Y = async () => {
130
+ let { id: a = "" } = _(), { navigate: d } = e(), [y, O] = m(!1), { data: k, loading: A, error: j, refetch: M } = i(a), { data: N, loading: P, error: F, refetch: I } = n({ notebookId: a }), [K] = r(), q = k?.cosNotebook ?? null, J = N?.cosListAnalyses ?? [], Y = async () => {
131
131
  if (!q) return;
132
132
  let e = await K({ variables: { id: q.id } });
133
133
  if (e.error) throw Error(e.error.message);
134
134
  if (!e.data?.cosArchiveNotebook) throw t.error("Could not archive notebook", "The server did not confirm the change."), Error("Archive not confirmed");
135
135
  await M(), t.success("Notebook archived", `“${q.title}” was archived.`);
136
136
  };
137
- if (A) return /* @__PURE__ */ h(d, {
137
+ if (A) return /* @__PURE__ */ h(f, {
138
138
  title: "Notebook",
139
139
  backPath: "notebooks",
140
- children: /* @__PURE__ */ h(u, { label: "Loading notebook…" })
140
+ children: /* @__PURE__ */ h(l, { label: "Loading notebook…" })
141
141
  });
142
- if (j) return /* @__PURE__ */ h(d, {
142
+ if (j) return /* @__PURE__ */ h(f, {
143
143
  title: "Notebook",
144
144
  backPath: "notebooks",
145
145
  children: /* @__PURE__ */ h(c, {
@@ -147,7 +147,7 @@ function K() {
147
147
  onRetry: () => void M()
148
148
  })
149
149
  });
150
- if (!q) return /* @__PURE__ */ h(d, {
150
+ if (!q) return /* @__PURE__ */ h(f, {
151
151
  title: "Notebook",
152
152
  backPath: "notebooks",
153
153
  children: /* @__PURE__ */ h(s, {
@@ -156,7 +156,7 @@ function K() {
156
156
  description: "This notebook may have been removed or is outside your current scope.",
157
157
  action: /* @__PURE__ */ h(D, {
158
158
  type: "button",
159
- onClick: () => l("notebooks"),
159
+ onClick: () => d("notebooks"),
160
160
  children: "Back to notebooks"
161
161
  })
162
162
  })
@@ -172,213 +172,222 @@ function K() {
172
172
  /* @__PURE__ */ g(D, {
173
173
  type: "button",
174
174
  variant: "outline",
175
- onClick: () => l(`notebooks/${q.id}/edit`),
175
+ onClick: () => d(`notebooks/${q.id}/edit`),
176
176
  children: [/* @__PURE__ */ h(S, { className: "size-4" }), "Edit"]
177
177
  }),
178
178
  /* @__PURE__ */ h(o, {
179
179
  ariaLabel: `Actions for ${q.title}`,
180
180
  entityName: q.title,
181
- onEdit: () => l(`notebooks/${q.id}/edit`),
182
181
  onDelete: q.status === "ARCHIVED" ? void 0 : Y,
183
182
  deleteLabel: "Archive notebook"
184
183
  })
185
184
  ]
186
185
  });
187
- return /* @__PURE__ */ g(d, {
186
+ return /* @__PURE__ */ g(f, {
188
187
  title: q.title,
189
188
  description: "Notebook detail",
190
189
  backPath: "notebooks",
191
190
  actions: Z,
192
191
  children: [/* @__PURE__ */ g("div", {
193
192
  className: "space-y-6",
194
- children: [/* @__PURE__ */ g("section", {
195
- className: "rounded-card border border-border-default bg-bg-elevated p-6",
196
- children: [
197
- /* @__PURE__ */ g("div", {
198
- className: "flex flex-wrap items-center gap-3",
199
- children: [
200
- /* @__PURE__ */ h(p, { status: q.status }),
201
- q.runtime ? /* @__PURE__ */ g(E, {
202
- variant: "outline",
203
- children: ["Runtime: ", q.runtime]
204
- }) : null,
205
- q.isShared ? /* @__PURE__ */ g(E, {
206
- variant: "secondary",
207
- className: "gap-1",
208
- children: [
209
- /* @__PURE__ */ h(w, {
210
- className: "size-3",
211
- "aria-hidden": "true"
212
- }),
213
- "Shared",
214
- q.shareSlug ? `: ${q.shareSlug}` : ""
215
- ]
216
- }) : /* @__PURE__ */ h(E, {
217
- variant: "outline",
218
- children: "Private"
219
- })
220
- ]
221
- }),
222
- q.description ? /* @__PURE__ */ h("p", {
223
- className: "mt-4 text-sm text-text-secondary",
224
- children: q.description
225
- }) : /* @__PURE__ */ h("p", {
226
- className: "mt-4 text-sm text-text-secondary",
227
- children: "No description provided."
228
- }),
229
- /* @__PURE__ */ g("dl", {
230
- className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
231
- children: [
232
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
233
- className: "text-xs uppercase tracking-wide text-text-secondary",
234
- children: "Linked datasets"
235
- }), /* @__PURE__ */ h("dd", {
236
- className: "mt-1 text-sm tabular-nums text-text-primary",
237
- children: q.datasetIds.length
238
- })] }),
239
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
240
- className: "text-xs uppercase tracking-wide text-text-secondary",
241
- children: "Created"
242
- }), /* @__PURE__ */ h("dd", {
243
- className: "mt-1 text-sm text-text-primary",
244
- children: U(q.createdAt)
245
- })] }),
246
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
193
+ children: [
194
+ /* @__PURE__ */ g("section", {
195
+ className: "rounded-card border border-border-default bg-bg-elevated p-6",
196
+ children: [
197
+ /* @__PURE__ */ g("div", {
198
+ className: "flex flex-wrap items-center gap-3",
199
+ children: [
200
+ /* @__PURE__ */ h(p, { status: q.status }),
201
+ q.runtime ? /* @__PURE__ */ g(E, {
202
+ variant: "outline",
203
+ children: ["Runtime: ", q.runtime]
204
+ }) : null,
205
+ q.isShared ? /* @__PURE__ */ g(E, {
206
+ variant: "secondary",
207
+ className: "gap-1",
208
+ children: [
209
+ /* @__PURE__ */ h(w, {
210
+ className: "size-3",
211
+ "aria-hidden": "true"
212
+ }),
213
+ "Shared",
214
+ q.shareSlug ? `: ${q.shareSlug}` : ""
215
+ ]
216
+ }) : /* @__PURE__ */ h(E, {
217
+ variant: "outline",
218
+ children: "Private"
219
+ })
220
+ ]
221
+ }),
222
+ q.description ? /* @__PURE__ */ h("p", {
223
+ className: "mt-4 text-sm text-text-secondary",
224
+ children: q.description
225
+ }) : /* @__PURE__ */ h("p", {
226
+ className: "mt-4 text-sm text-text-secondary",
227
+ children: "No description provided."
228
+ }),
229
+ /* @__PURE__ */ g("dl", {
230
+ className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
231
+ children: [
232
+ /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
233
+ className: "text-xs uppercase tracking-wide text-text-secondary",
234
+ children: "Linked datasets"
235
+ }), /* @__PURE__ */ h("dd", {
236
+ className: "mt-1 text-sm tabular-nums text-text-primary",
237
+ children: q.datasetIds.length
238
+ })] }),
239
+ /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
240
+ className: "text-xs uppercase tracking-wide text-text-secondary",
241
+ children: "Created"
242
+ }), /* @__PURE__ */ h("dd", {
243
+ className: "mt-1 text-sm text-text-primary",
244
+ children: U(q.createdAt)
245
+ })] }),
246
+ /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
247
+ className: "text-xs uppercase tracking-wide text-text-secondary",
248
+ children: "Updated"
249
+ }), /* @__PURE__ */ h("dd", {
250
+ className: "mt-1 text-sm text-text-primary",
251
+ children: U(q.updatedAt)
252
+ })] }),
253
+ /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
254
+ className: "text-xs uppercase tracking-wide text-text-secondary",
255
+ children: "Notebook file"
256
+ }), /* @__PURE__ */ h("dd", {
257
+ className: "mt-1 text-sm text-text-primary",
258
+ children: q.file?.id ? /* @__PURE__ */ h(W, {
259
+ fileId: q.file.id,
260
+ label: "Download notebook"
261
+ }) : /* @__PURE__ */ h("span", {
262
+ className: "text-text-secondary",
263
+ children: "No file attached"
264
+ })
265
+ })] })
266
+ ]
267
+ }),
268
+ q.tags.length > 0 ? /* @__PURE__ */ g("div", {
269
+ className: "mt-6",
270
+ children: [/* @__PURE__ */ h("p", {
247
271
  className: "text-xs uppercase tracking-wide text-text-secondary",
248
- children: "Updated"
249
- }), /* @__PURE__ */ h("dd", {
250
- className: "mt-1 text-sm text-text-primary",
251
- children: U(q.updatedAt)
252
- })] }),
253
- /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("dt", {
272
+ children: "Tags"
273
+ }), /* @__PURE__ */ h("div", {
274
+ className: "mt-2 flex flex-wrap gap-2",
275
+ children: q.tags.map((e) => /* @__PURE__ */ h(E, {
276
+ variant: "outline",
277
+ children: e
278
+ }, e))
279
+ })]
280
+ }) : null,
281
+ X ? /* @__PURE__ */ g("div", {
282
+ className: "mt-6",
283
+ children: [/* @__PURE__ */ h("p", {
254
284
  className: "text-xs uppercase tracking-wide text-text-secondary",
255
- children: "Notebook file"
256
- }), /* @__PURE__ */ h("dd", {
257
- className: "mt-1 text-sm text-text-primary",
258
- children: q.file?.id ? /* @__PURE__ */ h(W, {
259
- fileId: q.file.id,
260
- label: "Download notebook"
261
- }) : /* @__PURE__ */ h("span", {
262
- className: "text-text-secondary",
263
- children: "No file attached"
264
- })
265
- })] })
266
- ]
267
- }),
268
- q.tags.length > 0 ? /* @__PURE__ */ g("div", {
269
- className: "mt-6",
270
- children: [/* @__PURE__ */ h("p", {
271
- className: "text-xs uppercase tracking-wide text-text-secondary",
272
- children: "Tags"
273
- }), /* @__PURE__ */ h("div", {
274
- className: "mt-2 flex flex-wrap gap-2",
275
- children: q.tags.map((e) => /* @__PURE__ */ h(E, {
276
- variant: "outline",
277
- children: e
278
- }, e))
285
+ children: "Environment"
286
+ }), /* @__PURE__ */ h("pre", {
287
+ className: "mt-2 max-h-64 overflow-auto rounded-card border border-border-default bg-bg-sunken p-4 font-mono text-xs text-text-primary",
288
+ children: X
289
+ })]
290
+ }) : null
291
+ ]
292
+ }),
293
+ /* @__PURE__ */ g("section", {
294
+ className: "space-y-4",
295
+ children: [/* @__PURE__ */ g("div", {
296
+ className: "flex items-center gap-2",
297
+ children: [/* @__PURE__ */ h(x, {
298
+ className: "size-5 text-text-secondary",
299
+ "aria-hidden": "true"
300
+ }), /* @__PURE__ */ h("h2", {
301
+ className: "text-lg font-semibold text-text-primary",
302
+ children: "Discussion"
279
303
  })]
280
- }) : null,
281
- X ? /* @__PURE__ */ g("div", {
282
- className: "mt-6",
283
- children: [/* @__PURE__ */ h("p", {
284
- className: "text-xs uppercase tracking-wide text-text-secondary",
285
- children: "Environment"
286
- }), /* @__PURE__ */ h("pre", {
287
- className: "mt-2 max-h-64 overflow-auto rounded-card border border-border-default bg-bg-sunken p-4 font-mono text-xs text-text-primary",
288
- children: X
304
+ }), /* @__PURE__ */ h(u, {
305
+ entityType: "cosmicintersection-notebook",
306
+ entityId: q.id,
307
+ title: q.title,
308
+ widgetKey: "notebook-discussion"
309
+ })]
310
+ }),
311
+ /* @__PURE__ */ g("section", {
312
+ className: "space-y-4",
313
+ children: [/* @__PURE__ */ g("div", {
314
+ className: "flex flex-wrap items-center justify-between gap-3",
315
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h2", {
316
+ className: "text-lg font-semibold text-text-primary",
317
+ children: "Analyses"
318
+ }), /* @__PURE__ */ h("p", {
319
+ className: "text-sm text-text-secondary",
320
+ children: "Analysis runs executed against this notebook."
321
+ })] }), /* @__PURE__ */ g(D, {
322
+ type: "button",
323
+ variant: "outline",
324
+ onClick: () => O(!0),
325
+ children: [/* @__PURE__ */ h(C, { className: "size-4" }), "Run analysis"]
289
326
  })]
290
- }) : null,
291
- /* @__PURE__ */ h("div", {
292
- className: "mt-6 flex flex-wrap items-center gap-2",
293
- children: /* @__PURE__ */ g(f, {
294
- href: "/conversations",
295
- className: "inline-flex items-center gap-1.5 rounded-button border border-border-default px-3 py-1.5 text-sm text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary",
296
- children: [/* @__PURE__ */ h(x, {
297
- className: "size-4",
298
- "aria-hidden": "true"
299
- }), "Discuss in conversations"]
327
+ }), P ? /* @__PURE__ */ h(l, {
328
+ variant: "rows",
329
+ rows: 3,
330
+ label: "Loading analyses…"
331
+ }) : F ? /* @__PURE__ */ h(c, {
332
+ message: "We could not load analyses for this notebook.",
333
+ onRetry: () => void I()
334
+ }) : J.length === 0 ? /* @__PURE__ */ h(s, {
335
+ icon: v,
336
+ title: "No analyses yet.",
337
+ description: "Run an analysis to generate results and artifacts from this notebook.",
338
+ action: /* @__PURE__ */ g(D, {
339
+ type: "button",
340
+ onClick: () => O(!0),
341
+ children: [/* @__PURE__ */ h(C, { className: "size-4" }), "Run analysis"]
300
342
  })
301
- })
302
- ]
303
- }), /* @__PURE__ */ g("section", {
304
- className: "space-y-4",
305
- children: [/* @__PURE__ */ g("div", {
306
- className: "flex flex-wrap items-center justify-between gap-3",
307
- children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h2", {
308
- className: "text-lg font-semibold text-text-primary",
309
- children: "Analyses"
310
- }), /* @__PURE__ */ h("p", {
311
- className: "text-sm text-text-secondary",
312
- children: "Analysis runs executed against this notebook."
313
- })] }), /* @__PURE__ */ g(D, {
314
- type: "button",
315
- variant: "outline",
316
- onClick: () => O(!0),
317
- children: [/* @__PURE__ */ h(C, { className: "size-4" }), "Run analysis"]
343
+ }) : /* @__PURE__ */ h("div", {
344
+ className: "rounded-card border border-border-default bg-bg-elevated",
345
+ children: /* @__PURE__ */ g(L, { children: [/* @__PURE__ */ h(V, { children: /* @__PURE__ */ g(H, { children: [
346
+ /* @__PURE__ */ h(B, { children: "Title" }),
347
+ /* @__PURE__ */ h(B, { children: "Method" }),
348
+ /* @__PURE__ */ h(B, { children: "AI" }),
349
+ /* @__PURE__ */ h(B, { children: "Status" }),
350
+ /* @__PURE__ */ h(B, { children: "Started" }),
351
+ /* @__PURE__ */ h(B, { children: "Output" })
352
+ ] }) }), /* @__PURE__ */ h(R, { children: J.map((e) => /* @__PURE__ */ g(H, { children: [
353
+ /* @__PURE__ */ h(z, {
354
+ className: "font-medium text-text-primary",
355
+ children: e.title
356
+ }),
357
+ /* @__PURE__ */ h(z, {
358
+ className: "text-text-secondary",
359
+ children: e.method ?? "—"
360
+ }),
361
+ /* @__PURE__ */ h(z, { children: e.aiAssisted ? /* @__PURE__ */ g(E, {
362
+ variant: "secondary",
363
+ className: "gap-1",
364
+ children: [/* @__PURE__ */ h(T, {
365
+ className: "size-3",
366
+ "aria-hidden": "true"
367
+ }), "AI"]
368
+ }) : /* @__PURE__ */ h("span", {
369
+ className: "text-text-secondary",
370
+ children: "—"
371
+ }) }),
372
+ /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(p, { status: e.status }) }),
373
+ /* @__PURE__ */ h(z, {
374
+ className: "whitespace-nowrap text-text-secondary",
375
+ children: U(e.startedAt)
376
+ }),
377
+ /* @__PURE__ */ h(z, { children: e.outputFile?.id ? /* @__PURE__ */ h(W, {
378
+ fileId: e.outputFile.id,
379
+ label: "Download"
380
+ }) : e.results && Object.keys(e.results).length > 0 ? /* @__PURE__ */ h("span", {
381
+ className: "text-xs text-text-secondary",
382
+ children: "Results recorded"
383
+ }) : /* @__PURE__ */ h("span", {
384
+ className: "text-text-secondary",
385
+ children: "—"
386
+ }) })
387
+ ] }, e.id)) })] })
318
388
  })]
319
- }), P ? /* @__PURE__ */ h(u, {
320
- variant: "rows",
321
- rows: 3,
322
- label: "Loading analyses…"
323
- }) : F ? /* @__PURE__ */ h(c, {
324
- message: "We could not load analyses for this notebook.",
325
- onRetry: () => void I()
326
- }) : J.length === 0 ? /* @__PURE__ */ h(s, {
327
- icon: v,
328
- title: "No analyses yet.",
329
- description: "Run an analysis to generate results and artifacts from this notebook.",
330
- action: /* @__PURE__ */ g(D, {
331
- type: "button",
332
- onClick: () => O(!0),
333
- children: [/* @__PURE__ */ h(C, { className: "size-4" }), "Run analysis"]
334
- })
335
- }) : /* @__PURE__ */ h("div", {
336
- className: "rounded-card border border-border-default bg-bg-elevated",
337
- children: /* @__PURE__ */ g(L, { children: [/* @__PURE__ */ h(V, { children: /* @__PURE__ */ g(H, { children: [
338
- /* @__PURE__ */ h(B, { children: "Title" }),
339
- /* @__PURE__ */ h(B, { children: "Method" }),
340
- /* @__PURE__ */ h(B, { children: "AI" }),
341
- /* @__PURE__ */ h(B, { children: "Status" }),
342
- /* @__PURE__ */ h(B, { children: "Started" }),
343
- /* @__PURE__ */ h(B, { children: "Output" })
344
- ] }) }), /* @__PURE__ */ h(R, { children: J.map((e) => /* @__PURE__ */ g(H, { children: [
345
- /* @__PURE__ */ h(z, {
346
- className: "font-medium text-text-primary",
347
- children: e.title
348
- }),
349
- /* @__PURE__ */ h(z, {
350
- className: "text-text-secondary",
351
- children: e.method ?? "—"
352
- }),
353
- /* @__PURE__ */ h(z, { children: e.aiAssisted ? /* @__PURE__ */ g(E, {
354
- variant: "secondary",
355
- className: "gap-1",
356
- children: [/* @__PURE__ */ h(T, {
357
- className: "size-3",
358
- "aria-hidden": "true"
359
- }), "AI"]
360
- }) : /* @__PURE__ */ h("span", {
361
- className: "text-text-secondary",
362
- children: "—"
363
- }) }),
364
- /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(p, { status: e.status }) }),
365
- /* @__PURE__ */ h(z, {
366
- className: "whitespace-nowrap text-text-secondary",
367
- children: U(e.startedAt)
368
- }),
369
- /* @__PURE__ */ h(z, { children: e.outputFile?.id ? /* @__PURE__ */ h(W, {
370
- fileId: e.outputFile.id,
371
- label: "Download"
372
- }) : e.results && Object.keys(e.results).length > 0 ? /* @__PURE__ */ h("span", {
373
- className: "text-xs text-text-secondary",
374
- children: "Results recorded"
375
- }) : /* @__PURE__ */ h("span", {
376
- className: "text-text-secondary",
377
- children: "—"
378
- }) })
379
- ] }, e.id)) })] })
380
- })]
381
- })]
389
+ })
390
+ ]
382
391
  }), /* @__PURE__ */ h(G, {
383
392
  notebookId: q.id,
384
393
  open: y,
@@ -1 +1 @@
1
- {"version":3,"file":"NotebookDetailPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/notebooks/NotebookDetailPage.tsx"],"sourcesContent":["/**\n * NotebookDetailPage — full record for one notebook.\n *\n * Header renders the notebook's metadata (status, runtime, environment JSON,\n * description, sharing, attached file download). Below it an Analyses section\n * lists `cosListAnalyses(notebookId)` and a \"Run analysis\" dialog kicks off a\n * new `cosRunAnalysis` bound to this notebook. Archive is available from the\n * header action menu. No fabricated data — everything is read from the backend.\n */\nimport { useState, type FormEvent } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n Beaker,\n Download,\n FileCode2,\n MessageSquare,\n Pencil,\n Play,\n Share2,\n Sparkles,\n} 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 Switch,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosAnalysesQuery,\n useCosArchiveNotebookMutation,\n useCosNotebookQuery,\n useCosRunAnalysisMutation,\n type CosAnalysis,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n EmptyState,\n ErrorState,\n LoadingState,\n PageLayout,\n SafeLink,\n StatusBadge,\n useFileDownloadUrl,\n} from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\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/** Renders a presigned download link for an attached wspace-files artifact. */\nfunction FileDownloadLink({ fileId, label }: { fileId: string; label: 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 link…</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 {label}\n </a>\n );\n}\n\ninterface RunAnalysisDialogProps {\n notebookId: string;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCompleted: () => void;\n}\n\n/** Dialog to launch a new analysis on this notebook. */\nfunction RunAnalysisDialog({\n notebookId,\n open,\n onOpenChange,\n onCompleted,\n}: RunAnalysisDialogProps) {\n const [title, setTitle] = useState('');\n const [method, setMethod] = useState('');\n const [aiAssisted, setAiAssisted] = useState(false);\n const [runAnalysis, { loading }] = useCosRunAnalysisMutation();\n\n const reset = () => {\n setTitle('');\n setMethod('');\n setAiAssisted(false);\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 const response = await runAnalysis({\n variables: {\n input: {\n notebookId,\n title: trimmed,\n method: method.trim() || undefined,\n aiAssisted,\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 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 run against this notebook. It starts in the running state and\n can be completed later with results.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-analysis-title\">Title</Label>\n <Input\n id=\"run-analysis-title\"\n value={title}\n onChange={(event) => setTitle(event.target.value)}\n placeholder=\"e.g. Period-folding search\"\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-analysis-method\">Method</Label>\n <Input\n id=\"run-analysis-method\"\n value={method}\n onChange={(event) => setMethod(event.target.value)}\n placeholder=\"e.g. box-least-squares\"\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <Switch\n id=\"run-analysis-ai\"\n checked={aiAssisted}\n onCheckedChange={(checked) => setAiAssisted(checked)}\n />\n <Label htmlFor=\"run-analysis-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\nexport default function NotebookDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useCosmicIntersection();\n const [runOpen, setRunOpen] = useState(false);\n\n const { data, loading, error, refetch } = useCosNotebookQuery(id);\n const {\n data: analysesData,\n loading: analysesLoading,\n error: analysesError,\n refetch: refetchAnalyses,\n } = useCosAnalysesQuery({ notebookId: id });\n const [archiveNotebook] = useCosArchiveNotebookMutation();\n\n const notebook = data?.cosNotebook ?? null;\n const analyses = analysesData?.cosListAnalyses ?? [];\n\n const handleArchive = async () => {\n if (!notebook) {\n return;\n }\n const response = await archiveNotebook({ variables: { id: notebook.id } });\n if (response.error) {\n throw new Error(response.error.message);\n }\n if (!response.data?.cosArchiveNotebook) {\n notify.error('Could not archive notebook', 'The server did not confirm the change.');\n throw new Error('Archive not confirmed');\n }\n await refetch();\n notify.success('Notebook archived', `“${notebook.title}” was archived.`);\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Notebook\" backPath=\"notebooks\">\n <LoadingState label=\"Loading notebook…\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title=\"Notebook\" backPath=\"notebooks\">\n <ErrorState\n message=\"We could not load this notebook. Please try again.\"\n onRetry={() => void refetch()}\n />\n </PageLayout>\n );\n }\n\n if (!notebook) {\n return (\n <PageLayout title=\"Notebook\" backPath=\"notebooks\">\n <EmptyState\n icon={FileCode2}\n title=\"Notebook not found.\"\n description=\"This notebook may have been removed or is outside your current scope.\"\n action={\n <Button type=\"button\" onClick={() => navigate('notebooks')}>\n Back to notebooks\n </Button>\n }\n />\n </PageLayout>\n );\n }\n\n const environmentJson =\n notebook.environment && Object.keys(notebook.environment).length > 0\n ? JSON.stringify(notebook.environment, null, 2)\n : null;\n\n const actions = (\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`notebooks/${notebook.id}/edit`)}\n >\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n <ActionMenu\n ariaLabel={`Actions for ${notebook.title}`}\n entityName={notebook.title}\n onEdit={() => navigate(`notebooks/${notebook.id}/edit`)}\n onDelete={notebook.status === 'ARCHIVED' ? undefined : handleArchive}\n deleteLabel=\"Archive notebook\"\n />\n </div>\n );\n\n return (\n <PageLayout\n title={notebook.title}\n description=\"Notebook detail\"\n backPath=\"notebooks\"\n actions={actions}\n >\n <div className=\"space-y-6\">\n {/* Overview */}\n <section className=\"rounded-card border border-border-default bg-bg-elevated p-6\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <StatusBadge status={notebook.status} />\n {notebook.runtime ? <Badge variant=\"outline\">Runtime: {notebook.runtime}</Badge> : null}\n {notebook.isShared ? (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Share2 className=\"size-3\" aria-hidden=\"true\" />\n Shared{notebook.shareSlug ? `: ${notebook.shareSlug}` : ''}\n </Badge>\n ) : (\n <Badge variant=\"outline\">Private</Badge>\n )}\n </div>\n\n {notebook.description ? (\n <p className=\"mt-4 text-sm text-text-secondary\">{notebook.description}</p>\n ) : (\n <p className=\"mt-4 text-sm text-text-secondary\">No description provided.</p>\n )}\n\n <dl className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">\n Linked datasets\n </dt>\n <dd className=\"mt-1 text-sm tabular-nums text-text-primary\">\n {notebook.datasetIds.length}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">Created</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">\n {formatDateTime(notebook.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">Updated</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">\n {formatDateTime(notebook.updatedAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">Notebook file</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">\n {notebook.file?.id ? (\n <FileDownloadLink fileId={notebook.file.id} label=\"Download notebook\" />\n ) : (\n <span className=\"text-text-secondary\">No file attached</span>\n )}\n </dd>\n </div>\n </dl>\n\n {notebook.tags.length > 0 ? (\n <div className=\"mt-6\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Tags</p>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notebook.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\">\n {tag}\n </Badge>\n ))}\n </div>\n </div>\n ) : null}\n\n {environmentJson ? (\n <div className=\"mt-6\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Environment</p>\n <pre className=\"mt-2 max-h-64 overflow-auto rounded-card border border-border-default bg-bg-sunken p-4 font-mono text-xs text-text-primary\">\n {environmentJson}\n </pre>\n </div>\n ) : null}\n\n <div className=\"mt-6 flex flex-wrap items-center gap-2\">\n <SafeLink\n href=\"/conversations\"\n className=\"inline-flex items-center gap-1.5 rounded-button border border-border-default px-3 py-1.5 text-sm text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <MessageSquare className=\"size-4\" aria-hidden=\"true\" />\n Discuss in conversations\n </SafeLink>\n </div>\n </section>\n\n {/* Analyses */}\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Analyses</h2>\n <p className=\"text-sm text-text-secondary\">\n Analysis runs executed against this notebook.\n </p>\n </div>\n <Button type=\"button\" variant=\"outline\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\n </div>\n\n {analysesLoading ? (\n <LoadingState variant=\"rows\" rows={3} label=\"Loading analyses…\" />\n ) : analysesError ? (\n <ErrorState\n message=\"We could not load analyses for this notebook.\"\n onRetry={() => void refetchAnalyses()}\n />\n ) : analyses.length === 0 ? (\n <EmptyState\n icon={Beaker}\n title=\"No analyses yet.\"\n description=\"Run an analysis to generate results and artifacts from this notebook.\"\n action={\n <Button type=\"button\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\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>Started</TableHead>\n <TableHead>Output</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {analyses.map((analysis: CosAnalysis) => (\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 className=\"whitespace-nowrap text-text-secondary\">\n {formatDateTime(analysis.startedAt)}\n </TableCell>\n <TableCell>\n {analysis.outputFile?.id ? (\n <FileDownloadLink fileId={analysis.outputFile.id} label=\"Download\" />\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 </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </section>\n </div>\n\n <RunAnalysisDialog\n notebookId={notebook.id}\n open={runOpen}\n onOpenChange={setRunOpen}\n onCompleted={() => void refetchAnalyses()}\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NotebookDetailPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/notebooks/NotebookDetailPage.tsx"],"sourcesContent":["/**\n * NotebookDetailPage — full record for one notebook.\n *\n * Header renders the notebook's metadata (status, runtime, environment JSON,\n * description, sharing, attached file download). Below it an Analyses section\n * lists `cosListAnalyses(notebookId)` and a \"Run analysis\" dialog kicks off a\n * new `cosRunAnalysis` bound to this notebook. Archive is available from the\n * header action menu. No fabricated data — everything is read from the backend.\n */\nimport { useState, type FormEvent } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n Beaker,\n Download,\n FileCode2,\n MessageSquare,\n Pencil,\n Play,\n Share2,\n Sparkles,\n} 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 Switch,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosAnalysesQuery,\n useCosArchiveNotebookMutation,\n useCosNotebookQuery,\n useCosRunAnalysisMutation,\n type CosAnalysis,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n DiscussionPanel,\n EmptyState,\n ErrorState,\n LoadingState,\n PageLayout,\n StatusBadge,\n useFileDownloadUrl,\n} from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\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/** Renders a presigned download link for an attached wspace-files artifact. */\nfunction FileDownloadLink({ fileId, label }: { fileId: string; label: 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 link…</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 {label}\n </a>\n );\n}\n\ninterface RunAnalysisDialogProps {\n notebookId: string;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCompleted: () => void;\n}\n\n/** Dialog to launch a new analysis on this notebook. */\nfunction RunAnalysisDialog({\n notebookId,\n open,\n onOpenChange,\n onCompleted,\n}: RunAnalysisDialogProps) {\n const [title, setTitle] = useState('');\n const [method, setMethod] = useState('');\n const [aiAssisted, setAiAssisted] = useState(false);\n const [runAnalysis, { loading }] = useCosRunAnalysisMutation();\n\n const reset = () => {\n setTitle('');\n setMethod('');\n setAiAssisted(false);\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 const response = await runAnalysis({\n variables: {\n input: {\n notebookId,\n title: trimmed,\n method: method.trim() || undefined,\n aiAssisted,\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 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 run against this notebook. It starts in the running state and\n can be completed later with results.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-analysis-title\">Title</Label>\n <Input\n id=\"run-analysis-title\"\n value={title}\n onChange={(event) => setTitle(event.target.value)}\n placeholder=\"e.g. Period-folding search\"\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"run-analysis-method\">Method</Label>\n <Input\n id=\"run-analysis-method\"\n value={method}\n onChange={(event) => setMethod(event.target.value)}\n placeholder=\"e.g. box-least-squares\"\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <Switch\n id=\"run-analysis-ai\"\n checked={aiAssisted}\n onCheckedChange={(checked) => setAiAssisted(checked)}\n />\n <Label htmlFor=\"run-analysis-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\nexport default function NotebookDetailPage() {\n const { id = '' } = useParams<{ id: string }>();\n const { navigate } = useCosmicIntersection();\n const [runOpen, setRunOpen] = useState(false);\n\n const { data, loading, error, refetch } = useCosNotebookQuery(id);\n const {\n data: analysesData,\n loading: analysesLoading,\n error: analysesError,\n refetch: refetchAnalyses,\n } = useCosAnalysesQuery({ notebookId: id });\n const [archiveNotebook] = useCosArchiveNotebookMutation();\n\n const notebook = data?.cosNotebook ?? null;\n const analyses = analysesData?.cosListAnalyses ?? [];\n\n const handleArchive = async () => {\n if (!notebook) {\n return;\n }\n const response = await archiveNotebook({ variables: { id: notebook.id } });\n if (response.error) {\n throw new Error(response.error.message);\n }\n if (!response.data?.cosArchiveNotebook) {\n notify.error('Could not archive notebook', 'The server did not confirm the change.');\n throw new Error('Archive not confirmed');\n }\n await refetch();\n notify.success('Notebook archived', `“${notebook.title}” was archived.`);\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Notebook\" backPath=\"notebooks\">\n <LoadingState label=\"Loading notebook…\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title=\"Notebook\" backPath=\"notebooks\">\n <ErrorState\n message=\"We could not load this notebook. Please try again.\"\n onRetry={() => void refetch()}\n />\n </PageLayout>\n );\n }\n\n if (!notebook) {\n return (\n <PageLayout title=\"Notebook\" backPath=\"notebooks\">\n <EmptyState\n icon={FileCode2}\n title=\"Notebook not found.\"\n description=\"This notebook may have been removed or is outside your current scope.\"\n action={\n <Button type=\"button\" onClick={() => navigate('notebooks')}>\n Back to notebooks\n </Button>\n }\n />\n </PageLayout>\n );\n }\n\n const environmentJson =\n notebook.environment && Object.keys(notebook.environment).length > 0\n ? JSON.stringify(notebook.environment, null, 2)\n : null;\n\n const actions = (\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`notebooks/${notebook.id}/edit`)}\n >\n <Pencil className=\"size-4\" />\n Edit\n </Button>\n <ActionMenu\n ariaLabel={`Actions for ${notebook.title}`}\n entityName={notebook.title}\n onDelete={notebook.status === 'ARCHIVED' ? undefined : handleArchive}\n deleteLabel=\"Archive notebook\"\n />\n </div>\n );\n\n return (\n <PageLayout\n title={notebook.title}\n description=\"Notebook detail\"\n backPath=\"notebooks\"\n actions={actions}\n >\n <div className=\"space-y-6\">\n {/* Overview */}\n <section className=\"rounded-card border border-border-default bg-bg-elevated p-6\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <StatusBadge status={notebook.status} />\n {notebook.runtime ? <Badge variant=\"outline\">Runtime: {notebook.runtime}</Badge> : null}\n {notebook.isShared ? (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Share2 className=\"size-3\" aria-hidden=\"true\" />\n Shared{notebook.shareSlug ? `: ${notebook.shareSlug}` : ''}\n </Badge>\n ) : (\n <Badge variant=\"outline\">Private</Badge>\n )}\n </div>\n\n {notebook.description ? (\n <p className=\"mt-4 text-sm text-text-secondary\">{notebook.description}</p>\n ) : (\n <p className=\"mt-4 text-sm text-text-secondary\">No description provided.</p>\n )}\n\n <dl className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">\n Linked datasets\n </dt>\n <dd className=\"mt-1 text-sm tabular-nums text-text-primary\">\n {notebook.datasetIds.length}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">Created</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">\n {formatDateTime(notebook.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">Updated</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">\n {formatDateTime(notebook.updatedAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-text-secondary\">Notebook file</dt>\n <dd className=\"mt-1 text-sm text-text-primary\">\n {notebook.file?.id ? (\n <FileDownloadLink fileId={notebook.file.id} label=\"Download notebook\" />\n ) : (\n <span className=\"text-text-secondary\">No file attached</span>\n )}\n </dd>\n </div>\n </dl>\n\n {notebook.tags.length > 0 ? (\n <div className=\"mt-6\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Tags</p>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notebook.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\">\n {tag}\n </Badge>\n ))}\n </div>\n </div>\n ) : null}\n\n {environmentJson ? (\n <div className=\"mt-6\">\n <p className=\"text-xs uppercase tracking-wide text-text-secondary\">Environment</p>\n <pre className=\"mt-2 max-h-64 overflow-auto rounded-card border border-border-default bg-bg-sunken p-4 font-mono text-xs text-text-primary\">\n {environmentJson}\n </pre>\n </div>\n ) : null}\n\n </section>\n\n {/* Discussion */}\n <section className=\"space-y-4\">\n <div className=\"flex items-center gap-2\">\n <MessageSquare 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-notebook\"\n entityId={notebook.id}\n title={notebook.title}\n widgetKey=\"notebook-discussion\"\n />\n </section>\n\n {/* Analyses */}\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Analyses</h2>\n <p className=\"text-sm text-text-secondary\">\n Analysis runs executed against this notebook.\n </p>\n </div>\n <Button type=\"button\" variant=\"outline\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\n </div>\n\n {analysesLoading ? (\n <LoadingState variant=\"rows\" rows={3} label=\"Loading analyses…\" />\n ) : analysesError ? (\n <ErrorState\n message=\"We could not load analyses for this notebook.\"\n onRetry={() => void refetchAnalyses()}\n />\n ) : analyses.length === 0 ? (\n <EmptyState\n icon={Beaker}\n title=\"No analyses yet.\"\n description=\"Run an analysis to generate results and artifacts from this notebook.\"\n action={\n <Button type=\"button\" onClick={() => setRunOpen(true)}>\n <Play className=\"size-4\" />\n Run analysis\n </Button>\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>Started</TableHead>\n <TableHead>Output</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {analyses.map((analysis: CosAnalysis) => (\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 className=\"whitespace-nowrap text-text-secondary\">\n {formatDateTime(analysis.startedAt)}\n </TableCell>\n <TableCell>\n {analysis.outputFile?.id ? (\n <FileDownloadLink fileId={analysis.outputFile.id} label=\"Download\" />\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 </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </section>\n </div>\n\n <RunAnalysisDialog\n notebookId={notebook.id}\n open={runOpen}\n onOpenChange={setRunOpen}\n onCompleted={() => void refetchAnalyses()}\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}