@burdenoff/microfe-cosmicintersection 2026.512.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.
Files changed (164) hide show
  1. package/dist/cosmicintersection/CosmicIntersectionRoot.js +38 -113
  2. package/dist/cosmicintersection/CosmicIntersectionRoot.js.map +1 -1
  3. package/dist/cosmicintersection/CosmicIntersectionRoutes.js +102 -44
  4. package/dist/cosmicintersection/CosmicIntersectionRoutes.js.map +1 -1
  5. package/dist/cosmicintersection/api/cosmicApi.js +853 -0
  6. package/dist/cosmicintersection/api/cosmicApi.js.map +1 -0
  7. package/dist/cosmicintersection/components/ActionMenu.js +106 -0
  8. package/dist/cosmicintersection/components/ActionMenu.js.map +1 -0
  9. package/dist/cosmicintersection/components/EmptyState.js +35 -0
  10. package/dist/cosmicintersection/components/EmptyState.js.map +1 -0
  11. package/dist/cosmicintersection/components/EntityFormShell.js +57 -0
  12. package/dist/cosmicintersection/components/EntityFormShell.js.map +1 -0
  13. package/dist/cosmicintersection/components/EntityTagsField.js +77 -0
  14. package/dist/cosmicintersection/components/EntityTagsField.js.map +1 -0
  15. package/dist/cosmicintersection/components/ErrorState.js +40 -0
  16. package/dist/cosmicintersection/components/ErrorState.js.map +1 -0
  17. package/dist/cosmicintersection/components/FileUploadField.js +146 -0
  18. package/dist/cosmicintersection/components/FileUploadField.js.map +1 -0
  19. package/dist/cosmicintersection/components/LoadingState.js +23 -0
  20. package/dist/cosmicintersection/components/LoadingState.js.map +1 -0
  21. package/dist/cosmicintersection/components/PageLayout.js +46 -0
  22. package/dist/cosmicintersection/components/PageLayout.js.map +1 -0
  23. package/dist/cosmicintersection/components/Pagination.js +65 -0
  24. package/dist/cosmicintersection/components/Pagination.js.map +1 -0
  25. package/dist/cosmicintersection/components/SafeLink.js +35 -0
  26. package/dist/cosmicintersection/components/SafeLink.js.map +1 -0
  27. package/dist/cosmicintersection/components/StatusBadge.js +53 -0
  28. package/dist/cosmicintersection/components/StatusBadge.js.map +1 -0
  29. package/dist/cosmicintersection/components/index.js +11 -0
  30. package/dist/cosmicintersection/context/CosmicIntersectionContext.js +46 -0
  31. package/dist/cosmicintersection/context/CosmicIntersectionContext.js.map +1 -0
  32. package/dist/cosmicintersection/index.js +0 -2
  33. package/dist/cosmicintersection/lib/mutationResult.js +12 -0
  34. package/dist/cosmicintersection/lib/mutationResult.js.map +1 -0
  35. package/dist/cosmicintersection/lib/toast.js +36 -0
  36. package/dist/cosmicintersection/lib/toast.js.map +1 -0
  37. package/dist/cosmicintersection/pages/access/AccessPage.js +340 -0
  38. package/dist/cosmicintersection/pages/access/AccessPage.js.map +1 -0
  39. package/dist/cosmicintersection/pages/analyses/AnalysesPage.js +484 -0
  40. package/dist/cosmicintersection/pages/analyses/AnalysesPage.js.map +1 -0
  41. package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js +164 -0
  42. package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js.map +1 -0
  43. package/dist/cosmicintersection/pages/collections/CollectionFormPage.js +117 -0
  44. package/dist/cosmicintersection/pages/collections/CollectionFormPage.js.map +1 -0
  45. package/dist/cosmicintersection/pages/collections/CollectionsPage.js +103 -0
  46. package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -0
  47. package/dist/cosmicintersection/pages/dashboard/DashboardPage.js +244 -0
  48. package/dist/cosmicintersection/pages/dashboard/DashboardPage.js.map +1 -0
  49. package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +460 -0
  50. package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js.map +1 -0
  51. package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js +218 -0
  52. package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js.map +1 -0
  53. package/dist/cosmicintersection/pages/datasets/DatasetsPage.js +252 -0
  54. package/dist/cosmicintersection/pages/datasets/DatasetsPage.js.map +1 -0
  55. package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js +393 -0
  56. package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js.map +1 -0
  57. package/dist/cosmicintersection/pages/notebooks/NotebookFormPage.js +313 -0
  58. package/dist/cosmicintersection/pages/notebooks/NotebookFormPage.js.map +1 -0
  59. package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js +203 -0
  60. package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js.map +1 -0
  61. package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js +244 -0
  62. package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js.map +1 -0
  63. package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js +210 -0
  64. package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js.map +1 -0
  65. package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js +193 -0
  66. package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js.map +1 -0
  67. package/dist/cosmicintersection/pages/releases/ReleaseFormPage.js +184 -0
  68. package/dist/cosmicintersection/pages/releases/ReleaseFormPage.js.map +1 -0
  69. package/dist/cosmicintersection/pages/releases/ReleasesPage.js +368 -0
  70. package/dist/cosmicintersection/pages/releases/ReleasesPage.js.map +1 -0
  71. package/dist/cosmicintersection/pages/runs/RunDetailPage.js +375 -0
  72. package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -0
  73. package/dist/cosmicintersection/pages/runs/RunsPage.js +180 -0
  74. package/dist/cosmicintersection/pages/runs/RunsPage.js.map +1 -0
  75. package/dist/cosmicintersection/pages/sources/SourceFormPage.js +229 -0
  76. package/dist/cosmicintersection/pages/sources/SourceFormPage.js.map +1 -0
  77. package/dist/cosmicintersection/pages/sources/SourcesPage.js +217 -0
  78. package/dist/cosmicintersection/pages/sources/SourcesPage.js.map +1 -0
  79. package/dist/cosmicintersection/utils/cn.js +10 -0
  80. package/dist/cosmicintersection/utils/cn.js.map +1 -0
  81. package/dist/index.js +2 -4
  82. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  83. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  84. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  85. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  86. package/package.json +2 -1
  87. package/dist/cosmicintersection/CosmicIntersectionRoot.d.ts +0 -5
  88. package/dist/cosmicintersection/CosmicIntersectionRoot.d.ts.map +0 -1
  89. package/dist/cosmicintersection/CosmicIntersectionRoutes.d.ts +0 -2
  90. package/dist/cosmicintersection/CosmicIntersectionRoutes.d.ts.map +0 -1
  91. package/dist/cosmicintersection/index.d.ts +0 -5
  92. package/dist/cosmicintersection/index.d.ts.map +0 -1
  93. package/dist/cosmicintersection/pages/AiDiscoveryPage.d.ts +0 -2
  94. package/dist/cosmicintersection/pages/AiDiscoveryPage.d.ts.map +0 -1
  95. package/dist/cosmicintersection/pages/AiDiscoveryPage.js +0 -363
  96. package/dist/cosmicintersection/pages/AiDiscoveryPage.js.map +0 -1
  97. package/dist/cosmicintersection/pages/DashboardPage.d.ts +0 -2
  98. package/dist/cosmicintersection/pages/DashboardPage.d.ts.map +0 -1
  99. package/dist/cosmicintersection/pages/DashboardPage.js +0 -306
  100. package/dist/cosmicintersection/pages/DashboardPage.js.map +0 -1
  101. package/dist/cosmicintersection/pages/SpaceScienceCitizenPage.d.ts +0 -2
  102. package/dist/cosmicintersection/pages/SpaceScienceCitizenPage.d.ts.map +0 -1
  103. package/dist/cosmicintersection/pages/SpaceScienceCitizenPage.js +0 -287
  104. package/dist/cosmicintersection/pages/SpaceScienceCitizenPage.js.map +0 -1
  105. package/dist/cosmicintersection/pages/SpaceScienceDataPage.d.ts +0 -2
  106. package/dist/cosmicintersection/pages/SpaceScienceDataPage.d.ts.map +0 -1
  107. package/dist/cosmicintersection/pages/SpaceScienceDataPage.js +0 -385
  108. package/dist/cosmicintersection/pages/SpaceScienceDataPage.js.map +0 -1
  109. package/dist/cosmicintersection/pages/SpaceScienceDataPage1.d.ts +0 -2
  110. package/dist/cosmicintersection/pages/SpaceScienceDataPage1.d.ts.map +0 -1
  111. package/dist/cosmicintersection/pages/SpaceScienceDataPage1.js +0 -420
  112. package/dist/cosmicintersection/pages/SpaceScienceDataPage1.js.map +0 -1
  113. package/dist/cosmicintersection/pages/SpaceScienceLearningPage.d.ts +0 -2
  114. package/dist/cosmicintersection/pages/SpaceScienceLearningPage.d.ts.map +0 -1
  115. package/dist/cosmicintersection/pages/SpaceScienceLearningPage.js +0 -309
  116. package/dist/cosmicintersection/pages/SpaceScienceLearningPage.js.map +0 -1
  117. package/dist/cosmicintersection/pages/SpaceScienceLearningPage1.d.ts +0 -2
  118. package/dist/cosmicintersection/pages/SpaceScienceLearningPage1.d.ts.map +0 -1
  119. package/dist/cosmicintersection/pages/SpaceScienceLearningPage1.js +0 -361
  120. package/dist/cosmicintersection/pages/SpaceScienceLearningPage1.js.map +0 -1
  121. package/dist/cosmicintersection/pages/SpaceSciencePage.d.ts +0 -2
  122. package/dist/cosmicintersection/pages/SpaceSciencePage.d.ts.map +0 -1
  123. package/dist/cosmicintersection/pages/SpaceSciencePage.js +0 -194
  124. package/dist/cosmicintersection/pages/SpaceSciencePage.js.map +0 -1
  125. package/dist/cosmicintersection/pages/SpaceScienceResearchPage.d.ts +0 -2
  126. package/dist/cosmicintersection/pages/SpaceScienceResearchPage.d.ts.map +0 -1
  127. package/dist/cosmicintersection/pages/SpaceScienceResearchPage.js +0 -290
  128. package/dist/cosmicintersection/pages/SpaceScienceResearchPage.js.map +0 -1
  129. package/dist/cosmicintersection/pages/SpaceScienceSimulationPage.d.ts +0 -2
  130. package/dist/cosmicintersection/pages/SpaceScienceSimulationPage.d.ts.map +0 -1
  131. package/dist/cosmicintersection/pages/SpaceScienceSimulationPage.js +0 -279
  132. package/dist/cosmicintersection/pages/SpaceScienceSimulationPage.js.map +0 -1
  133. package/dist/cosmicintersection/providers/CosmicIntersectionProvider.d.ts +0 -6
  134. package/dist/cosmicintersection/providers/CosmicIntersectionProvider.d.ts.map +0 -1
  135. package/dist/cosmicintersection/providers/CosmicIntersectionProvider.js +0 -27
  136. package/dist/cosmicintersection/providers/CosmicIntersectionProvider.js.map +0 -1
  137. package/dist/cosmicintersection/store/cosmicintersectionStore.d.ts +0 -18
  138. package/dist/cosmicintersection/store/cosmicintersectionStore.d.ts.map +0 -1
  139. package/dist/cosmicintersection/store/cosmicintersectionStore.js +0 -478
  140. package/dist/cosmicintersection/store/cosmicintersectionStore.js.map +0 -1
  141. package/dist/cosmicintersection/types/index.d.ts +0 -109
  142. package/dist/cosmicintersection/types/index.d.ts.map +0 -1
  143. package/dist/cosmicintersection/utils/cn.d.ts +0 -4
  144. package/dist/cosmicintersection/utils/cn.d.ts.map +0 -1
  145. package/dist/cosmicintersection/utils/i18n.d.ts +0 -6
  146. package/dist/cosmicintersection/utils/i18n.d.ts.map +0 -1
  147. package/dist/cosmicintersection/utils/i18n.js +0 -15
  148. package/dist/cosmicintersection/utils/i18n.js.map +0 -1
  149. package/dist/cosmicintersection/utils/navigation.d.ts +0 -2
  150. package/dist/cosmicintersection/utils/navigation.d.ts.map +0 -1
  151. package/dist/cosmicintersection/utils/navigation.js +0 -8
  152. package/dist/cosmicintersection/utils/navigation.js.map +0 -1
  153. package/dist/dev/main.d.ts +0 -2
  154. package/dist/dev/main.d.ts.map +0 -1
  155. package/dist/generated/global-operations.d.ts +0 -2
  156. package/dist/generated/global-operations.d.ts.map +0 -1
  157. package/dist/generated/global-types.d.ts +0 -18199
  158. package/dist/generated/global-types.d.ts.map +0 -1
  159. package/dist/generated/wspace-operations.d.ts +0 -2
  160. package/dist/generated/wspace-operations.d.ts.map +0 -1
  161. package/dist/generated/wspace-types.d.ts +0 -43046
  162. package/dist/generated/wspace-types.d.ts.map +0 -1
  163. package/dist/index.d.ts +0 -2
  164. package/dist/index.d.ts.map +0 -1
