@burdenoff/microfe-bigconsole 2026.716.4 → 2026.717.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bigconsole/BigConsoleRoot.js +8 -8
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +24 -24
- package/dist/bigconsole/components/preview/AiPreviewContent.js +116 -0
- package/dist/bigconsole/components/preview/AiPreviewContent.js.map +1 -0
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +82 -151
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/previewShared.js +13 -23
- package/dist/bigconsole/components/preview/previewShared.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +9 -9
- package/dist/bigconsole/hooks/index.js +5 -5
- package/dist/bigconsole/hooks/useWidgetCatalog.js +11 -11
- package/dist/bigconsole/index.js +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +3 -3
- package/dist/bigconsole/pages/DashboardViewPage.js +3 -3
- package/dist/bigconsole/pages/DataSinkViewPage.js +18 -18
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/index.js +3 -3
- package/package.json +1 -1
|
@@ -7,10 +7,10 @@ import { BigConsoleRoutes as o } from "./BigConsoleRoutes.js";
|
|
|
7
7
|
import { BigConsoleProvider as s } from "./context/BigConsoleContext.js";
|
|
8
8
|
import "./context/index.js";
|
|
9
9
|
import { BigConsoleQuotaProvider as c } from "./providers/BigConsoleQuotaProvider.js";
|
|
10
|
-
import l from "./
|
|
11
|
-
import u from "./components/
|
|
12
|
-
import d from "./
|
|
13
|
-
import f from "./components/
|
|
10
|
+
import l from "./hooks/useFilterUrlSync.js";
|
|
11
|
+
import u from "./components/DrilldownDashboardRenderer.js";
|
|
12
|
+
import d from "./components/preview/AiPreviewPanel.js";
|
|
13
|
+
import f from "./components/DrilldownModal.js";
|
|
14
14
|
import { useCallback as p, useEffect as m, useLayoutEffect as h, useRef as g, useState as _ } from "react";
|
|
15
15
|
import { useSearchParams as v } from "react-router-dom";
|
|
16
16
|
import { ErrorBoundary as y } from "@burdenoff/fe-libs/shared/components";
|
|
@@ -157,7 +157,7 @@ var F = i, I = r, L = a, R = /* @__PURE__ */ new Set(), z = (r) => {
|
|
|
157
157
|
r.productName
|
|
158
158
|
]);
|
|
159
159
|
let [X, Z] = v(), Q = e((e) => e.isOpen), $ = e((e) => e.closeModal);
|
|
160
|
-
|
|
160
|
+
l();
|
|
161
161
|
let te = p(() => {
|
|
162
162
|
$();
|
|
163
163
|
let e = new URLSearchParams(X);
|
|
@@ -174,7 +174,7 @@ var F = i, I = r, L = a, R = /* @__PURE__ */ new Set(), z = (r) => {
|
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
176
|
window.location.assign("/billing");
|
|
177
|
-
}, [B]), re = p((e, t) => /* @__PURE__ */ E(
|
|
177
|
+
}, [B]), re = p((e, t) => /* @__PURE__ */ E(u, {
|
|
178
178
|
dashboardId: e,
|
|
179
179
|
params: t
|
|
180
180
|
}), []);
|
|
@@ -194,9 +194,9 @@ var F = i, I = r, L = a, R = /* @__PURE__ */ new Set(), z = (r) => {
|
|
|
194
194
|
children: /* @__PURE__ */ E(n, {
|
|
195
195
|
basePath: z,
|
|
196
196
|
children: /* @__PURE__ */ D(t, { children: [
|
|
197
|
-
/* @__PURE__ */ E(
|
|
197
|
+
/* @__PURE__ */ E(d, {}),
|
|
198
198
|
/* @__PURE__ */ E(o, { ...r }),
|
|
199
|
-
Q && /* @__PURE__ */ E(
|
|
199
|
+
Q && /* @__PURE__ */ E(f, {
|
|
200
200
|
onClose: te,
|
|
201
201
|
renderDashboard: re
|
|
202
202
|
})
|
|
@@ -5,9 +5,9 @@ import { CrossFilterProvider as n } from "../../contexts/CrossFilterContext.js";
|
|
|
5
5
|
import "../../contexts/index.js";
|
|
6
6
|
import { useBigConsole as r } from "../../context/BigConsoleContext.js";
|
|
7
7
|
import "../../context/index.js";
|
|
8
|
-
import i from "
|
|
9
|
-
import
|
|
10
|
-
import o from "../../hooks/
|
|
8
|
+
import { getWidgetDefinition as i } from "../widgets/WidgetRegistry.js";
|
|
9
|
+
import a from "../../hooks/useWidgetCatalog.js";
|
|
10
|
+
import o from "../../hooks/useWidgetOperations.js";
|
|
11
11
|
import s from "../../hooks/useDashboardImageExport.js";
|
|
12
12
|
import { useInstalledWidgets as c } from "../../hooks/useInstalledWidgets.js";
|
|
13
13
|
import l from "./DashboardGrid.js";
|
|
@@ -32,14 +32,14 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
32
32
|
apiGatewayUrl: P,
|
|
33
33
|
authToken: F,
|
|
34
34
|
enabled: M
|
|
35
|
-
}), { definitions: Ee } =
|
|
35
|
+
}), { definitions: Ee } = a({
|
|
36
36
|
workspaceId: N,
|
|
37
37
|
apiGatewayUrl: P,
|
|
38
38
|
authToken: F,
|
|
39
39
|
enabled: M
|
|
40
40
|
}), I = t((e) => e.zoomLevel), L = t((e) => e.sidebarCollapsed), R = t((e) => e.toggleSidebar), z = !L, B = t((e) => e.setGlobalFilterValues), De = p((e) => {
|
|
41
41
|
B(e);
|
|
42
|
-
}, [B]), { createWidget: V } =
|
|
42
|
+
}, [B]), { createWidget: V } = o(v, f, { skipFetch: !0 }), H = e((e) => e.widgets), U = ce(() => {
|
|
43
43
|
let e = Array.from(H.values());
|
|
44
44
|
return v ? e.filter((e) => e.pageId === v) : e;
|
|
45
45
|
}, [H, v]), Oe = e((e) => e.selectedWidgetId), W = e((e) => e.selectWidget), G = e((e) => e.addWidget), K = e((e) => e.updateWidgetPosition), q = e((e) => e.configPanelOpen), ke = e((e) => e.closeConfigPanel);
|
|
@@ -68,14 +68,14 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
68
68
|
W(e);
|
|
69
69
|
}, [W]), Y = p(async (e, t) => {
|
|
70
70
|
D(null);
|
|
71
|
-
let n = t?.definition || (e.type ?
|
|
71
|
+
let n = t?.definition || (e.type ? i(e.type) : null), r = {
|
|
72
72
|
width: n?.defaultSize?.width ?? 4,
|
|
73
73
|
height: n?.defaultSize?.height ?? 4
|
|
74
|
-
},
|
|
75
|
-
if (t?.position)
|
|
74
|
+
}, a;
|
|
75
|
+
if (t?.position) a = t.position;
|
|
76
76
|
else {
|
|
77
77
|
let { x: e, y: t } = oe(U, r, { cols: 12 });
|
|
78
|
-
|
|
78
|
+
a = {
|
|
79
79
|
x: e,
|
|
80
80
|
y: t,
|
|
81
81
|
width: r.width,
|
|
@@ -93,7 +93,7 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
93
93
|
renderer: e.renderer,
|
|
94
94
|
template: e.template,
|
|
95
95
|
config: e.config || {},
|
|
96
|
-
position:
|
|
96
|
+
position: a,
|
|
97
97
|
refreshInterval: e.refreshInterval ?? void 0,
|
|
98
98
|
dataSinkId: o.dataSinkId,
|
|
99
99
|
parserId: o.parserId
|
|
@@ -116,11 +116,11 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
116
116
|
template: e.template,
|
|
117
117
|
refreshInterval: e.refreshInterval,
|
|
118
118
|
config: e.config || {},
|
|
119
|
-
position:
|
|
120
|
-
positionX:
|
|
121
|
-
positionY:
|
|
122
|
-
positionWidth:
|
|
123
|
-
positionHeight:
|
|
119
|
+
position: a,
|
|
120
|
+
positionX: a.x,
|
|
121
|
+
positionY: a.y,
|
|
122
|
+
positionWidth: a.width,
|
|
123
|
+
positionHeight: a.height,
|
|
124
124
|
dataSinkId: o.dataSinkId,
|
|
125
125
|
parserId: o.parserId,
|
|
126
126
|
translations: [],
|
|
@@ -146,19 +146,19 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
146
146
|
if (!t) return;
|
|
147
147
|
let n = JSON.parse(t);
|
|
148
148
|
if (!n || typeof n != "object" || !("type" in n)) return;
|
|
149
|
-
let r = n,
|
|
149
|
+
let r = n, a = i(r.type), o = null;
|
|
150
150
|
r.defaultConfig && r.category && (o = {
|
|
151
|
-
...
|
|
152
|
-
name: r.name ||
|
|
151
|
+
...a,
|
|
152
|
+
name: r.name || a.name,
|
|
153
153
|
category: r.category,
|
|
154
154
|
defaultConfig: r.defaultConfig,
|
|
155
|
-
defaultSize: r.defaultSize ||
|
|
155
|
+
defaultSize: r.defaultSize || a.defaultSize
|
|
156
156
|
});
|
|
157
157
|
let s = S.current?.getBoundingClientRect();
|
|
158
158
|
if (!s) return;
|
|
159
159
|
let c = {
|
|
160
|
-
width:
|
|
161
|
-
height:
|
|
160
|
+
width: a.defaultSize.width,
|
|
161
|
+
height: a.defaultSize.height
|
|
162
162
|
}, { x: l, y: u } = ae(e.clientX, e.clientY, s, w, c, { cols: 12 }), d = {
|
|
163
163
|
x: l,
|
|
164
164
|
y: u,
|
|
@@ -167,8 +167,8 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
167
167
|
};
|
|
168
168
|
Y({
|
|
169
169
|
type: r.type,
|
|
170
|
-
title: r.name ||
|
|
171
|
-
config: r.defaultConfig ||
|
|
170
|
+
title: r.name || a.name,
|
|
171
|
+
config: r.defaultConfig || a.defaultConfig
|
|
172
172
|
}, {
|
|
173
173
|
position: d,
|
|
174
174
|
definition: o
|
|
@@ -179,7 +179,7 @@ var v = f(function({ dashboardId: f, pageId: v, title: y, onPaste: le, onSave: u
|
|
|
179
179
|
}, [w, Y]), Pe = p((e) => {
|
|
180
180
|
e.preventDefault(), e.dataTransfer.dropEffect = "copy";
|
|
181
181
|
}, []), Fe = p((e, t) => {
|
|
182
|
-
let n = t ||
|
|
182
|
+
let n = t || i(e);
|
|
183
183
|
Y({
|
|
184
184
|
type: e,
|
|
185
185
|
title: n.name,
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import e from "../datasink/DataSinkTableViewer.js";
|
|
2
|
+
import t from "../../hooks/useWidgetOperations.js";
|
|
3
|
+
import n from "../../hooks/useDataSinkOperations.js";
|
|
4
|
+
import r from "../../hooks/useParserOperations.js";
|
|
5
|
+
import i from "../widgets/WidgetWrapper.js";
|
|
6
|
+
import a from "../DrilldownDashboardRenderer.js";
|
|
7
|
+
import { useEffect as o, useRef as s, useState as c } from "react";
|
|
8
|
+
import { Spinner as l } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
10
|
+
//#region src/bigconsole/components/preview/AiPreviewContent.tsx
|
|
11
|
+
var f = 4e3, p = 6e4;
|
|
12
|
+
function m({ label: e }) {
|
|
13
|
+
return /* @__PURE__ */ d("div", {
|
|
14
|
+
className: "flex items-center gap-2 px-1 py-8 text-sm text-text-muted",
|
|
15
|
+
children: [/* @__PURE__ */ u(l, { className: "size-4" }), e]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function h({ text: e }) {
|
|
19
|
+
return /* @__PURE__ */ u("p", {
|
|
20
|
+
className: "px-1 py-8 text-sm text-text-muted",
|
|
21
|
+
children: e
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function g(e, t, n) {
|
|
25
|
+
let [r, i] = c(null), [a, l] = c(!0), u = s(e);
|
|
26
|
+
return u.current = e, o(() => {
|
|
27
|
+
if (!t) {
|
|
28
|
+
l(!1);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let e = !1, r = Date.now(), a = async () => {
|
|
32
|
+
let t = await u.current();
|
|
33
|
+
e || (t != null && i(t), l(!1));
|
|
34
|
+
};
|
|
35
|
+
a();
|
|
36
|
+
let o = window.setInterval(() => {
|
|
37
|
+
!n || Date.now() - r > p || typeof document < "u" && document.visibilityState !== "visible" || a();
|
|
38
|
+
}, f);
|
|
39
|
+
return () => {
|
|
40
|
+
e = !0, window.clearInterval(o);
|
|
41
|
+
};
|
|
42
|
+
}, [t, n]), {
|
|
43
|
+
data: r,
|
|
44
|
+
loading: a
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function _({ id: t, live: r }) {
|
|
48
|
+
let { getDataSinkData: i } = n({ skipFetch: !0 }), { data: a, loading: o } = g(async () => {
|
|
49
|
+
let e = await i({ id: t }, { limit: 50 });
|
|
50
|
+
return e ? e.raw : null;
|
|
51
|
+
}, t, r);
|
|
52
|
+
return t ? o ? /* @__PURE__ */ u(m, { label: "Loading the data sink’s data…" }) : /* @__PURE__ */ u("div", {
|
|
53
|
+
"data-testid": "ai-preview-content-datasink",
|
|
54
|
+
children: /* @__PURE__ */ u(e, {
|
|
55
|
+
data: a,
|
|
56
|
+
maxHeight: "300px"
|
|
57
|
+
})
|
|
58
|
+
}) : /* @__PURE__ */ u(h, { text: "Waiting for the data sink to be created…" });
|
|
59
|
+
}
|
|
60
|
+
function v({ dashboardId: e }) {
|
|
61
|
+
return e ? /* @__PURE__ */ u("div", {
|
|
62
|
+
"data-testid": "ai-preview-content-dashboard",
|
|
63
|
+
className: "max-h-[340px] overflow-y-auto",
|
|
64
|
+
children: /* @__PURE__ */ u(a, {
|
|
65
|
+
dashboardId: e,
|
|
66
|
+
params: {}
|
|
67
|
+
})
|
|
68
|
+
}) : /* @__PURE__ */ u(h, { text: "Waiting for the dashboard to be created…" });
|
|
69
|
+
}
|
|
70
|
+
function y({ parserId: t, live: n }) {
|
|
71
|
+
let { executeParser: i } = r({ skipFetch: !0 }), { data: a, loading: o } = g(async () => {
|
|
72
|
+
let e = await i(t ?? "");
|
|
73
|
+
return e ? e.output : null;
|
|
74
|
+
}, t, n);
|
|
75
|
+
return t ? o ? /* @__PURE__ */ u(m, { label: "Running the parser…" }) : /* @__PURE__ */ d("div", {
|
|
76
|
+
"data-testid": "ai-preview-content-parser",
|
|
77
|
+
children: [/* @__PURE__ */ u("p", {
|
|
78
|
+
className: "mb-2 px-1 text-xs text-text-muted",
|
|
79
|
+
children: "Parser output (transformed rows):"
|
|
80
|
+
}), /* @__PURE__ */ u(e, {
|
|
81
|
+
data: a,
|
|
82
|
+
maxHeight: "280px"
|
|
83
|
+
})]
|
|
84
|
+
}) : /* @__PURE__ */ u(h, { text: "No parser in this build — the rows were already shaped." });
|
|
85
|
+
}
|
|
86
|
+
function b(e) {
|
|
87
|
+
let t = e.toUpperCase();
|
|
88
|
+
return t.includes("METRIC") || t.includes("KPI") || t.includes("CARD") || t.includes("STAT") ? 160 : t.includes("TABLE") || t.includes("LIST") ? 280 : 320;
|
|
89
|
+
}
|
|
90
|
+
function x({ dashboardId: e, live: n }) {
|
|
91
|
+
let { widgets: r, loading: a, refetch: c } = t(void 0, e, { skipFetch: !e }), l = s(c);
|
|
92
|
+
return l.current = c, o(() => {
|
|
93
|
+
if (!e) return;
|
|
94
|
+
let t = Date.now(), r = window.setInterval(() => {
|
|
95
|
+
!n || Date.now() - t > p || typeof document < "u" && document.visibilityState !== "visible" || l.current();
|
|
96
|
+
}, f);
|
|
97
|
+
return () => window.clearInterval(r);
|
|
98
|
+
}, [e, n]), e ? a && r.length === 0 ? /* @__PURE__ */ u(m, { label: "Loading widgets…" }) : r.length === 0 ? /* @__PURE__ */ u(h, { text: "No widgets on this dashboard yet." }) : /* @__PURE__ */ u("div", {
|
|
99
|
+
"data-testid": "ai-preview-content-widget",
|
|
100
|
+
className: "space-y-3",
|
|
101
|
+
children: r.map((e) => /* @__PURE__ */ u("div", {
|
|
102
|
+
className: "overflow-hidden rounded-md border border-border-subtle bg-bg-surface",
|
|
103
|
+
style: { height: b(e.type) },
|
|
104
|
+
children: /* @__PURE__ */ u(i, {
|
|
105
|
+
widget: e,
|
|
106
|
+
isLoading: !1,
|
|
107
|
+
error: null,
|
|
108
|
+
filterValues: {}
|
|
109
|
+
})
|
|
110
|
+
}, e.id))
|
|
111
|
+
}) : /* @__PURE__ */ u(h, { text: "Waiting for the dashboard — widgets live on it." });
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { v as DashboardContent, _ as DataSinkContent, y as ParserContent, x as WidgetsContent };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=AiPreviewContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AiPreviewContent.js","names":[],"sources":["../../../../src/bigconsole/components/preview/AiPreviewContent.tsx"],"sourcesContent":["/**\n * Live content renderers for the AI preview tabs.\n *\n * Each tab shows the REAL content of the entity the assistant just built —\n * the data sink's rows, the live dashboard, the parser's transformed output,\n * the rendered widget charts — not a list with an Open button. They reuse the\n * same components the real pages use (DataSinkTableViewer, DrilldownDashboard-\n * Renderer, WidgetWrapper) so what you see in the preview is what you get.\n *\n * These require Apollo + the BigConsole providers, which is why they live only\n * in the full AiPreviewPanel (mounted inside BigConsoleRoot), never in the\n * store-only app-shell mini panel.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\n\nimport { DataSinkTableViewer } from '../datasink/DataSinkTableViewer';\nimport { DrilldownDashboardRenderer } from '../DrilldownDashboardRenderer';\nimport { WidgetWrapper } from '../widgets/WidgetWrapper';\nimport { useDataSinkOperations } from '../../hooks/useDataSinkOperations';\nimport { useParserOperations } from '../../hooks/useParserOperations';\nimport { useWidgetOperations } from '../../hooks/useWidgetOperations';\n\n/** While the build is live, re-pull content on this cadence so it fills in. */\nconst CONTENT_POLL_MS = 4000;\n/** Stop the live re-pull after this long even if the turn is still running. */\nconst CONTENT_POLL_WINDOW_MS = 60_000;\n\nfunction CenteredSpinner({ label }: { label: string }) {\n return (\n <div className=\"flex items-center gap-2 px-1 py-8 text-sm text-text-muted\">\n <Spinner className=\"size-4\" />\n {label}\n </div>\n );\n}\n\nfunction Waiting({ text }: { text: string }) {\n return <p className=\"px-1 py-8 text-sm text-text-muted\">{text}</p>;\n}\n\n/**\n * Fetch-on-mount, then re-fetch every CONTENT_POLL_MS while `live`, bounded to\n * CONTENT_POLL_WINDOW_MS. Returns { data, loading, done }. `fetcher` must be\n * stable-ish; we hold it in a ref so the effect keys only on `key`/`live`.\n */\nfunction useLiveContent<T>(fetcher: () => Promise<T | null>, key: string | undefined, live: boolean) {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(true);\n const fetcherRef = useRef(fetcher);\n fetcherRef.current = fetcher;\n\n useEffect(() => {\n if (!key) {\n setLoading(false);\n return;\n }\n let cancelled = false;\n const startedAt = Date.now();\n const pull = async () => {\n const result = await fetcherRef.current();\n if (cancelled) return;\n if (result !== null && result !== undefined) setData(result);\n setLoading(false);\n };\n void pull();\n const intervalId = window.setInterval(() => {\n if (!live || Date.now() - startedAt > CONTENT_POLL_WINDOW_MS) return;\n if (typeof document !== 'undefined' && document.visibilityState !== 'visible') return;\n void pull();\n }, CONTENT_POLL_MS);\n return () => {\n cancelled = true;\n window.clearInterval(intervalId);\n };\n }, [key, live]);\n\n return { data, loading };\n}\n\nexport function DataSinkContent({ id, live }: { id?: string; live: boolean }) {\n const { getDataSinkData } = useDataSinkOperations({ skipFetch: true });\n const { data, loading } = useLiveContent(\n async () => {\n const res = await getDataSinkData({ id }, { limit: 50 });\n return res ? res.raw : null;\n },\n id,\n live\n );\n\n if (!id) return <Waiting text=\"Waiting for the data sink to be created…\" />;\n if (loading) return <CenteredSpinner label=\"Loading the data sink’s data…\" />;\n return (\n <div data-testid=\"ai-preview-content-datasink\">\n <DataSinkTableViewer data={data} maxHeight=\"300px\" />\n </div>\n );\n}\n\nexport function DashboardContent({ dashboardId }: { dashboardId?: string }) {\n if (!dashboardId) return <Waiting text=\"Waiting for the dashboard to be created…\" />;\n return (\n <div data-testid=\"ai-preview-content-dashboard\" className=\"max-h-[340px] overflow-y-auto\">\n <DrilldownDashboardRenderer dashboardId={dashboardId} params={{}} />\n </div>\n );\n}\n\nexport function ParserContent({ parserId, live }: { parserId?: string; live: boolean }) {\n const { executeParser } = useParserOperations({ skipFetch: true });\n const { data, loading } = useLiveContent(\n async () => {\n const res = await executeParser(parserId ?? '');\n return res ? res.output : null;\n },\n parserId,\n live\n );\n\n if (!parserId) return <Waiting text=\"No parser in this build — the rows were already shaped.\" />;\n if (loading) return <CenteredSpinner label=\"Running the parser…\" />;\n return (\n <div data-testid=\"ai-preview-content-parser\">\n <p className=\"mb-2 px-1 text-xs text-text-muted\">Parser output (transformed rows):</p>\n <DataSinkTableViewer data={data} maxHeight=\"280px\" />\n </div>\n );\n}\n\n/** Recharts needs a definite pixel height or it renders 0px tall. */\nfunction widgetBoxHeight(type: string): number {\n const t = type.toUpperCase();\n if (t.includes('METRIC') || t.includes('KPI') || t.includes('CARD') || t.includes('STAT')) return 160;\n if (t.includes('TABLE') || t.includes('LIST')) return 280;\n return 320;\n}\n\nexport function WidgetsContent({ dashboardId, live }: { dashboardId?: string; live: boolean }) {\n const { widgets, loading, refetch } = useWidgetOperations(undefined, dashboardId, {\n skipFetch: !dashboardId,\n });\n\n const refetchRef = useRef(refetch);\n refetchRef.current = refetch;\n useEffect(() => {\n if (!dashboardId) return;\n const startedAt = Date.now();\n const intervalId = window.setInterval(() => {\n if (!live || Date.now() - startedAt > CONTENT_POLL_WINDOW_MS) return;\n if (typeof document !== 'undefined' && document.visibilityState !== 'visible') return;\n void refetchRef.current();\n }, CONTENT_POLL_MS);\n return () => window.clearInterval(intervalId);\n }, [dashboardId, live]);\n\n if (!dashboardId) return <Waiting text=\"Waiting for the dashboard — widgets live on it.\" />;\n if (loading && widgets.length === 0) return <CenteredSpinner label=\"Loading widgets…\" />;\n if (widgets.length === 0) return <Waiting text=\"No widgets on this dashboard yet.\" />;\n\n return (\n <div data-testid=\"ai-preview-content-widget\" className=\"space-y-3\">\n {widgets.map((widget) => (\n <div\n key={widget.id}\n className=\"overflow-hidden rounded-md border border-border-subtle bg-bg-surface\"\n style={{ height: widgetBoxHeight(widget.type) }}\n >\n <WidgetWrapper widget={widget} isLoading={false} error={null} filterValues={{}} />\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,89 +1,45 @@
|
|
|
1
1
|
import { useBigConsoleNavigate as e } from "../../context/BigConsoleContext.js";
|
|
2
2
|
import "../../context/index.js";
|
|
3
3
|
import { PREVIEW_STEPS as t, useAssistantRunStore as n } from "../../assistant/assistantRunStore.js";
|
|
4
|
-
import r from "
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import { useEffect as l, useMemo as u, useRef as d, useState as f } from "react";
|
|
10
|
-
import { Loader2 as p, Sparkles as m, X as h } from "lucide-react";
|
|
11
|
-
import { Badge as g, Button as _, Tabs as ne, TabsContent as v, TabsList as y, TabsTrigger as b } from "@burdenoff/fe-libs/ui";
|
|
4
|
+
import { StepRail as r, formatAgo as i, useAssistantSidebarWidth as a } from "./previewShared.js";
|
|
5
|
+
import { DashboardContent as o, DataSinkContent as s, ParserContent as c, WidgetsContent as l } from "./AiPreviewContent.js";
|
|
6
|
+
import { useEffect as u, useState as d } from "react";
|
|
7
|
+
import { ArrowUpRight as f, Loader2 as p, Sparkles as m, X as h } from "lucide-react";
|
|
8
|
+
import { Button as g, Tabs as _, TabsContent as v, TabsList as y, TabsTrigger as b } from "@burdenoff/fe-libs/ui";
|
|
12
9
|
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
13
10
|
//#region src/bigconsole/components/preview/AiPreviewPanel.tsx
|
|
14
|
-
|
|
15
|
-
function E({ id: e, title: t, meta: n, isNew: r, onOpen: i }) {
|
|
11
|
+
function C({ label: e, onOpen: t }) {
|
|
16
12
|
return /* @__PURE__ */ S("div", {
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}) : null]
|
|
29
|
-
}), /* @__PURE__ */ S("div", {
|
|
30
|
-
className: "flex shrink-0 items-center gap-2",
|
|
31
|
-
children: [r ? /* @__PURE__ */ S(g, {
|
|
32
|
-
className: "bg-status-success-bg text-status-success-text",
|
|
33
|
-
children: [/* @__PURE__ */ x(m, { className: "mr-1 size-3" }), "just built"]
|
|
34
|
-
}) : null, i ? /* @__PURE__ */ x(_, {
|
|
35
|
-
size: "sm",
|
|
36
|
-
variant: "ghost",
|
|
37
|
-
onClick: i,
|
|
38
|
-
children: "Open"
|
|
39
|
-
}) : null]
|
|
40
|
-
})]
|
|
13
|
+
className: "mb-2 flex items-center justify-between gap-2",
|
|
14
|
+
children: [/* @__PURE__ */ x("span", {
|
|
15
|
+
className: "text-xs font-semibold uppercase tracking-wide text-text-muted",
|
|
16
|
+
children: e
|
|
17
|
+
}), t ? /* @__PURE__ */ S(g, {
|
|
18
|
+
size: "sm",
|
|
19
|
+
variant: "outline",
|
|
20
|
+
onClick: t,
|
|
21
|
+
"data-testid": "ai-preview-open-entity",
|
|
22
|
+
children: ["Open", /* @__PURE__ */ x(f, { className: "ml-1 size-3.5" })]
|
|
23
|
+
}) : null]
|
|
41
24
|
});
|
|
42
25
|
}
|
|
43
|
-
function
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
let [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
dashboards: W.refetch,
|
|
58
|
-
parsers: G.refetch,
|
|
59
|
-
widgets: K.refetch
|
|
60
|
-
}, l(() => {
|
|
61
|
-
if (!k) return;
|
|
62
|
-
let e = Infinity;
|
|
63
|
-
D || (e = Date.now() + w);
|
|
64
|
-
let t = () => {
|
|
65
|
-
typeof document < "u" && document.visibilityState !== "visible" || Date.now() > e || (q.current.sinks(), q.current.dashboards(), H && (q.current.parsers(), q.current.widgets()), V(Date.now()));
|
|
66
|
-
};
|
|
67
|
-
t();
|
|
68
|
-
let n = window.setInterval(t, C), r = () => {
|
|
69
|
-
document.visibilityState === "visible" && t();
|
|
70
|
-
};
|
|
71
|
-
return document.addEventListener("visibilitychange", r), () => {
|
|
72
|
-
window.clearInterval(n), document.removeEventListener("visibilitychange", r);
|
|
73
|
-
};
|
|
74
|
-
}, [
|
|
75
|
-
k,
|
|
76
|
-
D,
|
|
77
|
-
H
|
|
78
|
-
]), l(() => {
|
|
79
|
-
let e = t.find((e) => A[e] === "running");
|
|
80
|
-
e && z(e);
|
|
81
|
-
}, [A]);
|
|
82
|
-
let J = P ? Math.max(0, Math.floor((B - P) / 1e3)) : 0, Y = te(), X = u(() => U.dataSinks.slice(0, 25), [U.dataSinks]), Z = u(() => W.dashboards.slice(0, 25), [W.dashboards]), Q = u(() => G.parsers.slice(0, 25), [G.parsers]), $ = u(() => K.widgets.slice(0, 25), [K.widgets]);
|
|
83
|
-
return k ? O ? /* @__PURE__ */ S("section", {
|
|
26
|
+
function w() {
|
|
27
|
+
let f = e(), w = n((e) => e.isRunning), T = n((e) => e.previewOpen), E = n((e) => e.hasRun), D = n((e) => e.steps), O = n((e) => e.entityIds), k = n((e) => e.caption), A = n((e) => e.error), j = n((e) => e.updatedAt), M = n((e) => e.openPreview), N = n((e) => e.closePreview), P = n((e) => e.setRichMounted);
|
|
28
|
+
u(() => (P(!0), () => P(!1)), [P]);
|
|
29
|
+
let [F, I] = d("datasink"), [L, R] = d(() => Date.now()), z = O.dashboard;
|
|
30
|
+
u(() => {
|
|
31
|
+
if (!w) return;
|
|
32
|
+
let e = window.setInterval(() => R(Date.now()), 1e3);
|
|
33
|
+
return () => window.clearInterval(e);
|
|
34
|
+
}, [w]), u(() => {
|
|
35
|
+
let e = t.find((e) => D[e] === "running");
|
|
36
|
+
e && I(e);
|
|
37
|
+
}, [D]);
|
|
38
|
+
let B = j ? Math.max(0, Math.floor((L - j) / 1e3)) : 0, V = a();
|
|
39
|
+
return E ? T ? /* @__PURE__ */ S("section", {
|
|
84
40
|
"data-testid": "ai-preview-panel",
|
|
85
41
|
"aria-label": "AI preview",
|
|
86
|
-
style: { marginRight:
|
|
42
|
+
style: { marginRight: V ? V + 16 : void 0 },
|
|
87
43
|
className: "mx-4 mt-3 overflow-hidden rounded-lg border border-border-default bg-bg-sunken shadow-sm md:mx-6",
|
|
88
44
|
children: [
|
|
89
45
|
/* @__PURE__ */ S("div", {
|
|
@@ -96,7 +52,7 @@ function D() {
|
|
|
96
52
|
className: "truncate text-sm font-semibold text-text-primary",
|
|
97
53
|
children: "AI Preview"
|
|
98
54
|
}),
|
|
99
|
-
|
|
55
|
+
w ? /* @__PURE__ */ S("span", {
|
|
100
56
|
className: "inline-flex items-center gap-1.5 rounded-full bg-status-success-bg px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-status-success-text",
|
|
101
57
|
"data-testid": "ai-preview-live",
|
|
102
58
|
children: [/* @__PURE__ */ S("span", {
|
|
@@ -108,17 +64,17 @@ function D() {
|
|
|
108
64
|
className: "truncate text-xs text-text-muted",
|
|
109
65
|
"data-testid": "ai-preview-ago",
|
|
110
66
|
children: [
|
|
111
|
-
|
|
67
|
+
w ? k || "Working…" : A ? "Stopped" : "Done",
|
|
112
68
|
" · updated",
|
|
113
69
|
" ",
|
|
114
|
-
|
|
70
|
+
i(B)
|
|
115
71
|
]
|
|
116
72
|
})
|
|
117
73
|
]
|
|
118
|
-
}), /* @__PURE__ */ x(
|
|
74
|
+
}), /* @__PURE__ */ x(g, {
|
|
119
75
|
size: "sm",
|
|
120
76
|
variant: "ghost",
|
|
121
|
-
onClick:
|
|
77
|
+
onClick: N,
|
|
122
78
|
"aria-label": "Close preview",
|
|
123
79
|
"data-testid": "ai-preview-close",
|
|
124
80
|
children: /* @__PURE__ */ x(h, { className: "size-4" })
|
|
@@ -126,126 +82,101 @@ function D() {
|
|
|
126
82
|
}),
|
|
127
83
|
/* @__PURE__ */ x("div", {
|
|
128
84
|
className: "border-b border-border-subtle px-3 py-2",
|
|
129
|
-
children: /* @__PURE__ */ x(
|
|
85
|
+
children: /* @__PURE__ */ x(r, { steps: D })
|
|
130
86
|
}),
|
|
131
|
-
/* @__PURE__ */ S(
|
|
132
|
-
value:
|
|
133
|
-
onValueChange: (e) =>
|
|
87
|
+
/* @__PURE__ */ S(_, {
|
|
88
|
+
value: F,
|
|
89
|
+
onValueChange: (e) => I(e),
|
|
134
90
|
children: [/* @__PURE__ */ S(y, {
|
|
135
91
|
className: "mx-3 mt-2",
|
|
136
92
|
children: [
|
|
137
93
|
/* @__PURE__ */ x(b, {
|
|
138
94
|
value: "datasink",
|
|
139
95
|
"data-testid": "ai-preview-tab-datasink",
|
|
140
|
-
children: "Data
|
|
96
|
+
children: "Data Sink"
|
|
141
97
|
}),
|
|
142
98
|
/* @__PURE__ */ x(b, {
|
|
143
99
|
value: "dashboard",
|
|
144
100
|
"data-testid": "ai-preview-tab-dashboard",
|
|
145
|
-
children: "
|
|
101
|
+
children: "Dashboard"
|
|
146
102
|
}),
|
|
147
103
|
/* @__PURE__ */ x(b, {
|
|
148
104
|
value: "parser",
|
|
149
105
|
"data-testid": "ai-preview-tab-parser",
|
|
150
|
-
children: "
|
|
106
|
+
children: "Parser"
|
|
151
107
|
}),
|
|
152
108
|
/* @__PURE__ */ x(b, {
|
|
153
109
|
value: "widget",
|
|
154
110
|
"data-testid": "ai-preview-tab-widget",
|
|
155
|
-
children: "
|
|
111
|
+
children: "Widget"
|
|
156
112
|
})
|
|
157
113
|
]
|
|
158
114
|
}), /* @__PURE__ */ S("div", {
|
|
159
|
-
className: "max-h-[
|
|
115
|
+
className: "max-h-[440px] overflow-y-auto p-3",
|
|
160
116
|
children: [
|
|
161
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ S(v, {
|
|
162
118
|
value: "datasink",
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
meta: e.status,
|
|
171
|
-
isNew: e.id === j.datasink,
|
|
172
|
-
onOpen: () => g(`/datasinks/${e.id}`)
|
|
173
|
-
}, e.id))
|
|
119
|
+
children: [/* @__PURE__ */ x(C, {
|
|
120
|
+
label: "Data Sink",
|
|
121
|
+
onOpen: O.datasink ? () => f(`/datasinks/${O.datasink}`) : void 0
|
|
122
|
+
}), /* @__PURE__ */ x(s, {
|
|
123
|
+
id: O.datasink,
|
|
124
|
+
live: w
|
|
125
|
+
})]
|
|
174
126
|
}),
|
|
175
|
-
/* @__PURE__ */
|
|
127
|
+
/* @__PURE__ */ S(v, {
|
|
176
128
|
value: "dashboard",
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}) : Z.map((e) => /* @__PURE__ */ x(E, {
|
|
182
|
-
id: e.id,
|
|
183
|
-
title: e.name,
|
|
184
|
-
meta: `${String(e.widgetCount ?? 0)} widget(s)`,
|
|
185
|
-
isNew: e.id === j.dashboard,
|
|
186
|
-
onOpen: () => g(`/dashboards/${e.id}`)
|
|
187
|
-
}, e.id))
|
|
129
|
+
children: [/* @__PURE__ */ x(C, {
|
|
130
|
+
label: "Dashboard",
|
|
131
|
+
onOpen: O.dashboard ? () => f(`/dashboards/${O.dashboard}`) : void 0
|
|
132
|
+
}), /* @__PURE__ */ x(o, { dashboardId: O.dashboard })]
|
|
188
133
|
}),
|
|
189
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ S(v, {
|
|
190
135
|
value: "parser",
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
meta: `${e.type} · ${e.status}`,
|
|
199
|
-
isNew: e.id === j.parser,
|
|
200
|
-
onOpen: () => g(`/parsers/${e.id}`)
|
|
201
|
-
}, e.id)) : /* @__PURE__ */ x("p", {
|
|
202
|
-
className: "px-1 py-6 text-sm text-text-muted",
|
|
203
|
-
children: "Parsers are listed per dashboard — waiting for the dashboard to be created."
|
|
204
|
-
})
|
|
136
|
+
children: [/* @__PURE__ */ x(C, {
|
|
137
|
+
label: "Parser",
|
|
138
|
+
onOpen: O.parser ? () => f(`/parsers/${O.parser}`) : void 0
|
|
139
|
+
}), /* @__PURE__ */ x(c, {
|
|
140
|
+
parserId: O.parser,
|
|
141
|
+
live: w
|
|
142
|
+
})]
|
|
205
143
|
}),
|
|
206
|
-
/* @__PURE__ */
|
|
144
|
+
/* @__PURE__ */ S(v, {
|
|
207
145
|
value: "widget",
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
meta: e.type,
|
|
216
|
-
isNew: e.id === $[$.length - 1]?.id && A.widget === "done",
|
|
217
|
-
onOpen: () => g(`/dashboards/${H}`)
|
|
218
|
-
}, e.id)) : /* @__PURE__ */ x("p", {
|
|
219
|
-
className: "px-1 py-6 text-sm text-text-muted",
|
|
220
|
-
children: "Widgets live on a dashboard — waiting for the dashboard to be created."
|
|
221
|
-
})
|
|
146
|
+
children: [/* @__PURE__ */ x(C, {
|
|
147
|
+
label: "Widget",
|
|
148
|
+
onOpen: z ? () => f(`/dashboards/${z}`) : void 0
|
|
149
|
+
}), /* @__PURE__ */ x(l, {
|
|
150
|
+
dashboardId: z,
|
|
151
|
+
live: w
|
|
152
|
+
})]
|
|
222
153
|
})
|
|
223
154
|
]
|
|
224
155
|
})]
|
|
225
156
|
}),
|
|
226
|
-
|
|
157
|
+
A ? /* @__PURE__ */ x("p", {
|
|
227
158
|
className: "border-t border-border-subtle px-3 py-2 text-xs text-status-error-text",
|
|
228
159
|
"data-testid": "ai-preview-error",
|
|
229
|
-
children:
|
|
160
|
+
children: A
|
|
230
161
|
}) : null
|
|
231
162
|
]
|
|
232
163
|
}) : /* @__PURE__ */ x("div", {
|
|
233
164
|
className: "flex justify-end px-4 pt-3 md:px-6",
|
|
234
|
-
style: { marginRight:
|
|
235
|
-
children: /* @__PURE__ */ S(
|
|
165
|
+
style: { marginRight: V },
|
|
166
|
+
children: /* @__PURE__ */ S(g, {
|
|
236
167
|
size: "sm",
|
|
237
168
|
variant: "outline",
|
|
238
|
-
onClick:
|
|
169
|
+
onClick: M,
|
|
239
170
|
"data-testid": "ai-preview-open",
|
|
240
171
|
children: [
|
|
241
172
|
/* @__PURE__ */ x(m, { className: "mr-1.5 size-4" }),
|
|
242
173
|
"Preview",
|
|
243
|
-
|
|
174
|
+
w ? /* @__PURE__ */ x(p, { className: "ml-1.5 size-3.5 animate-spin" }) : null
|
|
244
175
|
]
|
|
245
176
|
})
|
|
246
177
|
}) : null;
|
|
247
178
|
}
|
|
248
179
|
//#endregion
|
|
249
|
-
export {
|
|
180
|
+
export { w as default };
|
|
250
181
|
|
|
251
182
|
//# sourceMappingURL=AiPreviewPanel.js.map
|