datajunction-ui
Version:
DataJunction UI
1,567 lines โข 50.8 kB
JavaScript
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,