@@ -0,0 +1,193 @@
1
+ import { useCosmicIntersection as e } from "../../context/CosmicIntersectionContext.js";
2
+ import { notify as t } from "../../lib/toast.js";
3
+ import { useCosArchivePipelineMutation as n, useCosPipelinesQuery as r, useCosStartRunMutation as i } from "../../api/cosmicApi.js";
4
+ import a from "../../components/ActionMenu.js";
5
+ import o from "../../components/EmptyState.js";
6
+ import s from "../../components/ErrorState.js";
7
+ import c from "../../components/LoadingState.js";
8
+ import l from "../../components/PageLayout.js";
9
+ import u, { usePagination as d } from "../../components/Pagination.js";
10
+ import f, { formatEnumLabel as p } from "../../components/StatusBadge.js";
11
+ import "../../components/index.js";
12
+ import { mutationSucceeded as m } from "../../lib/mutationResult.js";
13
+ import { useMemo as h, useState as g } from "react";
14
+ import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
15
+ import { GitBranch as b, Play as x, Plus as S } from "lucide-react";
16
+ import { Button as C, Select as w, SelectContent as T, SelectItem as E, SelectTrigger as D, SelectValue as O, Table as k, TableBody as A, TableCell as j, TableHead as M, TableHeader as N, TableRow as P } from "@burdenoff/fe-libs/ui";
17
+ //#region src/cosmicintersection/pages/pipelines/PipelinesPage.tsx
18
+ var F = [
19
+ "DRAFT",
20
+ "ACTIVE",
21
+ "PAUSED",
22
+ "ARCHIVED"
23
+ ], I = "ALL";
24
+ function L(e) {
25
+ if (!e) return "—";
26
+ let t = new Date(e);
27
+ return Number.isNaN(t.getTime()) ? "—" : t.toLocaleString();
28
+ }
29
+ function R() {
30
+ let { navigate: R } = e(), [z, B] = g(I), V = d({ resetKey: z }), { data: H, loading: U, error: W, refetch: G } = r({
31
+ status: z === I ? void 0 : z,
32
+ pagination: {
33
+ limit: V.limit,
34
+ offset: V.offset
35
+ }
36
+ }), [K] = i(), [q] = n(), J = h(() => H?.cosListPipelines.items ?? [], [H]), Y = H?.cosListPipelines.pageInfo, X = async (e) => {
37
+ let n = await K({ variables: { input: { pipelineId: e.id } } }), r = n.data?.cosStartRun?.id;
38
+ m(n, r, "Could not start a run") && (t.success("Run started", `A new run for “${e.name}” is queued.`), await G(), r && R(`runs/${r}`));
39
+ }, Z = async (e) => {
40
+ let n = await q({ variables: { id: e.id } });
41
+ if (!m(n, n.data?.cosArchivePipeline, "Could not archive pipeline")) throw Error("Archive not confirmed");
42
+ await G(), t.success("Pipeline archived", `“${e.name}” was archived.`);
43
+ };
44
+ return /* @__PURE__ */ v(l, {
45
+ title: "Pipelines",
46
+ description: "Orchestrate ingest, calibration, transform and export steps across your data.",
47
+ actions: /* @__PURE__ */ y(C, {
48
+ type: "button",
49
+ onClick: () => R("pipelines/create"),
50
+ children: [/* @__PURE__ */ v(S, { className: "size-4" }), "New pipeline"]
51
+ }),
52
+ children: /* @__PURE__ */ y("div", {
53
+ className: "space-y-4",
54
+ children: [/* @__PURE__ */ v("div", {
55
+ className: "flex flex-wrap items-center gap-3",
56
+ children: /* @__PURE__ */ y("label", {
57
+ className: "flex items-center gap-2 text-sm text-text-secondary",
58
+ children: [/* @__PURE__ */ v("span", { children: "Status" }), /* @__PURE__ */ y(w, {
59
+ value: z,
60
+ onValueChange: (e) => B(e),
61
+ children: [/* @__PURE__ */ v(D, {
62
+ "aria-label": "Filter by status",
63
+ className: "w-44",
64
+ children: /* @__PURE__ */ v(O, {})
65
+ }), /* @__PURE__ */ y(T, { children: [/* @__PURE__ */ v(E, {
66
+ value: I,
67
+ children: "All statuses"
68
+ }), F.map((e) => /* @__PURE__ */ v(E, {
69
+ value: e,
70
+ children: p(e)
71
+ }, e))] })]
72
+ })]
73
+ })
74
+ }), U ? /* @__PURE__ */ v(c, {
75
+ variant: "rows",
76
+ rows: 6,
77
+ label: "Loading pipelines…"
78
+ }) : W ? /* @__PURE__ */ v(s, {
79
+ message: "We could not load your pipelines. Please try again.",
80
+ onRetry: () => void G()
81
+ }) : J.length === 0 ? /* @__PURE__ */ v(o, {
82
+ icon: b,
83
+ title: z === I ? "No pipelines yet" : "No pipelines match this filter",
84
+ description: z === I ? "Pipelines orchestrate ingest, calibration, transform and export steps over your datasets." : "Try a different status filter to see more pipelines.",
85
+ action: z === I ? /* @__PURE__ */ y(C, {
86
+ type: "button",
87
+ onClick: () => R("pipelines/create"),
88
+ children: [/* @__PURE__ */ v(S, { className: "size-4" }), "New pipeline"]
89
+ }) : void 0
90
+ }) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("div", {
91
+ className: "overflow-x-auto rounded-card border border-border-default bg-bg-elevated",
92
+ children: /* @__PURE__ */ y(k, { children: [/* @__PURE__ */ v(N, { children: /* @__PURE__ */ y(P, { children: [
93
+ /* @__PURE__ */ v(M, { children: "Name" }),
94
+ /* @__PURE__ */ v(M, { children: "Status" }),
95
+ /* @__PURE__ */ v(M, { children: "Trigger" }),
96
+ /* @__PURE__ */ v(M, { children: "Schedule" }),
97
+ /* @__PURE__ */ v(M, { children: "Last run" }),
98
+ /* @__PURE__ */ v(M, {
99
+ className: "text-right",
100
+ children: "Version"
101
+ }),
102
+ /* @__PURE__ */ v(M, { children: "Tags" }),
103
+ /* @__PURE__ */ v(M, {
104
+ className: "w-12 text-right",
105
+ children: /* @__PURE__ */ v("span", {
106
+ className: "sr-only",
107
+ children: "Actions"
108
+ })
109
+ })
110
+ ] }) }), /* @__PURE__ */ v(A, { children: J.map((e) => /* @__PURE__ */ y(P, {
111
+ className: "cursor-pointer",
112
+ onClick: () => R(`pipelines/${e.id}`),
113
+ children: [
114
+ /* @__PURE__ */ v(j, {
115
+ className: "font-medium text-text-primary",
116
+ children: /* @__PURE__ */ y("div", {
117
+ className: "flex flex-col",
118
+ children: [/* @__PURE__ */ v("span", {
119
+ className: "truncate",
120
+ children: e.name
121
+ }), e.description ? /* @__PURE__ */ v("span", {
122
+ className: "mt-0.5 line-clamp-1 text-xs text-text-secondary",
123
+ children: e.description
124
+ }) : null]
125
+ })
126
+ }),
127
+ /* @__PURE__ */ v(j, { children: /* @__PURE__ */ v(f, { status: e.status }) }),
128
+ /* @__PURE__ */ v(j, {
129
+ className: "text-text-secondary",
130
+ children: p(e.trigger)
131
+ }),
132
+ /* @__PURE__ */ v(j, {
133
+ className: "font-mono text-xs text-text-secondary",
134
+ children: e.schedule || "—"
135
+ }),
136
+ /* @__PURE__ */ v(j, {
137
+ className: "whitespace-nowrap text-text-secondary",
138
+ children: L(e.lastRunAt)
139
+ }),
140
+ /* @__PURE__ */ y(j, {
141
+ className: "text-right tabular-nums text-text-secondary",
142
+ children: ["v", e.version]
143
+ }),
144
+ /* @__PURE__ */ v(j, { children: /* @__PURE__ */ y("div", {
145
+ className: "flex max-w-[12rem] flex-wrap gap-1",
146
+ children: [e.tags.length === 0 ? /* @__PURE__ */ v("span", {
147
+ className: "text-xs text-text-secondary",
148
+ children: "—"
149
+ }) : e.tags.slice(0, 3).map((e) => /* @__PURE__ */ v("span", {
150
+ className: "rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
151
+ children: e
152
+ }, e)), e.tags.length > 3 ? /* @__PURE__ */ y("span", {
153
+ className: "text-xs text-text-secondary",
154
+ children: ["+", e.tags.length - 3]
155
+ }) : null]
156
+ }) }),
157
+ /* @__PURE__ */ v(j, {
158
+ className: "text-right",
159
+ children: /* @__PURE__ */ v(a, {
160
+ ariaLabel: `Actions for ${e.name}`,
161
+ entityName: e.name,
162
+ onView: () => R(`pipelines/${e.id}`),
163
+ onEdit: () => R(`pipelines/${e.id}/edit`),
164
+ onDelete: () => Z(e),
165
+ deleteLabel: "Archive pipeline",
166
+ extraItems: [{
167
+ key: "start",
168
+ label: "Start run",
169
+ icon: x,
170
+ onSelect: () => void X(e),
171
+ disabled: e.status === "ARCHIVED"
172
+ }]
173
+ })
174
+ })
175
+ ]
176
+ }, e.id)) })] })
177
+ }), /* @__PURE__ */ v(u, {
178
+ offset: V.offset,
179
+ limit: V.limit,
180
+ loadedCount: J.length,
181
+ hasMore: Y?.hasMore ?? !1,
182
+ onPrev: V.prevPage,
183
+ onNext: V.nextPage,
184
+ itemLabel: "pipelines",
185
+ loading: U
186
+ })] })]
187
+ })
188
+ });
189
+ }
190
+ //#endregion
191
+ export { R as default };
192
+
193
+ //# sourceMappingURL=PipelinesPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelinesPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/pipelines/PipelinesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { GitBranch, Play, Plus } from 'lucide-react';\nimport {\n Button,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosArchivePipelineMutation,\n useCosPipelinesQuery,\n useCosStartRunMutation,\n type CosPipeline,\n type CosPipelineStatus,\n} from '../../api/cosmicApi';\nimport {\n ActionMenu,\n EmptyState,\n ErrorState,\n LoadingState,\n PageLayout,\n Pagination,\n StatusBadge,\n formatEnumLabel,\n usePagination,\n} from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { mutationSucceeded } from '../../lib/mutationResult';\nimport { notify } from '../../lib/toast';\n\nconst STATUS_OPTIONS: CosPipelineStatus[] = ['DRAFT', 'ACTIVE', 'PAUSED', 'ARCHIVED'];\nconst ALL = 'ALL';\n\nfunction formatDate(value?: string | null): string {\n if (!value) {\n return '—';\n }\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? '—' : date.toLocaleString();\n}\n\nexport default function PipelinesPage() {\n const { navigate } = useCosmicIntersection();\n const [status, setStatus] = useState<CosPipelineStatus | typeof ALL>(ALL);\n const pagination = usePagination({ resetKey: status });\n\n const { data, loading, error, refetch } = useCosPipelinesQuery({\n status: status === ALL ? undefined : status,\n pagination: { limit: pagination.limit, offset: pagination.offset },\n });\n\n const [startRun] = useCosStartRunMutation();\n const [archivePipeline] = useCosArchivePipelineMutation();\n\n const pipelines = useMemo(() => data?.cosListPipelines.items ?? [], [data]);\n const pageInfo = data?.cosListPipelines.pageInfo;\n\n const handleStartRun = async (pipeline: CosPipeline) => {\n const response = await startRun({ variables: { input: { pipelineId: pipeline.id } } });\n const runId = response.data?.cosStartRun?.id;\n if (!mutationSucceeded(response, runId, 'Could not start a run')) {\n return;\n }\n notify.success('Run started', `A new run for “${pipeline.name}” is queued.`);\n await refetch();\n if (runId) {\n navigate(`runs/${runId}`);\n }\n };\n\n const handleArchive = async (pipeline: CosPipeline) => {\n const response = await archivePipeline({ variables: { id: pipeline.id } });\n if (\n !mutationSucceeded(response, response.data?.cosArchivePipeline, 'Could not archive pipeline')\n ) {\n throw new Error('Archive not confirmed');\n }\n await refetch();\n notify.success('Pipeline archived', `“${pipeline.name}” was archived.`);\n };\n\n const renderBody = () => {\n if (loading) {\n return <LoadingState variant=\"rows\" rows={6} label=\"Loading pipelines…\" />;\n }\n if (error) {\n return (\n <ErrorState\n message=\"We could not load your pipelines. Please try again.\"\n onRetry={() => void refetch()}\n />\n );\n }\n if (pipelines.length === 0) {\n return (\n <EmptyState\n icon={GitBranch}\n title={status === ALL ? 'No pipelines yet' : 'No pipelines match this filter'}\n description={\n status === ALL\n ? 'Pipelines orchestrate ingest, calibration, transform and export steps over your datasets.'\n : 'Try a different status filter to see more pipelines.'\n }\n action={\n status === ALL ? (\n <Button type=\"button\" onClick={() => navigate('pipelines/create')}>\n <Plus className=\"size-4\" />\n New pipeline\n </Button>\n ) : undefined\n }\n />\n );\n }\n\n return (\n <>\n <div className=\"overflow-x-auto rounded-card border border-border-default bg-bg-elevated\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Status</TableHead>\n <TableHead>Trigger</TableHead>\n <TableHead>Schedule</TableHead>\n <TableHead>Last run</TableHead>\n <TableHead className=\"text-right\">Version</TableHead>\n <TableHead>Tags</TableHead>\n <TableHead className=\"w-12 text-right\">\n <span className=\"sr-only\">Actions</span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {pipelines.map((pipeline) => (\n <TableRow\n key={pipeline.id}\n className=\"cursor-pointer\"\n onClick={() => navigate(`pipelines/${pipeline.id}`)}\n >\n <TableCell className=\"font-medium text-text-primary\">\n <div className=\"flex flex-col\">\n <span className=\"truncate\">{pipeline.name}</span>\n {pipeline.description ? (\n <span className=\"mt-0.5 line-clamp-1 text-xs text-text-secondary\">\n {pipeline.description}\n </span>\n ) : null}\n </div>\n </TableCell>\n <TableCell>\n <StatusBadge status={pipeline.status} />\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatEnumLabel(pipeline.trigger)}\n </TableCell>\n <TableCell className=\"font-mono text-xs text-text-secondary\">\n {pipeline.schedule || '—'}\n </TableCell>\n <TableCell className=\"whitespace-nowrap text-text-secondary\">\n {formatDate(pipeline.lastRunAt)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n v{pipeline.version}\n </TableCell>\n <TableCell>\n <div className=\"flex max-w-[12rem] flex-wrap gap-1\">\n {pipeline.tags.length === 0 ? (\n <span className=\"text-xs text-text-secondary\">—</span>\n ) : (\n pipeline.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))\n )}\n {pipeline.tags.length > 3 ? (\n <span className=\"text-xs text-text-secondary\">\n +{pipeline.tags.length - 3}\n </span>\n ) : null}\n </div>\n </TableCell>\n <TableCell className=\"text-right\">\n <ActionMenu\n ariaLabel={`Actions for ${pipeline.name}`}\n entityName={pipeline.name}\n onView={() => navigate(`pipelines/${pipeline.id}`)}\n onEdit={() => navigate(`pipelines/${pipeline.id}/edit`)}\n onDelete={() => handleArchive(pipeline)}\n deleteLabel=\"Archive pipeline\"\n extraItems={[\n {\n key: 'start',\n label: 'Start run',\n icon: Play,\n onSelect: () => void handleStartRun(pipeline),\n disabled: pipeline.status === 'ARCHIVED',\n },\n ]}\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n\n <Pagination\n offset={pagination.offset}\n limit={pagination.limit}\n loadedCount={pipelines.length}\n hasMore={pageInfo?.hasMore ?? false}\n onPrev={pagination.prevPage}\n onNext={pagination.nextPage}\n itemLabel=\"pipelines\"\n loading={loading}\n />\n </>\n );\n };\n\n return (\n <PageLayout\n title=\"Pipelines\"\n description=\"Orchestrate ingest, calibration, transform and export steps across your data.\"\n actions={\n <Button type=\"button\" onClick={() => navigate('pipelines/create')}>\n <Plus className=\"size-4\" />\n New pipeline\n </Button>\n }\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <label className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <span>Status</span>\n <Select\n value={status}\n onValueChange={(value) => setStatus(value as CosPipelineStatus | typeof ALL)}\n >\n <SelectTrigger aria-label=\"Filter by status\" className=\"w-44\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>All statuses</SelectItem>\n {STATUS_OPTIONS.map((option) => (\n <SelectItem key={option} value={option}>\n {formatEnumLabel(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n\n {renderBody()}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,184 @@
1
+ import { useCosmicIntersection as e } from "../../context/CosmicIntersectionContext.js";
2
+ import { notify as t } from "../../lib/toast.js";
3
+ import { useCosCreateReleaseMutation as n, useCosDatasetsQuery as r, useCosNotebooksQuery as i } from "../../api/cosmicApi.js";
4
+ import a from "../../components/EntityFormShell.js";
5
+ import o from "../../components/EntityTagsField.js";
6
+ import "../../components/index.js";
7
+ import { useState as s } from "react";
8
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
9
+ import { Checkbox as u, Input as d, Label as f, Select as p, SelectContent as m, SelectItem as h, SelectTrigger as g, SelectValue as _, Textarea as v } from "@burdenoff/fe-libs/ui";
10
+ //#region src/cosmicintersection/pages/releases/ReleaseFormPage.tsx
11
+ var y = "NONE";
12
+ function b() {
13
+ let { navigate: b } = e(), [x, { loading: S }] = n(), C = r({ pagination: {
14
+ limit: 50,
15
+ offset: 0
16
+ } }), w = i({ pagination: {
17
+ limit: 50,
18
+ offset: 0
19
+ } }), T = C.data?.cosListDatasets.items ?? [], E = w.data?.cosListNotebooks.items ?? [], [D, O] = s(""), [k, A] = s(""), [j, M] = s(""), [N, P] = s([]), [F, I] = s(""), [L, R] = s([]), [z, B] = s(y), V = (e) => {
20
+ R((t) => t.includes(e) ? t.filter((t) => t !== e) : [...t, e]);
21
+ };
22
+ return /* @__PURE__ */ l(a, {
23
+ title: "New release",
24
+ description: "Bundle datasets and a notebook into a versioned, citable publication.",
25
+ purpose: "A release is an immutable snapshot you can cite. Create it in draft here, then publish it (and optionally attach a DOI) from the releases list once the work is final.",
26
+ backLabel: "Back to releases",
27
+ onBack: () => b("releases"),
28
+ onSubmit: async (e) => {
29
+ e.preventDefault();
30
+ let n = D.trim();
31
+ if (!n) {
32
+ t.error("Title is required", "Give the release a descriptive title before saving.");
33
+ return;
34
+ }
35
+ (await x({ variables: { input: {
36
+ title: n,
37
+ version: k.trim() || void 0,
38
+ abstract: j.trim() || void 0,
39
+ authors: N.length ? N : void 0,
40
+ license: F.trim() || void 0,
41
+ datasetIds: L.length ? L : void 0,
42
+ notebookId: z === y ? void 0 : z
43
+ } } })).data?.cosCreateRelease?.id && (t.success("Release created", "Publish it from the releases list when it is ready."), b("releases"));
44
+ },
45
+ submitLabel: "Create release",
46
+ saving: S,
47
+ submitDisabled: !D.trim(),
48
+ children: [
49
+ /* @__PURE__ */ l("div", {
50
+ className: "grid grid-cols-1 gap-4 md:grid-cols-2",
51
+ children: [/* @__PURE__ */ l("div", {
52
+ className: "space-y-1.5",
53
+ children: [/* @__PURE__ */ c(f, {
54
+ htmlFor: "release-title",
55
+ children: "Title"
56
+ }), /* @__PURE__ */ c(d, {
57
+ id: "release-title",
58
+ value: D,
59
+ onChange: (e) => O(e.target.value),
60
+ placeholder: "Kepler DR3 stellar catalog",
61
+ required: !0
62
+ })]
63
+ }), /* @__PURE__ */ l("div", {
64
+ className: "space-y-1.5",
65
+ children: [/* @__PURE__ */ c(f, {
66
+ htmlFor: "release-version",
67
+ children: "Version"
68
+ }), /* @__PURE__ */ c(d, {
69
+ id: "release-version",
70
+ value: k,
71
+ onChange: (e) => A(e.target.value),
72
+ placeholder: "1.0.0"
73
+ })]
74
+ })]
75
+ }),
76
+ /* @__PURE__ */ l("div", {
77
+ className: "space-y-1.5",
78
+ children: [/* @__PURE__ */ c(f, {
79
+ htmlFor: "release-abstract",
80
+ children: "Abstract"
81
+ }), /* @__PURE__ */ c(v, {
82
+ id: "release-abstract",
83
+ value: j,
84
+ onChange: (e) => M(e.target.value),
85
+ rows: 4,
86
+ placeholder: "Summarize what this release contains and how it should be used."
87
+ })]
88
+ }),
89
+ /* @__PURE__ */ c(o, {
90
+ value: N,
91
+ onChange: P,
92
+ label: "Authors",
93
+ placeholder: "Add an author and press Enter"
94
+ }),
95
+ /* @__PURE__ */ l("div", {
96
+ className: "grid grid-cols-1 gap-4 md:grid-cols-2",
97
+ children: [/* @__PURE__ */ l("div", {
98
+ className: "space-y-1.5",
99
+ children: [/* @__PURE__ */ c(f, {
100
+ htmlFor: "release-license",
101
+ children: "License"
102
+ }), /* @__PURE__ */ c(d, {
103
+ id: "release-license",
104
+ value: F,
105
+ onChange: (e) => I(e.target.value),
106
+ placeholder: "CC-BY-4.0"
107
+ })]
108
+ }), /* @__PURE__ */ l("div", {
109
+ className: "space-y-1.5",
110
+ children: [
111
+ /* @__PURE__ */ c(f, {
112
+ htmlFor: "release-notebook",
113
+ children: "Notebook"
114
+ }),
115
+ /* @__PURE__ */ l(p, {
116
+ value: z,
117
+ onValueChange: B,
118
+ children: [/* @__PURE__ */ c(g, {
119
+ id: "release-notebook",
120
+ "aria-label": "Linked notebook",
121
+ children: /* @__PURE__ */ c(_, { placeholder: "No notebook" })
122
+ }), /* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, {
123
+ value: y,
124
+ children: "No notebook"
125
+ }), E.map((e) => /* @__PURE__ */ c(h, {
126
+ value: e.id,
127
+ children: e.title
128
+ }, e.id))] })]
129
+ }),
130
+ w.loading ? /* @__PURE__ */ c("p", {
131
+ className: "text-xs text-text-secondary",
132
+ children: "Loading notebooks…"
133
+ }) : null
134
+ ]
135
+ })]
136
+ }),
137
+ /* @__PURE__ */ l("div", {
138
+ className: "space-y-2",
139
+ children: [
140
+ /* @__PURE__ */ l(f, { children: ["Datasets ", L.length ? `(${L.length} selected)` : ""] }),
141
+ /* @__PURE__ */ c("div", {
142
+ className: "max-h-56 space-y-1 overflow-y-auto rounded-card border border-border-default bg-bg-sunken p-2",
143
+ children: C.loading ? /* @__PURE__ */ c("p", {
144
+ className: "px-2 py-3 text-sm text-text-secondary",
145
+ children: "Loading datasets…"
146
+ }) : T.length === 0 ? /* @__PURE__ */ c("p", {
147
+ className: "px-2 py-3 text-sm text-text-secondary",
148
+ children: "No datasets available to link yet."
149
+ }) : T.map((e) => {
150
+ let t = `release-dataset-${e.id}`;
151
+ return /* @__PURE__ */ l("label", {
152
+ htmlFor: t,
153
+ className: "flex cursor-pointer items-center gap-3 rounded-button px-2 py-1.5 hover:bg-bg-elevated",
154
+ children: [
155
+ /* @__PURE__ */ c(u, {
156
+ id: t,
157
+ checked: L.includes(e.id),
158
+ onCheckedChange: () => V(e.id)
159
+ }),
160
+ /* @__PURE__ */ c("span", {
161
+ className: "min-w-0 flex-1 truncate text-sm text-text-primary",
162
+ children: e.name
163
+ }),
164
+ /* @__PURE__ */ c("span", {
165
+ className: "text-xs text-text-secondary",
166
+ children: e.status
167
+ })
168
+ ]
169
+ }, e.id);
170
+ })
171
+ }),
172
+ /* @__PURE__ */ c("p", {
173
+ className: "text-xs text-text-secondary",
174
+ children: "Select the datasets this release certifies. You can attach a DOI when you publish."
175
+ })
176
+ ]
177
+ })
178
+ ]
179
+ });
180
+ }
181
+ //#endregion
182
+ export { b as default };
183
+
184
+ //# sourceMappingURL=ReleaseFormPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleaseFormPage.js","names":[],"sources":["../../../../src/cosmicintersection/pages/releases/ReleaseFormPage.tsx"],"sourcesContent":["import { useState, type FormEvent } from 'react';\nimport {\n Checkbox,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n useCosCreateReleaseMutation,\n useCosDatasetsQuery,\n useCosNotebooksQuery,\n type CosCreateReleaseInput,\n} from '../../api/cosmicApi';\nimport { EntityFormShell, EntityTagsField } from '../../components';\nimport { useCosmicIntersection } from '../../context/CosmicIntersectionContext';\nimport { notify } from '../../lib/toast';\n\nconst NONE = 'NONE';\n\nexport default function ReleaseFormPage() {\n const { navigate } = useCosmicIntersection();\n const [createRelease, { loading: saving }] = useCosCreateReleaseMutation();\n\n // Pull candidate datasets/notebooks to link. A generous page covers the common\n // case; the backend enforces referential integrity on submit.\n const datasetsQuery = useCosDatasetsQuery({ pagination: { limit: 50, offset: 0 } });\n const notebooksQuery = useCosNotebooksQuery({ pagination: { limit: 50, offset: 0 } });\n const datasets = datasetsQuery.data?.cosListDatasets.items ?? [];\n const notebooks = notebooksQuery.data?.cosListNotebooks.items ?? [];\n\n const [title, setTitle] = useState('');\n const [version, setVersion] = useState('');\n const [abstract, setAbstract] = useState('');\n const [authors, setAuthors] = useState<string[]>([]);\n const [license, setLicense] = useState('');\n const [datasetIds, setDatasetIds] = useState<string[]>([]);\n const [notebookId, setNotebookId] = useState<string>(NONE);\n\n const toggleDataset = (id: string) => {\n setDatasetIds((current) =>\n current.includes(id) ? current.filter((existing) => existing !== id) : [...current, id]\n );\n };\n\n const onSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const trimmedTitle = title.trim();\n if (!trimmedTitle) {\n notify.error('Title is required', 'Give the release a descriptive title before saving.');\n return;\n }\n\n const input: CosCreateReleaseInput = {\n title: trimmedTitle,\n version: version.trim() || undefined,\n abstract: abstract.trim() || undefined,\n authors: authors.length ? authors : undefined,\n license: license.trim() || undefined,\n datasetIds: datasetIds.length ? datasetIds : undefined,\n notebookId: notebookId === NONE ? undefined : notebookId,\n };\n\n const response = await createRelease({ variables: { input } });\n if (response.data?.cosCreateRelease?.id) {\n notify.success('Release created', 'Publish it from the releases list when it is ready.');\n navigate('releases');\n }\n };\n\n return (\n <EntityFormShell\n title=\"New release\"\n description=\"Bundle datasets and a notebook into a versioned, citable publication.\"\n purpose=\"A release is an immutable snapshot you can cite. Create it in draft here, then publish it (and optionally attach a DOI) from the releases list once the work is final.\"\n backLabel=\"Back to releases\"\n onBack={() => navigate('releases')}\n onSubmit={onSubmit}\n submitLabel=\"Create release\"\n saving={saving}\n submitDisabled={!title.trim()}\n >\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"release-title\">Title</Label>\n <Input\n id=\"release-title\"\n value={title}\n onChange={(event) => setTitle(event.target.value)}\n placeholder=\"Kepler DR3 stellar catalog\"\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"release-version\">Version</Label>\n <Input\n id=\"release-version\"\n value={version}\n onChange={(event) => setVersion(event.target.value)}\n placeholder=\"1.0.0\"\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"release-abstract\">Abstract</Label>\n <Textarea\n id=\"release-abstract\"\n value={abstract}\n onChange={(event) => setAbstract(event.target.value)}\n rows={4}\n placeholder=\"Summarize what this release contains and how it should be used.\"\n />\n </div>\n\n <EntityTagsField\n value={authors}\n onChange={setAuthors}\n label=\"Authors\"\n placeholder=\"Add an author and press Enter\"\n />\n\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"release-license\">License</Label>\n <Input\n id=\"release-license\"\n value={license}\n onChange={(event) => setLicense(event.target.value)}\n placeholder=\"CC-BY-4.0\"\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"release-notebook\">Notebook</Label>\n <Select value={notebookId} onValueChange={setNotebookId}>\n <SelectTrigger id=\"release-notebook\" aria-label=\"Linked notebook\">\n <SelectValue placeholder=\"No notebook\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>No notebook</SelectItem>\n {notebooks.map((notebook) => (\n <SelectItem key={notebook.id} value={notebook.id}>\n {notebook.title}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {notebooksQuery.loading ? (\n <p className=\"text-xs text-text-secondary\">Loading notebooks…</p>\n ) : null}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label>Datasets {datasetIds.length ? `(${datasetIds.length} selected)` : ''}</Label>\n <div className=\"max-h-56 space-y-1 overflow-y-auto rounded-card border border-border-default bg-bg-sunken p-2\">\n {datasetsQuery.loading ? (\n <p className=\"px-2 py-3 text-sm text-text-secondary\">Loading datasets…</p>\n ) : datasets.length === 0 ? (\n <p className=\"px-2 py-3 text-sm text-text-secondary\">\n No datasets available to link yet.\n </p>\n ) : (\n datasets.map((dataset) => {\n const checkboxId = `release-dataset-${dataset.id}`;\n return (\n <label\n key={dataset.id}\n htmlFor={checkboxId}\n className=\"flex cursor-pointer items-center gap-3 rounded-button px-2 py-1.5 hover:bg-bg-elevated\"\n >\n <Checkbox\n id={checkboxId}\n checked={datasetIds.includes(dataset.id)}\n onCheckedChange={() => toggleDataset(dataset.id)}\n />\n <span className=\"min-w-0 flex-1 truncate text-sm text-text-primary\">\n {dataset.name}\n </span>\n <span className=\"text-xs text-text-secondary\">{dataset.status}</span>\n </label>\n );\n })\n )}\n </div>\n <p className=\"text-xs text-text-secondary\">\n Select the datasets this release certifies. You can attach a DOI when you publish.\n </p>\n </div>\n </EntityFormShell>\n );\n}\n"],"mappings":"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"}