@burdenoff/microfe-cosmicintersection 2026.704.1 → 2026.704.3
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/CosmicIntersectionRoutes.js +45 -25
- package/dist/cosmicintersection/CosmicIntersectionRoutes.js.map +1 -1
- package/dist/cosmicintersection/api/cosmicApi.js +137 -66
- package/dist/cosmicintersection/api/cosmicApi.js.map +1 -1
- package/dist/cosmicintersection/components/ActivityFeedPanel.js +68 -0
- package/dist/cosmicintersection/components/ActivityFeedPanel.js.map +1 -0
- package/dist/cosmicintersection/components/DiscussionPanel.js +57 -0
- package/dist/cosmicintersection/components/DiscussionPanel.js.map +1 -0
- package/dist/cosmicintersection/components/FacetPanel.js +66 -0
- package/dist/cosmicintersection/components/FacetPanel.js.map +1 -0
- package/dist/cosmicintersection/components/LineageGraph.js +388 -0
- package/dist/cosmicintersection/components/LineageGraph.js.map +1 -0
- package/dist/cosmicintersection/components/ResultsChart.js +329 -0
- package/dist/cosmicintersection/components/ResultsChart.js.map +1 -0
- package/dist/cosmicintersection/components/StepDAG.js +104 -0
- package/dist/cosmicintersection/components/StepDAG.js.map +1 -0
- package/dist/cosmicintersection/components/index.js +5 -3
- package/dist/cosmicintersection/pages/access/AccessPage.js +220 -161
- package/dist/cosmicintersection/pages/access/AccessPage.js.map +1 -1
- package/dist/cosmicintersection/pages/analyses/AnalysesPage.js +332 -172
- package/dist/cosmicintersection/pages/analyses/AnalysesPage.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js +167 -109
- package/dist/cosmicintersection/pages/collections/CollectionDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js +87 -61
- package/dist/cosmicintersection/pages/collections/CollectionFormPage.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js +51 -42
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js +31 -18
- package/dist/cosmicintersection/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +330 -184
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/datasets/DatasetFormPage.js +7 -7
- package/dist/cosmicintersection/pages/datasets/DatasetsPage.js +321 -163
- package/dist/cosmicintersection/pages/datasets/DatasetsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/discovery/DiscoveryPage.js +358 -0
- package/dist/cosmicintersection/pages/discovery/DiscoveryPage.js.map +1 -0
- package/dist/cosmicintersection/pages/lineage/LineagePage.js +171 -0
- package/dist/cosmicintersection/pages/lineage/LineagePage.js.map +1 -0
- package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js +339 -260
- package/dist/cosmicintersection/pages/notebooks/NotebookDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js +143 -82
- package/dist/cosmicintersection/pages/notebooks/NotebooksPage.js.map +1 -1
- package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js +286 -142
- package/dist/cosmicintersection/pages/pipelines/PipelineDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js +305 -103
- package/dist/cosmicintersection/pages/pipelines/PipelineFormPage.js.map +1 -1
- package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js +183 -79
- package/dist/cosmicintersection/pages/pipelines/PipelinesPage.js.map +1 -1
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js +346 -204
- package/dist/cosmicintersection/pages/releases/ReleasesPage.js.map +1 -1
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js +184 -136
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/runs/RunsPage.js +182 -120
- package/dist/cosmicintersection/pages/runs/RunsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/sources/SourceDetailPage.js +234 -0
- package/dist/cosmicintersection/pages/sources/SourceDetailPage.js.map +1 -0
- package/dist/cosmicintersection/pages/sources/SourcesPage.js +250 -133
- package/dist/cosmicintersection/pages/sources/SourcesPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { cn as e } from "../utils/cn.js";
|
|
2
|
+
import { useId as t, useMemo as n } from "react";
|
|
3
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
+
import { Boxes as a, Cog as o, Database as s, LineChart as c, NotebookText as l, Radar as u, Tag as d } from "lucide-react";
|
|
5
|
+
//#region src/cosmicintersection/components/LineageGraph.tsx
|
|
6
|
+
var f = {
|
|
7
|
+
source: 0,
|
|
8
|
+
collection: 0,
|
|
9
|
+
dataset: 1,
|
|
10
|
+
run: 2,
|
|
11
|
+
notebook: 3,
|
|
12
|
+
analysis: 4,
|
|
13
|
+
release: 5
|
|
14
|
+
};
|
|
15
|
+
function p(e) {
|
|
16
|
+
let t = e.replace(/_/g, " ").toLowerCase();
|
|
17
|
+
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
18
|
+
}
|
|
19
|
+
var m = class {
|
|
20
|
+
nodes = /* @__PURE__ */ new Map();
|
|
21
|
+
edgeKeys = /* @__PURE__ */ new Set();
|
|
22
|
+
edges = [];
|
|
23
|
+
addNode(e) {
|
|
24
|
+
let t = this.nodes.get(e.id);
|
|
25
|
+
if (!t) {
|
|
26
|
+
this.nodes.set(e.id, e);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
e.emphasis && !t.emphasis && this.nodes.set(e.id, {
|
|
30
|
+
...t,
|
|
31
|
+
emphasis: !0
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
link(e, t) {
|
|
35
|
+
if (e === t || !this.nodes.has(e) || !this.nodes.has(t)) return;
|
|
36
|
+
let n = `${e}»${t}`;
|
|
37
|
+
this.edgeKeys.has(n) || (this.edgeKeys.add(n), this.edges.push({
|
|
38
|
+
from: e,
|
|
39
|
+
to: t
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
has(e) {
|
|
43
|
+
return this.nodes.has(e);
|
|
44
|
+
}
|
|
45
|
+
build() {
|
|
46
|
+
return {
|
|
47
|
+
nodes: [...this.nodes.values()],
|
|
48
|
+
edges: this.edges
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}, h = {
|
|
52
|
+
source: (e) => `src:${e}`,
|
|
53
|
+
collection: (e) => `col:${e}`,
|
|
54
|
+
dataset: (e) => `ds:${e}`,
|
|
55
|
+
run: (e) => `run:${e}`,
|
|
56
|
+
notebook: (e) => `nb:${e}`,
|
|
57
|
+
analysis: (e) => `an:${e}`,
|
|
58
|
+
release: (e) => `rel:${e}`
|
|
59
|
+
};
|
|
60
|
+
function g(e, t, n, r) {
|
|
61
|
+
if (e.addNode({
|
|
62
|
+
id: h.dataset(t.id),
|
|
63
|
+
type: "dataset",
|
|
64
|
+
title: t.name,
|
|
65
|
+
subtitle: p(t.status),
|
|
66
|
+
route: `datasets/${t.id}`,
|
|
67
|
+
column: f.dataset,
|
|
68
|
+
emphasis: r
|
|
69
|
+
}), t.sourceId) {
|
|
70
|
+
let r = n.sourcesById.get(t.sourceId);
|
|
71
|
+
e.addNode({
|
|
72
|
+
id: h.source(t.sourceId),
|
|
73
|
+
type: "source",
|
|
74
|
+
title: r?.name ?? "Linked source",
|
|
75
|
+
subtitle: r ? p(r.type) : void 0,
|
|
76
|
+
route: `sources/${t.sourceId}`,
|
|
77
|
+
column: f.source
|
|
78
|
+
}), e.link(h.source(t.sourceId), h.dataset(t.id));
|
|
79
|
+
}
|
|
80
|
+
if (t.collectionId) {
|
|
81
|
+
let r = n.collectionsById.get(t.collectionId);
|
|
82
|
+
e.addNode({
|
|
83
|
+
id: h.collection(t.collectionId),
|
|
84
|
+
type: "collection",
|
|
85
|
+
title: r?.name ?? "Collection",
|
|
86
|
+
route: `collections/${t.collectionId}`,
|
|
87
|
+
column: f.collection
|
|
88
|
+
}), e.link(h.collection(t.collectionId), h.dataset(t.id));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function _(e, t, n) {
|
|
92
|
+
let r = h.dataset(t.id);
|
|
93
|
+
for (let i of n.runs) {
|
|
94
|
+
if (i.datasetId !== t.id) continue;
|
|
95
|
+
let a = i.pipelineId ? n.pipelinesById?.get(i.pipelineId)?.name : void 0;
|
|
96
|
+
e.addNode({
|
|
97
|
+
id: h.run(i.id),
|
|
98
|
+
type: "run",
|
|
99
|
+
typeLabel: `Pipeline Run #${i.runNumber}`,
|
|
100
|
+
title: a ?? `Run #${i.runNumber}`,
|
|
101
|
+
subtitle: p(i.status),
|
|
102
|
+
route: `runs/${i.id}`,
|
|
103
|
+
column: f.run
|
|
104
|
+
}), e.link(r, h.run(i.id));
|
|
105
|
+
}
|
|
106
|
+
for (let i of n.notebooks) i.datasetIds.includes(t.id) && (e.addNode({
|
|
107
|
+
id: h.notebook(i.id),
|
|
108
|
+
type: "notebook",
|
|
109
|
+
title: i.title,
|
|
110
|
+
subtitle: p(i.status),
|
|
111
|
+
route: `notebooks/${i.id}`,
|
|
112
|
+
column: f.notebook
|
|
113
|
+
}), e.link(r, h.notebook(i.id)));
|
|
114
|
+
for (let i of n.analyses) {
|
|
115
|
+
let n = i.notebookId != null && e.has(h.notebook(i.notebookId));
|
|
116
|
+
i.datasetId !== t.id && !n || (e.addNode({
|
|
117
|
+
id: h.analysis(i.id),
|
|
118
|
+
type: "analysis",
|
|
119
|
+
title: i.title,
|
|
120
|
+
subtitle: p(i.status),
|
|
121
|
+
route: "analyses",
|
|
122
|
+
column: f.analysis
|
|
123
|
+
}), n && i.notebookId != null ? e.link(h.notebook(i.notebookId), h.analysis(i.id)) : e.link(r, h.analysis(i.id)));
|
|
124
|
+
}
|
|
125
|
+
for (let i of n.releases) i.datasetIds.includes(t.id) && (v(e, i), e.link(r, h.release(i.id)), i.notebookId != null && e.has(h.notebook(i.notebookId)) && e.link(h.notebook(i.notebookId), h.release(i.id)));
|
|
126
|
+
}
|
|
127
|
+
function v(e, t, n = !1) {
|
|
128
|
+
let r = t.doi ? " · DOI" : "";
|
|
129
|
+
e.addNode({
|
|
130
|
+
id: h.release(t.id),
|
|
131
|
+
type: "release",
|
|
132
|
+
title: t.title,
|
|
133
|
+
subtitle: `v${t.version}${r}`,
|
|
134
|
+
route: "releases",
|
|
135
|
+
column: f.release,
|
|
136
|
+
emphasis: n
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function y(e, t) {
|
|
140
|
+
let n = new m(), r = t.datasetsById.get(e);
|
|
141
|
+
return r ? (g(n, r, t, !0), _(n, r, t), n.build()) : n.build();
|
|
142
|
+
}
|
|
143
|
+
function b(e, t) {
|
|
144
|
+
let n = new m(), r = t.releases.find((t) => t.id === e);
|
|
145
|
+
if (!r) return n.build();
|
|
146
|
+
v(n, r, !0);
|
|
147
|
+
for (let e of r.datasetIds) {
|
|
148
|
+
let i = t.datasetsById.get(e);
|
|
149
|
+
i && (g(n, i, t, !1), n.link(h.dataset(i.id), h.release(r.id)));
|
|
150
|
+
}
|
|
151
|
+
if (r.notebookId != null) {
|
|
152
|
+
let e = t.notebooks.find((e) => e.id === r.notebookId);
|
|
153
|
+
n.addNode({
|
|
154
|
+
id: h.notebook(r.notebookId),
|
|
155
|
+
type: "notebook",
|
|
156
|
+
title: e?.title ?? "Notebook",
|
|
157
|
+
subtitle: e ? p(e.status) : void 0,
|
|
158
|
+
route: `notebooks/${r.notebookId}`,
|
|
159
|
+
column: f.notebook
|
|
160
|
+
}), n.link(h.notebook(r.notebookId), h.release(r.id));
|
|
161
|
+
for (let i of e?.datasetIds ?? []) {
|
|
162
|
+
let e = t.datasetsById.get(i);
|
|
163
|
+
e && (g(n, e, t, !1), n.link(h.dataset(e.id), h.notebook(r.notebookId)));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return n.build();
|
|
167
|
+
}
|
|
168
|
+
var x = {
|
|
169
|
+
source: {
|
|
170
|
+
label: "Source",
|
|
171
|
+
Icon: u,
|
|
172
|
+
chip: "bg-accent-blue-subtle text-accent-blue",
|
|
173
|
+
border: "border-accent-blue"
|
|
174
|
+
},
|
|
175
|
+
collection: {
|
|
176
|
+
label: "Collection",
|
|
177
|
+
Icon: a,
|
|
178
|
+
chip: "bg-accent-teal-subtle text-accent-teal",
|
|
179
|
+
border: "border-accent-teal"
|
|
180
|
+
},
|
|
181
|
+
dataset: {
|
|
182
|
+
label: "Dataset",
|
|
183
|
+
Icon: s,
|
|
184
|
+
chip: "bg-accent-indigo-subtle text-accent-indigo",
|
|
185
|
+
border: "border-accent-indigo"
|
|
186
|
+
},
|
|
187
|
+
run: {
|
|
188
|
+
label: "Pipeline Run",
|
|
189
|
+
Icon: o,
|
|
190
|
+
chip: "bg-accent-purple-subtle text-accent-purple",
|
|
191
|
+
border: "border-accent-purple"
|
|
192
|
+
},
|
|
193
|
+
notebook: {
|
|
194
|
+
label: "Notebook",
|
|
195
|
+
Icon: l,
|
|
196
|
+
chip: "bg-accent-teal-subtle text-accent-teal",
|
|
197
|
+
border: "border-accent-teal"
|
|
198
|
+
},
|
|
199
|
+
analysis: {
|
|
200
|
+
label: "Analysis",
|
|
201
|
+
Icon: c,
|
|
202
|
+
chip: "bg-accent-purple-subtle text-accent-purple",
|
|
203
|
+
border: "border-accent-purple"
|
|
204
|
+
},
|
|
205
|
+
release: {
|
|
206
|
+
label: "Release",
|
|
207
|
+
Icon: d,
|
|
208
|
+
chip: "bg-status-success-bg-subtle text-status-success-text",
|
|
209
|
+
border: "border-status-success-border"
|
|
210
|
+
}
|
|
211
|
+
}, S = {
|
|
212
|
+
full: {
|
|
213
|
+
nodeW: 190,
|
|
214
|
+
nodeH: 78,
|
|
215
|
+
colGap: 74,
|
|
216
|
+
rowGap: 30,
|
|
217
|
+
pad: 32,
|
|
218
|
+
iconSize: "size-8",
|
|
219
|
+
showSubtitle: !0
|
|
220
|
+
},
|
|
221
|
+
compact: {
|
|
222
|
+
nodeW: 150,
|
|
223
|
+
nodeH: 54,
|
|
224
|
+
colGap: 46,
|
|
225
|
+
rowGap: 18,
|
|
226
|
+
pad: 18,
|
|
227
|
+
iconSize: "size-6",
|
|
228
|
+
showSubtitle: !1
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
function C(e, t) {
|
|
232
|
+
let n = /* @__PURE__ */ new Map();
|
|
233
|
+
if (e.nodes.length === 0) return {
|
|
234
|
+
positions: n,
|
|
235
|
+
width: t.pad * 2,
|
|
236
|
+
height: t.pad * 2
|
|
237
|
+
};
|
|
238
|
+
let r = [...new Set(e.nodes.map((e) => e.column))].sort((e, t) => e - t), i = new Map(r.map((e, t) => [e, t])), a = /* @__PURE__ */ new Map();
|
|
239
|
+
for (let t of e.nodes) {
|
|
240
|
+
let e = a.get(t.column);
|
|
241
|
+
e ? e.push(t) : a.set(t.column, [t]);
|
|
242
|
+
}
|
|
243
|
+
let o = t.nodeH;
|
|
244
|
+
for (let e of a.values()) {
|
|
245
|
+
let n = e.length * t.nodeH + (e.length - 1) * t.rowGap;
|
|
246
|
+
o = Math.max(o, n);
|
|
247
|
+
}
|
|
248
|
+
for (let e of r) {
|
|
249
|
+
let r = a.get(e) ?? [], s = r.length * t.nodeH + (r.length - 1) * t.rowGap, c = t.pad + (o - s) / 2, l = t.pad + (i.get(e) ?? 0) * (t.nodeW + t.colGap);
|
|
250
|
+
r.forEach((e, r) => {
|
|
251
|
+
n.set(e.id, {
|
|
252
|
+
node: e,
|
|
253
|
+
x: l,
|
|
254
|
+
y: c + r * (t.nodeH + t.rowGap)
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
positions: n,
|
|
260
|
+
width: t.pad * 2 + r.length * t.nodeW + (r.length - 1) * t.colGap,
|
|
261
|
+
height: t.pad * 2 + o
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function w(e, t, n, r) {
|
|
265
|
+
let i = Math.max(24, (n - e) * .5);
|
|
266
|
+
return `M ${e} ${t} C ${e + i} ${t}, ${n - i} ${r}, ${n} ${r}`;
|
|
267
|
+
}
|
|
268
|
+
function T({ model: a, mode: o = "full", onNavigate: s, className: c }) {
|
|
269
|
+
let l = `cos-lineage-arrow-${t().replace(/:/g, "")}`, u = S[o], d = n(() => C(a, u), [a, u]), f = n(() => {
|
|
270
|
+
let e = /* @__PURE__ */ new Set(), t = [];
|
|
271
|
+
for (let n of [...a.nodes].sort((e, t) => e.column - t.column)) e.has(n.type) || (e.add(n.type), t.push(n.type));
|
|
272
|
+
return t;
|
|
273
|
+
}, [a.nodes]);
|
|
274
|
+
return a.nodes.length === 0 ? null : /* @__PURE__ */ i("div", {
|
|
275
|
+
className: e("flex flex-col gap-3", c),
|
|
276
|
+
children: [o === "full" && f.length > 0 ? /* @__PURE__ */ r("div", {
|
|
277
|
+
className: "flex flex-wrap items-center gap-x-4 gap-y-2",
|
|
278
|
+
children: f.map((t) => {
|
|
279
|
+
let n = x[t];
|
|
280
|
+
return /* @__PURE__ */ i("span", {
|
|
281
|
+
className: "inline-flex items-center gap-1.5 text-xs text-text-secondary",
|
|
282
|
+
children: [/* @__PURE__ */ r("span", {
|
|
283
|
+
className: e("flex size-5 items-center justify-center rounded-button", n.chip),
|
|
284
|
+
children: /* @__PURE__ */ r(n.Icon, {
|
|
285
|
+
className: "size-3",
|
|
286
|
+
"aria-hidden": "true"
|
|
287
|
+
})
|
|
288
|
+
}), n.label]
|
|
289
|
+
}, t);
|
|
290
|
+
})
|
|
291
|
+
}) : null, /* @__PURE__ */ r("div", {
|
|
292
|
+
className: e("overflow-x-auto rounded-card border border-border-seam bg-bg-canvas", o === "full" ? "p-1" : "p-0.5"),
|
|
293
|
+
children: /* @__PURE__ */ i("div", {
|
|
294
|
+
className: "relative",
|
|
295
|
+
style: {
|
|
296
|
+
width: d.width,
|
|
297
|
+
height: d.height,
|
|
298
|
+
minWidth: "100%",
|
|
299
|
+
backgroundImage: "radial-gradient(var(--color-border-subtle) 1px, transparent 1px)",
|
|
300
|
+
backgroundSize: o === "full" ? "20px 20px" : "16px 16px"
|
|
301
|
+
},
|
|
302
|
+
children: [/* @__PURE__ */ i("svg", {
|
|
303
|
+
className: "pointer-events-none absolute inset-0 text-border-strong",
|
|
304
|
+
width: d.width,
|
|
305
|
+
height: d.height,
|
|
306
|
+
viewBox: `0 0 ${d.width} ${d.height}`,
|
|
307
|
+
"aria-hidden": "true",
|
|
308
|
+
children: [/* @__PURE__ */ r("defs", { children: /* @__PURE__ */ r("marker", {
|
|
309
|
+
id: l,
|
|
310
|
+
viewBox: "0 0 8 8",
|
|
311
|
+
refX: "6.5",
|
|
312
|
+
refY: "4",
|
|
313
|
+
markerWidth: "6",
|
|
314
|
+
markerHeight: "6",
|
|
315
|
+
orient: "auto-start-reverse",
|
|
316
|
+
children: /* @__PURE__ */ r("path", {
|
|
317
|
+
d: "M1 1 L7 4 L1 7 z",
|
|
318
|
+
fill: "currentColor"
|
|
319
|
+
})
|
|
320
|
+
}) }), a.edges.map((e) => {
|
|
321
|
+
let t = d.positions.get(e.from), n = d.positions.get(e.to);
|
|
322
|
+
if (!t || !n) return null;
|
|
323
|
+
let i = t.x + u.nodeW, a = t.y + u.nodeH / 2, s = n.x;
|
|
324
|
+
return /* @__PURE__ */ r("path", {
|
|
325
|
+
d: w(i, a, s, n.y + u.nodeH / 2),
|
|
326
|
+
fill: "none",
|
|
327
|
+
stroke: "currentColor",
|
|
328
|
+
strokeWidth: o === "full" ? 1.5 : 1.25,
|
|
329
|
+
strokeLinecap: "round",
|
|
330
|
+
markerEnd: `url(#${l})`,
|
|
331
|
+
opacity: .7
|
|
332
|
+
}, `${e.from}»${e.to}`);
|
|
333
|
+
})]
|
|
334
|
+
}), [...d.positions.values()].map(({ node: t, x: n, y: a }) => {
|
|
335
|
+
let c = x[t.type], l = !!(t.route && s), d = /* @__PURE__ */ i("div", {
|
|
336
|
+
className: e("flex h-full w-full items-center gap-2.5 rounded-card border bg-bg-elevated px-3 shadow-sm transition-shadow", c.border, l && "group-hover:shadow-md", t.emphasis && "ring-1 ring-border-strong"),
|
|
337
|
+
children: [/* @__PURE__ */ r("span", {
|
|
338
|
+
className: e("flex shrink-0 items-center justify-center rounded-button", u.iconSize, c.chip),
|
|
339
|
+
"aria-hidden": "true",
|
|
340
|
+
children: /* @__PURE__ */ r(c.Icon, { className: o === "full" ? "size-4" : "size-3.5" })
|
|
341
|
+
}), /* @__PURE__ */ i("span", {
|
|
342
|
+
className: "flex min-w-0 flex-1 flex-col text-left",
|
|
343
|
+
children: [
|
|
344
|
+
/* @__PURE__ */ r("span", {
|
|
345
|
+
className: "truncate text-[10px] font-medium uppercase tracking-wide text-text-tertiary",
|
|
346
|
+
children: t.typeLabel ?? c.label
|
|
347
|
+
}),
|
|
348
|
+
/* @__PURE__ */ r("span", {
|
|
349
|
+
className: e("truncate font-semibold text-text-primary", o === "full" ? "text-sm" : "text-xs"),
|
|
350
|
+
children: t.title
|
|
351
|
+
}),
|
|
352
|
+
u.showSubtitle && t.subtitle ? /* @__PURE__ */ r("span", {
|
|
353
|
+
className: "truncate text-[11px] text-text-secondary",
|
|
354
|
+
children: t.subtitle
|
|
355
|
+
}) : null
|
|
356
|
+
]
|
|
357
|
+
})]
|
|
358
|
+
}), f = {
|
|
359
|
+
left: n,
|
|
360
|
+
top: a,
|
|
361
|
+
width: u.nodeW,
|
|
362
|
+
height: u.nodeH
|
|
363
|
+
};
|
|
364
|
+
if (l && t.route) {
|
|
365
|
+
let e = t.route;
|
|
366
|
+
return /* @__PURE__ */ r("button", {
|
|
367
|
+
type: "button",
|
|
368
|
+
onClick: () => s?.(e),
|
|
369
|
+
className: "group absolute rounded-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
370
|
+
style: f,
|
|
371
|
+
title: `${t.typeLabel ?? c.label}: ${t.title}`,
|
|
372
|
+
children: d
|
|
373
|
+
}, t.id);
|
|
374
|
+
}
|
|
375
|
+
return /* @__PURE__ */ r("div", {
|
|
376
|
+
className: "absolute",
|
|
377
|
+
style: f,
|
|
378
|
+
children: d
|
|
379
|
+
}, t.id);
|
|
380
|
+
})]
|
|
381
|
+
})
|
|
382
|
+
})]
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
//#endregion
|
|
386
|
+
export { y as buildDatasetLineage, b as buildReleaseLineage, T as default };
|
|
387
|
+
|
|
388
|
+
//# sourceMappingURL=LineageGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LineageGraph.js","names":[],"sources":["../../../src/cosmicintersection/components/LineageGraph.tsx"],"sourcesContent":["/**\n * LineageGraph — a reusable, dependency-free provenance DAG for CosmicIntersection.\n *\n * Renders a typed, left-to-right lineage graph (Source → Dataset → Pipeline Run →\n * Notebook / Analysis → Release) as custom inline SVG edges + absolutely-positioned\n * token-styled node cards. No graph library — the layout is a simple column/row\n * solver, edges are cubic-bezier `<path>`s. Every colour comes from fe-libs semantic\n * tokens (bg-*, text-*, border-*, status-*, accent-*) so it renders in every theme.\n *\n * The graph MODEL is derived client-side from existing cos entities by the pure\n * `buildDatasetLineage` / `buildReleaseLineage` builders exported below — the\n * component itself never fetches. Nodes with a `route` are clickable and call\n * `onNavigate` (basePath-relative), matching the rest of the MFE's navigation.\n *\n * Modes:\n * - `full` — page mode (larger cards, legend, dotted canvas). See mockup 20.\n * - `compact` — detail-panel mini map (smaller cards, no legend). See mockup 03.\n */\nimport { useId, useMemo } from 'react';\nimport {\n Boxes,\n Cog,\n Database,\n LineChart,\n NotebookText,\n Radar,\n Tag,\n type LucideIcon,\n} from 'lucide-react';\n\nimport type {\n CosAnalysis,\n CosCollection,\n CosDataset,\n CosNotebook,\n CosPipeline,\n CosPipelineRun,\n CosRelease,\n CosSource,\n} from '../api/cosmicApi';\nimport { cn } from '../utils/cn';\n\n// ============================================================================\n// MODEL\n// ============================================================================\n\nexport type LineageNodeType =\n | 'source'\n | 'collection'\n | 'dataset'\n | 'run'\n | 'notebook'\n | 'analysis'\n | 'release';\n\nexport interface LineageNode {\n /** Stable, unique within a model (e.g. `ds:<uuid>`). */\n id: string;\n type: LineageNodeType;\n title: string;\n /** Overrides the default type label (e.g. \"Pipeline Run #340\"). */\n typeLabel?: string;\n /** Small third line — status, version, DOI hint (hidden in compact mode). */\n subtitle?: string;\n /** basePath-relative route; when set (and `onNavigate` given) the node is clickable. */\n route?: string;\n /** Semantic column / layer index, 0 = leftmost (upstream). */\n column: number;\n /** Highlight the graph root (the entity the lineage was requested for). */\n emphasis?: boolean;\n}\n\nexport interface LineageEdge {\n from: string;\n to: string;\n}\n\nexport interface LineageModel {\n nodes: LineageNode[];\n edges: LineageEdge[];\n}\n\n/** Data pools the builders read from — resolved maps + already-filtered lists. */\nexport interface LineageDataPools {\n datasetsById: Map<string, CosDataset>;\n sourcesById: Map<string, CosSource>;\n collectionsById: Map<string, CosCollection>;\n runs: CosPipelineRun[];\n notebooks: CosNotebook[];\n analyses: CosAnalysis[];\n releases: CosRelease[];\n pipelinesById?: Map<string, CosPipeline>;\n}\n\n// ============================================================================\n// BUILDERS (pure — no hooks, no fetching)\n// ============================================================================\n\nconst COLUMN: Record<LineageNodeType, number> = {\n source: 0,\n collection: 0,\n dataset: 1,\n run: 2,\n notebook: 3,\n analysis: 4,\n release: 5,\n};\n\nfunction humanEnum(value: string): string {\n const lower = value.replace(/_/g, ' ').toLowerCase();\n return lower.charAt(0).toUpperCase() + lower.slice(1);\n}\n\n/** Incrementally assembles a de-duplicated node/edge model. */\nclass LineageBuilder {\n private readonly nodes = new Map<string, LineageNode>();\n private readonly edgeKeys = new Set<string>();\n private readonly edges: LineageEdge[] = [];\n\n addNode(node: LineageNode): void {\n const existing = this.nodes.get(node.id);\n if (!existing) {\n this.nodes.set(node.id, node);\n return;\n }\n // Preserve an emphasis flag once set (root wins over a later plain add).\n if (node.emphasis && !existing.emphasis) {\n this.nodes.set(node.id, { ...existing, emphasis: true });\n }\n }\n\n link(from: string, to: string): void {\n if (from === to) {\n return;\n }\n // Only connect endpoints that actually exist in the graph.\n if (!this.nodes.has(from) || !this.nodes.has(to)) {\n return;\n }\n const key = `${from}»${to}`;\n if (this.edgeKeys.has(key)) {\n return;\n }\n this.edgeKeys.add(key);\n this.edges.push({ from, to });\n }\n\n has(id: string): boolean {\n return this.nodes.has(id);\n }\n\n build(): LineageModel {\n return { nodes: [...this.nodes.values()], edges: this.edges };\n }\n}\n\nconst nid = {\n source: (id: string) => `src:${id}`,\n collection: (id: string) => `col:${id}`,\n dataset: (id: string) => `ds:${id}`,\n run: (id: string) => `run:${id}`,\n notebook: (id: string) => `nb:${id}`,\n analysis: (id: string) => `an:${id}`,\n release: (id: string) => `rel:${id}`,\n};\n\n/** Add a dataset node plus its upstream source/collection to the builder. */\nfunction addDatasetUpstream(\n builder: LineageBuilder,\n dataset: CosDataset,\n pools: LineageDataPools,\n emphasis: boolean\n): void {\n builder.addNode({\n id: nid.dataset(dataset.id),\n type: 'dataset',\n title: dataset.name,\n subtitle: humanEnum(dataset.status),\n route: `datasets/${dataset.id}`,\n column: COLUMN.dataset,\n emphasis,\n });\n\n if (dataset.sourceId) {\n const source = pools.sourcesById.get(dataset.sourceId);\n builder.addNode({\n id: nid.source(dataset.sourceId),\n type: 'source',\n title: source?.name ?? 'Linked source',\n subtitle: source ? humanEnum(source.type) : undefined,\n route: `sources/${dataset.sourceId}`,\n column: COLUMN.source,\n });\n builder.link(nid.source(dataset.sourceId), nid.dataset(dataset.id));\n }\n\n if (dataset.collectionId) {\n const collection = pools.collectionsById.get(dataset.collectionId);\n builder.addNode({\n id: nid.collection(dataset.collectionId),\n type: 'collection',\n title: collection?.name ?? 'Collection',\n route: `collections/${dataset.collectionId}`,\n column: COLUMN.collection,\n });\n builder.link(nid.collection(dataset.collectionId), nid.dataset(dataset.id));\n }\n}\n\n/** Add the downstream fan for a dataset: runs, notebooks, analyses, releases. */\nfunction addDatasetDownstream(\n builder: LineageBuilder,\n dataset: CosDataset,\n pools: LineageDataPools\n): void {\n const datasetNode = nid.dataset(dataset.id);\n\n for (const run of pools.runs) {\n if (run.datasetId !== dataset.id) {\n continue;\n }\n const pipelineName = run.pipelineId\n ? pools.pipelinesById?.get(run.pipelineId)?.name\n : undefined;\n builder.addNode({\n id: nid.run(run.id),\n type: 'run',\n typeLabel: `Pipeline Run #${run.runNumber}`,\n title: pipelineName ?? `Run #${run.runNumber}`,\n subtitle: humanEnum(run.status),\n route: `runs/${run.id}`,\n column: COLUMN.run,\n });\n builder.link(datasetNode, nid.run(run.id));\n }\n\n for (const notebook of pools.notebooks) {\n if (!notebook.datasetIds.includes(dataset.id)) {\n continue;\n }\n builder.addNode({\n id: nid.notebook(notebook.id),\n type: 'notebook',\n title: notebook.title,\n subtitle: humanEnum(notebook.status),\n route: `notebooks/${notebook.id}`,\n column: COLUMN.notebook,\n });\n builder.link(datasetNode, nid.notebook(notebook.id));\n }\n\n for (const analysis of pools.analyses) {\n const linkedToNotebook =\n analysis.notebookId != null && builder.has(nid.notebook(analysis.notebookId));\n if (analysis.datasetId !== dataset.id && !linkedToNotebook) {\n continue;\n }\n builder.addNode({\n id: nid.analysis(analysis.id),\n type: 'analysis',\n title: analysis.title,\n subtitle: humanEnum(analysis.status),\n // No per-analysis detail route exists — land on the analyses list.\n route: 'analyses',\n column: COLUMN.analysis,\n });\n if (linkedToNotebook && analysis.notebookId != null) {\n builder.link(nid.notebook(analysis.notebookId), nid.analysis(analysis.id));\n } else {\n builder.link(datasetNode, nid.analysis(analysis.id));\n }\n }\n\n for (const release of pools.releases) {\n if (!release.datasetIds.includes(dataset.id)) {\n continue;\n }\n addReleaseNode(builder, release);\n builder.link(datasetNode, nid.release(release.id));\n if (release.notebookId != null && builder.has(nid.notebook(release.notebookId))) {\n builder.link(nid.notebook(release.notebookId), nid.release(release.id));\n }\n }\n}\n\nfunction addReleaseNode(builder: LineageBuilder, release: CosRelease, emphasis = false): void {\n const doiSuffix = release.doi ? ' · DOI' : '';\n builder.addNode({\n id: nid.release(release.id),\n type: 'release',\n title: release.title,\n subtitle: `v${release.version}${doiSuffix}`,\n // No per-release detail route exists — land on the releases list.\n route: 'releases',\n column: COLUMN.release,\n emphasis,\n });\n}\n\n/**\n * Provenance for a single dataset: its upstream (source + collection) and its\n * full downstream fan (runs, notebooks, analyses, releases). The dataset is the\n * emphasised root.\n */\nexport function buildDatasetLineage(datasetId: string, pools: LineageDataPools): LineageModel {\n const builder = new LineageBuilder();\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n return builder.build();\n }\n addDatasetUpstream(builder, dataset, pools, true);\n addDatasetDownstream(builder, dataset, pools);\n return builder.build();\n}\n\n/**\n * Provenance for a release: the release plus its input datasets and notebook,\n * each expanded UPSTREAM (source/collection for datasets; the notebook's own\n * datasets). The release is the emphasised root.\n */\nexport function buildReleaseLineage(releaseId: string, pools: LineageDataPools): LineageModel {\n const builder = new LineageBuilder();\n const release = pools.releases.find((item) => item.id === releaseId);\n if (!release) {\n return builder.build();\n }\n\n addReleaseNode(builder, release, true);\n\n for (const datasetId of release.datasetIds) {\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n continue;\n }\n addDatasetUpstream(builder, dataset, pools, false);\n builder.link(nid.dataset(dataset.id), nid.release(release.id));\n }\n\n if (release.notebookId != null) {\n const notebook = pools.notebooks.find((item) => item.id === release.notebookId);\n builder.addNode({\n id: nid.notebook(release.notebookId),\n type: 'notebook',\n title: notebook?.title ?? 'Notebook',\n subtitle: notebook ? humanEnum(notebook.status) : undefined,\n route: `notebooks/${release.notebookId}`,\n column: COLUMN.notebook,\n });\n builder.link(nid.notebook(release.notebookId), nid.release(release.id));\n\n for (const datasetId of notebook?.datasetIds ?? []) {\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n continue;\n }\n addDatasetUpstream(builder, dataset, pools, false);\n builder.link(nid.dataset(dataset.id), nid.notebook(release.notebookId));\n }\n }\n\n return builder.build();\n}\n\n// ============================================================================\n// PRESENTATION\n// ============================================================================\n\ninterface NodeMeta {\n label: string;\n Icon: LucideIcon;\n /** Icon-chip classes (semantic accent tokens only). */\n chip: string;\n /** Card border colour class. */\n border: string;\n}\n\nconst NODE_META: Record<LineageNodeType, NodeMeta> = {\n source: {\n label: 'Source',\n Icon: Radar,\n chip: 'bg-accent-blue-subtle text-accent-blue',\n border: 'border-accent-blue',\n },\n collection: {\n label: 'Collection',\n Icon: Boxes,\n chip: 'bg-accent-teal-subtle text-accent-teal',\n border: 'border-accent-teal',\n },\n dataset: {\n label: 'Dataset',\n Icon: Database,\n chip: 'bg-accent-indigo-subtle text-accent-indigo',\n border: 'border-accent-indigo',\n },\n run: {\n label: 'Pipeline Run',\n Icon: Cog,\n chip: 'bg-accent-purple-subtle text-accent-purple',\n border: 'border-accent-purple',\n },\n notebook: {\n label: 'Notebook',\n Icon: NotebookText,\n chip: 'bg-accent-teal-subtle text-accent-teal',\n border: 'border-accent-teal',\n },\n analysis: {\n label: 'Analysis',\n Icon: LineChart,\n chip: 'bg-accent-purple-subtle text-accent-purple',\n border: 'border-accent-purple',\n },\n release: {\n label: 'Release',\n Icon: Tag,\n chip: 'bg-status-success-bg-subtle text-status-success-text',\n border: 'border-status-success-border',\n },\n};\n\ninterface Dims {\n nodeW: number;\n nodeH: number;\n colGap: number;\n rowGap: number;\n pad: number;\n iconSize: string;\n showSubtitle: boolean;\n}\n\nconst DIMS: Record<'full' | 'compact', Dims> = {\n full: {\n nodeW: 190,\n nodeH: 78,\n colGap: 74,\n rowGap: 30,\n pad: 32,\n iconSize: 'size-8',\n showSubtitle: true,\n },\n compact: {\n nodeW: 150,\n nodeH: 54,\n colGap: 46,\n rowGap: 18,\n pad: 18,\n iconSize: 'size-6',\n showSubtitle: false,\n },\n};\n\ninterface Positioned {\n node: LineageNode;\n x: number;\n y: number;\n}\n\ninterface Layout {\n positions: Map<string, Positioned>;\n width: number;\n height: number;\n}\n\nfunction computeLayout(model: LineageModel, dims: Dims): Layout {\n const positions = new Map<string, Positioned>();\n if (model.nodes.length === 0) {\n return { positions, width: dims.pad * 2, height: dims.pad * 2 };\n }\n\n // Present columns, remapped to contiguous indices so empty layers collapse.\n const presentCols = [...new Set(model.nodes.map((n) => n.column))].sort((a, b) => a - b);\n const colOrder = new Map(presentCols.map((c, i) => [c, i]));\n\n const byColumn = new Map<number, LineageNode[]>();\n for (const node of model.nodes) {\n const list = byColumn.get(node.column);\n if (list) {\n list.push(node);\n } else {\n byColumn.set(node.column, [node]);\n }\n }\n\n let contentH = dims.nodeH;\n for (const list of byColumn.values()) {\n const h = list.length * dims.nodeH + (list.length - 1) * dims.rowGap;\n contentH = Math.max(contentH, h);\n }\n\n for (const col of presentCols) {\n const list = byColumn.get(col) ?? [];\n const colH = list.length * dims.nodeH + (list.length - 1) * dims.rowGap;\n const startY = dims.pad + (contentH - colH) / 2;\n const x = dims.pad + (colOrder.get(col) ?? 0) * (dims.nodeW + dims.colGap);\n list.forEach((node, i) => {\n positions.set(node.id, { node, x, y: startY + i * (dims.nodeH + dims.rowGap) });\n });\n }\n\n const width =\n dims.pad * 2 + presentCols.length * dims.nodeW + (presentCols.length - 1) * dims.colGap;\n const height = dims.pad * 2 + contentH;\n return { positions, width, height };\n}\n\nfunction edgePath(x1: number, y1: number, x2: number, y2: number): string {\n const dx = Math.max(24, (x2 - x1) * 0.5);\n return `M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2} ${y2}`;\n}\n\nexport interface LineageGraphProps {\n model: LineageModel;\n mode?: 'full' | 'compact';\n onNavigate?: (route: string) => void;\n className?: string;\n}\n\nexport function LineageGraph({ model, mode = 'full', onNavigate, className }: LineageGraphProps) {\n const markerId = `cos-lineage-arrow-${useId().replace(/:/g, '')}`;\n const dims = DIMS[mode];\n\n const layout = useMemo(() => computeLayout(model, dims), [model, dims]);\n\n const legendTypes = useMemo(() => {\n const seen = new Set<LineageNodeType>();\n const ordered: LineageNodeType[] = [];\n for (const node of [...model.nodes].sort((a, b) => a.column - b.column)) {\n if (!seen.has(node.type)) {\n seen.add(node.type);\n ordered.push(node.type);\n }\n }\n return ordered;\n }, [model.nodes]);\n\n if (model.nodes.length === 0) {\n return null;\n }\n\n return (\n <div className={cn('flex flex-col gap-3', className)}>\n {mode === 'full' && legendTypes.length > 0 ? (\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n {legendTypes.map((type) => {\n const meta = NODE_META[type];\n return (\n <span\n key={type}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n className={cn(\n 'flex size-5 items-center justify-center rounded-button',\n meta.chip\n )}\n >\n <meta.Icon className=\"size-3\" aria-hidden=\"true\" />\n </span>\n {meta.label}\n </span>\n );\n })}\n </div>\n ) : null}\n\n <div\n className={cn(\n 'overflow-x-auto rounded-card border border-border-seam bg-bg-canvas',\n mode === 'full' ? 'p-1' : 'p-0.5'\n )}\n >\n <div\n className=\"relative\"\n style={{\n width: layout.width,\n height: layout.height,\n minWidth: '100%',\n backgroundImage: 'radial-gradient(var(--color-border-subtle) 1px, transparent 1px)',\n backgroundSize: mode === 'full' ? '20px 20px' : '16px 16px',\n }}\n >\n {/* Edges (behind the node cards). */}\n <svg\n className=\"pointer-events-none absolute inset-0 text-border-strong\"\n width={layout.width}\n height={layout.height}\n viewBox={`0 0 ${layout.width} ${layout.height}`}\n aria-hidden=\"true\"\n >\n <defs>\n <marker\n id={markerId}\n viewBox=\"0 0 8 8\"\n refX=\"6.5\"\n refY=\"4\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M1 1 L7 4 L1 7 z\" fill=\"currentColor\" />\n </marker>\n </defs>\n {model.edges.map((edge) => {\n const from = layout.positions.get(edge.from);\n const to = layout.positions.get(edge.to);\n if (!from || !to) {\n return null;\n }\n const x1 = from.x + dims.nodeW;\n const y1 = from.y + dims.nodeH / 2;\n const x2 = to.x;\n const y2 = to.y + dims.nodeH / 2;\n return (\n <path\n key={`${edge.from}»${edge.to}`}\n d={edgePath(x1, y1, x2, y2)}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={mode === 'full' ? 1.5 : 1.25}\n strokeLinecap=\"round\"\n markerEnd={`url(#${markerId})`}\n opacity={0.7}\n />\n );\n })}\n </svg>\n\n {/* Node cards. */}\n {[...layout.positions.values()].map(({ node, x, y }) => {\n const meta = NODE_META[node.type];\n const clickable = Boolean(node.route && onNavigate);\n const content = (\n <div\n className={cn(\n 'flex h-full w-full items-center gap-2.5 rounded-card border bg-bg-elevated px-3 shadow-sm transition-shadow',\n meta.border,\n clickable && 'group-hover:shadow-md',\n node.emphasis && 'ring-1 ring-border-strong'\n )}\n >\n <span\n className={cn(\n 'flex shrink-0 items-center justify-center rounded-button',\n dims.iconSize,\n meta.chip\n )}\n aria-hidden=\"true\"\n >\n <meta.Icon className={mode === 'full' ? 'size-4' : 'size-3.5'} />\n </span>\n <span className=\"flex min-w-0 flex-1 flex-col text-left\">\n <span className=\"truncate text-[10px] font-medium uppercase tracking-wide text-text-tertiary\">\n {node.typeLabel ?? meta.label}\n </span>\n <span\n className={cn(\n 'truncate font-semibold text-text-primary',\n mode === 'full' ? 'text-sm' : 'text-xs'\n )}\n >\n {node.title}\n </span>\n {dims.showSubtitle && node.subtitle ? (\n <span className=\"truncate text-[11px] text-text-secondary\">\n {node.subtitle}\n </span>\n ) : null}\n </span>\n </div>\n );\n\n const style = { left: x, top: y, width: dims.nodeW, height: dims.nodeH } as const;\n\n if (clickable && node.route) {\n const route = node.route;\n return (\n <button\n key={node.id}\n type=\"button\"\n onClick={() => onNavigate?.(route)}\n className=\"group absolute rounded-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n style={style}\n title={`${node.typeLabel ?? meta.label}: ${node.title}`}\n >\n {content}\n </button>\n );\n }\n\n return (\n <div key={node.id} className=\"absolute\" style={style}>\n {content}\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n}\n\nexport default LineageGraph;\n"],"mappings":"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"}
|