@bitcobblers/wod-wiki-ui 0.11.43 → 0.35.2116
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/{chunk-PZXX6GBK.mjs → chunk-GUN6PZNI.mjs} +3570 -1598
- package/dist/chunk-GUN6PZNI.mjs.map +1 -0
- package/dist/extensions/index.cjs +3486 -1536
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +2 -2
- package/dist/extensions/index.d.ts +2 -2
- package/dist/extensions/index.mjs +1 -1
- package/dist/{index-CTQ7Hrsa.d.cts → index-DMTXLSJ0.d.cts} +61 -7
- package/dist/{index-CTQ7Hrsa.d.ts → index-DMTXLSJ0.d.ts} +61 -7
- package/dist/index.cjs +3944 -1662
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +426 -127
- package/dist/index.d.ts +426 -127
- package/dist/index.mjs +353 -78
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +46 -1
- package/package.json +4 -4
- package/dist/chunk-PZXX6GBK.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { cn, WidgetProblemBadge, WidgetChart } from './chunk-
|
|
2
|
-
export { AGG_OPTIONS,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { defaultTokenValues, substituteTokens, parseQuery, isDashboardWidgetType, unknownWidgetTypeMessage, unknownTokensMessage, isFindQuery,
|
|
1
|
+
import { cn, WidgetProblemBadge, WidgetChart, toChartResult } from './chunk-GUN6PZNI.mjs';
|
|
2
|
+
export { AGG_OPTIONS, CANONICAL_BLOCK_TYPES, CLAUSE_META, CONTENT_GROUPING_DIMENSIONS, ComposerRegistry, DEFAULT_DIAGNOSTICS_DEBOUNCE_MS, DEFAULT_OUTPUT_FILTERS, DEFAULT_PRIMARY_FILTER, DefaultFrontmatterWidget, EditorDialog, GROUPBY_OPTIONS, GoalRings, KIND_OPTIONS, METRIC_OPTIONS, MULTI_VALUE_TYPES, MetricBadge, OUTPUT_TYPE_CLASS, OUTPUT_TYPE_DOT, OutputFilterPills, OutputStatementsTable, PLANE_OPTIONS, ProposedMetricBadge, QueryBlockView, QueryValue, ROLLUP_OPTIONS, RowsResultsChrome, RowsTable, SERIES_COLORS, SOURCE_OPTIONS, SUGGESTION_BINDINGS, StackedBar, TARGET_OPTIONS, TIME_OPTIONS, TONE_CLASS, TokenSlotPill, TopList, UNIT_OPTIONS, WHERE_AGGREGATORS, WHERE_METRICS, WidgetChart, WidgetProblemBadge, WqlBars, WqlComposer, WqlDiagnosticsStrip, WqlEmptyState, WqlQueryInspectorModal, WqlTable, WqlTimeseries, ZoneDistribution, activeCursorSection, addRuntimePanel, blockContentId, blockTypesFromBlocks, canonicalSuggestionItems, catalogIdsFromBlocks, cn, compactNumber, composerRegistry, configureOverlayActions, cursorFocusExtension, dateRangeSlot, dispatchAddRuntimePanel, dispatchExpandRuntimePanel, dispatchGutterHighlights, dispatchRemoveRuntimePanel, editQueryClause, editingWidgetsField, editorPreset, editorTheme, embedPreviewDecorations, expandRuntimePanel, extractBlockQueries, extractMetricsByCategory, fenceCompletion, findQueryBlockSection, findWorkoutErrors, forceSectionParse, formatClockTime, formatMMSS, formatTimestamp, frontmatterPreview, frontmatterPreviewField, frontmatterSuggestions, frontmatterVisibility, getClauseMeta, getCursorFocusState, getOverlayActions, getSuggestionBinding, gutterHighlightsField, gutterUnified, handleFenceAutoWrap, hashCode, inlineButtonDecoration, invalidateSuggestions, lineIdsExtension, linkOpen, linkPreview, loadSuggestions, markdownSyntaxHiding, markdownTablePreview, matchFilterTypeahead, mergeSeries, mergeSuggestionItems, mergeTagSuggestions, navigationFacet, normalizeOutputFilter, patchBlockQuery, presentBadges, previewDecorations, queryBlockPreview, readSessionRpe, registerCustomCompletionSource, removeRuntimePanel, resolveQueryDraft, runtimePanelField, saveBlockQuerySource, sectionAtPos, sectionField, sectionGeometry, sessionQueryInsert, sessionQueryWql, setGutterHighlights, setSuggestionBinding, smartIncrement, summarizeAggregate, summarizeFind, summarizePipeline, tagsFromStaticBlocks, toggleWidgetEdit, tooltipTimestamp, unregisterCustomCompletionSource, urlAtPos, useChartShape, useComposerSlots, useSuggestions, useVisualViewportRect, useWqlStageCounts, widgetBlockPreview, wodAutoWrap, wodAutocompletion, wodEditorKeymap, wodLinter, wodOverlayPanel, workoutLintSource, wqlToPills, wrapInTimeFence } from './chunk-GUN6PZNI.mjs';
|
|
3
|
+
import { Eye, ExternalLink, Edit3, ChevronUp, ChevronDown, ChevronRight, Copy, Trash2 } from 'lucide-react';
|
|
4
|
+
import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
5
|
+
import { useMemo, useState, useEffect, Fragment, useCallback } from 'react';
|
|
6
|
+
import { defaultTokenValues, substituteTokens, parseQuery, isDashboardWidgetType, unknownWidgetTypeMessage, unknownTokensMessage, resolveWidgetType, isFindQuery, isPipelineQuery, SharedQueryDocumentRunner } from '@bitcobblers/wod-wiki-wql';
|
|
7
7
|
|
|
8
8
|
// src/contracts/dedupe.ts
|
|
9
9
|
var CODEMIRROR_SINGLETON_DEPS = [
|
|
@@ -21,25 +21,119 @@ var CODEMIRROR_SINGLETON_DEPS = [
|
|
|
21
21
|
"@lezer/lr",
|
|
22
22
|
"@lezer/markdown"
|
|
23
23
|
];
|
|
24
|
-
function WidgetFrame({ title, question, query, span, children }) {
|
|
24
|
+
function WidgetFrame({ id, title, question, query, span, showQuery = false, onInspect, onOpenInExplorer, toolbar, children }) {
|
|
25
25
|
return /* @__PURE__ */ jsxs(
|
|
26
26
|
"div",
|
|
27
27
|
{
|
|
28
|
+
id,
|
|
28
29
|
className: cn(
|
|
29
|
-
"bg-card border border-border rounded-lg p-4 flex flex-col min-h-0",
|
|
30
|
+
"relative group/frame bg-card border border-border rounded-lg p-4 flex flex-col min-h-0",
|
|
30
31
|
span
|
|
31
32
|
),
|
|
32
33
|
children: [
|
|
33
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-
|
|
34
|
-
/* @__PURE__ */
|
|
35
|
-
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 mb-2", children: [
|
|
35
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
36
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: title }),
|
|
37
|
+
question && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: question })
|
|
38
|
+
] }),
|
|
39
|
+
(onInspect || onOpenInExplorer) && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
40
|
+
onInspect && /* @__PURE__ */ jsx(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
type: "button",
|
|
44
|
+
onClick: onInspect,
|
|
45
|
+
title: "Inspect widget query",
|
|
46
|
+
"aria-label": `Inspect query for ${title || "widget"}`,
|
|
47
|
+
className: "inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors",
|
|
48
|
+
children: /* @__PURE__ */ jsx(Eye, { className: "w-3.5 h-3.5" })
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
onOpenInExplorer && /* @__PURE__ */ jsx(
|
|
52
|
+
"button",
|
|
53
|
+
{
|
|
54
|
+
type: "button",
|
|
55
|
+
onClick: onOpenInExplorer,
|
|
56
|
+
title: "Open in explorer",
|
|
57
|
+
"aria-label": `Open ${title || "widget"} in explorer`,
|
|
58
|
+
className: "inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors",
|
|
59
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { className: "w-3.5 h-3.5" })
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
] })
|
|
36
63
|
] }),
|
|
37
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
64
|
+
toolbar && /* @__PURE__ */ jsx("div", { className: "mb-3", children: toolbar }),
|
|
65
|
+
showQuery && query != null && query !== "" && /* @__PURE__ */ jsx("div", { className: "font-mono text-[11px] text-primary/90 bg-background/60 rounded px-2 py-1 mb-3 whitespace-pre-wrap break-all", children: query }),
|
|
38
66
|
/* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0", children })
|
|
39
67
|
]
|
|
40
68
|
}
|
|
41
69
|
);
|
|
42
70
|
}
|
|
71
|
+
function WidgetToolButton({
|
|
72
|
+
label,
|
|
73
|
+
onClick,
|
|
74
|
+
disabled,
|
|
75
|
+
active,
|
|
76
|
+
children
|
|
77
|
+
}) {
|
|
78
|
+
return /* @__PURE__ */ jsx(
|
|
79
|
+
"button",
|
|
80
|
+
{
|
|
81
|
+
type: "button",
|
|
82
|
+
onClick,
|
|
83
|
+
title: label,
|
|
84
|
+
"aria-label": label,
|
|
85
|
+
disabled,
|
|
86
|
+
className: cn(
|
|
87
|
+
"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground disabled:opacity-40 disabled:hover:text-muted-foreground transition-colors",
|
|
88
|
+
active && "text-primary bg-primary/10"
|
|
89
|
+
),
|
|
90
|
+
children
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
function WidgetEditButton({ title, onClick }) {
|
|
95
|
+
return /* @__PURE__ */ jsx(
|
|
96
|
+
"button",
|
|
97
|
+
{
|
|
98
|
+
type: "button",
|
|
99
|
+
onClick,
|
|
100
|
+
title: "Edit widget",
|
|
101
|
+
"aria-label": `Edit widget ${title || ""}`.trim(),
|
|
102
|
+
className: "inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors",
|
|
103
|
+
children: /* @__PURE__ */ jsx(Edit3, { className: "w-3.5 h-3.5" })
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
function ScalarTokenInput({
|
|
108
|
+
name,
|
|
109
|
+
value,
|
|
110
|
+
disabled,
|
|
111
|
+
onCommit
|
|
112
|
+
}) {
|
|
113
|
+
const [draft, setDraft] = useState(value);
|
|
114
|
+
useEffect(() => setDraft(value), [value]);
|
|
115
|
+
const commit = () => {
|
|
116
|
+
if (draft !== value) onCommit(draft);
|
|
117
|
+
};
|
|
118
|
+
return /* @__PURE__ */ jsx(
|
|
119
|
+
"input",
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
value: draft,
|
|
123
|
+
disabled,
|
|
124
|
+
onChange: (e) => setDraft(e.target.value),
|
|
125
|
+
onBlur: commit,
|
|
126
|
+
onKeyDown: (e) => {
|
|
127
|
+
if (e.key === "Enter") {
|
|
128
|
+
commit();
|
|
129
|
+
e.currentTarget.blur();
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"aria-label": `Token ${name}`,
|
|
133
|
+
className: "w-20 rounded-lg border border-border bg-card px-2 py-1 text-xs font-mono text-foreground focus:outline-none focus:border-primary disabled:opacity-60"
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
}
|
|
43
137
|
function DashboardTokenControls({ tokens, values, onChange }) {
|
|
44
138
|
if (tokens.length === 0) return null;
|
|
45
139
|
const readOnly = !onChange;
|
|
@@ -60,7 +154,9 @@ function DashboardTokenControls({ tokens, values, onChange }) {
|
|
|
60
154
|
{
|
|
61
155
|
type: "button",
|
|
62
156
|
disabled: readOnly,
|
|
63
|
-
onClick: () =>
|
|
157
|
+
onClick: () => {
|
|
158
|
+
if (option !== current) onChange?.(token.name, option);
|
|
159
|
+
},
|
|
64
160
|
className: cn(
|
|
65
161
|
"text-xs px-2.5 py-1 rounded-md transition-colors",
|
|
66
162
|
option === current ? "bg-primary text-primary-foreground font-medium" : "text-muted-foreground hover:text-foreground hover:bg-muted",
|
|
@@ -70,12 +166,11 @@ function DashboardTokenControls({ tokens, values, onChange }) {
|
|
|
70
166
|
},
|
|
71
167
|
option
|
|
72
168
|
)) }) : readOnly ? /* @__PURE__ */ jsx("span", { className: "text-xs text-foreground font-mono", children: current }) : /* @__PURE__ */ jsx(
|
|
73
|
-
|
|
169
|
+
ScalarTokenInput,
|
|
74
170
|
{
|
|
75
|
-
|
|
171
|
+
name: token.name,
|
|
76
172
|
value: current,
|
|
77
|
-
|
|
78
|
-
className: "w-20 rounded-lg border border-border bg-card px-2 py-1 text-xs font-mono text-foreground focus:outline-none focus:border-primary"
|
|
173
|
+
onCommit: (next) => onChange?.(token.name, next)
|
|
79
174
|
}
|
|
80
175
|
)
|
|
81
176
|
] }, token.name);
|
|
@@ -83,19 +178,91 @@ function DashboardTokenControls({ tokens, values, onChange }) {
|
|
|
83
178
|
}
|
|
84
179
|
);
|
|
85
180
|
}
|
|
181
|
+
function createExecutorDocumentHost(executor, range = {}) {
|
|
182
|
+
return {
|
|
183
|
+
runAggregate: (queryText, overrides) => executor.runQuery(queryText, {
|
|
184
|
+
context: overrides.context,
|
|
185
|
+
rangeStart: range.rangeStart,
|
|
186
|
+
rangeEnd: range.rangeEnd,
|
|
187
|
+
preferredUnit: range.preferredUnit
|
|
188
|
+
}),
|
|
189
|
+
runFind: async (queryText, context) => {
|
|
190
|
+
const parsed = parseQuery(queryText);
|
|
191
|
+
if (!isFindQuery(parsed)) return { kind: "find", error: `not a content query: ${queryText}` };
|
|
192
|
+
const res = await executor.runFind(parsed, {
|
|
193
|
+
context,
|
|
194
|
+
range: range.rangeStart !== void 0 ? { start: range.rangeStart, end: range.rangeEnd ?? Number.MAX_SAFE_INTEGER, endExclusive: false } : void 0
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
kind: "find",
|
|
198
|
+
notes: res.notes,
|
|
199
|
+
blocks: res.blocks,
|
|
200
|
+
efforts: res.efforts,
|
|
201
|
+
containers: res.containers,
|
|
202
|
+
runs: res.runs,
|
|
203
|
+
table: res.table
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
runPipeline: async (queryText, context) => {
|
|
207
|
+
const res = await executor.runPipeline?.(queryText, {
|
|
208
|
+
context,
|
|
209
|
+
rangeStart: range.rangeStart,
|
|
210
|
+
rangeEnd: range.rangeEnd,
|
|
211
|
+
preferredUnit: range.preferredUnit
|
|
212
|
+
});
|
|
213
|
+
return res ?? { error: "pipeline queries are not supported by this executor" };
|
|
214
|
+
},
|
|
215
|
+
rollupEnsure: range.rollupEnsure
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function outputToRunResult(parsed, out) {
|
|
219
|
+
const base = toChartResult({ parsed, series: out.series, unit: out.unit, error: out.error, table: out.table });
|
|
220
|
+
return Object.assign(base, {
|
|
221
|
+
...out.notes ? { notes: out.notes } : {},
|
|
222
|
+
...out.blocks ? { blocks: out.blocks } : {},
|
|
223
|
+
...out.efforts ? { efforts: out.efforts } : {},
|
|
224
|
+
...out.containers ? { containers: out.containers } : {},
|
|
225
|
+
...out.runs ? { runs: out.runs } : {}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
86
228
|
function spanClass(widget) {
|
|
229
|
+
if (widget.spanFull) return "col-span-1 md:col-span-2 lg:col-span-4";
|
|
230
|
+
if (widget.spanCols != null) {
|
|
231
|
+
if (widget.spanCols <= 1) return "col-span-1";
|
|
232
|
+
if (widget.spanCols === 2) return "col-span-1 md:col-span-2";
|
|
233
|
+
if (widget.spanCols === 3) return "col-span-1 md:col-span-2 lg:col-span-3";
|
|
234
|
+
return "col-span-1 md:col-span-2 lg:col-span-4";
|
|
235
|
+
}
|
|
87
236
|
const resolved = resolveWidgetType(widget.type);
|
|
88
237
|
if (resolved === "value") return "col-span-1";
|
|
89
238
|
if (resolved === "table") return "col-span-1 md:col-span-2";
|
|
90
239
|
return "col-span-1 md:col-span-2 lg:col-span-4";
|
|
91
240
|
}
|
|
241
|
+
var SIZE_OPTIONS = [
|
|
242
|
+
{ label: "Span 1 column", span: { spanCols: 1 }, testId: "widget-size-1" },
|
|
243
|
+
{ label: "Span 2 columns", span: { spanCols: 2 }, testId: "widget-size-2" },
|
|
244
|
+
{ label: "Span 4 columns", span: { spanCols: 4 }, testId: "widget-size-4" },
|
|
245
|
+
{ label: "Full row", span: { spanFull: true }, testId: "widget-size-full" }
|
|
246
|
+
];
|
|
247
|
+
function sizeIsActive(widget, span) {
|
|
248
|
+
if (span.spanFull) return widget.spanFull === true;
|
|
249
|
+
return !widget.spanFull && (widget.spanCols ?? null) === (span.spanCols ?? null);
|
|
250
|
+
}
|
|
92
251
|
function DashboardView({
|
|
93
252
|
document,
|
|
253
|
+
headings,
|
|
94
254
|
executor,
|
|
95
255
|
onEnsureRollupFacts,
|
|
96
256
|
tokenValues,
|
|
97
257
|
onTokenChange,
|
|
98
|
-
|
|
258
|
+
editMode = false,
|
|
259
|
+
onEditWidget,
|
|
260
|
+
onInspectWidget,
|
|
261
|
+
onOpenInExplorer,
|
|
262
|
+
onDuplicateWidget,
|
|
263
|
+
onRemoveWidget,
|
|
264
|
+
onMoveWidget,
|
|
265
|
+
onResizeWidget,
|
|
99
266
|
rangeStart,
|
|
100
267
|
rangeEnd,
|
|
101
268
|
preferredUnit
|
|
@@ -106,8 +273,15 @@ function DashboardView({
|
|
|
106
273
|
);
|
|
107
274
|
const resolved = useMemo(
|
|
108
275
|
() => document.widgets.map((widget) => {
|
|
109
|
-
const { query, missing } = substituteTokens(widget.
|
|
110
|
-
|
|
276
|
+
const { query, missing } = substituteTokens(widget.body, values);
|
|
277
|
+
const attributes = {};
|
|
278
|
+
const allMissing = new Set(missing);
|
|
279
|
+
for (const [key, value] of Object.entries(widget.attributes)) {
|
|
280
|
+
const sub = substituteTokens(value, values);
|
|
281
|
+
attributes[key] = sub.query;
|
|
282
|
+
for (const m of sub.missing) allMissing.add(m);
|
|
283
|
+
}
|
|
284
|
+
return { widget, query, missing: [...allMissing], attributes };
|
|
111
285
|
}),
|
|
112
286
|
[document.widgets, values]
|
|
113
287
|
);
|
|
@@ -137,11 +311,17 @@ function DashboardView({
|
|
|
137
311
|
next[widget.key] = { error: parsed.error };
|
|
138
312
|
continue;
|
|
139
313
|
}
|
|
314
|
+
const resolvedType = resolveWidgetType(widget.type);
|
|
140
315
|
if (isFindQuery(parsed)) {
|
|
141
|
-
|
|
316
|
+
if (resolvedType !== "table" && resolvedType !== "list") {
|
|
317
|
+
next[widget.key] = { error: "content queries return things \u2014 use a table or list widget instead" };
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
} else if (!isPipelineQuery(parsed) && resolvedType === "list") {
|
|
321
|
+
next[widget.key] = { error: "aggregate queries return numbers \u2014 use a chart or value widget instead" };
|
|
142
322
|
continue;
|
|
143
323
|
}
|
|
144
|
-
runnable.push({ widget, query });
|
|
324
|
+
runnable.push({ widget, query, parsed });
|
|
145
325
|
}
|
|
146
326
|
if (!executor) {
|
|
147
327
|
if (!cancelled) {
|
|
@@ -150,15 +330,26 @@ function DashboardView({
|
|
|
150
330
|
}
|
|
151
331
|
return;
|
|
152
332
|
}
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
333
|
+
const host = createExecutorDocumentHost(executor, {
|
|
334
|
+
rangeStart,
|
|
335
|
+
rangeEnd,
|
|
336
|
+
preferredUnit,
|
|
337
|
+
rollupEnsure: onEnsureRollupFacts
|
|
338
|
+
});
|
|
157
339
|
await Promise.all(
|
|
158
|
-
runnable.map(async ({ widget, query }) => {
|
|
340
|
+
runnable.map(async ({ widget, query, parsed }) => {
|
|
159
341
|
try {
|
|
342
|
+
const runner = new SharedQueryDocumentRunner(host);
|
|
343
|
+
const res = await runner.run(query);
|
|
344
|
+
const out = res.outputs[0];
|
|
345
|
+
if (!out) {
|
|
346
|
+
next[widget.key] = { error: res.diagnostics[0] ?? "widget produced no output" };
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const error = out.error ?? res.diagnostics[0];
|
|
160
350
|
next[widget.key] = {
|
|
161
|
-
result:
|
|
351
|
+
result: outputToRunResult(parsed, out),
|
|
352
|
+
...error ? { error } : {}
|
|
162
353
|
};
|
|
163
354
|
} catch (err) {
|
|
164
355
|
next[widget.key] = { error: err instanceof Error ? err.message : String(err) };
|
|
@@ -174,46 +365,114 @@ function DashboardView({
|
|
|
174
365
|
return () => {
|
|
175
366
|
cancelled = true;
|
|
176
367
|
};
|
|
177
|
-
}, [resolvedKey, executor, onEnsureRollupFacts, rangeStart, rangeEnd, preferredUnit]);
|
|
368
|
+
}, [resolvedKey, resolved, executor, onEnsureRollupFacts, rangeStart, rangeEnd, preferredUnit]);
|
|
178
369
|
return /* @__PURE__ */ jsxs("div", { "data-testid": "dashboard-view", children: [
|
|
179
370
|
/* @__PURE__ */ jsx(DashboardTokenControls, { tokens: document.tokens, values, onChange: onTokenChange }),
|
|
180
371
|
loading && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mb-3", children: "Loading widgets\u2026" }),
|
|
181
|
-
/* @__PURE__ */
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
372
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4", children: [
|
|
373
|
+
resolved.map(({ widget, query, attributes }, index) => {
|
|
374
|
+
const run = runs[widget.key];
|
|
375
|
+
const canArrange = editMode && (onEditWidget || onDuplicateWidget || onRemoveWidget || onMoveWidget || onResizeWidget);
|
|
376
|
+
const before = (headings ?? []).filter((h) => h.beforeWidget === index);
|
|
377
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
378
|
+
before.map((h) => /* @__PURE__ */ jsx(
|
|
379
|
+
"div",
|
|
380
|
+
{
|
|
381
|
+
id: h.id,
|
|
382
|
+
className: cn("col-span-full font-semibold text-foreground", h.level <= 2 ? "text-base mt-2" : "text-sm"),
|
|
383
|
+
children: h.text
|
|
384
|
+
},
|
|
385
|
+
h.id
|
|
386
|
+
)),
|
|
387
|
+
/* @__PURE__ */ jsx(
|
|
388
|
+
WidgetFrame,
|
|
389
|
+
{
|
|
390
|
+
id: `widget-${widget.key}`,
|
|
391
|
+
title: widget.title ?? "",
|
|
392
|
+
question: widget.question ?? "",
|
|
393
|
+
query,
|
|
394
|
+
span: spanClass(widget),
|
|
395
|
+
onInspect: onInspectWidget ? () => onInspectWidget(widget) : void 0,
|
|
396
|
+
onOpenInExplorer: onOpenInExplorer ? () => onOpenInExplorer(widget, query) : void 0,
|
|
397
|
+
toolbar: canArrange ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", "data-testid": `widget-toolbar-${widget.key}`, children: [
|
|
398
|
+
onEditWidget && /* @__PURE__ */ jsx(WidgetEditButton, { title: widget.title ?? "", onClick: () => onEditWidget(widget) }),
|
|
399
|
+
onMoveWidget && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
400
|
+
/* @__PURE__ */ jsx(
|
|
401
|
+
WidgetToolButton,
|
|
402
|
+
{
|
|
403
|
+
label: `Move ${widget.title || "widget"} up`,
|
|
404
|
+
disabled: index === 0,
|
|
405
|
+
onClick: () => onMoveWidget(widget, -1),
|
|
406
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "w-3.5 h-3.5" })
|
|
407
|
+
}
|
|
408
|
+
),
|
|
409
|
+
/* @__PURE__ */ jsx(
|
|
410
|
+
WidgetToolButton,
|
|
411
|
+
{
|
|
412
|
+
label: `Move ${widget.title || "widget"} down`,
|
|
413
|
+
disabled: index === resolved.length - 1,
|
|
414
|
+
onClick: () => onMoveWidget(widget, 1),
|
|
415
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "w-3.5 h-3.5" })
|
|
416
|
+
}
|
|
417
|
+
)
|
|
418
|
+
] }),
|
|
419
|
+
onResizeWidget && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0 rounded bg-muted/60 p-0.5", children: SIZE_OPTIONS.map((option) => /* @__PURE__ */ jsx(
|
|
420
|
+
"button",
|
|
421
|
+
{
|
|
422
|
+
type: "button",
|
|
423
|
+
"data-testid": `${option.testId}-${widget.key}`,
|
|
424
|
+
title: option.label,
|
|
425
|
+
"aria-label": `${option.label} for ${widget.title || "widget"}`,
|
|
426
|
+
"aria-pressed": sizeIsActive(widget, option.span),
|
|
427
|
+
disabled: sizeIsActive(widget, option.span),
|
|
428
|
+
onClick: () => onResizeWidget(widget, option.span),
|
|
429
|
+
className: "inline-flex items-center justify-center px-1 py-0.5 max-lg:min-h-11 max-lg:min-w-11 text-xs font-mono rounded text-muted-foreground hover:text-foreground disabled:text-primary disabled:bg-primary/10",
|
|
430
|
+
children: option.span.spanFull ? /* @__PURE__ */ jsx(ChevronRight, { className: "w-3 h-3" }) : option.span.spanCols
|
|
431
|
+
},
|
|
432
|
+
option.testId
|
|
433
|
+
)) }),
|
|
434
|
+
onDuplicateWidget && /* @__PURE__ */ jsx(
|
|
435
|
+
WidgetToolButton,
|
|
436
|
+
{
|
|
437
|
+
label: `Duplicate ${widget.title || "widget"}`,
|
|
438
|
+
onClick: () => onDuplicateWidget(widget),
|
|
439
|
+
children: /* @__PURE__ */ jsx(Copy, { className: "w-3.5 h-3.5" })
|
|
440
|
+
}
|
|
441
|
+
),
|
|
442
|
+
onRemoveWidget && /* @__PURE__ */ jsx(
|
|
443
|
+
WidgetToolButton,
|
|
444
|
+
{
|
|
445
|
+
label: `Remove ${widget.title || "widget"}`,
|
|
446
|
+
onClick: () => onRemoveWidget(widget),
|
|
447
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5" })
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
] }) : void 0,
|
|
451
|
+
children: run?.error ? /* @__PURE__ */ jsx(WidgetProblemBadge, { message: run.error }) : /* @__PURE__ */ jsx(
|
|
452
|
+
WidgetChart,
|
|
453
|
+
{
|
|
454
|
+
type: widget.type,
|
|
455
|
+
result: run?.result,
|
|
456
|
+
label: widget.title,
|
|
457
|
+
unit: preferredUnit,
|
|
458
|
+
attributes
|
|
459
|
+
}
|
|
460
|
+
)
|
|
461
|
+
},
|
|
462
|
+
widget.key
|
|
463
|
+
)
|
|
464
|
+
] }, widget.key);
|
|
465
|
+
}),
|
|
466
|
+
(headings ?? []).filter((h) => h.beforeWidget >= resolved.length).map((h) => /* @__PURE__ */ jsx(
|
|
467
|
+
"div",
|
|
185
468
|
{
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
span: spanClass(widget),
|
|
190
|
-
children: /* @__PURE__ */ jsxs("div", { className: "relative group/card h-full min-h-[160px]", children: [
|
|
191
|
-
onEditQuery && /* @__PURE__ */ jsx(
|
|
192
|
-
"button",
|
|
193
|
-
{
|
|
194
|
-
type: "button",
|
|
195
|
-
onClick: () => onEditQuery(widget),
|
|
196
|
-
title: "Edit widget query",
|
|
197
|
-
"aria-label": `Edit query for ${widget.title ?? "widget"}`,
|
|
198
|
-
className: "absolute top-0 right-0 p-1 rounded bg-muted/80 text-muted-foreground hover:text-foreground opacity-0 group-hover/card:opacity-100 transition-opacity z-10",
|
|
199
|
-
children: /* @__PURE__ */ jsx(Edit3, { className: "w-3.5 h-3.5" })
|
|
200
|
-
}
|
|
201
|
-
),
|
|
202
|
-
run?.error ? /* @__PURE__ */ jsx(WidgetProblemBadge, { message: run.error }) : /* @__PURE__ */ jsx(
|
|
203
|
-
WidgetChart,
|
|
204
|
-
{
|
|
205
|
-
type: widget.type,
|
|
206
|
-
result: run?.result,
|
|
207
|
-
label: widget.title,
|
|
208
|
-
unit: preferredUnit,
|
|
209
|
-
params: widget.params
|
|
210
|
-
}
|
|
211
|
-
)
|
|
212
|
-
] })
|
|
469
|
+
id: h.id,
|
|
470
|
+
className: cn("col-span-full font-semibold text-foreground", h.level <= 2 ? "text-base mt-2" : "text-sm"),
|
|
471
|
+
children: h.text
|
|
213
472
|
},
|
|
214
|
-
|
|
215
|
-
)
|
|
216
|
-
|
|
473
|
+
h.id
|
|
474
|
+
))
|
|
475
|
+
] })
|
|
217
476
|
] });
|
|
218
477
|
}
|
|
219
478
|
function RangeSelector({ weeks: weeksProp, onWeeksChange, className }) {
|
|
@@ -257,16 +516,32 @@ function useAnalyticsQueries(queries, weeks, executor, refreshKey = 0, preferred
|
|
|
257
516
|
}
|
|
258
517
|
const now = Date.now();
|
|
259
518
|
const rangeStart = now - weeks * WEEK;
|
|
260
|
-
const
|
|
519
|
+
const host = createExecutorDocumentHost(executor, {
|
|
520
|
+
rangeStart,
|
|
521
|
+
rangeEnd: now,
|
|
522
|
+
preferredUnit,
|
|
523
|
+
rollupEnsure: onEnsureRollupFacts
|
|
524
|
+
});
|
|
525
|
+
const runner = new SharedQueryDocumentRunner(host);
|
|
261
526
|
try {
|
|
262
|
-
if (consumesRollups && onEnsureRollupFacts) {
|
|
263
|
-
await onEnsureRollupFacts().catch(() => void 0);
|
|
264
|
-
}
|
|
265
527
|
const settled = await Promise.all(
|
|
266
|
-
queries.map(async (q) =>
|
|
267
|
-
q.
|
|
268
|
-
|
|
269
|
-
|
|
528
|
+
queries.map(async (q) => {
|
|
529
|
+
const res = await runner.run(q.query);
|
|
530
|
+
const out = res.outputs[0];
|
|
531
|
+
const error = out?.error ?? res.diagnostics[0];
|
|
532
|
+
const result = toChartResult({
|
|
533
|
+
parsed: parseQuery(q.query),
|
|
534
|
+
series: out?.series,
|
|
535
|
+
unit: out?.unit,
|
|
536
|
+
error,
|
|
537
|
+
table: out?.table
|
|
538
|
+
});
|
|
539
|
+
if (out?.notes) result.notes = out.notes;
|
|
540
|
+
if (out?.blocks) result.blocks = out.blocks;
|
|
541
|
+
if (out?.efforts) result.efforts = out.efforts;
|
|
542
|
+
if (out?.runs) result.runs = out.runs;
|
|
543
|
+
return [q.key, result];
|
|
544
|
+
})
|
|
270
545
|
);
|
|
271
546
|
if (!cancelled) setResults(Object.fromEntries(settled));
|
|
272
547
|
} finally {
|
|
@@ -405,15 +680,15 @@ function AnalyticsUnitPreference({ className, unit: unitProp, forced = false, st
|
|
|
405
680
|
}
|
|
406
681
|
|
|
407
682
|
// src/version.ts
|
|
408
|
-
var VERSION = "0.
|
|
409
|
-
var GIT_SHA = "
|
|
410
|
-
var BUILD_TIME = "2026-
|
|
683
|
+
var VERSION = "0.35.2116";
|
|
684
|
+
var GIT_SHA = "a4d411f";
|
|
685
|
+
var BUILD_TIME = "2026-10-12T00:14:24.795Z";
|
|
411
686
|
var SEMVER = {
|
|
412
|
-
version: "0.
|
|
413
|
-
gitSha: "
|
|
414
|
-
buildTime: "2026-
|
|
687
|
+
version: "0.35.2116",
|
|
688
|
+
gitSha: "a4d411f",
|
|
689
|
+
buildTime: "2026-10-12T00:14:24.795Z"
|
|
415
690
|
};
|
|
416
691
|
|
|
417
|
-
export { ANALYTICS_UNIT_STORAGE_KEY, AnalyticsUnitPreference, BUILD_TIME, CODEMIRROR_SINGLETON_DEPS, DEFAULT_ANALYTICS_UNIT, DashboardTokenControls, DashboardView, GIT_SHA, RangeSelector, SEMVER, VERSION, WidgetFrame, getDashboardEffectiveUnit, getEffectiveAnalyticsUnit, readStoredUnit, useAnalyticsQueries, useAnalyticsUnitPreference };
|
|
692
|
+
export { ANALYTICS_UNIT_STORAGE_KEY, AnalyticsUnitPreference, BUILD_TIME, CODEMIRROR_SINGLETON_DEPS, DEFAULT_ANALYTICS_UNIT, DashboardTokenControls, DashboardView, GIT_SHA, RangeSelector, SEMVER, VERSION, WidgetEditButton, WidgetFrame, WidgetToolButton, getDashboardEffectiveUnit, getEffectiveAnalyticsUnit, readStoredUnit, useAnalyticsQueries, useAnalyticsUnitPreference };
|
|
418
693
|
//# sourceMappingURL=index.mjs.map
|
|
419
694
|
//# sourceMappingURL=index.mjs.map
|