UNPKG

datajunction-ui

Version:
1,567 lines โ€ข 50.8 kB
import { jsxs as s, jsx as e, Fragment as C } from "react/jsx-runtime"; import * as M from "react"; import { useContext as F, useState as E, useEffect as G } from "react"; import { D as U, z as I, aO as P, cv as Y } from "./index-n79cxNwC.js"; import { Link as k } from "react-router-dom"; import { N as R } from "./NodeListActions-BJVAKd6-.js"; /* empty css */ const D = (t) => { var o, m, i; return ((i = (m = (o = t == null ? void 0 : t.data) == null ? void 0 : o.findNodesPaginated) == null ? void 0 : m.edges) == null ? void 0 : i.map((c) => c.node)) || []; }; function J(t) { const o = F(U).DataJunctionAPI, [m, i] = E({ ownedNodes: [], ownedHasMore: {}, recentlyEdited: [], editedHasMore: {}, watchedNodes: [], collections: [], notifications: [], materializedNodes: [], needsAttention: { nodesMissingDescription: [], invalidNodes: [], staleDrafts: [], orphanedDimensions: [] }, hasPersonalNamespace: null }), [c, p] = E({ myNodes: !0, collections: !0, notifications: !0, materializations: !0, needsAttention: !0, namespace: !0 }); return G(() => { if (!t) { p({ myNodes: !1, collections: !1, notifications: !1, materializations: !1, needsAttention: !1, namespace: !1 }); return; } p({ myNodes: !0, collections: !0, notifications: !0, materializations: !0, needsAttention: !0, namespace: !0 }); const g = ["METRIC", "TRANSFORM", "DIMENSION", "CUBE"], a = (r) => { var f, u, x; return ((x = (u = (f = r == null ? void 0 : r.data) == null ? void 0 : f.findNodesPaginated) == null ? void 0 : u.pageInfo) == null ? void 0 : x.hasNextPage) ?? !1; }, n = async () => { try { const [r, f, u] = await Promise.all([ Promise.all( g.map( (v) => o.getWorkspaceOwnedNodes(t, 11, v) ) ), Promise.all( g.map( (v) => o.getWorkspaceRecentlyEdited(t, 11, v) ) ), o.getWorkspaceCollections(t) ]), x = Object.fromEntries( g.map((v, w) => [ v.toLowerCase(), a(r[w]) ]) ), y = Object.fromEntries( g.map((v, w) => [ v.toLowerCase(), a(f[w]) ]) ); i((v) => { var w; return { ...v, ownedNodes: r.flatMap((S) => D(S)), ownedHasMore: x, recentlyEdited: f.flatMap((S) => D(S)), editedHasMore: y, collections: ((w = u == null ? void 0 : u.data) == null ? void 0 : w.listCollections) || [] }; }); } catch (r) { console.error("Error fetching nodes/collections:", r); } p((r) => ({ ...r, myNodes: !1, collections: !1 })); }, h = async () => { try { const [r, f] = await Promise.all([ o.getNotificationPreferences({ entity_type: "node" }), o.getSubscribedHistory(50) ]), u = (r || []).map((N) => N.entity_name), x = f || [], y = Array.from( new Set(x.map((N) => N.entity_name)) ), [v, w] = await Promise.all([ u.length > 0 ? o.getNodesByNames(u) : Promise.resolve([]), y.length > 0 ? o.getNodesByNames(y) : Promise.resolve([]) ]), S = Object.fromEntries( (w || []).map((N) => [N.name, N]) ), z = x.map((N) => { var b, A, B; return { ...N, node_type: (b = S[N.entity_name]) == null ? void 0 : b.type, display_name: (B = (A = S[N.entity_name]) == null ? void 0 : A.current) == null ? void 0 : B.displayName }; }); i((N) => ({ ...N, watchedNodes: v || [], notifications: z })); } catch (r) { console.error("Error fetching watched/notifications:", r); } p((r) => ({ ...r, notifications: !1 })); }, l = async () => { try { const r = await o.getWorkspaceMaterializations(t, 6); i((f) => ({ ...f, materializedNodes: D(r) })); } catch (r) { console.error("Error fetching materializations:", r); } p((r) => ({ ...r, materializations: !1 })); }, d = async () => { try { const f = `users.${t.split("@")[0]}`, [ u, x, y, v, w ] = await Promise.all([ o.getWorkspaceNodesMissingDescription(t, 100), o.getWorkspaceInvalidNodes(t, 100), o.getWorkspaceDraftNodes(t, 100), o.getWorkspaceOrphanedDimensions(t, 100), o.namespaces() ]), S = /* @__PURE__ */ new Date(); S.setDate(S.getDate() - 7); const z = D(y); i((N) => ({ ...N, needsAttention: { nodesMissingDescription: D(u), invalidNodes: D(x), staleDrafts: z.filter( (b) => { var A; return new Date((A = b.current) == null ? void 0 : A.updatedAt) < S; } ), orphanedDimensions: D(v) }, hasPersonalNamespace: (w || []).some( (b) => b.namespace === f ) })); } catch (r) { console.error("Error fetching needs attention:", r); } p((r) => ({ ...r, needsAttention: !1, namespace: !1 })); }; n(), h(), l(), d(); }, [o, t]), { data: m, loadingStates: c }; } function T({ title: t, actionLink: o, actionText: m = "View All โ†’", loading: i = !1, emptyState: c = null, children: p, cardStyle: g = {}, contentStyle: a = {}, showHeader: n = !0 }) { const h = M.Children.toArray(p).filter( (d) => d !== !1 && d !== null && d !== void 0 ).length > 0, l = !i && !h && c; return /* @__PURE__ */ s("section", { children: [ n && /* @__PURE__ */ s("div", { className: "section-title-row", children: [ /* @__PURE__ */ e("h2", { className: "settings-section-title", children: t }), o && /* @__PURE__ */ e(k, { to: o, style: { fontSize: "13px" }, children: m }) ] }), /* @__PURE__ */ e( "div", { className: "settings-card", style: { padding: "0.75rem", ...g, ...a }, children: i ? /* @__PURE__ */ e("div", { style: { textAlign: "center", padding: "2rem" }, children: /* @__PURE__ */ e(I, {}) }) : l ? c : p } ) ] }); } function V({ icon: t, message: o, action: m }) { return /* @__PURE__ */ s( "div", { style: { padding: "2rem", textAlign: "center", color: "#666", fontSize: "12px" }, children: [ t && /* @__PURE__ */ e("div", { style: { fontSize: "24px", marginBottom: "0.5rem" }, children: t }), /* @__PURE__ */ e("p", { children: o }), m ] } ); } function W({ type: t, size: o = "medium", abbreviated: m = !1, style: i = {} }) { if (!t) return null; const c = { small: { fontSize: "7px", padding: "0.44em" }, medium: { fontSize: "9px", padding: "0.44em" }, large: { fontSize: "11px", padding: "0.44em" } }, p = c[o] || c.medium, g = m ? t.charAt(0) : t; return /* @__PURE__ */ e( "span", { className: `node_type__${t.toLowerCase()} badge node_type`, style: { ...p, flexShrink: 0, ...i, marginRight: 0 }, children: g } ); } function O({ node: t, size: o = "medium", showFullName: m = !1, ellipsis: i = !1, style: c = {} }) { var h; if (!(t != null && t.name)) return null; const p = { small: { fontSize: "10px", fontWeight: "500" }, medium: { fontSize: "12px", fontWeight: "500" }, large: { fontSize: "14px", fontWeight: "500" } }, g = p[o] || p.medium, a = m ? t.name : ((h = t.current) == null ? void 0 : h.displayName) || t.name.split(".").pop(), n = i ? { display: "block", flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : {}; return /* @__PURE__ */ e( "a", { href: `/nodes/${t.name}`, style: { ...g, textDecoration: "none", ...n, ...c }, children: a } ); } function H({ node: t, size: o = "medium", showBadge: m = !0, abbreviatedBadge: i = !1, ellipsis: c = !1, gap: p = "6px", containerStyle: g = {} }) { return t ? /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: p, ...c ? { minWidth: 0, overflow: "hidden" } : {}, ...g }, children: [ /* @__PURE__ */ e(O, { node: t, size: o, ellipsis: c }), m && t.type && /* @__PURE__ */ e( W, { type: t.type, size: o, abbreviated: i } ) ] } ) : null; } function q({ node: t }) { var o; return t ? /* @__PURE__ */ s( "a", { href: `/nodes/${t.name}`, style: { display: "inline-flex", alignItems: "center", gap: "3px", padding: "2px 6px", fontSize: "12px", border: "1px solid var(--border-color, #ddd)", borderRadius: "3px", textDecoration: "none", color: "inherit", backgroundColor: "var(--card-bg, #f8f9fa)", whiteSpace: "nowrap", flexShrink: 0 }, children: [ /* @__PURE__ */ e(W, { type: t.type, size: "small", abbreviated: !0 }), ((o = t.current) == null ? void 0 : o.displayName) || t.name.split(".").pop() ] } ) : null; } function K({ notifications: t, username: o, loading: m }) { const i = {}; t.forEach((g) => { i[g.entity_name] || (i[g.entity_name] = []), i[g.entity_name].push(g); }); const p = Object.entries(i).map(([g, a]) => ({ nodeName: g, entries: a, mostRecent: a[0], // Assuming already sorted by date count: a.length })).slice(0, 15).map( ({ nodeName: g, entries: a, mostRecent: n, count: h }) => { var x, y, v, w, S; const l = (x = n.details) == null ? void 0 : x.version, d = l ? `/nodes/${n.entity_name}/revisions/${l}` : `/nodes/${n.entity_name}/history`, r = a.map((z) => z.user).filter((z) => z != null && z !== ""), f = [...new Set(r)], u = f.length === 0 ? n.user === o ? "you" : ((y = n.user) == null ? void 0 : y.split("@")[0]) || "unknown" : f.length === 1 ? f[0] === o ? "you" : (v = f[0]) == null ? void 0 : v.split("@")[0] : f.includes(o) ? `you + ${f.length - 1} other${f.length - 1 > 1 ? "s" : ""}` : `${f.length} users`; return /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", padding: "0.5rem 0", borderBottom: "1px solid var(--border-color, #eee)", fontSize: "12px" }, children: [ /* @__PURE__ */ e( "a", { href: d, style: { fontSize: "13px", fontWeight: "500", textDecoration: "none", flexShrink: 0 }, children: n.display_name || n.entity_name.split(".").pop() } ), n.node_type && /* @__PURE__ */ e( W, { type: n.node_type.toUpperCase(), size: "medium" } ), /* @__PURE__ */ s("span", { style: { color: "#888", whiteSpace: "nowrap" }, children: [ h > 1 ? `${h} updates` : ((w = n.activity_type) == null ? void 0 : w.charAt(0).toUpperCase()) + ((S = n.activity_type) == null ? void 0 : S.slice(1)) + "d", " ", "by ", u, " ยท ", P(n.created_at) ] }) ] }, g ); } ); return /* @__PURE__ */ e( T, { title: "Notifications", actionLink: "/notifications", loading: m, cardStyle: { padding: "0", maxHeight: "300px", overflowY: "auto" }, emptyState: /* @__PURE__ */ e( V, { icon: "๐Ÿ””", message: "No notifications yet.", action: /* @__PURE__ */ e("p", { style: { fontSize: "11px", marginTop: "0.5rem" }, children: "Watch nodes to get notified of changes." }) } ), children: t.length > 0 && /* @__PURE__ */ e( "div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem", padding: "0.5rem" }, children: p } ) } ); } function Q({ nodesMissingDescription: t, invalidNodes: o, staleDrafts: m, staleMaterializations: i, orphanedDimensions: c, username: p, loading: g, personalNamespace: a, hasPersonalNamespace: n, namespaceLoading: h }) { const l = [ { id: "invalid", icon: "โŒ", label: "Invalid", nodes: o, viewAllLink: `/?ownedBy=${p}&statuses=INVALID` }, { id: "stale-drafts", icon: "โฐ", label: "Stale Drafts", nodes: m, viewAllLink: `/?ownedBy=${p}&mode=DRAFT` }, { id: "stale-materializations", icon: "๐Ÿ“ฆ", label: "Stale Materializations", nodes: i, viewAllLink: `/?ownedBy=${p}&hasMaterialization=true` }, { id: "no-description", icon: "๐Ÿ“", label: "No Description", nodes: t, viewAllLink: `/?ownedBy=${p}&missingDescription=true` }, { id: "orphaned-dimensions", icon: "๐Ÿ”—", label: "Orphaned Dimensions", nodes: c, viewAllLink: `/?ownedBy=${p}&orphanedDimension=true` } ]; return /* @__PURE__ */ s("section", { style: { minWidth: 0, width: "100%" }, children: [ /* @__PURE__ */ e("h2", { className: "settings-section-title", children: "Needs Attention" }), /* @__PURE__ */ e("div", { className: "settings-card", style: { padding: "0.25rem 0.75rem" }, children: g ? /* @__PURE__ */ e("div", { style: { textAlign: "center", padding: "1rem" }, children: /* @__PURE__ */ e(I, {}) }) : /* @__PURE__ */ s(C, { children: [ l.map((d, r) => /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", padding: "0.35rem 0", borderBottom: r < l.length - 1 ? "1px solid var(--border-color, #f0f0f0)" : "none", minWidth: 0 }, children: [ /* @__PURE__ */ s( "span", { style: { fontSize: "11px", fontWeight: 600, color: "#555", whiteSpace: "nowrap", flexShrink: 0 }, children: [ d.label, " ", /* @__PURE__ */ s( "span", { style: { color: d.nodes.length > 0 ? "#dc3545" : "#28a745", fontWeight: 500 }, children: [ "(", d.nodes.length, ")" ] } ) ] } ), d.nodes.length > 0 ? /* @__PURE__ */ e( "div", { style: { flex: 1, overflow: "hidden", maskImage: "linear-gradient(to right, black 75%, transparent 100%)", WebkitMaskImage: "linear-gradient(to right, black 75%, transparent 100%)" }, children: /* @__PURE__ */ e( "div", { style: { display: "flex", gap: "0.25rem", flexWrap: "nowrap" }, children: d.nodes.slice(0, 20).map((f) => /* @__PURE__ */ e(q, { node: f }, f.name)) } ) } ) : /* @__PURE__ */ e("span", { style: { fontSize: "10px", color: "#28a745", flex: 1 }, children: "All good" }), d.nodes.length > 0 && /* @__PURE__ */ e( k, { to: d.viewAllLink, style: { fontSize: "11px", flexShrink: 0 }, children: "โ†’" } ) ] }, d.id )), !h && !n && /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", padding: "0.35rem 0", fontSize: "11px" }, children: [ /* @__PURE__ */ e("span", { style: { fontWeight: 600, color: "#555", flexShrink: 0 }, children: "Personal namespace" }), /* @__PURE__ */ s( k, { to: `/namespaces/${a}`, style: { fontSize: "10px" }, children: [ "Create ", a, " โ†’" ] } ) ] } ) ] }) }) ] }); } function X({ nodes: t, showUpdatedAt: o }) { const m = (i) => new Date(i).toLocaleDateString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }); return /* @__PURE__ */ e("div", { className: "node-list", children: t.map((i) => { var c; return /* @__PURE__ */ s("div", { className: "subscription-item node-list-item", children: [ /* @__PURE__ */ s("div", { className: "node-list-item-content", children: [ /* @__PURE__ */ e("div", { className: "node-list-item-display", children: /* @__PURE__ */ e( H, { node: i, size: "large", ellipsis: !0, gap: "0.5rem" } ) }), /* @__PURE__ */ e("div", { className: "node-list-item-name", children: i.name }) ] }), /* @__PURE__ */ s("div", { className: "node-list-item-actions", children: [ o && ((c = i.current) == null ? void 0 : c.updatedAt) && /* @__PURE__ */ e("span", { className: "node-list-item-updated", children: m(i.current.updatedAt) }), /* @__PURE__ */ e("div", { className: "node-list-item-actions-wrapper", children: /* @__PURE__ */ e(R, { nodeName: i.name }) }) ] }) ] }, i.name); }) }); } function Z(t) { const o = new Date(t), i = /* @__PURE__ */ new Date() - o, c = Math.floor(i / (1e3 * 60)), p = Math.floor(i / (1e3 * 60 * 60)), g = Math.floor(i / (1e3 * 60 * 60 * 24)); return c < 60 ? `${c}m` : p < 24 ? `${p}h` : g < 30 ? `${g}d` : o.toLocaleDateString("en-US", { month: "short", day: "numeric" }); } function ee(t) { return t.charAt(0).toUpperCase() + t.slice(1); } function te({ type: t, nodes: o, hasMore: m, username: i, activeTab: c }) { const p = o, g = () => { const a = new URLSearchParams(); return c === "owned" ? (a.append("ownedBy", i), a.append("type", t)) : c === "watched" ? a.append("type", t) : c === "edited" && (a.append("updatedBy", i), a.append("type", t)), `/?${a.toString()}`; }; return /* @__PURE__ */ s("div", { className: "type-group-card", children: [ /* @__PURE__ */ e("div", { className: "type-group-header", children: /* @__PURE__ */ s("span", { className: "type-group-title", children: [ ee(t), "s" ] }) }), /* @__PURE__ */ e("div", { className: "type-group-nodes", children: p.map((a) => { var x, y, v, w; const n = a.status === "invalid", h = a.mode === "draft", l = (x = a.gitInfo) == null ? void 0 : x.repo, d = (y = a.gitInfo) == null ? void 0 : y.branch, r = (v = a.gitInfo) == null ? void 0 : v.defaultBranch, f = d && d === r, u = l || d; return /* @__PURE__ */ s("div", { className: "type-group-node", children: [ /* @__PURE__ */ e(W, { type: a.type, size: "small", abbreviated: !0 }), n && /* @__PURE__ */ e( "span", { className: "type-group-node-status-icon", title: "Invalid node", children: "โš ๏ธ" } ), h && /* @__PURE__ */ e( "span", { className: "type-group-node-status-icon", title: "Draft mode", children: "๐Ÿ“" } ), /* @__PURE__ */ e( O, { node: a, size: "small", ellipsis: !0, style: { flex: 1, minWidth: 0 } } ), u && /* @__PURE__ */ s( "span", { className: `type-group-node-git-info ${f ? "type-group-node-git-info--default" : ""}`, title: `${l || ""}${l && d ? " / " : ""}${d || ""}${f ? " (default)" : ""}`, style: { display: "flex", alignItems: "center", gap: "4px", maxWidth: "40%" }, children: [ f && /* @__PURE__ */ e("span", { style: { lineHeight: 1, flexShrink: 0 }, children: "โญ" }), l && /* @__PURE__ */ e( "span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 }, children: l } ), l && d && /* @__PURE__ */ s( "svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: [ /* @__PURE__ */ e("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ e("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ e("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ e("path", { d: "M18 9a9 9 0 0 1-9 9" }) ] } ), d && /* @__PURE__ */ e( "span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 }, children: d } ) ] } ), ((w = a.current) == null ? void 0 : w.updatedAt) && /* @__PURE__ */ e("span", { className: "type-group-node-time", children: Z(a.current.updatedAt) }), /* @__PURE__ */ e("div", { className: "type-group-node-actions", children: /* @__PURE__ */ e(R, { nodeName: a.name }) }) ] }, a.name); }) }), m && /* @__PURE__ */ e(k, { to: g(), className: "type-group-more", children: "More โ†’" }) ] }); } function ne({ groupedData: t, username: o, activeTab: m }) { return !t || t.length === 0 ? /* @__PURE__ */ e( "div", { style: { padding: "1rem", textAlign: "center", color: "#666", fontSize: "12px" }, children: "No nodes to display" } ) : /* @__PURE__ */ e("div", { className: "type-group-grid", children: t.map((i) => /* @__PURE__ */ e( te, { type: i.type, nodes: i.nodes, hasMore: i.hasMore, username: o, activeTab: m }, i.type )) }); } const ie = ["metric", "cube", "dimension", "transform", "source"]; function ae(t, o = {}) { const m = {}; return t.forEach((i) => { const c = (i.type || "unknown").toLowerCase(); m[c] || (m[c] = []), m[c].push(i); }), ie.filter((i) => { var c; return ((c = m[i]) == null ? void 0 : c.length) > 0; }).map((i) => ({ type: i, nodes: m[i], hasMore: o[i] ?? !1 })); } function oe({ ownedNodes: t, ownedHasMore: o = {}, watchedNodes: m, recentlyEdited: i, editedHasMore: c = {}, username: p, loading: g }) { const [a, n] = M.useState("owned"), h = M.useRef(!1); M.useEffect(() => { h.current || (t.length === 0 && i.length > 0 ? (n("edited"), h.current = !0) : t.length > 0 && (h.current = !0)); }, [t.length, i.length]); const [l, d] = M.useState(() => { const b = localStorage.getItem("workspace_groupByType"); return b === null ? !0 : b === "true"; }), r = new Set(t.map((b) => b.name)), f = m.filter((b) => !r.has(b.name)), u = /* @__PURE__ */ new Set([ ...r, ...m.map((b) => b.name) ]); i.filter((b) => !u.has(b.name)); const y = (() => { switch (a) { case "owned": return t; case "watched": return f; case "edited": return i; default: return t; } })(), v = t.length > 0 || f.length > 0 || i.length > 0, w = 8, S = (b) => { const A = b.target.checked; d(A), localStorage.setItem("workspace_groupByType", A.toString()); }, N = l ? ae(y, a === "owned" ? o : a === "edited" ? c : {}) : null; return /* @__PURE__ */ e( T, { title: "My Nodes", actionLink: `/?ownedBy=${p}`, loading: g, cardStyle: { padding: "0.25rem 0.75rem" }, emptyState: /* @__PURE__ */ s("div", { style: { padding: "0.75rem 0" }, children: [ /* @__PURE__ */ e( "p", { style: { fontSize: "12px", color: "#666", marginBottom: "0.75rem" }, children: "No nodes yet." } ), /* @__PURE__ */ s("div", { style: { display: "flex", gap: "0.75rem" }, children: [ /* @__PURE__ */ s( "div", { style: { flex: 1, padding: "0.75rem", backgroundColor: "var(--card-bg, #f8f9fa)", border: "1px dashed var(--border-color, #dee2e6)", borderRadius: "6px", textAlign: "center" }, children: [ /* @__PURE__ */ e("div", { style: { fontSize: "16px", marginBottom: "0.25rem" }, children: "โž•" }), /* @__PURE__ */ e( "div", { style: { fontSize: "11px", fontWeight: "500", marginBottom: "0.25rem" }, children: "Create a node" } ), /* @__PURE__ */ e( "p", { style: { fontSize: "10px", color: "#666", marginBottom: "0.5rem" }, children: "Build your data model" } ), /* @__PURE__ */ e( k, { to: "/create/source", style: { display: "inline-block", padding: "3px 8px", fontSize: "10px", backgroundColor: "var(--primary-color, #4a90d9)", color: "#fff", borderRadius: "4px", textDecoration: "none" }, children: "Create โ†’" } ) ] } ), /* @__PURE__ */ s( "div", { style: { flex: 1, padding: "0.75rem", backgroundColor: "var(--card-bg, #f8f9fa)", border: "1px dashed var(--border-color, #dee2e6)", borderRadius: "6px", textAlign: "center" }, children: [ /* @__PURE__ */ e("div", { style: { fontSize: "16px", marginBottom: "0.25rem" }, children: "๐Ÿ‘ค" }), /* @__PURE__ */ e( "div", { style: { fontSize: "11px", fontWeight: "500", marginBottom: "0.25rem" }, children: "Claim ownership" } ), /* @__PURE__ */ e( "p", { style: { fontSize: "10px", color: "#666", marginBottom: "0.5rem" }, children: "Add yourself as owner" } ), /* @__PURE__ */ e( k, { to: "/", style: { display: "inline-block", padding: "3px 8px", fontSize: "10px", backgroundColor: "#6c757d", color: "#fff", borderRadius: "4px", textDecoration: "none" }, children: "Browse โ†’" } ) ] } ) ] }) ] }), children: v && /* @__PURE__ */ s(C, { children: [ /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "0.5rem", marginBottom: "0.5rem", paddingTop: "0.5rem", paddingBottom: y.length > 0 ? "0.5rem" : "0", borderBottom: y.length > 0 ? "1px solid var(--border-color, #eee)" : "none" }, children: [ /* @__PURE__ */ s("div", { style: { display: "flex", gap: "0.5rem" }, children: [ /* @__PURE__ */ e( "button", { onClick: () => n("owned"), style: { padding: "4px 10px", fontSize: "11px", border: "none", borderRadius: "4px", cursor: "pointer", backgroundColor: a === "owned" ? "var(--primary-color, #4a90d9)" : "#e9ecef", color: a === "owned" ? "#fff" : "#495057" }, children: "Owned" } ), /* @__PURE__ */ s( "button", { onClick: () => n("watched"), style: { padding: "4px 10px", fontSize: "11px", border: "none", borderRadius: "4px", cursor: "pointer", backgroundColor: a === "watched" ? "var(--primary-color, #4a90d9)" : "#e9ecef", color: a === "watched" ? "#fff" : "#495057" }, children: [ "Watched (", f.length, ")" ] } ), /* @__PURE__ */ e( "button", { onClick: () => n("edited"), style: { padding: "4px 10px", fontSize: "11px", border: "none", borderRadius: "4px", cursor: "pointer", backgroundColor: a === "edited" ? "var(--primary-color, #4a90d9)" : "#e9ecef", color: a === "edited" ? "#fff" : "#495057" }, children: "Recent Edits" } ) ] }), y.length > 0 && /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [ /* @__PURE__ */ e( "input", { type: "checkbox", id: "groupByType", checked: l, onChange: S, style: { cursor: "pointer" } } ), /* @__PURE__ */ e( "label", { htmlFor: "groupByType", style: { fontSize: "11px", cursor: "pointer", userSelect: "none", color: "#495057", fontWeight: "500" }, children: "Group by Type" } ) ] } ) ] } ), y.length > 0 ? /* @__PURE__ */ e(C, { children: l ? /* @__PURE__ */ e( ne, { groupedData: N, username: p, activeTab: a } ) : /* @__PURE__ */ s(C, { children: [ /* @__PURE__ */ e( X, { nodes: y.slice(0, w), showUpdatedAt: !0 } ), y.length > w && /* @__PURE__ */ s( "div", { style: { textAlign: "center", padding: "0.5rem", fontSize: "12px", color: "#666" }, children: [ "+", y.length - w, " more" ] } ) ] }) }) : /* @__PURE__ */ s( "div", { style: { padding: "1rem", textAlign: "center", color: "#666", fontSize: "12px" }, children: [ a === "owned" && "No owned nodes", a === "watched" && "No watched nodes", a === "edited" && "No recent edits" ] } ) ] }) } ); } function re({ nodes: t, loading: o }) { const m = (t || []).slice().sort((a, n) => { var d, r, f, u; const h = (r = (d = a.current) == null ? void 0 : d.availability) == null ? void 0 : r.validThroughTs, l = (u = (f = n.current) == null ? void 0 : f.availability) == null ? void 0 : u.validThroughTs; return !h && !l ? 0 : h ? l ? l - h : -1 : 1; }), i = (a) => { if (!a) return { icon: "โณ", text: "Pending", color: "#6c757d" }; const n = a.validThroughTs ? new Date(a.validThroughTs) : null, l = n ? (/* @__PURE__ */ new Date() - n) / (1e3 * 60 * 60) : null; return n ? l <= 24 ? { icon: "๐ŸŸข", text: c(n), color: "#28a745" } : l <= 72 ? { icon: "๐ŸŸก", text: c(n), color: "#ffc107" } : { icon: "๐Ÿ”ด", text: c(n), color: "#dc3545" } : { icon: "โณ", text: "Pending", color: "#6c757d" }; }, c = (a) => { const h = /* @__PURE__ */ new Date() - a, l = Math.floor(h / (1e3 * 60 * 60)), d = Math.floor(l / 24); return l < 1 ? "just now" : l < 24 ? `${l}h ago` : d === 1 ? "yesterday" : `${d}d ago`; }, p = 5, g = m.slice(0, p).map((a) => { var h, l, d, r, f; const n = i((h = a.current) == null ? void 0 : h.availability); return /* @__PURE__ */ s( "div", { style: { padding: "0.5rem", border: "1px solid var(--border-color, #e0e0e0)", borderRadius: "4px", backgroundColor: "var(--card-bg, #fff)" }, children: [ /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "4px" }, children: [ /* @__PURE__ */ e(H, { node: a, size: "medium" }), /* @__PURE__ */ s("span", { style: { fontSize: "10px", color: n.color }, children: [ n.icon, " ", n.text ] }) ] } ), /* @__PURE__ */ s("div", { style: { fontSize: "10px", color: "#666" }, children: [ (d = (l = a.current) == null ? void 0 : l.materializations) == null ? void 0 : d.map((u) => /* @__PURE__ */ s("span", { style: { marginRight: "8px" }, children: [ "๐Ÿ• ", u.schedule || "No schedule" ] }, u.name)), ((f = (r = a.current) == null ? void 0 : r.availability) == null ? void 0 : f.table) && /* @__PURE__ */ s("span", { style: { color: "#888" }, children: [ "โ†’ ", a.current.availability.table ] }) ] }) ] }, a.name ); }); return /* @__PURE__ */ e( T, { title: "Materializations", actionLink: "/?hasMaterialization=true", loading: o, cardStyle: { padding: "0.75rem 1rem", maxHeight: "300px", overflowY: "auto" }, emptyState: /* @__PURE__ */ s("div", { style: { padding: "0" }, children: [ /* @__PURE__ */ e( "p", { style: { fontSize: "12px", color: "#666", marginBottom: "0.75rem" }, children: "No materializations configured." } ), /* @__PURE__ */ s( "div", { style: { padding: "0.75rem", backgroundColor: "var(--card-bg, #f8f9fa)", border: "1px dashed var(--border-color, #dee2e6)", borderRadius: "6px", textAlign: "center" }, children: [ /* @__PURE__ */ e("div", { style: { fontSize: "16px", marginBottom: "0.25rem" }, children: "๐Ÿ“ฆ" }), /* @__PURE__ */ e( "div", { style: { fontSize: "11px", fontWeight: "500", marginBottom: "0.25rem" }, children: "Materialize a node" } ), /* @__PURE__ */ e( "p", { style: { fontSize: "10px", color: "#666", marginBottom: "0.5rem" }, children: "Speed up queries with cached data" } ), /* @__PURE__ */ e( k, { to: "/", style: { display: "inline-block", padding: "3px 8px", fontSize: "10px", backgroundColor: "var(--primary-color, #4a90d9)", color: "#fff", borderRadius: "4px", textDecoration: "none" }, children: "Browse nodes โ†’" } ) ] } ) ] }), children: m.length > 0 && /* @__PURE__ */ s( "div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [ g, m.length > p && /* @__PURE__ */ s( "div", { style: { textAlign: "center", padding: "0.5rem", fontSize: "12px", color: "#666" }, children: [ "+", m.length - p, " more" ] } ) ] } ) } ); } function se({ ownedNodes: t, recentlyEdited: o, loading: m }) { const i = [...t, ...o], c = /* @__PURE__ */ new Map(); i.forEach((n) => { var h, l; if (n.gitInfo && n.gitInfo.repo) { const d = n.name.split(".").slice(0, -1).join("."); let r; if (n.gitInfo.parentNamespace) r = n.gitInfo.parentNamespace; else { const y = d.lastIndexOf("."); r = y > 0 ? d.slice(0, y) : d; } c.has(r) || c.set(r, { baseNamespace: r, repo: n.gitInfo.repo, defaultBranch: n.gitInfo.defaultBranch, branches: /* @__PURE__ */ new Map() }); const f = c.get(r), u = n.gitInfo.branch; f.branches.has(u) || f.branches.set(u, { branch: n.gitInfo.branch, isDefault: n.gitInfo.isDefaultBranch, namespace: d, nodes: [], lastActivity: (h = n.current) == null ? void 0 : h.updatedAt }); const x = f.branches.get(u); x.nodes.push(n), (l = n.current) != null && l.updatedAt && (!x.lastActivity || n.current.updatedAt > x.lastActivity) && (x.lastActivity = n.current.updatedAt); } }), c.forEach((n) => { n.defaultBranch && !n.branches.has(n.defaultBranch) && n.branches.set(n.defaultBranch, { branch: n.defaultBranch, isDefault: !0, namespace: `${n.baseNamespace}.${n.defaultBranch}`, nodes: [], lastActivity: null }); }); const p = Array.from(c.values()).map((n) => ({ ...n, branches: Array.from(n.branches.values()).sort((h, l) => h.isDefault && !l.isDefault ? -1 : !h.isDefault && l.isDefault ? 1 : !h.lastActivity && !l.lastActivity ? 0 : h.lastActivity ? l.lastActivity ? new Date(l.lastActivity) - new Date(h.lastActivity) : -1 : 1) })).sort((n, h) => { const l = Math.max( ...n.branches.map( (r) => r.lastActivity ? new Date(r.lastActivity).getTime() : 0 ) ); return Math.max( ...h.branches.map( (r) => r.lastActivity ? new Date(r.lastActivity).getTime() : 0 ) ) - l; }), g = 3, a = p.slice(0, g).map((n, h) => { const l = h === p.slice(0, g).length - 1; return /* @__PURE__ */ s("div", { children: [ /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: "8px", padding: "0.75rem 0 0.5rem 0", marginTop: "0" }, children: [ /* @__PURE__ */ e( "a", { href: `/namespaces/${n.baseNamespace}`, style: { fontSize: "12px", fontWeight: "600", textDecoration: "none" }, children: n.baseNamespace } ), /* @__PURE__ */ e( "span", { style: { fontSize: "9px", padding: "2px 6px", backgroundColor: "#f0f0f0", color: "#666", borderRadius: "3px", fontWeight: "500" }, children: n.repo } ) ] } ), n.branches.map((d) => /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "0px 1em 0.4em 1em" }, children: [ /* @__PURE__ */ s( "div", { style: { display: "flex", alignItems: "center", gap: "6px", minWidth: 0, flex: 1 }, children: [ /* @__PURE__ */ e( "a", { href: `/namespaces/${d.namespace}`, style: { fontSize: "12px", fontWeight: "500", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: d.branch } ), d.isDefault && /* @__PURE__ */ e("span", { style: { fontSize: "10px" }, children: "โญ" }) ] } ), d.lastActivity && /* @__PURE__ */ s( "span", { style: { fontSize: "10px", color: "#888", whiteSpace: "nowrap" }, children: [ "updated ", P(d.lastActivity) ] } ) ] }, d.branch )), !l && /* @__PURE__ */ e( "div", { style: { borderBottom: "1px solid var(--border-color, #ddd)", margin: "0.5rem 0" } } ) ] }, n.baseNamespace); }); return /* @__PURE__ */ e( T, { title: "Git Namespaces", loading: m, cardStyle: { padding: "0.25rem 0.25rem 0.5em 0.75rem", maxHeight: "300px", overflowY: "auto" }, emptyState: /* @__PURE__ */ s("div", { style: { padding: "0", textAlign: "center" }, children: [ /* @__PURE__ */ e( "p", { style: { fontSize: "12px", color: "#666", marginBottom: "0.75rem" }, children: "No git-managed namespaces." } ), /* @__PURE__ */ s( "div", { style: { padding: "0.75rem", backgroundColor: "var(--card-bg, #f8f9fa)", border: "1px dashed var(--border-color, #dee2e6)", borderRadius: "6px" }, children: [ /* @__PURE__ */ e("div", { style: { fontSize: "16px", marginBottom: "0.25rem" }, children: "๐ŸŒฟ" }), /* @__PURE__ */ e( "div", { style: { fontSize: "11px", fontWeight: "500", marginBottom: "0.25rem" }, children: "Set up git-backed namespaces" } ), /* @__PURE__ */ e("p", { style: { fontSize: "10px", color: "#666", marginBottom: "0" }, children: "Manage your nodes with version control" }) ] } ) ] }), children: p.length > 0 && /* @__PURE__ */ s("div", { style: { display: "flex", flexDirection: "column" }, children: [ a, p.length > g && /* @__PURE__ */ s( "div", { style: { textAlign: "center", padding: "0.5rem", fontSize: "12px", color: "#666" }, children: [ "+", p.length - g, " more git namespace", p.length - g !== 1 ? "s" : "" ] } ) ] }) } ); } function ge() { var B; const { currentUser: t, loading: o } = Y(), { data: m, loadingStates: i } = J( t == null ? void 0 : t.username ), { ownedNodes: c = [], ownedHasMore: p = {}, recentlyEdited: g = [], editedHasMore: a = {}, watchedNodes: n = [], notifications: h = [], materializedNodes: l = [], needsAttention: { nodesMissingDescription: d = [], invalidNodes: r = [], staleDrafts: f = [], orphanedDimensions: u = [] } = {}, hasPersonalNamespace: x = null } = m, y = i.myNodes, v = i.notifications, w = i.materializations, S = i.needsAttention, z = i.namespace, N = l.filter((j) => { var $, _; const L = (_ = ($ = j.current) == null ? void 0 : $.availability) == null ? void 0 : _.validThroughTs; return L ? (Date.now() - L) / (1e3 * 60 * 60) > 72 : !1; }), A = `users.${((B = t == null ? void 0 : t.username) == null ? void 0 : B.split("@")[0]) || ""}`; return o ? /* @__PURE__ */ s("div", { className: "settings-page", style: { padding: "1.5rem 2rem" }, children: [ /* @__PURE__ */ e("h1", { className: "settings-title", children: "Dashboard" }), /* @__PURE__ */ e("div", { style: { textAlign: "center", padding: "3rem" }, children: /* @__PURE__ */ e(I, {}) }) ] }) : /* @__PURE__ */ e("div", { className: "settings-page", style: { padding: "1.5rem 2rem" }, children: /* @__PURE__ */ s("div", { className: "workspace-layout", children: [ /* @__PURE__ */ e("div", { className: "workspace-left-column", children: /* @__PURE__ */ e( oe, { ownedNodes: c, ownedHasMore: p, watchedNodes: n, recentlyEdited: g, editedHasMore: a, username: t == null ? void 0 : t.username, loading: y } ) }), /* @__PURE__ */ s("div", { className: "workspace-right-column", children: [ /* @__PURE__ */ e( Q, { nodesMissingDescription: d, invalidNodes: r, staleDrafts: f, staleMaterializations: N, orphanedDimensions: u,